diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e922ddc0..48937e287 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -139,6 +139,12 @@ jobs: cxx: clang++ args: cd android && ./ab.sh -j2 APP_ABI=armeabi-v7a UNITTEST=1 HEADLESS=1 id: android-arm32 + - os: ubuntu-latest + extra: android + cc: clang + cxx: clang++ + args: cd android && ./ab.sh -j2 APP_ABI=x86 UNITTEST=1 HEADLESS=1 + id: android-x86_32 - os: ubuntu-latest extra: android cc: clang @@ -149,8 +155,14 @@ jobs: extra: android cc: clang cxx: clang++ - args: cd android && ./ab.sh -j2 APP_ABI=arm64-v8a OPENXR=1 - id: android-vr + args: cd android && ./ab.sh -j2 APP_ABI=arm64-v8a OPENXR=1 OPENXR_PLATFORM_QUEST=1 + id: android-vr-quest + - os: ubuntu-latest + extra: android + cc: clang + cxx: clang++ + args: cd android && ./ab.sh -j2 APP_ABI=arm64-v8a OPENXR=1 OPENXR_PLATFORM_PICO=1 + id: android-vr-pico - os: ubuntu-latest extra: android cc: clang @@ -219,7 +231,7 @@ jobs: run: | sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" sudo apt-get update -y -qq - sudo apt-get install libsdl2-dev libgl1-mesa-dev libglu1-mesa-dev libsdl2-ttf-dev libfontconfig1-dev + sudo apt-get install libsdl2-dev libgl1-mesa-dev libglu1-mesa-dev - name: Create macOS git-version.cpp for tagged release if: startsWith(github.ref, 'refs/tags/') && runner.os == 'macOS' && matrix.extra == 'test' @@ -229,8 +241,6 @@ jobs: - name: Setup ccache uses: hendrikmuhs/ccache-action@v1.2 - # Disable ccache on macos for now, it's become buggy for some reason. - if: matrix.id != 'macos' with: key: ${{ matrix.id }} @@ -333,7 +343,7 @@ jobs: run: | sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" sudo apt-get update -y -qq - sudo apt-get install libsdl2-dev libgl1-mesa-dev libglu1-mesa-dev libsdl2-ttf-dev libfontconfig1-dev + sudo apt-get install libsdl2-dev libgl1-mesa-dev libglu1-mesa-dev - name: Install macOS dependencies if: runner.os == 'macOS' diff --git a/.gitignore b/.gitignore index 78c80c60c..fd1d2d372 100644 --- a/.gitignore +++ b/.gitignore @@ -105,7 +105,6 @@ Windows/*.ipch # For vim *.swp tags -*.ctags # Other VCS .bzr/ @@ -118,8 +117,6 @@ debian/ppsspp/ # Libretro build *.o -*.tmp -*.a # YouCompleteMe file .ycm_extra_conf.pyc @@ -134,5 +131,3 @@ CMakeFiles .cache/ build libretro/obj/local - -ppsspp_retroachievements.dat diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e25c599bb..ec2783861 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -158,4 +158,4 @@ libretro-build-tvos-arm64: - .core-defs - .cmake-defs variables: - CORE_ARGS: -DIOS_PLATFORM=TVOS -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ios.cmake -DLIBRETRO=ON + CORE_ARGS: -DIOS_PLATFORM=TVOS -DUSE_FFMPEG=NO -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ios.cmake -DLIBRETRO=ON diff --git a/.gitmodules b/.gitmodules index 82a4f4bf2..a3c92a992 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,12 +44,3 @@ [submodule "cpu_features"] path = ext/cpu_features url = https://github.com/google/cpu_features.git -[submodule "ext/rcheevos"] - path = ext/rcheevos - url = https://github.com/RetroAchievements/rcheevos.git -[submodule "ext/naett"] - path = ext/naett - url = https://github.com/erkkah/naett.git -[submodule "ext/libchdr"] - path = ext/libchdr - url = https://github.com/rtissera/libchdr.git diff --git a/CMakeLists.txt b/CMakeLists.txt index caaef3378..053707f31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,6 @@ if(CMAKE_SYSTEM_PROCESSOR) set(MIPS_DEVICE ON) elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^riscv64") set(RISCV64_DEVICE ON) - elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^loongarch64") - set(LOONGARCH64_DEVICE ON) else() message("Unknown CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") endif() @@ -141,7 +139,6 @@ option(ARMV7 "Set to ON if targeting an ARMv7 processor" ${ARMV7_DEVICE}) option(ARM "Set to ON if targeting an ARM processor" ${ARM_DEVICE}) option(MIPS "Set to ON if targeting a MIPS processor" ${MIPS_DEVICE}) option(RISCV64 "Set to ON if targeting a RISCV64 processor" ${RISCV64_DEVICE}) -option(LOONGARCH64 "Set to ON if targeting a LOONGARCH64 processor" ${LOONGARCH64_DEVICE}) option(X86 "Set to ON if targeting an X86 processor" ${X86_DEVICE}) option(X86_64 "Set to ON if targeting an X86_64 processor" ${X86_64_DEVICE}) # :: Environments @@ -149,7 +146,7 @@ option(USING_EGL "Set to ON if target environment uses EGL" ${USING_EGL}) option(USING_FBDEV "Set to ON if target environment uses fbdev (eg. Pandora)" ${USING_FBDEV}) option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2}) option(USING_X11_VULKAN "Set to OFF if target environment doesn't use X11 for Vulkan" ON) -option(USE_WAYLAND_WSI "Enable or disable Wayland WSI support for Vulkan" ON) +option(USE_WAYLAND_WSI "Enable or disable Wayland WSI support for Vulkan" ${USE_WAYLAND_WSI}) option(USE_VULKAN_DISPLAY_KHR "Enable or disable full screen display of Vulkan" ${USE_VULKAN_DISPLAY_KHR}) # :: Frontends option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI}) @@ -177,20 +174,20 @@ option(USE_UBSAN "Use undefined behaviour sanitizer" OFF) if(UNIX AND NOT (APPLE OR ANDROID) AND VULKAN) if(USING_X11_VULKAN) message("Using X11 for Vulkan") - find_package(X11) - include_directories(${X11_Xlib_INCLUDE_PATH}) add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) else() message("NOT using X11 for Vulkan") endif() # add_definitions(-DVK_USE_PLATFORM_XCB_KHR) - find_package(Wayland) - if(NOT WAYLAND_FOUND) - message(STATUS "Could not find Wayland libraries, disabling Wayland WSI support for Vulkan.") - elseif(USE_WAYLAND_WSI) - include_directories(${WAYLAND_INCLUDE_DIR}) - add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR) + if(USE_WAYLAND_WSI) + find_package(Wayland) + if(NOT WAYLAND_FOUND) + message(STATUS "Could not find Wayland libraries, disabling Wayland WSI support for Vulkan.") + else() + include_directories(${WAYLAND_INCLUDE_DIR}) + add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR) + endif() endif() if(USE_VULKAN_DISPLAY_KHR) @@ -220,16 +217,6 @@ else() set(CoreLinkType STATIC) endif() -if(NOT ANDROID AND NOT WIN32 AND (NOT APPLE OR IOS)) - set(HTTPS_NOT_AVAILABLE ON) -endif() - -# Made this flag negative because it's hopefully quite temporary and didn't -# want to have to update all build systems. -if(HTTPS_NOT_AVAILABLE) - add_definitions(-DHTTPS_NOT_AVAILABLE) -endif() - # Work around for some misfeature of the current glslang build system include_directories(ext/glslang) @@ -259,22 +246,11 @@ endif() if(NOT LIBRETRO AND NOT IOS AND NOT MACOSX) find_package(SDL2) - find_package(SDL2_ttf) - find_package(Fontconfig) - - # TODO: this can be removed once CI supports newer SDL2_ttf - if (NOT SDL2_ttf_FOUND) - find_package(PkgConfig) - if(PkgConfig_FOUND) - pkg_check_modules(SDL2_ttf_PKGCONFIG IMPORTED_TARGET SDL2_ttf) - endif() - endif() endif() if(MACOSX AND NOT IOS) if(USE_SYSTEM_LIBSDL2) find_package(SDL2) - find_package(SDL2_ttf) else() find_library(SDL2Fwk SDL2 REQUIRED PATHS SDL/macOS) message(STATUS "found SDL2Fwk=${SDL2Fwk}") @@ -328,9 +304,6 @@ endif() if(RISCV64) message("Generating for RISCV64, ${CMAKE_BUILD_TYPE}") endif() -if(LOONGARCH64) - message("Generating for LOONGARCH64, ${CMAKE_BUILD_TYPE}") -endif() if(X86) message("Generating for x86, ${CMAKE_BUILD_TYPE}") endif() @@ -406,8 +379,6 @@ if(NOT MSVC) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -parallel -fopenmp") endif() - add_definitions(-fno-math-errno) - if(X86 OR X86_64) # enable sse2 code generation add_definitions(-msse2) @@ -433,13 +404,8 @@ if(NOT MSVC) add_definitions(-Wno-psabi) endif() add_definitions(-D_XOPEN_SOURCE=700) - add_definitions(-D_XOPEN_SOURCE_EXTENDED -D__BSD_VISIBLE=1 -D_BSD_SOURCE -D_DEFAULT_SOURCE) - if(CMAKE_SYSTEM_NAME MATCHES "Linux|SunOS" OR MINGW) - add_definitions(-D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64) - endif() - if(${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD") - add_definitions(-D_NETBSD_SOURCE) - endif() + add_definitions(-D_XOPEN_SOURCE_EXTENDED -D__BSD_VISIBLE=1) + add_definitions(-D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64) elseif(ANDROID) add_definitions(-fsigned-char) endif() @@ -451,7 +417,6 @@ else() endif() set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D_NDEBUG") - set(CMAKE_EXE_LINKER_FLAGS /NODEFAULTLIB:"libcmt.lib") endif() if(WIN32) @@ -544,14 +509,6 @@ set(CommonRISCV64 ) source_group(RISCV64 FILES ${CommonRISCV64}) -set(CommonLOONGARCH64 - ${CommonJIT} - Common/LoongArchCPUDetect.cpp - Core/MIPS/fake/FakeJit.cpp - Core/MIPS/fake/FakeJit.h -) -source_group(LOONGARCH64 FILES ${CommonLOONGARCH64}) - if(WIN32) set(CommonD3D Common/GPU/D3D9/D3D9ShaderCompiler.cpp @@ -590,7 +547,6 @@ add_library(Common STATIC ${CommonARM64} ${CommonMIPS} ${CommonRISCV64} - ${CommonLOONGARCH64} ${CommonD3D} ${CommonVR} Common/Serialize/Serializer.cpp @@ -610,7 +566,6 @@ add_library(Common STATIC Common/Data/Collections/FixedSizeQueue.h Common/Data/Collections/Hashmaps.h Common/Data/Collections/TinySet.h - Common/Data/Collections/FastVec.h Common/Data/Collections/ThreadSafeList.h Common/Data/Color/RGBAUtil.cpp Common/Data/Color/RGBAUtil.h @@ -675,8 +630,6 @@ add_library(Common STATIC Common/File/FileDescriptor.h Common/GPU/DataFormat.h Common/GPU/MiscTypes.h - Common/GPU/GPUBackendCommon.cpp - Common/GPU/GPUBackendCommon.h Common/GPU/thin3d.cpp Common/GPU/thin3d.h Common/GPU/thin3d_create.h @@ -698,8 +651,6 @@ add_library(Common STATIC Common/GPU/OpenGL/GLFrameData.cpp Common/GPU/OpenGL/GLFrameData.h Common/GPU/OpenGL/thin3d_gl.cpp - Common/GPU/OpenGL/GLMemory.cpp - Common/GPU/OpenGL/GLMemory.h Common/GPU/OpenGL/GLRenderManager.cpp Common/GPU/OpenGL/GLRenderManager.h Common/GPU/OpenGL/GLQueueRunner.cpp @@ -712,8 +663,6 @@ add_library(Common STATIC Common/GPU/Vulkan/VulkanDebug.h Common/GPU/Vulkan/VulkanContext.cpp Common/GPU/Vulkan/VulkanContext.h - Common/GPU/Vulkan/VulkanDescSet.cpp - Common/GPU/Vulkan/VulkanDescSet.h Common/GPU/Vulkan/VulkanFramebuffer.cpp Common/GPU/Vulkan/VulkanFramebuffer.h Common/GPU/Vulkan/VulkanImage.cpp @@ -753,10 +702,6 @@ add_library(Common STATIC Common/Net/HTTPClient.h Common/Net/HTTPHeaders.cpp Common/Net/HTTPHeaders.h - Common/Net/HTTPNaettRequest.cpp - Common/Net/HTTPNaettRequest.h - Common/Net/HTTPRequest.cpp - Common/Net/HTTPRequest.h Common/Net/HTTPServer.cpp Common/Net/HTTPServer.h Common/Net/NetBuffer.cpp @@ -781,8 +726,6 @@ add_library(Common STATIC Common/Render/Text/draw_text.h Common/Render/Text/draw_text_android.cpp Common/Render/Text/draw_text_android.h - Common/Render/Text/draw_text_sdl.cpp - Common/Render/Text/draw_text_sdl.h Common/Render/Text/draw_text_win.cpp Common/Render/Text/draw_text_win.h Common/Render/Text/draw_text_uwp.cpp @@ -793,8 +736,6 @@ add_library(Common STATIC Common/System/NativeApp.h Common/System/Request.cpp Common/System/Request.h - Common/System/OSD.cpp - Common/System/OSD.h Common/Thread/Channel.h Common/Thread/ParallelLoop.cpp Common/Thread/ParallelLoop.h @@ -813,8 +754,6 @@ add_library(Common STATIC Common/UI/UI.h Common/UI/Context.cpp Common/UI/Context.h - Common/UI/IconCache.cpp - Common/UI/IconCache.h Common/UI/UIScreen.cpp Common/UI/UIScreen.h Common/UI/Tween.cpp @@ -852,10 +791,8 @@ add_library(Common STATIC Common/MemArenaDarwin.cpp Common/MemArenaPosix.cpp Common/MemArenaWin32.cpp - Common/MemArenaHorizon.cpp Common/MemArena.h Common/MemoryUtil.cpp - Common/MemoryUtilHorizon.cpp Common/MemoryUtil.h Common/OSVersion.cpp Common/OSVersion.h @@ -901,11 +838,7 @@ if(USE_FFMPEG) set(PLATFORM_ARCH "android/x86") endif() elseif(IOS) - if(IOS_PLATFORM STREQUAL "TVOS") - set(PLATFORM_ARCH "tvos/arm64") - else() - set(PLATFORM_ARCH "ios/universal") - endif() + set(PLATFORM_ARCH "ios/universal") elseif(MACOSX) set(PLATFORM_ARCH "macosx/universal") elseif(LINUX) @@ -919,8 +852,6 @@ if(USE_FFMPEG) set(PLATFORM_ARCH "linux/mips32") elseif(RISCV64) set(PLATFORM_ARCH "linux/riscv64") - elseif(LOONGARCH64) - set(PLATFORM_ARCH "linux/loongarch64") elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) set(PLATFORM_ARCH "linux/x86_64") elseif(X86) @@ -1001,7 +932,6 @@ endif() find_package(LIBZIP) if(LIBZIP_FOUND AND USE_SYSTEM_LIBZIP) - include_directories(${LIBZIP_INCLUDE_DIRS}) add_definitions(-DSHARED_LIBZIP) else() add_library(libzip STATIC @@ -1219,6 +1149,15 @@ set(nativeExtra) set(nativeExtraLibs) if(ANDROID) + set(nativeExtra ${nativeExtra} + Common/GL/GLInterface/EGLAndroid.cpp + Common/GL/GLInterface/EGLAndroid.h + Common/GL/GLInterface/EGL.cpp + Common/GL/GLInterface/EGL.h + Common/GL/GLInterface/GLInterface.cpp + Common/GL/GLInterfaceBase.h + ) + set(NativeAppSource ${NativeAppSource} android/jni/app-android.cpp android/jni/AndroidJavaGLContext.cpp @@ -1349,22 +1288,6 @@ else() SDL/SDLVulkanGraphicsContext.cpp ) endif() - if(SDL2_ttf_FOUND OR - (SDL2_ttf_PKGCONFIG_FOUND AND - SDL2_ttf_PKGCONFIG_VERSION VERSION_GREATER_EQUAL "2.0.18")) - add_definitions(-DUSE_SDL2_TTF) - if(FONTCONFIG_FOUND) - add_definitions(-DUSE_SDL2_TTF_FONTCONFIG) - set(nativeExtraLibs ${nativeExtraLibs} Fontconfig::Fontconfig) - endif() - elseif(SDL2_ttf_PKGCONFIG_FOUND) - message(WARNING "Found SDL2_ttf <2.0.18 - this is too old, falling back to atlas") - endif() - if(SDL2_ttf_FOUND) - set(nativeExtraLibs ${nativeExtraLibs} SDL2_ttf::SDL2_ttf) - elseif(SDL2_ttf_PKGCONFIG_FOUND) - set(nativeExtraLibs ${nativeExtraLibs} PkgConfig::SDL2_ttf_PKGCONFIG) - endif() if(APPLE) set(nativeExtra ${nativeExtra} SDL/SDLMain.h @@ -1426,8 +1349,6 @@ list(APPEND NativeAppSource UI/BackgroundAudio.cpp UI/ChatScreen.h UI/ChatScreen.cpp - UI/DebugOverlay.cpp - UI/DebugOverlay.h UI/DevScreens.cpp UI/DevScreens.h UI/DisplayLayoutScreen.cpp @@ -1442,8 +1363,6 @@ list(APPEND NativeAppSource UI/MiscScreens.cpp UI/PauseScreen.h UI/PauseScreen.cpp - UI/TabbedDialogScreen.h - UI/TabbedDialogScreen.cpp UI/GameScreen.h UI/GameScreen.cpp UI/GameSettingsScreen.h @@ -1484,8 +1403,6 @@ list(APPEND NativeAppSource UI/CustomButtonMappingScreen.cpp UI/Theme.h UI/Theme.cpp - UI/RetroAchievementScreens.cpp - UI/RetroAchievementScreens.h ) if(ANDROID) @@ -1519,7 +1436,7 @@ if(LINUX AND NOT ANDROID) endif() set(ATOMIC_LIB) -if(ANDROID OR (LINUX AND ARM_DEVICE) OR (LINUX AND RISCV64) OR (LINUX AND LOONGARCH64)) +if(ANDROID OR (LINUX AND ARM_DEVICE) OR (LINUX AND RISCV64)) set(ATOMIC_LIB atomic) endif() @@ -1576,8 +1493,6 @@ set(CoreExtra) set(CoreExtraLibs) set(CoreExtra ${CoreExtra} - Core/MIPS/IR/IRAnalysis.cpp - Core/MIPS/IR/IRAnalysis.h Core/MIPS/IR/IRCompALU.cpp Core/MIPS/IR/IRCompBranch.cpp Core/MIPS/IR/IRCompFPU.cpp @@ -1591,8 +1506,6 @@ set(CoreExtra ${CoreExtra} Core/MIPS/IR/IRInterpreter.h Core/MIPS/IR/IRJit.cpp Core/MIPS/IR/IRJit.h - Core/MIPS/IR/IRNativeCommon.cpp - Core/MIPS/IR/IRNativeCommon.h Core/MIPS/IR/IRPassSimplify.cpp Core/MIPS/IR/IRPassSimplify.h Core/MIPS/IR/IRRegCache.cpp @@ -1632,17 +1545,6 @@ list(APPEND CoreExtra Core/MIPS/ARM64/Arm64RegCache.h Core/MIPS/ARM64/Arm64RegCacheFPU.cpp Core/MIPS/ARM64/Arm64RegCacheFPU.h - Core/MIPS/ARM64/Arm64IRAsm.cpp - Core/MIPS/ARM64/Arm64IRCompALU.cpp - Core/MIPS/ARM64/Arm64IRCompBranch.cpp - Core/MIPS/ARM64/Arm64IRCompFPU.cpp - Core/MIPS/ARM64/Arm64IRCompLoadStore.cpp - Core/MIPS/ARM64/Arm64IRCompSystem.cpp - Core/MIPS/ARM64/Arm64IRCompVec.cpp - Core/MIPS/ARM64/Arm64IRJit.cpp - Core/MIPS/ARM64/Arm64IRJit.h - Core/MIPS/ARM64/Arm64IRRegCache.cpp - Core/MIPS/ARM64/Arm64IRRegCache.h GPU/Common/VertexDecoderArm64.cpp Core/Util/DisArm64.cpp ) @@ -1663,17 +1565,6 @@ list(APPEND CoreExtra Core/MIPS/x86/RegCache.h Core/MIPS/x86/RegCacheFPU.cpp Core/MIPS/x86/RegCacheFPU.h - Core/MIPS/x86/X64IRAsm.cpp - Core/MIPS/x86/X64IRCompALU.cpp - Core/MIPS/x86/X64IRCompBranch.cpp - Core/MIPS/x86/X64IRCompFPU.cpp - Core/MIPS/x86/X64IRCompLoadStore.cpp - Core/MIPS/x86/X64IRCompSystem.cpp - Core/MIPS/x86/X64IRCompVec.cpp - Core/MIPS/x86/X64IRJit.cpp - Core/MIPS/x86/X64IRJit.h - Core/MIPS/x86/X64IRRegCache.cpp - Core/MIPS/x86/X64IRRegCache.h GPU/Common/VertexDecoderX86.cpp GPU/Software/DrawPixelX86.cpp GPU/Software/SamplerX86.cpp @@ -1685,17 +1576,6 @@ list(APPEND CoreExtra ) list(APPEND CoreExtra - Core/MIPS/RiscV/RiscVAsm.cpp - Core/MIPS/RiscV/RiscVCompALU.cpp - Core/MIPS/RiscV/RiscVCompBranch.cpp - Core/MIPS/RiscV/RiscVCompFPU.cpp - Core/MIPS/RiscV/RiscVCompLoadStore.cpp - Core/MIPS/RiscV/RiscVCompSystem.cpp - Core/MIPS/RiscV/RiscVCompVec.cpp - Core/MIPS/RiscV/RiscVJit.cpp - Core/MIPS/RiscV/RiscVJit.h - Core/MIPS/RiscV/RiscVRegCache.cpp - Core/MIPS/RiscV/RiscVRegCache.h GPU/Common/VertexDecoderRiscV.cpp ) @@ -1916,8 +1796,6 @@ add_library(${CoreLibName} ${CoreLinkType} Core/CoreTiming.h Core/CwCheat.cpp Core/CwCheat.h - Core/FrameTiming.cpp - Core/FrameTiming.h Core/HDRemaster.cpp Core/HDRemaster.h Core/Instance.cpp @@ -1926,8 +1804,6 @@ add_library(${CoreLibName} ${CoreLinkType} Core/KeyMap.h Core/KeyMapDefaults.cpp Core/KeyMapDefaults.h - Core/RetroAchievements.h - Core/RetroAchievements.cpp Core/ThreadEventQueue.h Core/TiltEventProcessor.h Core/TiltEventProcessor.cpp @@ -1954,8 +1830,6 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Debugger/WebSocket/GameBroadcaster.h Core/Debugger/WebSocket/GameSubscriber.cpp Core/Debugger/WebSocket/GameSubscriber.h - Core/Debugger/WebSocket/ClientConfigSubscriber.cpp - Core/Debugger/WebSocket/ClientConfigSubscriber.h Core/Debugger/WebSocket/GPUBufferSubscriber.cpp Core/Debugger/WebSocket/GPUBufferSubscriber.h Core/Debugger/WebSocket/GPURecordSubscriber.cpp @@ -2265,8 +2139,6 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Util/AudioFormat.h Core/Util/GameManager.cpp Core/Util/GameManager.h - Core/Util/GameDB.cpp - Core/Util/GameDB.h Core/Util/PortManager.cpp Core/Util/PortManager.h Core/Util/BlockAllocator.cpp @@ -2325,18 +2197,9 @@ else() include_directories(ext/zstd/lib) endif() -include_directories(ext/libchdr/include) - -target_link_libraries(${CoreLibName} Common native chdr kirk cityhash sfmt19937 xbrz xxhash rcheevos ${GlslangLibs} +target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs} ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) -if(NOT HTTPS_NOT_AVAILABLE) - target_link_libraries(${CoreLibName} naett) - if(WIN32) - target_link_libraries(${CoreLibName} winhttp) - endif() -endif() - target_compile_features(${CoreLibName} PUBLIC cxx_std_17) if(FFmpeg_FOUND) @@ -2483,12 +2346,11 @@ set(WindowsFiles Windows/Debugger/Debugger_MemoryDlg.h Windows/Debugger/Debugger_Lists.cpp Windows/Debugger/Debugger_Lists.h + Windows/Debugger/Debugger_SymbolMap.h Windows/Debugger/Debugger_VFPUDlg.cpp Windows/Debugger/Debugger_VFPUDlg.h Windows/Debugger/WatchItemWindow.cpp Windows/Debugger/WatchItemWindow.h - Windows/Debugger/EditSymbolsWindow.cpp - Windows/Debugger/EditSymbolsWindow.h Windows/GEDebugger/CtrlDisplayListView.cpp Windows/GEDebugger/SimpleGLWindow.cpp Windows/GEDebugger/TabState.cpp @@ -2532,13 +2394,6 @@ set(WindowsFiles Windows/W32Util/ShellUtil.h Windows/W32Util/TabControl.cpp Windows/W32Util/TabControl.h - Windows/W32Util/IatHook.h - Windows/W32Util/ContextMenu.h - Windows/W32Util/ContextMenu.cpp - Windows/W32Util/DarkMode.h - Windows/W32Util/DarkMode.cpp - Windows/W32Util/UAHMenuBar.h - Windows/W32Util/UAHMenuBar.cpp Windows/WindowsHost.cpp Windows/WindowsHost.h Windows/MainWindow.cpp @@ -2562,7 +2417,7 @@ set(WindowsFiles list(APPEND LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT}) if(WIN32) - list(APPEND LinkCommon kernel32 user32 gdi32 shell32 comctl32 dsound xinput d3d9 winmm dinput8 ole32 winspool ksuser mf uxtheme mfplat mfreadwrite mfuuid shlwapi) + list(APPEND LinkCommon kernel32 user32 gdi32 shell32 comctl32 dsound xinput d3d9 winmm dinput8 ole32 winspool ksuser mf mfplat mfreadwrite mfuuid shlwapi) #setup_target_project(${TargetBin} Windows) list(APPEND NativeAppSource ${WindowsFiles}) endif() diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 1d2c8b043..ce047cd41 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -315,14 +315,6 @@ const u8* ARM64XEmitter::AlignCodePage() return m_code; } -const u8 *ARM64XEmitter::NopAlignCode16() { - int bytes = ((-(intptr_t)m_code) & 15); - for (int i = 0; i < bytes / 4; i++) { - Write32(0xD503201F); // official nop instruction - } - return m_code; -} - void ARM64XEmitter::FlushIcache() { FlushIcacheSection(m_lastCacheFlushEnd, m_code); @@ -514,7 +506,7 @@ void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const voi distance >>= 2; - _assert_msg_(distance >= -0x2000 && distance <= 0x1FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance); + _assert_msg_(distance >= -0x1FFF && distance < 0x1FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance); Rt = DecodeReg(Rt); Write32((b64Bit << 31) | (0x36 << 24) | (op << 24) | \ @@ -2128,13 +2120,6 @@ void ARM64FloatEmitter::EmitCopy(bool Q, u32 op, u32 imm5, u32 imm4, ARM64Reg Rd (1 << 10) | (Rn << 5) | Rd); } -void ARM64FloatEmitter::EmitScalarPairwise(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) { - Rd = DecodeReg(Rd); - Rn = DecodeReg(Rn); - - Write32((1 << 30) | (U << 29) | (0b111100011 << 20) | (size << 22) | (opcode << 12) | (1 << 11) | (Rn << 5) | Rd); -} - void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) { _assert_msg_(!IsSingle(Rd), "%s doesn't support singles!", __FUNCTION__); @@ -2234,45 +2219,6 @@ void ARM64FloatEmitter::FCVTU(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round) { EmitConvertScalarToInt(Rd, Rn, round, true); } -void ARM64FloatEmitter::FCVTZS(ARM64Reg Rd, ARM64Reg Rn, int scale) { - if (IsScalar(Rd)) { - int imm = (IsDouble(Rn) ? 64 : 32) * 2 - scale; - Rd = DecodeReg(Rd); - Rn = DecodeReg(Rn); - - Write32((1 << 30) | (0 << 29) | (0x1F << 24) | (imm << 16) | (0x1F << 11) | (1 << 10) | (Rn << 5) | Rd); - } else { - bool sf = Is64Bit(Rd); - u32 type = 0; - if (IsDouble(Rd)) - type = 1; - int rmode = 3; - int opcode = 0; - - Write32((sf << 31) | (0 << 29) | (0x1E << 24) | (type << 22) | (rmode << 19) | (opcode << 16) | (scale << 10) | (Rn << 5) | Rd); - - } -} - -void ARM64FloatEmitter::FCVTZU(ARM64Reg Rd, ARM64Reg Rn, int scale) { - if (IsScalar(Rd)) { - int imm = (IsDouble(Rn) ? 64 : 32) * 2 - scale; - Rd = DecodeReg(Rd); - Rn = DecodeReg(Rn); - - Write32((1 << 30) | (1 << 29) | (0x1F << 24) | (imm << 16) | (0x1F << 11) | (1 << 10) | (Rn << 5) | Rd); - } else { - bool sf = Is64Bit(Rd); - u32 type = 0; - if (IsDouble(Rd)) - type = 1; - int rmode = 3; - int opcode = 1; - - Write32((sf << 31) | (0 << 29) | (0x1E << 24) | (type << 22) | (rmode << 19) | (opcode << 16) | (scale << 10) | (Rn << 5) | Rd); - } -} - void ARM64FloatEmitter::EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn) { Rd = DecodeReg(Rd); @@ -2307,17 +2253,6 @@ void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd (cond << 12) | (3 << 10) | (Rn << 5) | Rd); } -void ARM64FloatEmitter::EmitCondCompare(bool M, bool S, CCFlags cond, int op, u8 nzcv, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rn), "%s doesn't support vector!", __FUNCTION__); - bool is_double = IsDouble(Rn); - - Rn = DecodeReg(Rn); - Rm = DecodeReg(Rm); - - Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | \ - (cond << 12) | (1 << 10) | (Rn << 5) | (op << 4) | nzcv); -} - void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { _assert_msg_(!IsSingle(Rd), "%s doesn't support singles!", __FUNCTION__); @@ -2963,22 +2898,6 @@ void ARM64FloatEmitter::FSQRT(ARM64Reg Rd, ARM64Reg Rn) EmitScalar1Source(0, 0, IsDouble(Rd), 3, Rd, Rn); } -// Scalar - pairwise -void ARM64FloatEmitter::FADDP(ARM64Reg Rd, ARM64Reg Rn) { - EmitScalarPairwise(1, IsDouble(Rd), 0b01101, Rd, Rn); -} -void ARM64FloatEmitter::FMAXP(ARM64Reg Rd, ARM64Reg Rn) { - EmitScalarPairwise(1, IsDouble(Rd), 0b01111, Rd, Rn); -} -void ARM64FloatEmitter::FMINP(ARM64Reg Rd, ARM64Reg Rn) { - EmitScalarPairwise(1, IsDouble(Rd) ? 3 : 2, 0b01111, Rd, Rn); -} -void ARM64FloatEmitter::FMAXNMP(ARM64Reg Rd, ARM64Reg Rn) { - EmitScalarPairwise(1, IsDouble(Rd), 0b01100, Rd, Rn); -} -void ARM64FloatEmitter::FMINNMP(ARM64Reg Rd, ARM64Reg Rn) { - EmitScalarPairwise(1, IsDouble(Rd) ? 3 : 2, 0b01100, Rd, Rn); -} // Scalar - 2 Source void ARM64FloatEmitter::FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) @@ -3061,12 +2980,6 @@ void ARM64FloatEmitter::BSL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EmitThreeSame(1, 1, 3, Rd, Rn, Rm); } -void ARM64FloatEmitter::BIT(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - EmitThreeSame(1, 2, 3, Rd, Rn, Rm); -} -void ARM64FloatEmitter::BIF(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - EmitThreeSame(1, 3, 3, Rd, Rn, Rm); -} void ARM64FloatEmitter::DUP(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index) { u32 imm5 = 0; @@ -3102,9 +3015,6 @@ void ARM64FloatEmitter::FADD(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EmitThreeSame(0, size >> 6, 0x1A, Rd, Rn, Rm); } -void ARM64FloatEmitter::FADDP(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - EmitThreeSame(1, size >> 6, 0x1A, Rd, Rn, Rm); -} void ARM64FloatEmitter::FMAX(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EmitThreeSame(0, size >> 6, 0x1E, Rd, Rn, Rm); @@ -3137,14 +3047,6 @@ void ARM64FloatEmitter::FCVTZU(u8 size, ARM64Reg Rd, ARM64Reg Rn) { Emit2RegMisc(IsQuad(Rd), 1, 2 | (size >> 6), 0x1B, Rd, Rn); } -void ARM64FloatEmitter::FCVTZS(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale) { - int imm = size * 2 - scale; - EmitShiftImm(IsQuad(Rd), false, imm >> 3, imm & 7, 0x1F, Rd, Rn); -} -void ARM64FloatEmitter::FCVTZU(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale) { - int imm = size * 2 - scale; - EmitShiftImm(IsQuad(Rd), true, imm >> 3, imm & 7, 0x1F, Rd, Rn); -} void ARM64FloatEmitter::FDIV(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EmitThreeSame(1, size >> 6, 0x1F, Rd, Rn, Rm); @@ -3248,61 +3150,6 @@ void ARM64FloatEmitter::XTN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn) Emit2RegMisc(true, 0, dest_size >> 4, 0x12, Rd, Rn); } -void ARM64FloatEmitter::CMEQ(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - EmitThreeSame(true, size >> 4, 0b10001, Rd, Rn, Rm); -} - -void ARM64FloatEmitter::CMGE(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - EmitThreeSame(false, size >> 4, 0b00111, Rd, Rn, Rm); -} - -void ARM64FloatEmitter::CMGT(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - EmitThreeSame(false, size >> 4, 0b00110, Rd, Rn, Rm); -} - -void ARM64FloatEmitter::CMHI(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - EmitThreeSame(true, size >> 4, 0b00110, Rd, Rn, Rm); -} - -void ARM64FloatEmitter::CMHS(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - EmitThreeSame(true, size >> 4, 0b00111, Rd, Rn, Rm); -} - -void ARM64FloatEmitter::CMTST(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - EmitThreeSame(false, size >> 4, 0b10001, Rd, Rn, Rm); -} - -void ARM64FloatEmitter::CMEQ(u8 size, ARM64Reg Rd, ARM64Reg Rn) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - Emit2RegMisc(IsQuad(Rd), false, size >> 4, 0b01001, Rd, Rn); -} - -void ARM64FloatEmitter::CMGE(u8 size, ARM64Reg Rd, ARM64Reg Rn) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - Emit2RegMisc(IsQuad(Rd), true, size >> 4, 0b01000, Rd, Rn); -} - -void ARM64FloatEmitter::CMGT(u8 size, ARM64Reg Rd, ARM64Reg Rn) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - Emit2RegMisc(IsQuad(Rd), false, size >> 4, 0b01000, Rd, Rn); -} - -void ARM64FloatEmitter::CMLE(u8 size, ARM64Reg Rd, ARM64Reg Rn) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - Emit2RegMisc(IsQuad(Rd), true, size >> 4, 0b01001, Rd, Rn); -} - -void ARM64FloatEmitter::CMLT(u8 size, ARM64Reg Rd, ARM64Reg Rn) { - _assert_msg_(!IsQuad(Rd) || size != 64, "%s cannot be used for scalar double", __FUNCTION__); - Emit2RegMisc(IsQuad(Rd), false, size >> 4, 0b01010, Rd, Rn); -} - // Move void ARM64FloatEmitter::DUP(u8 size, ARM64Reg Rd, ARM64Reg Rn) { @@ -3435,95 +3282,6 @@ void ARM64FloatEmitter::SMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index) EmitCopy(b64Bit, 0, imm5, 5, Rd, Rn); } -void ARM64FloatEmitter::EncodeModImm(bool Q, u8 op, u8 cmode, u8 o2, ARM64Reg Rd, u8 abcdefgh) { - Rd = DecodeReg(Rd); - u8 abc = abcdefgh >> 5; - u8 defgh = abcdefgh & 0x1F; - Write32((Q << 30) | (op << 29) | (0xF << 24) | (abc << 16) | (cmode << 12) | (o2 << 11) | (1 << 10) | (defgh << 5) | Rd); -} - -void ARM64FloatEmitter::FMOV(u8 size, ARM64Reg Rd, u8 imm8) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles", __FUNCTION__); - _assert_msg_(size == 32 || size == 64, "%s: unsupported size", __FUNCTION__); - _assert_msg_(IsQuad(Rd) || size == 32, "Use non-SIMD FMOV to load one double imm8"); - EncodeModImm(IsQuad(Rd), size >> 6, 0b1111, 0, Rd, imm8); -} - -void ARM64FloatEmitter::MOVI(u8 size, ARM64Reg Rd, u8 imm8, u8 shift, bool MSL) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles", __FUNCTION__); - _assert_msg_(size == 8 || size == 16 || size == 32 || size == 64, "%s: unsupported size %d", __FUNCTION__, size); - _assert_msg_((shift & 7) == 0 && shift < size, "%s: unsupported shift %d", __FUNCTION__, shift); - _assert_msg_(!MSL || (size == 32 && shift > 0 && shift <= 16), "MOVI MSL shift requires size 32, shift must be 8 or 16"); - _assert_msg_(size != 64 || shift == 0, "MOVI 64-bit imm cannot be shifted"); - - u8 cmode = 0; - if (size == 8) - cmode = 0b1110; - else if (size == 16) - cmode = 0b1000 | (shift >> 2); - else if (MSL) - cmode = 0b1100 | (shift >> 3); - else if (size == 32) - cmode = (shift >> 2); - else if (size == 64) - cmode = 0b1110; - else - _assert_msg_(false, "%s: unhandled case", __FUNCTION__); - - EncodeModImm(IsQuad(Rd), size >> 6, cmode, 0, Rd, imm8); -} - -void ARM64FloatEmitter::MVNI(u8 size, ARM64Reg Rd, u8 imm8, u8 shift, bool MSL) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles", __FUNCTION__); - _assert_msg_(size == 16 || size == 32, "%s: unsupported size %d", __FUNCTION__, size); - _assert_msg_((shift & 7) == 0 && shift < size, "%s: unsupported shift %d", __FUNCTION__, shift); - _assert_msg_(!MSL || (size == 32 && shift > 0 && shift <= 16), "MVNI MSL shift requires size 32, shift must be 8 or 16"); - - u8 cmode = 0; - if (size == 16) - cmode = 0b1000 | (shift >> 2); - else if (MSL) - cmode = 0b1100 | (shift >> 3); - else if (size == 32) - cmode = (shift >> 2); - else - _assert_msg_(false, "%s: unhandled case", __FUNCTION__); - - EncodeModImm(IsQuad(Rd), 1, cmode, 0, Rd, imm8); -} - -void ARM64FloatEmitter::ORR(u8 size, ARM64Reg Rd, u8 imm8, u8 shift) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles", __FUNCTION__); - _assert_msg_(size == 16 || size == 32, "%s: unsupported size %d", __FUNCTION__, size); - _assert_msg_((shift & 7) == 0 && shift < size, "%s: unsupported shift %d", __FUNCTION__, shift); - - u8 cmode = 0; - if (size == 16) - cmode = 0b1001 | (shift >> 2); - else if (size == 32) - cmode = 0b0001 | (shift >> 2); - else - _assert_msg_(false, "%s: unhandled case", __FUNCTION__); - - EncodeModImm(IsQuad(Rd), 0, cmode, 0, Rd, imm8); -} - -void ARM64FloatEmitter::BIC(u8 size, ARM64Reg Rd, u8 imm8, u8 shift) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles", __FUNCTION__); - _assert_msg_(size == 16 || size == 32, "%s: unsupported size %d", __FUNCTION__, size); - _assert_msg_((shift & 7) == 0 && shift < size, "%s: unsupported shift %d", __FUNCTION__, shift); - - u8 cmode = 0; - if (size == 16) - cmode = 0b1001 | (shift >> 2); - else if (size == 32) - cmode = 0b0001 | (shift >> 2); - else - _assert_msg_(false, "%s: unhandled case", __FUNCTION__); - - EncodeModImm(IsQuad(Rd), 1, cmode, 0, Rd, imm8); -} - // One source void ARM64FloatEmitter::FCVT(u8 size_to, u8 size_from, ARM64Reg Rd, ARM64Reg Rn) { @@ -3586,38 +3344,22 @@ void ARM64FloatEmitter::UCVTF(ARM64Reg Rd, ARM64Reg Rn) void ARM64FloatEmitter::SCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale) { - if (IsScalar(Rn)) { - int imm = (IsDouble(Rn) ? 64 : 32) * 2 - scale; - Rd = DecodeReg(Rd); - Rn = DecodeReg(Rn); + bool sf = Is64Bit(Rn); + u32 type = 0; + if (IsDouble(Rd)) + type = 1; - Write32((1 << 30) | (0 << 29) | (0x1F << 24) | (imm << 16) | (0x1C << 11) | (1 << 10) | (Rn << 5) | Rd); - } else { - bool sf = Is64Bit(Rn); - u32 type = 0; - if (IsDouble(Rd)) - type = 1; - - EmitConversion2(sf, 0, false, type, 0, 2, 64 - scale, Rd, Rn); - } + EmitConversion2(sf, 0, false, type, 0, 2, 64 - scale, Rd, Rn); } void ARM64FloatEmitter::UCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale) { - if (IsScalar(Rn)) { - int imm = (IsDouble(Rn) ? 64 : 32) * 2 - scale; - Rd = DecodeReg(Rd); - Rn = DecodeReg(Rn); + bool sf = Is64Bit(Rn); + u32 type = 0; + if (IsDouble(Rd)) + type = 1; - Write32((1 << 30) | (1 << 29) | (0x1F << 24) | (imm << 16) | (0x1C << 11) | (1 << 10) | (Rn << 5) | Rd); - } else { - bool sf = Is64Bit(Rn); - u32 type = 0; - if (IsDouble(Rd)) - type = 1; - - EmitConversion2(sf, 0, false, type, 0, 3, 64 - scale, Rd, Rn); - } + EmitConversion2(sf, 0, false, type, 0, 3, 64 - scale, Rd, Rn); } void ARM64FloatEmitter::FCMP(ARM64Reg Rn, ARM64Reg Rm) @@ -3674,14 +3416,6 @@ void ARM64FloatEmitter::FCSEL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags con EmitCondSelect(0, 0, cond, Rd, Rn, Rm); } -void ARM64FloatEmitter::FCCMP(ARM64Reg Rn, ARM64Reg Rm, u8 nzcv, CCFlags cond) { - EmitCondCompare(0, 0, cond, 0, nzcv, Rn, Rm); -} - -void ARM64FloatEmitter::FCCMPE(ARM64Reg Rn, ARM64Reg Rm, u8 nzcv, CCFlags cond) { - EmitCondCompare(0, 0, cond, 1, nzcv, Rn, Rm); -} - // Permute void ARM64FloatEmitter::UZP1(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { @@ -3708,20 +3442,6 @@ void ARM64FloatEmitter::ZIP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) EmitPermute(size, 7, Rd, Rn, Rm); } -void ARM64FloatEmitter::EXT(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, int index) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles!", __FUNCTION__); - - bool quad = IsQuad(Rd); - _assert_msg_(index >= 0 && index < 16 && (quad || index < 8), "%s start index out of bounds", __FUNCTION__); - _assert_msg_(IsQuad(Rd) == IsQuad(Rn) && IsQuad(Rd) == IsQuad(Rm), "%s operands not same size", __FUNCTION__); - - Rd = DecodeReg(Rd); - Rn = DecodeReg(Rn); - Rm = DecodeReg(Rm); - - Write32((quad << 30) | (0x17 << 25) | (Rm << 16) | (index << 11) | (Rn << 5) | Rd); -} - // Shift by immediate void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift) { @@ -3747,12 +3467,6 @@ void ARM64FloatEmitter::USHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift) { USHLL(src_size, Rd, Rn, shift, true); } -void ARM64FloatEmitter::SHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn) { - SHLL(src_size, Rd, Rn, false); -} -void ARM64FloatEmitter::SHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn) { - SHLL(src_size, Rd, Rn, true); -} void ARM64FloatEmitter::SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn) { SXTL(src_size, Rd, Rn, false); @@ -3792,11 +3506,6 @@ void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, EmitShiftImm(upper, 1, imm >> 3, imm & 7, 0x14, Rd, Rn); } -void ARM64FloatEmitter::SHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper) { - _assert_msg_(src_size <= 32, "%s shift amount cannot be 64", __FUNCTION__); - Emit2RegMisc(upper, 1, src_size >> 4, 0b10011, Rd, Rn); -} - void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper) { _assert_msg_(shift > 0, "%s shift amount must be greater than zero!", __FUNCTION__); @@ -4187,131 +3896,20 @@ void ARM64FloatEmitter::MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch, bool } // TODO: Quite a few values could be generated easily using the MOVI instruction and friends. -void ARM64FloatEmitter::MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch, bool negate) { - _assert_msg_(!IsSingle(Rd), "%s doesn't support singles", __FUNCTION__); +void ARM64FloatEmitter::MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch) { + // TODO: Make it work with more element sizes + // TODO: Optimize - there are shorter solution for many values + ARM64Reg s = (ARM64Reg)(S0 + DecodeReg(Rd)); int ival; memcpy(&ival, &value, 4); - uint8_t imm8; if (ival == 0) { // Make sure to not catch negative zero here - // Prefer MOVI 0, which may have no latency on some CPUs. - MOVI(32, Rd, 0); - if (negate) - FNEG(32, Rd, Rd); - } else if (negate && FPImm8FromFloat(-value, &imm8)) { - FMOV(32, Rd, imm8); - } else if (FPImm8FromFloat(value, &imm8)) { - FMOV(32, Rd, imm8); - if (negate) { - FNEG(32, Rd, Rd); - } - } else if (TryAnyMOVI(32, Rd, ival)) { - if (negate) { - FNEG(32, Rd, Rd); - } - } else if (TryAnyMOVI(32, Rd, ival ^ 0x80000000)) { - if (!negate) { - FNEG(32, Rd, Rd); - } + EOR(Rd, Rd, Rd); } else { - _assert_msg_(scratch != INVALID_REG, "Failed to find a way to generate FP immediate %f without scratch", value); - if (negate) { - ival ^= 0x80000000; - } - m_emit->MOVI2R(scratch, ival); - DUP(32, Rd, scratch); + MOVI2F(s, value, scratch); + DUP(32, Rd, Rd, 0); } } -bool ARM64FloatEmitter::TryMOVI(u8 size, ARM64Reg Rd, uint64_t elementValue) { - if (size == 8) { - // Can always do 8. - MOVI(size, Rd, elementValue & 0xFF); - return true; - } else if (size == 16) { - if ((elementValue & 0xFF00) == 0) { - MOVI(size, Rd, elementValue & 0xFF, 0); - return true; - } else if ((elementValue & 0x00FF) == 0) { - MOVI(size, Rd, (elementValue >> 8) & 0xFF, 8); - return true; - } else if ((elementValue & 0xFF00) == 0xFF00) { - MVNI(size, Rd, ~elementValue & 0xFF, 0); - return true; - } else if ((elementValue & 0x00FF) == 0x00FF) { - MVNI(size, Rd, (~elementValue >> 8) & 0xFF, 8); - return true; - } - - return false; - } else if (size == 32) { - for (int shift = 0; shift < 32; shift += 8) { - uint32_t mask = 0xFFFFFFFF &~ (0xFF << shift); - if ((elementValue & mask) == 0) { - MOVI(size, Rd, (elementValue >> shift) & 0xFF, shift); - return true; - } else if ((elementValue & mask) == mask) { - MVNI(size, Rd, (~elementValue >> shift) & 0xFF, shift); - return true; - } - } - - // Maybe an MSL shift will work? - for (int shift = 8; shift <= 16; shift += 8) { - uint32_t mask = 0xFFFFFFFF & ~(0xFF << shift); - uint32_t ones = (1 << shift) - 1; - uint32_t notOnes = 0xFFFFFF00 << shift; - if ((elementValue & mask) == ones) { - MOVI(size, Rd, (elementValue >> shift) & 0xFF, shift, true); - return true; - } else if ((elementValue & mask) == notOnes) { - MVNI(size, Rd, (elementValue >> shift) & 0xFF, shift, true); - return true; - } - } - - return false; - } else if (size == 64) { - uint8_t imm8 = 0; - for (int i = 0; i < 8; ++i) { - uint8_t byte = (elementValue >> (i * 8)) & 0xFF; - if (byte != 0 && byte != 0xFF) - return false; - - if (byte == 0xFF) - imm8 |= 1 << i; - } - - // Didn't run into any partial bytes, so size 64 is doable. - MOVI(size, Rd, imm8); - return true; - } - return false; -} - -bool ARM64FloatEmitter::TryAnyMOVI(u8 size, ARM64Reg Rd, uint64_t elementValue) { - // Try the original size first in case that's more optimal. - if (TryMOVI(size, Rd, elementValue)) - return true; - - uint64_t value = elementValue; - if (size != 64) { - uint64_t masked = elementValue & ((1 << size) - 1); - for (int i = size; i < 64; ++i) { - value |= masked << i; - } - } - - for (int attempt = 8; attempt <= 64; attempt += attempt) { - // Original size was already attempted above. - if (attempt != size) { - if (TryMOVI(attempt, Rd, value)) - return true; - } - } - - return false; -} - void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { u32 val; bool shift; diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index 0c3603d1b..aaeb24fb1 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -94,7 +94,7 @@ enum ARM64Reg // R19-R28. R29 (FP), R30 (LR) are always saved and FP updated appropriately. const u32 ALL_CALLEE_SAVED = 0x1FF80000; -const u32 ALL_CALLEE_SAVED_FP = 0x0000FF00; // q8-q15 +const u32 ALL_CALLEE_SAVED_FP = 0x0000FF00; // d8-d15 inline bool Is64Bit(ARM64Reg reg) { return (reg & 0x20) != 0; } inline bool IsSingle(ARM64Reg reg) { return (reg & 0xC0) == 0x40; } @@ -290,23 +290,6 @@ public: } m_shifttype = ST_LSL; } - ArithOption(ARM64Reg Rd, bool index, bool signExtend) { - if (index) - m_shift = 4; - else - m_shift = 0; - - m_destReg = Rd; - m_type = TYPE_EXTENDEDREG; - if (Is64Bit(Rd)) { - m_width = WIDTH_64BIT; - m_extend = EXTEND_UXTX; - } else { - m_width = WIDTH_32BIT; - m_extend = signExtend ? EXTEND_SXTW : EXTEND_UXTW; - } - m_shifttype = ST_LSL; - } ArithOption(ARM64Reg Rd, ShiftType shift_type, u32 shift) { m_destReg = Rd; @@ -418,7 +401,6 @@ public: void ReserveCodeSpace(u32 bytes); const u8* AlignCode16(); const u8* AlignCodePage(); - const u8 *NopAlignCode16(); void FlushIcache(); void FlushIcacheSection(const u8* start, const u8* end); u8* GetWritableCodePtr(); @@ -820,13 +802,6 @@ public: void FSQRT(ARM64Reg Rd, ARM64Reg Rn); void FMOV(ARM64Reg Rd, ARM64Reg Rn, bool top = false); // Also generalized move between GPR/FP - // Scalar - pairwise - void FADDP(ARM64Reg Rd, ARM64Reg Rn); - void FMAXP(ARM64Reg Rd, ARM64Reg Rn); - void FMINP(ARM64Reg Rd, ARM64Reg Rn); - void FMAXNMP(ARM64Reg Rd, ARM64Reg Rn); - void FMINNMP(ARM64Reg Rd, ARM64Reg Rn); - // Scalar - 2 Source void FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void FMUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); @@ -851,12 +826,9 @@ public: void AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void EOR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void BSL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void BIT(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void BIF(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void DUP(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index); void FABS(u8 size, ARM64Reg Rd, ARM64Reg Rn); void FADD(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void FADDP(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void FMAX(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void FMLA(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void FMLS(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); @@ -866,8 +838,6 @@ public: void FCVTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn); void FCVTZS(u8 size, ARM64Reg Rd, ARM64Reg Rn); void FCVTZU(u8 size, ARM64Reg Rd, ARM64Reg Rn); - void FCVTZS(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale); - void FCVTZU(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale); void FDIV(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void FNEG(u8 size, ARM64Reg Rd, ARM64Reg Rn); @@ -898,18 +868,6 @@ public: void XTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn); void XTN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn); - void CMEQ(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void CMGE(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void CMGT(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void CMHI(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void CMHS(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void CMTST(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void CMEQ(u8 size, ARM64Reg Rd, ARM64Reg Rn); - void CMGE(u8 size, ARM64Reg Rd, ARM64Reg Rn); - void CMGT(u8 size, ARM64Reg Rd, ARM64Reg Rn); - void CMLE(u8 size, ARM64Reg Rd, ARM64Reg Rn); - void CMLT(u8 size, ARM64Reg Rd, ARM64Reg Rn); - // Move void DUP(u8 size, ARM64Reg Rd, ARM64Reg Rn); void INS(u8 size, ARM64Reg Rd, u8 index, ARM64Reg Rn); @@ -917,18 +875,6 @@ public: void UMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index); void SMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index); - // Vector immediates - void FMOV(u8 size, ARM64Reg Rd, u8 imm8); - // MSL means bits shifted in are 1s. For size=64, each bit of imm8 is expanded to 8 actual bits. - void MOVI(u8 size, ARM64Reg Rd, u8 imm8, u8 shift = 0, bool MSL = false); - void MVNI(u8 size, ARM64Reg Rd, u8 imm8, u8 shift = 0, bool MSL = false); - void ORR(u8 size, ARM64Reg Rd, u8 imm8, u8 shift = 0); - void BIC(u8 size, ARM64Reg Rd, u8 imm8, u8 shift = 0); - - bool TryMOVI(u8 size, ARM64Reg Rd, uint64_t value); - // Allow using a different size. Unclear if there's a penalty. - bool TryAnyMOVI(u8 size, ARM64Reg Rd, uint64_t value); - // One source void FCVT(u8 size_to, u8 size_from, ARM64Reg Rd, ARM64Reg Rn); @@ -937,8 +883,6 @@ public: // and one that outputs to a scalar fp register. void FCVTS(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round); void FCVTU(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round); - void FCVTZS(ARM64Reg Rd, ARM64Reg Rn, int scale); - void FCVTZU(ARM64Reg Rd, ARM64Reg Rn, int scale); // Scalar convert int to float. No rounding mode specifier necessary. void SCVTF(ARM64Reg Rd, ARM64Reg Rn); @@ -965,10 +909,6 @@ public: // Conditional select void FCSEL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond); - // Conditional compare - void FCCMP(ARM64Reg Rn, ARM64Reg Rm, u8 nzcv, CCFlags cond); - void FCCMPE(ARM64Reg Rn, ARM64Reg Rm, u8 nzcv, CCFlags cond); - // Permute void UZP1(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void TRN1(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); @@ -976,17 +916,12 @@ public: void UZP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void TRN2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void ZIP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - // Related to permute, extract vector from pair (always by byte arrangement.) - void EXT(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, int index); // Shift by immediate void SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift); void SSHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift); void USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift); void USHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift); - // Shift == src_size for these. - void SHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn); - void SHLL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn); void SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift); void SHRN2(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift); void SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn); @@ -1003,7 +938,7 @@ public: void FMLA(u8 esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index); void MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG, bool negate = false); - void MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG, bool negate = false); + void MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG); // ABI related void ABI_PushRegisters(uint32_t gpr_registers, uint32_t fp_registers); @@ -1018,7 +953,6 @@ private: void EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void EmitCopy(bool Q, u32 op, u32 imm5, u32 imm4, ARM64Reg Rd, ARM64Reg Rn); - void EmitScalarPairwise(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn); void Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn); void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn); void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm); @@ -1027,7 +961,6 @@ private: void EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn); void EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm); void EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); - void EmitCondCompare(bool M, bool S, CCFlags cond, int op, u8 nzcv, ARM64Reg Rn, ARM64Reg Rm); void EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64Reg Rd, u32 imm8); void EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn); @@ -1041,11 +974,9 @@ private: void EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra, int opcode); void EncodeLoadStorePair(u32 size, bool load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm); void EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm); - void EncodeModImm(bool Q, u8 op, u8 cmode, u8 o2, ARM64Reg Rd, u8 abcdefgh); void SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper); void USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper); - void SHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper); void SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper); void SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper); void UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper); diff --git a/Common/ArmCPUDetect.cpp b/Common/ArmCPUDetect.cpp index 32119f988..41b747566 100644 --- a/Common/ArmCPUDetect.cpp +++ b/Common/ArmCPUDetect.cpp @@ -32,15 +32,14 @@ #if defined(CPU_FEATURES_OS_LINUX) #define USE_CPU_FEATURES 1 #endif -#elif PPSSPP_ARCH(ARM64) +#elif PPSSPP_ARCH(ARM64) && defined(__aarch64__) #include "ext/cpu_features/include/cpuinfo_aarch64.h" -#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) || defined(CPU_FEATURES_OS_WINDOWS) +#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) #define USE_CPU_FEATURES 1 #endif #endif -#include #include #include "Common/CommonTypes.h" @@ -55,7 +54,7 @@ std::string GetCPUBrandString(); #else // No CPUID on ARM, so we'll have to read the registry -#include "Common/CommonWindows.h" +#include std::string GetCPUBrandString() { std::string cpu_string; diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 00b686b3d..d6e3d241e 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -613,14 +613,6 @@ const u8 *ARMXEmitter::AlignCode16() return code; } -const u8 *ARMXEmitter::NopAlignCode16() { - int bytes = ((-(intptr_t)code) & 15); - for (int i = 0; i < bytes / 4; i++) { - Write32(0xE320F000); // one of many possible nops - } - return code; -} - const u8 *ARMXEmitter::AlignCodePage() { ReserveCodeSpace((-(intptr_t)code) & 4095); diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index f1cf4dd22..46a36c880 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -446,8 +446,6 @@ public: void ReserveCodeSpace(u32 bytes); const u8 *AlignCode16(); const u8 *AlignCodePage(); - const u8 *NopAlignCode16(); - void FlushIcache(); void FlushIcacheSection(u8 *start, u8 *end); u8 *GetWritableCodePtr(); diff --git a/Common/CPUDetect.cpp b/Common/CPUDetect.cpp index 2628f91d4..aa43930ea 100644 --- a/Common/CPUDetect.cpp +++ b/Common/CPUDetect.cpp @@ -17,7 +17,7 @@ // Reference : https://stackoverflow.com/questions/6121792/how-to-check-if-a-cpu-supports-the-sse3-instruction-set #include "ppsspp_config.h" -#if (PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)) && !defined(__EMSCRIPTEN__) +#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #include "ext/cpu_features/include/cpuinfo_x86.h" diff --git a/Common/CPUDetect.h b/Common/CPUDetect.h index db1ea377a..1feb20483 100644 --- a/Common/CPUDetect.h +++ b/Common/CPUDetect.h @@ -109,28 +109,13 @@ struct CPUInfo { bool RiscV_D; bool RiscV_C; bool RiscV_V; + bool RiscV_B; bool RiscV_Zicsr; bool RiscV_Zba; bool RiscV_Zbb; bool RiscV_Zbc; bool RiscV_Zbs; - // LoongArch specific extension flags. - bool LOONGARCH_CPUCFG; - bool LOONGARCH_LAM; - bool LOONGARCH_UAL; - bool LOONGARCH_FPU; - bool LOONGARCH_LSX; - bool LOONGARCH_LASX; - bool LOONGARCH_CRC32; - bool LOONGARCH_COMPLEX; - bool LOONGARCH_CRYPTO; - bool LOONGARCH_LVZ; - bool LOONGARCH_LBT_X86; - bool LOONGARCH_LBT_ARM; - bool LOONGARCH_LBT_MIPS; - bool LOONGARCH_PTW; - // Quirks struct { // Samsung Galaxy S7 devices (Exynos 8890) have a big.LITTLE configuration where the cacheline size differs between big and LITTLE. diff --git a/Common/CodeBlock.h b/Common/CodeBlock.h index 766d0a1cc..e2f269ed2 100644 --- a/Common/CodeBlock.h +++ b/Common/CodeBlock.h @@ -10,11 +10,6 @@ #include "Common/Log.h" #include "Common/MemoryUtil.h" -#if PPSSPP_PLATFORM(SWITCH) -#include -#include -#endif // PPSSPP_PLATFORM(SWITCH) - // Everything that needs to generate code should inherit from this. // You get memory management for free, plus, you can use all emitter functions without // having to prefix them with gen-> or something similar. @@ -32,7 +27,7 @@ public: virtual const u8 *GetCodePtr() const = 0; - u8 *GetBasePtr() const { + u8 *GetBasePtr() { return region; } @@ -70,20 +65,9 @@ public: // Call this before you generate any code. void AllocCodeSpace(int size) { region_size = size; -#if PPSSPP_PLATFORM(SWITCH) - Result rc = jitCreate(&jitController, size); - if(R_FAILED(rc)) { - printf("Failed to create Jitbuffer of size 0x%x err: 0x%x\n", size, rc); - } - printf("[NXJIT]: Initialized RX: %p RW: %p\n", jitController.rx_addr, jitController.rw_addr); - - region = (u8 *)jitController.rx_addr; - writableRegion = (u8 *)jitController.rw_addr; -#else // PPSSPP_PLATFORM(SWITCH) // The protection will be set to RW if PlatformIsWXExclusive. region = (u8 *)AllocateExecutableMemory(region_size); writableRegion = region; -#endif // !PPSSPP_PLATFORM(SWITCH) T::SetCodePointer(region, writableRegion); } @@ -151,13 +135,8 @@ public: // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. void FreeCodeSpace() { -#if !PPSSPP_PLATFORM(SWITCH) ProtectMemoryPages(region, region_size, MEM_PROT_READ | MEM_PROT_WRITE); FreeExecutableMemory(region, region_size); -#else // !PPSSPP_PLATFORM(SWITCH) - jitClose(&jitController); - printf("[NXJIT]: Jit closed\n"); -#endif // PPSSPP_PLATFORM(SWITCH) region = nullptr; writableRegion = nullptr; region_size = 0; @@ -197,7 +176,5 @@ private: const uint8_t *writeStart_ = nullptr; uint8_t *writableRegion = nullptr; size_t writeEstimated_ = 0; -#if PPSSPP_PLATFORM(SWITCH) - Jit jitController; -#endif // PPSSPP_PLATFORM(SWITCH) }; + diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 93e91681b..67e208b17 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -399,7 +399,6 @@ - @@ -451,13 +450,11 @@ - - @@ -472,7 +469,6 @@ - @@ -492,12 +488,10 @@ - - @@ -509,7 +503,6 @@ - @@ -532,6 +525,27 @@ + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + @@ -545,7 +559,6 @@ - @@ -561,7 +574,6 @@ - @@ -831,7 +843,6 @@ - @@ -847,7 +858,6 @@ - @@ -882,12 +892,10 @@ - - @@ -901,7 +909,6 @@ - @@ -920,12 +927,10 @@ - - @@ -937,13 +942,11 @@ - - @@ -972,6 +975,36 @@ + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + @@ -983,7 +1016,6 @@ - @@ -992,7 +1024,6 @@ - diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 73aefb932..b24536cc1 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -32,6 +32,15 @@ + + GL\GLInterface + + + GL\GLInterface + + + GL + @@ -440,6 +449,9 @@ Render + + GPU + GPU\Vulkan @@ -488,36 +500,6 @@ File - - GPU\OpenGL - - - GPU - - - GPU - - - UI - - - System - - - Net - - - ext\naett - - - Net - - - Render\Text - - - GPU\Vulkan - @@ -544,6 +526,15 @@ + + GL\GLInterface + + + GL\GLInterface + + + GL\GLInterface + @@ -878,7 +869,6 @@ GPU\Vulkan - GPU\Vulkan @@ -942,41 +932,17 @@ File - - GPU\OpenGL - - - Data\Collections - - - GPU - - - UI - - - System - - - Net - - - ext\naett - - - Net - - - Render\Text - - - GPU\Vulkan - {1b593f03-7b28-4707-9228-4981796f5589} + + {2f2ca112-9e26-499e-9cb9-38a78b4ac09d} + + + {2c723cf4-75b6-406a-90c0-ebb7a13ba476} + {7be79ad5-3520-46a1-a370-dce2a943978c} @@ -1076,12 +1042,6 @@ {d6d5f6e0-1c72-496b-af11-6d52d5123033} - - {34f45db9-5c08-49cb-b349-b9e760ce3213} - - - {b681797d-7747-487f-b448-5ef5b2d2805b} - diff --git a/Common/CommonFuncs.h b/Common/CommonFuncs.h index 65b334409..2b2d46f91 100644 --- a/Common/CommonFuncs.h +++ b/Common/CommonFuncs.h @@ -30,11 +30,8 @@ #include #include -#if (PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)) && !defined(__EMSCRIPTEN__) +#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #define Crash() {asm ("int $3");} -#elif PPSSPP_PLATFORM(SWITCH) -// TODO: Implement Crash() for Switch, lets not use breakpoint for the time being -#define Crash() {*((volatile u32 *)0x0) = 0xDEADC0DE;} #elif PPSSPP_ARCH(ARM) #define Crash() {asm ("bkpt #0");} #elif PPSSPP_ARCH(ARM64) diff --git a/Common/CommonTypes.h b/Common/CommonTypes.h index 2fc1451c0..ab2b7145a 100644 --- a/Common/CommonTypes.h +++ b/Common/CommonTypes.h @@ -36,39 +36,6 @@ typedef signed __int64 s64; #else -#ifdef __SWITCH__ -// Some HID conflicts -#define KEY_UP PKEY_UP -#define KEY_DOWN PKEY_DOWN -// Other conflicts -#define Event _Event -#define Framebuffer _Framebuffer -#define Waitable _Waitable -#define ThreadContext _ThreadContext -#include -// Cleanup -#undef KEY_UP -#undef KEY_DOWN -#undef Event -#undef Framebuffer -#undef Waitable -#undef ThreadContext - -// Conflicting types with libnx -#ifndef _u64 -#define u64 _u64 -#endif // _u64 - -#ifndef s64 -#define s64 _s64 -#endif // _s64 - -typedef unsigned char u_char; -typedef unsigned short u_short; -typedef unsigned int u_int; -typedef unsigned long u_long; -#endif // __SWITCH__ - typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; diff --git a/Common/ConsoleListener.cpp b/Common/ConsoleListener.cpp index 86fe3e07a..d83d800b3 100644 --- a/Common/ConsoleListener.cpp +++ b/Common/ConsoleListener.cpp @@ -358,7 +358,7 @@ void ConsoleListener::LogWriterThread() for (char *Text = logLocal, *End = logLocal + logLocalSize; Text < End; ) { - LogLevel Level = LogLevel::LINFO; + LogTypes::LOG_LEVELS Level = LogTypes::LINFO; char *next = (char *) memchr(Text + 1, '\033', End - Text); size_t Len = next - Text; @@ -367,7 +367,7 @@ void ConsoleListener::LogWriterThread() if (Text[0] == '\033' && Text + 1 < End) { - Level = (LogLevel)(Text[1] - '0'); + Level = (LogTypes::LOG_LEVELS) (Text[1] - '0'); Len -= 2; Text += 2; } @@ -384,7 +384,7 @@ void ConsoleListener::LogWriterThread() delete [] logLocal; } -void ConsoleListener::SendToThread(LogLevel Level, const char *Text) +void ConsoleListener::SendToThread(LogTypes::LOG_LEVELS Level, const char *Text) { // Oops, we're already quitting. Just do nothing. if (logPendingWritePos == (u32) -1) @@ -462,7 +462,7 @@ void ConsoleListener::SendToThread(LogLevel Level, const char *Text) SetEvent(hTriggerEvent); } -void ConsoleListener::WriteToConsole(LogLevel Level, const char *Text, size_t Len) +void ConsoleListener::WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Text, size_t Len) { _dbg_assert_msg_(IsOpen(), "Don't call this before opening the console."); @@ -479,20 +479,21 @@ void ConsoleListener::WriteToConsole(LogLevel Level, const char *Text, size_t Le WORD Color; static wchar_t tempBuf[2048]; - switch (Level) { - case LogLevel::LNOTICE: // light green + switch (Level) + { + case NOTICE_LEVEL: // light green Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; - case LogLevel::LERROR: // light red + case ERROR_LEVEL: // light red Color = FOREGROUND_RED | FOREGROUND_INTENSITY; break; - case LogLevel::LWARNING: // light yellow + case WARNING_LEVEL: // light yellow Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; - case LogLevel::LINFO: // cyan + case INFO_LEVEL: // cyan Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break; - case LogLevel::LDEBUG: // gray + case DEBUG_LEVEL: // gray Color = FOREGROUND_INTENSITY; break; default: // off-white @@ -592,7 +593,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool COORD Coo = GetCoordinates(OldCursor, LBufWidth); SetConsoleCursorPosition(hConsole, Coo); - // if (SLog.length() > 0) Log(LogLevel::LNOTICE, SLog.c_str()); + // if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str()); // Resize the window too if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true); @@ -614,16 +615,18 @@ void ConsoleListener::Log(const LogMessage &msg) { char ColorAttr[16] = ""; char ResetAttr[16] = ""; - if (bUseColor) { + if (bUseColor) + { strcpy(ResetAttr, "\033[0m"); - switch (msg.level) { - case LogLevel::LNOTICE: // light green + switch (msg.level) + { + case NOTICE_LEVEL: // light green strcpy(ColorAttr, "\033[92m"); break; - case LogLevel::LERROR: // light red + case ERROR_LEVEL: // light red strcpy(ColorAttr, "\033[91m"); break; - case LogLevel::LWARNING: // light yellow + case WARNING_LEVEL: // light yellow strcpy(ColorAttr, "\033[93m"); break; default: @@ -653,3 +656,5 @@ void ConsoleListener::ClearScreen(bool Cursor) if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); #endif } + + diff --git a/Common/ConsoleListener.h b/Common/ConsoleListener.h index a84bb2576..99c673075 100644 --- a/Common/ConsoleListener.h +++ b/Common/ConsoleListener.h @@ -54,8 +54,8 @@ private: static unsigned int WINAPI RunThread(void *lpParam); void LogWriterThread(); - void SendToThread(LogLevel Level, const char *Text); - void WriteToConsole(LogLevel Level, const char *Text, size_t Len); + void SendToThread(LogTypes::LOG_LEVELS Level, const char *Text); + void WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Text, size_t Len); static int refCount; static HANDLE hThread; diff --git a/Common/Crypto/md5.cpp b/Common/Crypto/md5.cpp index cce49809d..22a839565 100644 --- a/Common/Crypto/md5.cpp +++ b/Common/Crypto/md5.cpp @@ -62,7 +62,7 @@ /* * MD5 context setup */ -void ppsspp_md5_starts( md5_context *ctx ) +void md5_starts( md5_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -73,7 +73,7 @@ void ppsspp_md5_starts( md5_context *ctx ) ctx->state[3] = 0x10325476; } -static void ppsspp_md5_process( md5_context *ctx, unsigned char data[64] ) +static void md5_process( md5_context *ctx, unsigned char data[64] ) { unsigned long X[16], A, B, C, D; @@ -199,7 +199,7 @@ static void ppsspp_md5_process( md5_context *ctx, unsigned char data[64] ) /* * MD5 process buffer */ -void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen ) +void md5_update( md5_context *ctx, unsigned char *input, int ilen ) { int fill; unsigned long left; @@ -220,7 +220,7 @@ void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); - ppsspp_md5_process( ctx, ctx->buffer ); + md5_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; @@ -228,7 +228,7 @@ void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen ) while( ilen >= 64 ) { - ppsspp_md5_process( ctx, input ); + md5_process( ctx, input ); input += 64; ilen -= 64; } @@ -251,7 +251,7 @@ static const unsigned char md5_padding[64] = /* * MD5 final digest */ -void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] ) +void md5_finish( md5_context *ctx, unsigned char output[16] ) { unsigned long last, padn; unsigned long high, low; @@ -267,8 +267,8 @@ void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] ) last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - ppsspp_md5_update( ctx, (unsigned char *) md5_padding, padn ); - ppsspp_md5_update( ctx, msglen, 8 ); + md5_update( ctx, (unsigned char *) md5_padding, padn ); + md5_update( ctx, msglen, 8 ); PUT_ULONG_LE( ctx->state[0], output, 0 ); PUT_ULONG_LE( ctx->state[1], output, 4 ); @@ -279,13 +279,13 @@ void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] ) /* * output = MD5( input buffer ) */ -void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] ) +void md5( unsigned char *input, int ilen, unsigned char output[16] ) { md5_context ctx; - ppsspp_md5_starts( &ctx ); - ppsspp_md5_update( &ctx, input, ilen ); - ppsspp_md5_finish( &ctx, output ); + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); memset( &ctx, 0, sizeof( md5_context ) ); } @@ -293,14 +293,14 @@ void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] ) /* * MD5 HMAC context setup */ -void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ) +void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ) { int i; unsigned char sum[16]; if( keylen > 64 ) { - ppsspp_md5( key, keylen, sum ); + md5( key, keylen, sum ); keylen = 16; key = sum; } @@ -314,8 +314,8 @@ void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ) ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); } - ppsspp_md5_starts( ctx ); - ppsspp_md5_update( ctx, ctx->ipad, 64 ); + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); memset( sum, 0, sizeof( sum ) ); } @@ -323,23 +323,23 @@ void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ) /* * MD5 HMAC process buffer */ -void ppsspp_md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen ) +void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen ) { - ppsspp_md5_update( ctx, input, ilen ); + md5_update( ctx, input, ilen ); } /* * MD5 HMAC final digest */ -void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) { unsigned char tmpbuf[16]; - ppsspp_md5_finish( ctx, tmpbuf ); - ppsspp_md5_starts( ctx ); - ppsspp_md5_update( ctx, ctx->opad, 64 ); - ppsspp_md5_update( ctx, tmpbuf, 16 ); - ppsspp_md5_finish( ctx, output ); + md5_finish( ctx, tmpbuf ); + md5_starts( ctx ); + md5_update( ctx, ctx->opad, 64 ); + md5_update( ctx, tmpbuf, 16 ); + md5_finish( ctx, output ); memset( tmpbuf, 0, sizeof( tmpbuf ) ); } @@ -347,14 +347,14 @@ void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) /* * output = HMAC-MD5( hmac key, input buffer ) */ -void ppsspp_md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen, +void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen, unsigned char output[16] ) { md5_context ctx; - ppsspp_md5_hmac_starts( &ctx, key, keylen ); - ppsspp_md5_hmac_update( &ctx, input, ilen ); - ppsspp_md5_hmac_finish( &ctx, output ); + md5_hmac_starts( &ctx, key, keylen ); + md5_hmac_update( &ctx, input, ilen ); + md5_hmac_finish( &ctx, output ); memset( &ctx, 0, sizeof( md5_context ) ); } @@ -464,7 +464,7 @@ static const unsigned char md5_hmac_test_sum[7][16] = /* * Checkup routine */ -int ppsspp_md5_self_test( int verbose ) +int md5_self_test( int verbose ) { int i, buflen; unsigned char buf[1024]; diff --git a/Common/Crypto/md5.h b/Common/Crypto/md5.h index da522c34d..a69024d11 100644 --- a/Common/Crypto/md5.h +++ b/Common/Crypto/md5.h @@ -46,7 +46,7 @@ extern "C" { * * \param ctx context to be initialized */ -void ppsspp_md5_starts( md5_context *ctx ); +void md5_starts( md5_context *ctx ); /** * \brief MD5 process buffer @@ -55,7 +55,7 @@ void ppsspp_md5_starts( md5_context *ctx ); * \param input buffer holding the data * \param ilen length of the input data */ -void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen ); +void md5_update( md5_context *ctx, unsigned char *input, int ilen ); /** * \brief MD5 final digest @@ -63,7 +63,7 @@ void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen ); * \param ctx MD5 context * \param output MD5 checksum result */ -void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] ); +void md5_finish( md5_context *ctx, unsigned char output[16] ); /** * \brief Output = MD5( input buffer ) @@ -72,7 +72,7 @@ void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] ); * \param ilen length of the input data * \param output MD5 checksum result */ -void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] ); +void md5( unsigned char *input, int ilen, unsigned char output[16] ); /** * \brief Output = MD5( file contents ) @@ -83,7 +83,7 @@ void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] ); * \return 0 if successful, 1 if fopen failed, * or 2 if fread failed */ -int ppsspp_md5_file( char *path, unsigned char output[16] ); +int md5_file( char *path, unsigned char output[16] ); /** * \brief MD5 HMAC context setup @@ -92,7 +92,7 @@ int ppsspp_md5_file( char *path, unsigned char output[16] ); * \param key HMAC secret key * \param keylen length of the HMAC key */ -void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ); +void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ); /** * \brief MD5 HMAC process buffer @@ -101,7 +101,7 @@ void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen ); * \param input buffer holding the data * \param ilen length of the input data */ -void ppsspp_md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen ); +void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen ); /** * \brief MD5 HMAC final digest @@ -109,7 +109,7 @@ void ppsspp_md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen ); * \param ctx HMAC context * \param output MD5 HMAC checksum result */ -void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] ); +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ); /** * \brief Output = HMAC-MD5( hmac key, input buffer ) @@ -120,7 +120,7 @@ void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] ); * \param ilen length of the input data * \param output HMAC-MD5 result */ -void ppsspp_md5_hmac( unsigned char *key, int keylen, +void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen, unsigned char output[16] ); @@ -129,7 +129,7 @@ void ppsspp_md5_hmac( unsigned char *key, int keylen, * * \return 0 if successful, or 1 if the test failed */ -int ppsspp_md5_self_test( int verbose ); +int md5_self_test( int verbose ); #ifdef __cplusplus } diff --git a/Common/Data/Collections/FastVec.h b/Common/Data/Collections/FastVec.h deleted file mode 100644 index 08e5176d4..000000000 --- a/Common/Data/Collections/FastVec.h +++ /dev/null @@ -1,225 +0,0 @@ -#pragma once - -// Yet another replacement for std::vector, this time for use in graphics queues. -// Its major difference is that you can append uninitialized structures and initialize them after. -// This is not allows by std::vector but is very useful for our sometimes oversized unions. -// Also, copies during resize are done by memcpy, not by any move constructor or similar. - -#include -#include - -#ifdef _DEBUG -#include "Common/Log.h" -#endif - -template -class FastVec { -public: - FastVec() {} - FastVec(size_t initialCapacity) { - capacity_ = initialCapacity; - data_ = (T *)malloc(initialCapacity * sizeof(T)); - } - ~FastVec() { if (data_) free(data_); } - - T &push_uninitialized() { - if (size_ < capacity_) { - size_++; - return data_[size_ - 1]; - } else { - ExtendByOne(); - return data_[size_ - 1]; - } - } - - void push_back(const T &t) { - T &dest = push_uninitialized(); - dest = t; - } - - // Move constructor - FastVec(FastVec &&other) { - data_ = other.data_; - size_ = other.size_; - capacity_ = other.capacity_; - other.data_ = nullptr; - other.size_ = 0; - other.capacity_ = 0; - } - - FastVec &operator=(FastVec &&other) { - if (this != &other) { - delete[] data_; - data_ = other.data_; - size_ = other.size_; - capacity_ = other.capacity_; - other.data_ = nullptr; - other.size_ = 0; - other.capacity_ = 0; - } - return *this; - } - - // No copy constructor. - FastVec(const FastVec &other) = delete; - FastVec &operator=(const FastVec &other) = delete; - - size_t size() const { return size_; } - size_t capacity() const { return capacity_; } - void clear() { size_ = 0; } - bool empty() const { return size_ == 0; } - - const T *data() { return data_; } - T *begin() { return data_; } - T *end() { return data_ + size_; } - const T *begin() const { return data_; } - const T *end() const { return data_ + size_; } - - // Out of bounds (past size() - 1) is undefined behavior. - T &operator[] (const size_t index) { return data_[index]; } - const T &operator[] (const size_t index) const { return data_[index]; } - T &at(const size_t index) { return data_[index]; } - const T &at(const size_t index) const { return data_[index]; } - - // These two are invalid if empty(). - const T &back() const { return (*this)[size() - 1]; } - const T &front() const { return (*this)[0]; } - - // Limited functionality for inserts and similar, add as needed. - T &insert(T *iter) { - int pos = iter - data_; - ExtendByOne(); - if (pos + 1 < (int)size_) { - memmove(data_ + pos + 1, data_ + pos, (size_ - pos) * sizeof(T)); - } - return data_[pos]; - } - - void insert(T *destIter, const T *beginIter, const T *endIter) { - int pos = destIter - data_; - if (beginIter == endIter) - return; - size_t newItems = endIter - beginIter; - IncreaseCapacityTo(size_ + newItems); - memmove(data_ + pos + newItems, data_ + pos, (size_ - pos) * sizeof(T)); - memcpy(data_ + pos, beginIter, newItems * sizeof(T)); - size_ += newItems; - } - - void resize(size_t size) { - if (size < size_) { - size_ = size; - } else { - // TODO - } - } - - void reserve(size_t newCapacity) { - IncreaseCapacityTo(newCapacity); - } - - void extend(const T *newData, size_t count) { - IncreaseCapacityTo(size_ + count); - memcpy(data_ + size_, newData, count * sizeof(T)); - size_ += count; - } - - T *extend_uninitialized(size_t count) { - size_t sz = size_; - if (size_ + count <= capacity_) { - size_ += count; - return &data_[sz]; - } else { - size_t newCapacity = size_ + count * 2; // Leave some extra room when growing in all cases - if (newCapacity < capacity_ * 2) { - // Standard amortized O(1). - newCapacity = capacity_ * 2; - } - IncreaseCapacityTo(newCapacity); - size_ += count; - return &data_[sz]; - } - } - - void LockCapacity() { -#ifdef _DEBUG - capacityLocked_ = true; -#endif - } - -private: - void IncreaseCapacityTo(size_t newCapacity) { -#ifdef _DEBUG - _dbg_assert_(!capacityLocked_); -#endif - if (newCapacity <= capacity_) - return; - T *oldData = data_; - data_ = (T *)malloc(sizeof(T) * newCapacity); - if (capacity_ != 0) { - memcpy(data_, oldData, sizeof(T) * size_); - free(oldData); - } - capacity_ = newCapacity; - } - - void ExtendByOne() { - size_t newCapacity = capacity_ * 2; - if (newCapacity < 16) { - newCapacity = 16; - } - IncreaseCapacityTo(newCapacity); - size_++; - } - - size_t size_ = 0; - size_t capacity_ = 0; - T *data_ = nullptr; -#ifdef _DEBUG - bool capacityLocked_ = false; -#endif -}; - -// Simple cyclical vector. -template -class HistoryBuffer { -public: - T &Add(size_t index) { -#ifdef _DEBUG - _dbg_assert_((int64_t)index >= 0); -#endif - if (index > maxIndex_) - maxIndex_ = index; - T &entry = data_[index % size]; - entry = T{}; - return entry; - } - - const T &Back(size_t index) const { -#ifdef _DEBUG - _dbg_assert_(index < maxIndex_ && index < size); -#endif - return data_[(maxIndex_ - index) % size]; - } - - // Out of bounds (past size() - 1) is undefined behavior. - T &operator[] (const size_t index) { -#ifdef _DEBUG - _dbg_assert_(index <= maxIndex_); -#endif - return data_[index % size]; - } - const T &operator[] (const size_t index) const { -#ifdef _DEBUG - _dbg_assert_(index <= maxIndex_); -#endif - return data_[index % size]; - } - size_t MaxIndex() const { - return maxIndex_; - } - -private: - T data_[size]{}; - size_t maxIndex_ = 0; -}; diff --git a/Common/Data/Collections/FixedSizeQueue.h b/Common/Data/Collections/FixedSizeQueue.h index 621f4f003..e8578c6bd 100644 --- a/Common/Data/Collections/FixedSizeQueue.h +++ b/Common/Data/Collections/FixedSizeQueue.h @@ -222,3 +222,4 @@ private: volatile int curReadBlock; volatile int curWriteBlock; }; + diff --git a/Common/Data/Collections/Hashmaps.h b/Common/Data/Collections/Hashmaps.h index a9e5dece9..ca5de0540 100644 --- a/Common/Data/Collections/Hashmaps.h +++ b/Common/Data/Collections/Hashmaps.h @@ -29,7 +29,7 @@ enum class BucketState : uint8_t { // we always use very small values, so it's probably better to have them in the same // cache-line as the corresponding key. // Enforces that value are pointers to make sure that combined storage makes sense. -template +template class DenseHashMap { public: DenseHashMap(int initialCapacity) : capacity_(initialCapacity) { @@ -37,44 +37,23 @@ public: state.resize(initialCapacity); } - // Returns true if the entry was found, and writes the entry to *value. - // Returns false and does not write to value if no entry was found. - // Note that nulls can be stored. - bool Get(const Key &key, Value *value) const { + // Returns nullptr if no entry was found. + Value Get(const Key &key) { uint32_t mask = capacity_ - 1; uint32_t pos = HashKey(key) & mask; // No? Let's go into search mode. Linear probing. uint32_t p = pos; while (true) { - if (state[p] == BucketState::TAKEN && KeyEquals(key, map[p].key)) { - *value = map[p].value; - return true; - } else if (state[p] == BucketState::FREE) { - return false; - } + if (state[p] == BucketState::TAKEN && KeyEquals(key, map[p].key)) + return map[p].value; + else if (state[p] == BucketState::FREE) + return NullValue; p = (p + 1) & mask; // If the state is REMOVED, we just keep on walking. if (p == pos) { - // We looped around the whole map. _assert_msg_(false, "DenseHashMap: Hit full on Get()"); } } - return false; - } - - // Only works if Value can be nullptr - Value GetOrNull(const Key &key) const { - Value value; - if (Get(key, &value)) { - return value; - } else { - return (Value)nullptr; - } - } - - bool ContainsKey(const Key &key) const { - // Slightly wasteful, though compiler might optimize it. - Value value; - return Get(key, &value); + return NullValue; } // Asserts if we already had the key! @@ -135,7 +114,6 @@ public: return false; } - // This will never crash if you call it without locking - but, the value might not be right. size_t size() const { return count_; } @@ -212,7 +190,7 @@ private: // Like the above, uses linear probing for cache-friendliness. // Does not perform hashing at all so expects well-distributed keys. -template +template class PrehashMap { public: PrehashMap(int initialCapacity) : capacity_(initialCapacity) { @@ -221,24 +199,22 @@ public: } // Returns nullptr if no entry was found. - bool Get(uint32_t hash, Value *value) { + Value Get(uint32_t hash) { uint32_t mask = capacity_ - 1; uint32_t pos = hash & mask; // No? Let's go into search mode. Linear probing. uint32_t p = pos; while (true) { - if (state[p] == BucketState::TAKEN && hash == map[p].hash) { - *value = map[p].value; - return true; - } else if (state[p] == BucketState::FREE) { - return false; - } + if (state[p] == BucketState::TAKEN && hash == map[p].hash) + return map[p].value; + else if (state[p] == BucketState::FREE) + return NullValue; p = (p + 1) & mask; // If the state is REMOVED, we just keep on walking. if (p == pos) { _assert_msg_(false, "PrehashMap: Hit full on Get()"); } } - return false; + return NullValue; } // Returns false if we already had the key! Which is a bit different. diff --git a/Common/Data/Collections/TinySet.h b/Common/Data/Collections/TinySet.h index 6521beab4..702a98dc0 100644 --- a/Common/Data/Collections/TinySet.h +++ b/Common/Data/Collections/TinySet.h @@ -187,7 +187,7 @@ struct FixedTinyVec { bool operator == (const FixedTinyVec &other) const { if (count_ != other.count_) return false; - for (int i = 0; i < count_; i++) { + for (size_t i = 0; i < count_; i++) { if (!(data_[i] == other.data_[i])) { return false; } diff --git a/Common/Data/Convert/ColorConv.cpp b/Common/Data/Convert/ColorConv.cpp index ba32cc098..01c434e6e 100644 --- a/Common/Data/Convert/ColorConv.cpp +++ b/Common/Data/Convert/ColorConv.cpp @@ -617,7 +617,6 @@ void ConvertRGB565ToBGR565(u16 *dst, const u16 *src, u32 numPixels) { u32 i = 0; #endif - // TODO: Add a 64-bit loop too. const u32 *src32 = (const u32 *)src; u32 *dst32 = (u32 *)dst; for (; i < numPixels / 2; i++) { diff --git a/Common/Data/Encoding/Utf8.cpp b/Common/Data/Encoding/Utf8.cpp index fb3e829d1..760fe6b07 100644 --- a/Common/Data/Encoding/Utf8.cpp +++ b/Common/Data/Encoding/Utf8.cpp @@ -219,15 +219,13 @@ int u8_strlen(const char *s) } /* reads the next utf-8 sequence out of a string, updating an index */ -uint32_t u8_nextchar(const char *s, int *index) { +uint32_t u8_nextchar(const char *s, int *i) { uint32_t ch = 0; int sz = 0; - int i = *index; do { - ch = (ch << 6) + (unsigned char)s[i++]; + ch = (ch << 6) + (unsigned char)s[(*i)++]; sz++; - } while (s[i] && ((s[i]) & 0xC0) == 0x80); - *index = i; + } while (s[*i] && ((s[*i]) & 0xC0) == 0x80); return ch - offsetsFromUTF8[sz - 1]; } @@ -428,17 +426,6 @@ int u8_is_locale_utf8(const char *locale) return 0; } -bool AnyEmojiInString(const char *s, size_t byteCount) { - int i = 0; - while (i < byteCount) { - uint32_t c = u8_nextchar(s, &i); - if (CodepointIsProbablyEmoji(c)) { - return true; - } - } - return false; -} - int UTF8StringNonASCIICount(const char *utf8string) { UTF8 utf(utf8string); int count = 0; @@ -571,12 +558,6 @@ std::u16string ConvertUTF8ToUCS2(const std::string &source) { return dst; } -std::string CodepointToUTF8(uint32_t codePoint) { - char temp[16]{}; - UTF8::encode(temp, codePoint); - return std::string(temp); -} - #ifndef _WIN32 // Replacements for the Win32 wstring functions. Not to be used from emulation code! diff --git a/Common/Data/Encoding/Utf8.h b/Common/Data/Encoding/Utf8.h index 5123ef8a4..29d09f67e 100644 --- a/Common/Data/Encoding/Utf8.h +++ b/Common/Data/Encoding/Utf8.h @@ -26,15 +26,6 @@ int u8_strlen(const char *s); void u8_inc(const char *s, int *i); void u8_dec(const char *s, int *i); -inline bool CodepointIsProbablyEmoji(uint32_t c) { - // Original check was some ranges grabbed from https://stackoverflow.com/a/62898106. - // But let's just go with checking if outside the BMP, it's not a big deal if we accidentally - // switch to color when not needed if someone uses a weird glyph. - return c > 0xFFFF; -} - -bool AnyEmojiInString(const char *s, size_t byteCount); - class UTF8 { public: static const uint32_t INVALID = (uint32_t)-1; @@ -98,8 +89,6 @@ bool UTF8StringHasNonASCII(const char *utf8string); // Removes overlong encodings and similar. std::string SanitizeUTF8(const std::string &utf8string); -std::string CodepointToUTF8(uint32_t codePoint); - // UTF8 to Win32 UTF-16 // Should be used when calling Win32 api calls diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index a93e530f9..79ff0aebe 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -7,7 +7,6 @@ #include -// Hm, what's this for? #ifndef _MSC_VER #include #endif @@ -20,17 +19,17 @@ #include #include "Common/Data/Format/IniFile.h" -#include "Common/Data/Text/Parsers.h" #include "Common/File/VFS/VFS.h" #include "Common/File/FileUtil.h" -#include "Common/Log.h" -#include "Common/Math/math_util.h" +#include "Common/Data/Text/Parsers.h" + +#ifdef _WIN32 +#include "Common/Data/Encoding/Utf8.h" +#endif #include "Common/StringUtils.h" -// This unescapes # signs. -// NOTE: These parse functions can make better use of the string_view - the pos argument should not be needed, for example. -static bool ParseLineKey(std::string_view line, size_t &pos, std::string *keyOut) { +static bool ParseLineKey(const std::string &line, size_t &pos, std::string *keyOut) { std::string key = ""; while (pos < line.size()) { @@ -45,8 +44,7 @@ static bool ParseLineKey(std::string_view line, size_t &pos, std::string *keyOut } // Escaped. - key += line.substr(pos, next - pos - 1); - key.push_back('#'); + key += line.substr(pos, next - pos - 1) + "#"; pos = next + 1; } else if (line[next] == '=') { // Hurray, done. @@ -62,11 +60,11 @@ static bool ParseLineKey(std::string_view line, size_t &pos, std::string *keyOut return true; } -static bool ParseLineValue(std::string_view line, size_t &pos, std::string *valueOut) { +static bool ParseLineValue(const std::string &line, size_t &pos, std::string *valueOut) { std::string value = ""; - std::string_view strippedLine = StripSpaces(line.substr(pos)); - if (strippedLine.size() >= 2 && strippedLine[0] == '"' && strippedLine[strippedLine.size() - 1] == '"') { + std::string strippedLine = StripSpaces(line.substr(pos)); + if (strippedLine[0] == '"' && strippedLine[strippedLine.size()-1] == '"') { // Don't remove comment if is surrounded by " " value += line.substr(pos); pos = line.npos; // Won't enter the while below @@ -86,8 +84,7 @@ static bool ParseLineValue(std::string_view line, size_t &pos, std::string *valu break; } else { // Escaped. - value += line.substr(pos, next - pos - 1); - value.push_back('#'); + value += line.substr(pos, next - pos - 1) + "#"; pos = next + 1; } } @@ -99,7 +96,7 @@ static bool ParseLineValue(std::string_view line, size_t &pos, std::string *valu return true; } -static bool ParseLineComment(std::string_view line, size_t &pos, std::string *commentOut) { +static bool ParseLineComment(const std::string& line, size_t &pos, std::string *commentOut) { // Don't bother with anything if we don't need the comment data. if (commentOut) { // Include any whitespace/formatting in the comment. @@ -120,7 +117,8 @@ static bool ParseLineComment(std::string_view line, size_t &pos, std::string *co return true; } -static bool ParseLine(std::string_view line, std::string* keyOut, std::string* valueOut, std::string* commentOut) +// Ugh, this is ugly. +static bool ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) { // Rules: // 1. A line starting with ; is commented out. @@ -144,7 +142,7 @@ static bool ParseLine(std::string_view line, std::string* keyOut, std::string* v return true; } -static std::string EscapeHash(std::string_view value) { +static std::string EscapeComments(const std::string &value) { std::string result = ""; for (size_t pos = 0; pos < value.size(); ) { @@ -153,8 +151,7 @@ static std::string EscapeHash(std::string_view value) { result += value.substr(pos); pos = value.npos; } else { - result += value.substr(pos, next - pos); - result += "\\#"; + result += value.substr(pos, next - pos) + "\\#"; pos = next + 1; } } @@ -162,56 +159,34 @@ static std::string EscapeHash(std::string_view value) { return result; } -void ParsedIniLine::ParseFrom(std::string_view line) { - line = StripSpaces(line); - if (line.empty()) { - key.clear(); - value.clear(); - comment.clear(); - } else if (line[0] == '#') { - key.clear(); - value.clear(); - comment = line; - } else { - ParseLine(line, &key, &value, &comment); - } -} - -void ParsedIniLine::Reconstruct(std::string *output) const { - if (!key.empty()) { - *output = EscapeHash(key) + " = " + EscapeHash(value) + comment; - } else { - *output = comment; - } -} - void Section::Clear() { - lines_.clear(); + lines.clear(); } -bool Section::GetKeys(std::vector &keys) const { - keys.clear(); - for (auto liter = lines_.begin(); liter != lines_.end(); ++liter) { - if (!liter->Key().empty()) - keys.push_back(std::string(liter->Key())); - } - return true; -} - -ParsedIniLine *Section::GetLine(const char *key) { - for (auto &line : lines_) { - if (equalsNoCase(line.Key(), key)) +std::string* Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut) +{ + for (std::vector::iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + std::string& line = *iter; + std::string lineKey; + ParseLine(line, &lineKey, valueOut, commentOut); + if (!strcasecmp(lineKey.c_str(), key)) return &line; } - return nullptr; + return 0; } -const ParsedIniLine *Section::GetLine(const char* key) const { - for (auto &line : lines_) { - if (equalsNoCase(line.Key(), key)) +const std::string* Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut) const +{ + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + const std::string& line = *iter; + std::string lineKey; + ParseLine(line, &lineKey, valueOut, commentOut); + if (!strcasecmp(lineKey.c_str(), key)) return &line; } - return nullptr; + return 0; } void Section::Set(const char* key, uint32_t newValue) { @@ -223,7 +198,6 @@ void Section::Set(const char* key, uint64_t newValue) { } void Section::Set(const char* key, float newValue) { - _dbg_assert_(!my_isnanorinf(newValue)); Set(key, StringFromFormat("%f", newValue).c_str()); } @@ -235,13 +209,19 @@ void Section::Set(const char* key, int newValue) { Set(key, StringFromInt(newValue).c_str()); } -void Section::Set(const char* key, const char* newValue) { - ParsedIniLine *line = GetLine(key); - if (line) { - line->SetValue(newValue); - } else { +void Section::Set(const char* key, const char* newValue) +{ + std::string value, commented; + std::string* line = GetLine(key, &value, &commented); + if (line) + { + // Change the value - keep the key and comment + *line = StripSpaces(key) + " = " + EscapeComments(newValue) + commented; + } + else + { // The key did not already exist in this section - let's add it. - lines_.emplace_back(ParsedIniLine(key, newValue)); + lines.emplace_back(std::string(key) + " = " + EscapeComments(newValue)); } } @@ -253,15 +233,16 @@ void Section::Set(const char* key, const std::string& newValue, const std::strin Delete(key); } -bool Section::Get(const char* key, std::string* value, const char* defaultValue) const { - const ParsedIniLine *line = GetLine(key); - if (!line) { - if (defaultValue) { +bool Section::Get(const char* key, std::string* value, const char* defaultValue) const +{ + const std::string* line = GetLine(key, value, 0); + if (!line) + { + if (defaultValue) + { *value = defaultValue; } return false; - } else { - *value = line->Value(); } return true; } @@ -306,7 +287,7 @@ void Section::Set(const char* key, const std::vector& newValues) } void Section::AddComment(const std::string &comment) { - lines_.emplace_back(ParsedIniLine::CommentOnly("# " + comment)); + lines.emplace_back("# " + comment); } bool Section::Get(const char* key, std::vector& values) const @@ -341,7 +322,7 @@ bool Section::Get(const char* key, int* value, int defaultValue) const { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParse(temp, value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; @@ -371,7 +352,7 @@ bool Section::Get(const char* key, bool* value, bool defaultValue) const { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParse(temp, value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; @@ -381,7 +362,7 @@ bool Section::Get(const char* key, float* value, float defaultValue) const { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParse(temp, value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; @@ -391,35 +372,46 @@ bool Section::Get(const char* key, double* value, double defaultValue) const { std::string temp; bool retval = Get(key, &temp, 0); - if (retval && TryParse(temp, value)) + if (retval && TryParse(temp.c_str(), value)) return true; *value = defaultValue; return false; } -bool Section::Exists(const char *key) const { - for (auto &line : lines_) { - if (equalsNoCase(key, line.Key())) +bool Section::Exists(const char *key) const +{ + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + std::string lineKey; + ParseLine(*iter, &lineKey, NULL, NULL); + if (!strcasecmp(lineKey.c_str(), key)) return true; } return false; } -std::map Section::ToMap() const { +std::map Section::ToMap() const +{ std::map outMap; - for (auto &line : lines_) { - if (!line.Key().empty()) { - outMap[std::string(line.Key())] = line.Value(); + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + std::string lineKey, lineValue; + if (ParseLine(*iter, &lineKey, &lineValue, NULL)) { + outMap[lineKey] = lineValue; } } return outMap; } -bool Section::Delete(const char *key) { - ParsedIniLine *line = GetLine(key); - for (auto liter = lines_.begin(); liter != lines_.end(); ++liter) { - if (line == &*liter) { - lines_.erase(liter); + +bool Section::Delete(const char *key) +{ + std::string* line = GetLine(key, 0, 0); + for (std::vector::iterator liter = lines.begin(); liter != lines.end(); ++liter) + { + if (line == &*liter) + { + lines.erase(liter); return true; } } @@ -428,36 +420,42 @@ bool Section::Delete(const char *key) { // IniFile -const Section* IniFile::GetSection(const char* sectionName) const { - for (const auto &iter : sections) +const Section* IniFile::GetSection(const char* sectionName) const +{ + for (std::vector
::const_iterator iter = sections.begin(); iter != sections.end(); ++iter) if (!strcasecmp(iter->name().c_str(), sectionName)) - return iter.get(); - return nullptr; + return (&(*iter)); + return 0; } -Section* IniFile::GetSection(const char* sectionName) { - for (const auto &iter : sections) +Section* IniFile::GetSection(const char* sectionName) +{ + for (std::vector
::iterator iter = sections.begin(); iter != sections.end(); ++iter) if (!strcasecmp(iter->name().c_str(), sectionName)) - return iter.get(); - return nullptr; + return (&(*iter)); + return 0; } -Section* IniFile::GetOrCreateSection(const char* sectionName) { +Section* IniFile::GetOrCreateSection(const char* sectionName) +{ Section* section = GetSection(sectionName); - if (!section) { - sections.push_back(std::unique_ptr
(new Section(sectionName))); - section = sections.back().get(); + if (!section) + { + sections.push_back(Section(sectionName)); + section = §ions[sections.size() - 1]; } return section; } -bool IniFile::DeleteSection(const char* sectionName) { +bool IniFile::DeleteSection(const char* sectionName) +{ Section* s = GetSection(sectionName); if (!s) return false; - - for (auto iter = sections.begin(); iter != sections.end(); ++iter) { - if (iter->get() == s) { + for (std::vector
::iterator iter = sections.begin(); iter != sections.end(); ++iter) + { + if (&(*iter) == s) + { sections.erase(iter); return true; } @@ -465,21 +463,35 @@ bool IniFile::DeleteSection(const char* sectionName) { return false; } -bool IniFile::Exists(const char* sectionName, const char* key) const { +bool IniFile::Exists(const char* sectionName, const char* key) const +{ const Section* section = GetSection(sectionName); if (!section) return false; return section->Exists(key); } -bool IniFile::DeleteKey(const char* sectionName, const char* key) { +void IniFile::SetLines(const char* sectionName, const std::vector &lines) +{ + Section* section = GetOrCreateSection(sectionName); + section->lines.clear(); + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + section->lines.push_back(*iter); + } +} + +bool IniFile::DeleteKey(const char* sectionName, const char* key) +{ Section* section = GetSection(sectionName); if (!section) return false; - ParsedIniLine *line = section->GetLine(key); - for (auto liter = section->lines_.begin(); liter != section->lines_.end(); ++liter) { - if (line == &(*liter)) { - section->lines_.erase(liter); + std::string* line = section->GetLine(key, 0, 0); + for (std::vector::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter) + { + if (line == &(*liter)) + { + section->lines.erase(liter); return true; } } @@ -487,13 +499,55 @@ bool IniFile::DeleteKey(const char* sectionName, const char* key) { } // Return a list of all keys in a section -bool IniFile::GetKeys(const char* sectionName, std::vector& keys) const { - const Section *section = GetSection(sectionName); +bool IniFile::GetKeys(const char* sectionName, std::vector& keys) const +{ + const Section* section = GetSection(sectionName); if (!section) return false; - return section->GetKeys(keys); + keys.clear(); + for (std::vector::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter) + { + std::string key; + ParseLine(*liter, &key, 0, 0); + if (!key.empty()) + keys.push_back(key); + } + return true; } +// Return a list of all lines in a section +bool IniFile::GetLines(const char* sectionName, std::vector& lines, const bool remove_comments) const +{ + const Section* section = GetSection(sectionName); + if (!section) + return false; + + lines.clear(); + for (std::vector::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter) + { + std::string line = StripSpaces(*iter); + + if (remove_comments) + { + int commentPos = (int)line.find('#'); + if (commentPos == 0) + { + continue; + } + + if (commentPos != (int)std::string::npos) + { + line = StripSpaces(line.substr(0, commentPos)); + } + } + + lines.push_back(line); + } + + return true; +} + + void IniFile::SortSections() { std::sort(sections.begin(), sections.end()); @@ -502,7 +556,7 @@ void IniFile::SortSections() bool IniFile::Load(const Path &path) { sections.clear(); - sections.push_back(std::unique_ptr
(new Section(""))); + sections.push_back(Section("")); // first section consists of the comments before the first real section // Open file @@ -558,18 +612,16 @@ bool IniFile::Load(std::istream &in) { if (sectionNameEnd != std::string::npos) { // New section! std::string sub = line.substr(1, sectionNameEnd - 1); - sections.push_back(std::unique_ptr
(new Section(sub))); + sections.push_back(Section(sub)); if (sectionNameEnd + 1 < line.size()) { - sections.back()->comment = line.substr(sectionNameEnd + 1); + sections[sections.size() - 1].comment = line.substr(sectionNameEnd + 1); } } else { if (sections.empty()) { - sections.push_back(std::unique_ptr
(new Section(""))); + sections.push_back(Section("")); } - ParsedIniLine parsedLine; - parsedLine.ParseFrom(line); - sections.back()->lines_.push_back(parsedLine); + sections[sections.size() - 1].lines.push_back(line); } } } @@ -589,14 +641,13 @@ bool IniFile::Save(const Path &filename) // TODO: Do we still need this? It's annoying. fprintf(file, "\xEF\xBB\xBF"); - for (const auto §ion : sections) { - if (!section->name().empty() && (!section->lines_.empty() || !section->comment.empty())) { - fprintf(file, "[%s]%s\n", section->name().c_str(), section->comment.c_str()); + for (const Section §ion : sections) { + if (!section.name().empty() && (!section.lines.empty() || !section.comment.empty())) { + fprintf(file, "[%s]%s\n", section.name().c_str(), section.comment.c_str()); } - for (const auto &line : section->lines_) { - std::string buffer; - line.Reconstruct(&buffer); - fprintf(file, "%s\n", buffer.c_str()); + + for (const std::string &s : section.lines) { + fprintf(file, "%s\n", s.c_str()); } } diff --git a/Common/Data/Format/IniFile.h b/Common/Data/Format/IniFile.h index 1103721ca..cbe73f185 100644 --- a/Common/Data/Format/IniFile.h +++ b/Common/Data/Format/IniFile.h @@ -5,10 +5,8 @@ #pragma once #include -#include #include #include -#include #include #include @@ -16,39 +14,6 @@ class VFSInterface; -class ParsedIniLine { -public: - ParsedIniLine() {} - ParsedIniLine(std::string_view key, std::string_view value) { - this->key = key; - this->value = value; - } - ParsedIniLine(std::string_view key, std::string_view value, std::string_view comment) { - this->key = key; - this->value = value; - this->comment = comment; - } - static ParsedIniLine CommentOnly(std::string_view comment) { - return ParsedIniLine(std::string_view(), std::string_view(), comment); - } - - // Comments only come from "ParseFrom". - void ParseFrom(std::string_view line); - void Reconstruct(std::string *output) const; - - // Having these as views allows a more efficient internal representation, like one joint string. - std::string_view Key() const { return key; } - std::string_view Value() const { return value; } - std::string_view Comment() const { return comment; } - - void SetValue(std::string_view newValue) { value = newValue; } - -private: - std::string key; - std::string value; - std::string comment; -}; - class Section { friend class IniFile; @@ -63,8 +28,8 @@ public: std::map ToMap() const; - ParsedIniLine *GetLine(const char *key); - const ParsedIniLine *GetLine(const char *key) const; + std::string *GetLine(const char* key, std::string* valueOut, std::string* commentOut); + const std::string *GetLine(const char* key, std::string* valueOut, std::string* commentOut) const; void Set(const char* key, const char* newValue); void Set(const char* key, const std::string& newValue, const std::string& defaultValue); @@ -105,9 +70,6 @@ public: bool Get(const char* key, double* value, double defaultValue = false) const; bool Get(const char* key, std::vector& values) const; - // Return a list of all keys in this section - bool GetKeys(std::vector &keys) const; - bool operator < (const Section& other) const { return name_ < other.name_; } @@ -117,7 +79,7 @@ public: } protected: - std::vector lines_; + std::vector lines; std::string name_; std::string comment; }; @@ -125,10 +87,12 @@ protected: class IniFile { public: bool Load(const Path &path); + bool Load(const std::string &filename) { return Load(Path(filename)); } bool Load(std::istream &istream); bool LoadFromVFS(VFSInterface &vfs, const std::string &filename); bool Save(const Path &path); + bool Save(const std::string &filename) { return Save(Path(filename)); } // Returns true if key exists in section bool Exists(const char* sectionName, const char* key) const; @@ -173,19 +137,21 @@ public: bool GetKeys(const char* sectionName, std::vector& keys) const; + void SetLines(const char* sectionName, const std::vector &lines); + bool GetLines(const char* sectionName, std::vector& lines, const bool remove_comments = true) const; + bool DeleteKey(const char* sectionName, const char* key); bool DeleteSection(const char* sectionName); void SortSections(); - - std::vector> &Sections() { return sections; } + std::vector
&Sections() { return sections; } bool HasSection(const char *section) { return GetSection(section) != 0; } Section* GetOrCreateSection(const char* section); private: - std::vector> sections; + std::vector
sections; const Section* GetSection(const char* section) const; Section* GetSection(const char* section); diff --git a/Common/Data/Format/JSONReader.h b/Common/Data/Format/JSONReader.h index 0f5804eca..792d6a669 100644 --- a/Common/Data/Format/JSONReader.h +++ b/Common/Data/Format/JSONReader.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/Common/Data/Format/JSONWriter.h b/Common/Data/Format/JSONWriter.h index 0938c4e80..d82b7151c 100644 --- a/Common/Data/Format/JSONWriter.h +++ b/Common/Data/Format/JSONWriter.h @@ -9,8 +9,6 @@ // // Zero dependencies apart from stdlib (if you remove the vhjson usage.) -#pragma once - #include #include #include diff --git a/Common/Data/Text/I18n.cpp b/Common/Data/Text/I18n.cpp index 63b01a904..a4d894abd 100644 --- a/Common/Data/Text/I18n.cpp +++ b/Common/Data/Text/I18n.cpp @@ -40,8 +40,6 @@ static const char * const g_categoryNames[(size_t)I18NCat::CATEGORY_COUNT] = { "UI Elements", "Upgrade", "VR", - "Achievements", - "PSPSettings", }; I18NRepo g_i18nrepo; @@ -140,13 +138,13 @@ bool I18NRepo::LoadIni(const std::string &languageID, const Path &overridePath) Clear(); - const std::vector> §ions = ini.Sections(); + const std::vector
§ions = ini.Sections(); std::lock_guard guard(catsLock_); for (auto §ion : sections) { for (size_t i = 0; i < (size_t)I18NCat::CATEGORY_COUNT; i++) { - if (!strcmp(section->name().c_str(), g_categoryNames[i])) { - cats_[i].reset(new I18NCategory(*section.get())); + if (!strcmp(section.name().c_str(), g_categoryNames[i])) { + cats_[i].reset(new I18NCategory(section)); } } } diff --git a/Common/Data/Text/I18n.h b/Common/Data/Text/I18n.h index 65baa2aec..0756490f2 100644 --- a/Common/Data/Text/I18n.h +++ b/Common/Data/Text/I18n.h @@ -56,8 +56,6 @@ enum class I18NCat : uint8_t { UI_ELEMENTS, UPGRADE, VR, - ACHIEVEMENTS, - PSPSETTINGS, CATEGORY_COUNT, NONE = CATEGORY_COUNT, }; @@ -116,9 +114,8 @@ public: std::string LanguageID(); std::shared_ptr GetCategory(I18NCat category); + std::shared_ptr GetCategoryByName(const char *name); - // Translate the string, by looking up "key" in the file, and falling back to either def or key, in that order, if the lookup fails. - // def can (and usually is) set to nullptr. const char *T(I18NCat category, const char *key, const char *def = nullptr) { if (category == I18NCat::NONE) return def ? def : key; diff --git a/Common/Data/Text/Parsers.cpp b/Common/Data/Text/Parsers.cpp index 438742ffd..03470f8f0 100644 --- a/Common/Data/Text/Parsers.cpp +++ b/Common/Data/Text/Parsers.cpp @@ -19,7 +19,7 @@ void NiceSizeFormat(uint64_t size, char *out, size_t bufSize) { if (s == 0) snprintf(out, bufSize, "%d B", (int)size); else - snprintf(out, bufSize, "%3.2f %s", f, sizes[s]); + snprintf(out, bufSize, "%3.1f %s", f, sizes[s]); } std::string NiceSizeFormat(uint64_t size) { diff --git a/Common/Data/Text/WrapText.cpp b/Common/Data/Text/WrapText.cpp index 65989e7c0..8d661d285 100644 --- a/Common/Data/Text/WrapText.cpp +++ b/Common/Data/Text/WrapText.cpp @@ -177,18 +177,20 @@ void WordWrapper::AppendWord(int endIndex, int lastChar, bool addNewline) { } void WordWrapper::Wrap() { + out_.clear(); + // First, let's check if it fits as-is. size_t len = strlen(str_); + + // We know it'll be approximately this size. It's fine if the guess is a little off. + out_.reserve(len + len / 16); + if (MeasureWidth(str_, len) <= maxW_) { // If it fits, we don't need to go through each character. out_ = str_; return; } - out_.clear(); - // We know it'll be approximately this size. It's fine if the guess is a little off. - out_.reserve(len + len / 16); - if (flags_ & FLAG_ELLIPSIZE_TEXT) { ellipsisWidth_ = MeasureWidth("...", 3); } diff --git a/Common/FakeCPUDetect.cpp b/Common/FakeCPUDetect.cpp index af0ecb9ef..e04ed356e 100644 --- a/Common/FakeCPUDetect.cpp +++ b/Common/FakeCPUDetect.cpp @@ -18,14 +18,12 @@ #include "ppsspp_config.h" #if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) #define REAL_CPUDETECT_AVAIL 1 -#elif (PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)) && !defined(__EMSCRIPTEN__) +#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #define REAL_CPUDETECT_AVAIL 1 #elif PPSSPP_ARCH(MIPS) || PPSSPP_ARCH(MIPS64) #define REAL_CPUDETECT_AVAIL 1 #elif PPSSPP_ARCH(RISCV64) #define REAL_CPUDETECT_AVAIL 1 -#elif PPSSPP_ARCH(LOONGARCH64) -#define REAL_CPUDETECT_AVAIL 1 #endif #ifndef REAL_CPUDETECT_AVAIL diff --git a/Common/File/AndroidContentURI.cpp b/Common/File/AndroidContentURI.cpp index 5c5a72221..6456b8cad 100644 --- a/Common/File/AndroidContentURI.cpp +++ b/Common/File/AndroidContentURI.cpp @@ -1,14 +1,14 @@ #include "Common/File/AndroidContentURI.h" -bool AndroidContentURI::Parse(std::string_view path) { +bool AndroidContentURI::Parse(const std::string &path) { const char *prefix = "content://"; if (!startsWith(path, prefix)) { return false; } - std::string_view components = path.substr(strlen(prefix)); + std::string components = path.substr(strlen(prefix)); - std::vector parts; + std::vector parts; SplitString(components, '/', parts); if (parts.size() == 3) { // Single file URI. @@ -60,7 +60,7 @@ AndroidContentURI AndroidContentURI::WithRootFilePath(const std::string &filePat return uri; } -AndroidContentURI AndroidContentURI::WithComponent(std::string_view filePath) { +AndroidContentURI AndroidContentURI::WithComponent(const std::string &filePath) { AndroidContentURI uri = *this; if (uri.file.empty()) { // Not sure what to do. @@ -68,17 +68,16 @@ AndroidContentURI AndroidContentURI::WithComponent(std::string_view filePath) { } if (uri.file.back() == ':') { // Special case handling for Document URIs: Treat the ':' as a directory separator too (but preserved in the filename). - uri.file.append(filePath); + uri.file = uri.file + filePath; } else { - uri.file.push_back('/'); - uri.file.append(filePath); + uri.file = uri.file + "/" + filePath; } return uri; } -AndroidContentURI AndroidContentURI::WithExtraExtension(std::string_view extension) { +AndroidContentURI AndroidContentURI::WithExtraExtension(const std::string &extension) { AndroidContentURI uri = *this; - uri.file.append(extension); + uri.file = uri.file + extension; return uri; } diff --git a/Common/File/AndroidContentURI.h b/Common/File/AndroidContentURI.h index 7015e0a20..23ce2a9e0 100644 --- a/Common/File/AndroidContentURI.h +++ b/Common/File/AndroidContentURI.h @@ -23,15 +23,15 @@ private: std::string file; public: AndroidContentURI() {} - explicit AndroidContentURI(std::string_view path) { + explicit AndroidContentURI(const std::string &path) { Parse(path); } - bool Parse(std::string_view path); + bool Parse(const std::string &path); AndroidContentURI WithRootFilePath(const std::string &filePath); - AndroidContentURI WithComponent(std::string_view filePath); - AndroidContentURI WithExtraExtension(std::string_view extension); // The ext string contains the dot. + AndroidContentURI WithComponent(const std::string &filePath); + AndroidContentURI WithExtraExtension(const std::string &extension); AndroidContentURI WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const; AndroidContentURI WithReplacedExtension(const std::string &newExtension) const; diff --git a/Common/File/AndroidStorage.cpp b/Common/File/AndroidStorage.cpp index efb8a3360..c4ddcc73c 100644 --- a/Common/File/AndroidStorage.cpp +++ b/Common/File/AndroidStorage.cpp @@ -61,16 +61,16 @@ void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj) { _dbg_assert_(computeRecursiveDirectorySize); } -bool Android_IsContentUri(std::string_view filename) { +bool Android_IsContentUri(const std::string &filename) { return startsWith(filename, "content://"); } -int Android_OpenContentUriFd(std::string_view filename, Android_OpenContentUriMode mode) { +int Android_OpenContentUriFd(const std::string &filename, Android_OpenContentUriMode mode) { if (!g_nativeActivity) { return -1; } - std::string fname(filename); + std::string fname = filename; // PPSSPP adds an ending slash to directories before looking them up. // TODO: Fix that in the caller (or don't call this for directories). if (fname.back() == '/') diff --git a/Common/File/AndroidStorage.h b/Common/File/AndroidStorage.h index b50625e42..1b4585f77 100644 --- a/Common/File/AndroidStorage.h +++ b/Common/File/AndroidStorage.h @@ -2,7 +2,6 @@ #include #include -#include #include "Common/File/DirListing.h" @@ -40,8 +39,8 @@ extern std::string g_externalDir; void Android_StorageSetNativeActivity(jobject nativeActivity); -bool Android_IsContentUri(std::string_view uri); -int Android_OpenContentUriFd(std::string_view uri, const Android_OpenContentUriMode mode); +bool Android_IsContentUri(const std::string &uri); +int Android_OpenContentUriFd(const std::string &uri, const Android_OpenContentUriMode mode); StorageError Android_CreateDirectory(const std::string &parentTreeUri, const std::string &dirName); StorageError Android_CreateFile(const std::string &parentTreeUri, const std::string &fileName); StorageError Android_MoveFile(const std::string &fileUri, const std::string &srcParentUri, const std::string &destParentUri); @@ -64,8 +63,8 @@ void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj); // Stub out the Android Storage wrappers, so that we can avoid ifdefs everywhere. -inline bool Android_IsContentUri(std::string_view uri) { return false; } -inline int Android_OpenContentUriFd(std::string_view uri, const Android_OpenContentUriMode mode) { return -1; } +inline bool Android_IsContentUri(const std::string &uri) { return false; } +inline int Android_OpenContentUriFd(const std::string &uri, const Android_OpenContentUriMode mode) { return -1; } inline StorageError Android_CreateDirectory(const std::string &parentTreeUri, const std::string &dirName) { return StorageError::UNKNOWN; } inline StorageError Android_CreateFile(const std::string &parentTreeUri, const std::string &fileName) { return StorageError::UNKNOWN; } inline StorageError Android_MoveFile(const std::string &fileUri, const std::string &srcParentUri, const std::string &destParentUri) { return StorageError::UNKNOWN; } diff --git a/Common/File/DirListing.cpp b/Common/File/DirListing.cpp index 0ee76098a..b793e8505 100644 --- a/Common/File/DirListing.cpp +++ b/Common/File/DirListing.cpp @@ -6,7 +6,6 @@ #include #if PPSSPP_PLATFORM(UWP) #include -#include #endif #else #include @@ -184,7 +183,7 @@ bool GetFilesInDir(const Path &directory, std::vector *files, const ch std::string tmp; while (*filter) { if (*filter == ':') { - filters.insert(tmp); + filters.insert(std::move(tmp)); tmp.clear(); } else { tmp.push_back(*filter); @@ -192,7 +191,7 @@ bool GetFilesInDir(const Path &directory, std::vector *files, const ch filter++; } if (!tmp.empty()) - filters.insert(tmp); + filters.insert(std::move(tmp)); } #if PPSSPP_PLATFORM(WINDOWS) @@ -221,13 +220,6 @@ bool GetFilesInDir(const Path &directory, std::vector *files, const ch HANDLE hFind = FindFirstFileEx((directory.ToWString() + L"\\*").c_str(), FindExInfoStandard, &ffd, FindExSearchNameMatch, NULL, 0); #endif if (hFind == INVALID_HANDLE_VALUE) { -#if PPSSPP_PLATFORM(UWP) - // This step just to avoid empty results by adding fake folders - // it will help also to navigate back between selected folder - // we must ignore this function for any request other than UI navigation - if (GetFakeFolders(directory, files, filter, filters)) - return true; -#endif return false; } do { diff --git a/Common/File/DiskFree.cpp b/Common/File/DiskFree.cpp index 35a0947df..34a5ba520 100644 --- a/Common/File/DiskFree.cpp +++ b/Common/File/DiskFree.cpp @@ -23,19 +23,9 @@ #include "Common/File/AndroidStorage.h" #include "Common/Data/Encoding/Utf8.h" -#if PPSSPP_PLATFORM(UWP) -#include "UWP/UWPHelpers/StorageManager.h" -#endif - bool free_disk_space(const Path &path, int64_t &space) { #ifdef _WIN32 ULARGE_INTEGER free; -#if PPSSPP_PLATFORM(UWP) - if (GetDriveFreeSpace(path, space)) { - return true; - } - else -#endif if (GetDiskFreeSpaceExW(path.ToWString().c_str(), &free, nullptr, nullptr)) { space = free.QuadPart; return true; diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index d41e49f68..41a338f77 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -54,7 +54,6 @@ #include // getcwd #if PPSSPP_PLATFORM(UWP) #include -#include "UWP/UWPHelpers/StorageManager.h" #endif #else #include @@ -137,20 +136,14 @@ FILE *OpenCFile(const Path &path, const char *mode) { } // TODO: Support append modes and stuff... For now let's go with the most common one. - Android_OpenContentUriMode openMode = Android_OpenContentUriMode::READ_WRITE_TRUNCATE; - const char *fmode = "wb"; - if (!strcmp(mode, "at") || !strcmp(mode, "a")) { - openMode = Android_OpenContentUriMode::READ_WRITE; - fmode = "ab"; - } - int descriptor = Android_OpenContentUriFd(path.ToString(), openMode); + int descriptor = Android_OpenContentUriFd(path.ToString(), Android_OpenContentUriMode::READ_WRITE_TRUNCATE); if (descriptor < 0) { INFO_LOG(COMMON, "Opening '%s' for write failed", path.ToString().c_str()); return nullptr; } - FILE *f = fdopen(descriptor, fmode); + FILE *f = fdopen(descriptor, "wb"); if (f && (!strcmp(mode, "at") || !strcmp(mode, "a"))) { - // Append mode - not sure we got a "true" append mode, so seek to the end. + // Append mode. fseek(f, 0, SEEK_END); } return f; @@ -165,18 +158,7 @@ FILE *OpenCFile(const Path &path, const char *mode) { } #if defined(_WIN32) && defined(UNICODE) -#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__) - // We shouldn't use _wfopen here, - // this function is not allowed to read outside Local and Installation folders - // FileSystem (broadFileSystemAccess) doesn't apply on _wfopen - // if we have custom memory stick location _wfopen will return null - // 'GetFileStreamFromApp' will convert 'mode' to [access, share, creationDisposition] - // then it will call 'CreateFile2FromAppW' -> convert HANDLE to FILE* - FILE* file = GetFileStreamFromApp(path.ToString(), mode); - return file; -#else return _wfopen(path.ToWString().c_str(), ConvertUTF8ToWString(mode).c_str()); -#endif #else return fopen(path.c_str(), mode); #endif @@ -592,7 +574,7 @@ bool CreateFullPath(const Path &path) { return false; } - std::vector parts; + std::vector parts; SplitString(diff, '/', parts); // Probably not necessary sanity check, ported from the old code. @@ -602,7 +584,7 @@ bool CreateFullPath(const Path &path) { } Path curPath = root; - for (auto part : parts) { + for (auto &part : parts) { curPath /= part; if (!File::Exists(curPath)) { File::CreateDir(curPath); @@ -677,15 +659,10 @@ bool Rename(const Path &srcFilename, const Path &destFilename) { INFO_LOG(COMMON, "Rename: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #if defined(_WIN32) && defined(UNICODE) -#if PPSSPP_PLATFORM(UWP) - if (MoveFileFromAppW(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str())) - return true; -#else std::wstring srcw = srcFilename.ToWString(); std::wstring destw = destFilename.ToWString(); if (_wrename(srcw.c_str(), destw.c_str()) == 0) return true; -#endif #else if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) return true; @@ -969,7 +946,7 @@ bool OpenFileInEditor(const Path &fileName) { #if PPSSPP_PLATFORM(WINDOWS) #if PPSSPP_PLATFORM(UWP) - OpenFile(fileName.ToString()); + // Do nothing. #else ShellExecuteW(nullptr, L"open", fileName.ToWString().c_str(), nullptr, nullptr, SW_SHOW); #endif @@ -1181,7 +1158,6 @@ uint8_t *ReadLocalFile(const Path &filename, size_t *size) { return nullptr; } fseek(file, 0, SEEK_SET); - // NOTE: If you find ~10 memory leaks from here, with very varying sizes, it might be the VFPU LUTs. uint8_t *contents = new uint8_t[f_size + 1]; if (fread(contents, 1, f_size, file) != f_size) { delete[] contents; diff --git a/Common/File/Path.cpp b/Common/File/Path.cpp index a3d773f74..b80a5e7ca 100644 --- a/Common/File/Path.cpp +++ b/Common/File/Path.cpp @@ -12,17 +12,13 @@ #include "android/jni/app-android.h" -#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__) -#include "UWP/UWPHelpers/StorageManager.h" -#endif - #if HOST_IS_CASE_SENSITIVE #include #include #include #endif -Path::Path(std::string_view str) { +Path::Path(const std::string &str) { Init(str); } @@ -33,7 +29,7 @@ Path::Path(const std::wstring &str) { } #endif -void Path::Init(std::string_view str) { +void Path::Init(const std::string &str) { if (str.empty()) { type_ = PathType::UNDEFINED; path_.clear(); @@ -81,7 +77,7 @@ void Path::Init(std::string_view str) { // We always use forward slashes internally, we convert to backslash only when // converted to a wstring. -Path Path::operator /(std::string_view subdir) const { +Path Path::operator /(const std::string &subdir) const { if (type_ == PathType::CONTENT_URI) { AndroidContentURI uri(path_); return Path(uri.WithComponent(subdir).ToString()); @@ -104,18 +100,18 @@ Path Path::operator /(std::string_view subdir) const { return Path(fullPath); } -void Path::operator /=(std::string_view subdir) { +void Path::operator /=(const std::string &subdir) { *this = *this / subdir; } -Path Path::WithExtraExtension(std::string_view ext) const { +Path Path::WithExtraExtension(const std::string &ext) const { if (type_ == PathType::CONTENT_URI) { AndroidContentURI uri(path_); return Path(uri.WithExtraExtension(ext).ToString()); } _dbg_assert_(!ext.empty() && ext[0] == '.'); - return Path(path_ + std::string(ext)); + return Path(path_ + ext); } Path Path::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const { @@ -161,7 +157,7 @@ std::string Path::GetFilename() const { return path_; } -std::string GetExtFromString(std::string_view str) { +std::string GetExtFromString(const std::string &str) { size_t pos = str.rfind("."); if (pos == std::string::npos) { return ""; @@ -171,7 +167,7 @@ std::string GetExtFromString(std::string_view str) { // Don't want to detect "df/file" from "/as.df/file" return ""; } - std::string ext(str.substr(pos)); + std::string ext = str.substr(pos); for (size_t i = 0; i < ext.size(); i++) { ext[i] = tolower(ext[i]); } @@ -262,15 +258,6 @@ std::wstring Path::ToWString() const { } return w; } -std::string Path::ToCString() const { - std::string w = path_; - for (size_t i = 0; i < w.size(); i++) { - if (w[i] == '/') { - w[i] = '\\'; - } - } - return w; -} #endif std::string Path::ToVisualString(const char *relativeRoot) const { @@ -278,9 +265,6 @@ std::string Path::ToVisualString(const char *relativeRoot) const { return AndroidContentURI(path_).ToVisualString(); #if PPSSPP_PLATFORM(WINDOWS) } else if (type_ == PathType::NATIVE) { -#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__) - return GetPreviewPath(path_); -#else // It can be useful to show the path as relative to the memstick if (relativeRoot) { std::string root = ReplaceAll(relativeRoot, "/", "\\"); @@ -293,7 +277,6 @@ std::string Path::ToVisualString(const char *relativeRoot) const { } else { return ReplaceAll(path_, "/", "\\"); } -#endif #else if (relativeRoot) { std::string root = relativeRoot; diff --git a/Common/File/Path.h b/Common/File/Path.h index 0be3e0aab..3e09c0c3c 100644 --- a/Common/File/Path.h +++ b/Common/File/Path.h @@ -3,7 +3,6 @@ #include "ppsspp_config.h" #include -#include #if defined(__APPLE__) @@ -37,11 +36,11 @@ enum class PathType { class Path { private: - void Init(std::string_view str); + void Init(const std::string &str); public: Path() : type_(PathType::UNDEFINED) {} - explicit Path(std::string_view str); + explicit Path(const std::string &str); #if PPSSPP_PLATFORM(WINDOWS) explicit Path(const std::wstring &str); @@ -72,13 +71,13 @@ public: bool IsAbsolute() const; // Returns a path extended with a subdirectory. - Path operator /(std::string_view subdir) const; + Path operator /(const std::string &subdir) const; // Navigates down into a subdir. - void operator /=(std::string_view subdir); + void operator /=(const std::string &subdir); // File extension manipulation. - Path WithExtraExtension(std::string_view ext) const; + Path WithExtraExtension(const std::string &ext) const; Path WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const; Path WithReplacedExtension(const std::string &newExtension) const; @@ -91,11 +90,6 @@ public: #if PPSSPP_PLATFORM(WINDOWS) std::wstring ToWString() const; - std::string ToCString() const; // Flips the slashes back to Windows standard, but string still UTF-8. -#else - std::string ToCString() const { - return ToString(); - } #endif // Pass in a relative root to turn the path into a relative path - if it is one! @@ -140,7 +134,7 @@ private: }; // Utility function for parsing out file extensions. -std::string GetExtFromString(std::string_view str); +std::string GetExtFromString(const std::string &str); // Utility function for fixing the case of paths. Only present on Unix-like systems. diff --git a/Common/File/PathBrowser.cpp b/Common/File/PathBrowser.cpp index 6091b73ef..36e03dca5 100644 --- a/Common/File/PathBrowser.cpp +++ b/Common/File/PathBrowser.cpp @@ -38,7 +38,7 @@ bool LoadRemoteFileList(const Path &url, const std::string &userAgent, bool *can http::RequestParams req(baseURL.Resource(), "text/plain, text/html; q=0.9, */*; q=0.8"); if (http.Resolve(baseURL.Host().c_str(), baseURL.Port())) { if (http.Connect(2, 20.0, cancel)) { - net::RequestProgress progress(cancel); + http::RequestProgress progress(cancel); code = http.GET(req, &result, responseHeaders, &progress); http.Disconnect(); } @@ -78,7 +78,7 @@ bool LoadRemoteFileList(const Path &url, const std::string &userAgent, bool *can return false; } - for (auto &item : items) { + for (std::string item : items) { // Apply some workarounds. if (item.empty()) continue; @@ -210,7 +210,7 @@ std::string PathBrowser::GetFriendlyPath() const { bool PathBrowser::GetListing(std::vector &fileInfo, const char *filter, bool *cancel) { std::unique_lock guard(pendingLock_); while (!IsListingReady() && (!cancel || !*cancel)) { - // In case cancel changes, just sleep. TODO: Replace with condition variable. + // In case cancel changes, just sleep. guard.unlock(); sleep_ms(50); guard.lock(); @@ -221,6 +221,14 @@ bool PathBrowser::GetListing(std::vector &fileInfo, const char * } bool PathBrowser::CanNavigateUp() { +/* Leaving this commented out, not sure if there's a use in UWP for navigating up from the user data folder. +#if PPSSPP_PLATFORM(UWP) + // Can't navigate up from memstick folder :( + if (path_ == GetSysDirectory(DIRECTORY_MEMSTICK_ROOT)) { + return false; + } +#endif +*/ return path_.CanNavigateUp(); } diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index 041616c14..260a6b007 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -4,7 +4,6 @@ #include "Common/File/VFS/VFS.h" #include "Common/File/FileUtil.h" #include "Common/File/AndroidStorage.h" -#include "Common/StringUtils.h" VFS g_VFS; @@ -28,7 +27,7 @@ void VFS::Clear() { static bool IsLocalAbsolutePath(const char *path) { bool isUnixLocal = path[0] == '/'; #ifdef _WIN32 - bool isWindowsLocal = (isalpha(path[0]) && path[1] == ':') || startsWith(path, "\\\\") || startsWith(path, "//"); + bool isWindowsLocal = isalpha(path[0]) && path[1] == ':'; #else bool isWindowsLocal = false; #endif diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index fbee2f8ba..c934a6e3d 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -272,7 +272,6 @@ VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference, size zip_stat_t zstat; if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0) { lock_.unlock(); - delete openFile; return nullptr; } diff --git a/Common/GL/GLInterface/EGL.cpp b/Common/GL/GLInterface/EGL.cpp new file mode 100644 index 000000000..5f3c782f2 --- /dev/null +++ b/Common/GL/GLInterface/EGL.cpp @@ -0,0 +1,402 @@ +// Copyright 2012 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "Common/Log.h" +#include "Common/GL/GLInterface/EGL.h" + +// Show the current FPS +void cInterfaceEGL::Swap() { + eglSwapBuffers(egl_dpy, egl_surf); +} + +void cInterfaceEGL::SwapInterval(int Interval) { + eglSwapInterval(egl_dpy, Interval); +} + +void* cInterfaceEGL::GetFuncAddress(const std::string& name) { + return (void*)eglGetProcAddress(name.c_str()); +} + +void cInterfaceEGL::DetectMode() { + EGLint num_configs; + bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false; + static const int renderable_types[3] = { + EGL_OPENGL_BIT, + (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */ + EGL_OPENGL_ES2_BIT, + }; + + static const char *renderable_names[3] = { + "OpenGL", "OpenGL ES 3", "OpenGL ES 2" + }; + + for (int i = 0; i < 3; i++) { + int renderable_type = renderable_types[i]; + const char *renderable_name = renderable_names[i]; + // attributes for a visual in RGBA format with at least + // 8 bits per color + int attribs[] = { + EGL_RENDERABLE_TYPE, renderable_type, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_TRANSPARENT_TYPE, EGL_NONE, + EGL_SAMPLES, 0, + EGL_NONE + }; + + // Get how many configs there are + if (!eglChooseConfig( egl_dpy, attribs, nullptr, 0, &num_configs)) { + EGL_ILOG("DetectMode: couldn't get an EGL visual config with renderable_type=%s", renderable_name); + continue; + } + EGL_ILOG("DetectMode: got an EGL visual config with renderable_type=%s", renderable_name); + + EGLConfig* config = new EGLConfig[num_configs]; + + // Get all the configurations + if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs)) { + EGL_ILOG("DetectMode: couldn't choose an EGL visual config\n"); + delete[] config; + continue; + } + + for (int i = 0; i < num_configs; ++i) { + EGLint attribVal; + bool ret; + ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal); + if (ret) { + if ((attribVal & EGL_OPENGL_BIT) && s_opengl_mode != GLInterfaceMode::MODE_DETECT_ES) + supportsGL = true; + if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */ + supportsGLES3 = true; // Apparently, this cannot be completely trusted so we implement a fallback to ES 2.0 below. + if (attribVal & EGL_OPENGL_ES2_BIT) + supportsGLES2 = true; + } + } + delete[] config; + } + + if (supportsGL) + s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + else if (supportsGLES3) + s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; + else if (supportsGLES2) + s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; + + if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode + s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL +} + +static void LogEGLConfig(EGLDisplay egl_dpy, EGLConfig config) { + EGLint red = 0, green = 0, blue = 0, alpha = 0, depth = 0, stencil = 0, format = -1, type; + + struct { + EGLint value; + const char *name; + } vals[] = { + { EGL_RED_SIZE, "EGL_RED_SIZE" }, + { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" }, + { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" }, + { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" }, + { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" }, + { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" }, + { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" }, + { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" }, + { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" }, + { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" }, + { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" }, + { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" }, + { EGL_COLOR_BUFFER_TYPE, "EGL_COLOR_BUFFER_TYPE" }, + { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" }, + { EGL_CONFIG_ID, "EGL_CONFIG_ID" }, + { EGL_SAMPLES, "EGL_SAMPLES" }, + }; + + for (int i = 0; i < (int)(sizeof(vals)/sizeof(vals[0])); i++) { + EGLint value; + eglGetConfigAttrib(egl_dpy, config, vals[i].value, &value); + EGL_ILOG(" %s = %d", vals[i].name, value); + } +} + +const char *cInterfaceEGL::EGLGetErrorString(EGLint error) { + switch (error) { + case EGL_SUCCESS: return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; + case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; + default: + return "(UNKNOWN)"; + } +} + +bool cInterfaceEGL::ChooseAndCreate(void *window_handle, bool core, bool use565) { + int attribs32[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Keep this first! + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + EGL_TRANSPARENT_TYPE, EGL_NONE, + EGL_NONE, 0 + }; + int attribs16[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Keep this first! + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + EGL_TRANSPARENT_TYPE, EGL_NONE, + EGL_NONE, 0 + }; + int attribsFallback32[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Keep this first! + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_NONE, 0 + }; + int attribsFallback16[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Keep this first! + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 16, + EGL_NONE, 0 + }; + + int *attribs = attribs32; + int *attribsFallback = attribsFallback32; + if (use565) { + attribs = attribs16; + attribsFallback = attribsFallback16; + } + + EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE, 0, + EGL_NONE, 0, + EGL_NONE, 0, + EGL_NONE, 0, + }; + + switch (s_opengl_mode) { + case MODE_OPENGL: + EGL_ILOG("Setting RENDERABLE_TYPE to EGL_OPENGL_BIT"); + attribs[1] = EGL_OPENGL_BIT; + // 1 will be major version, and 3 the minor version. + ctx_attribs[2] = 0x30FB; /* EGL_CONTEXT_MINOR_VERSION_KHR */ + // Let's always use a core profile here. + ctx_attribs[4] = 0x30FD; /* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR */ + ctx_attribs[5] = 1; /* EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR */ + break; + case MODE_OPENGLES2: + EGL_ILOG("Setting RENDERABLE_TYPE to EGL_OPENGL_ES2_BIT"); + attribs[1] = EGL_OPENGL_ES2_BIT; + ctx_attribs[1] = 2; + break; + case MODE_OPENGLES3: + EGL_ILOG("Setting RENDERABLE_TYPE to EGL_OPENGL_ES3_BIT_KHR"); + attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */ + ctx_attribs[1] = 3; + break; + default: + EGL_ELOG("Unknown OpenGL mode set\n"); + return false; + break; + } + + EGL_ILOG("Calling eglChooseConfig to get number of configs (use16bit=%d)...", (int)use565); + + EGLConfig *configs; + EGLint num_configs = 0; + if (!eglChooseConfig(egl_dpy, attribs, NULL, 0, &num_configs) || num_configs == 0) { + EGL_ILOG("Error: couldn't get a number of configs. Trying with fallback config (no stencil, not specifying transparent:none)\n"); + attribsFallback[1] = attribs[1]; + attribs = attribsFallback; + if (!eglChooseConfig(egl_dpy, attribs, NULL, 0, &num_configs) || num_configs == 0) { + eglTerminate(egl_dpy); + return false; + } + } + + EGL_ILOG("Got %d configs. Now choosing...", num_configs); + configs = new EGLConfig[num_configs]; + + if (!eglChooseConfig(egl_dpy, attribs, configs, num_configs, &num_configs)) { + EGL_ELOG("Error: couldn't get an EGL visual config (num_configs=%d)! Terminating EGL.\n", num_configs); + eglTerminate(egl_dpy); + return false; + } + + int chosenConfig = -1; + // Find our ideal config in the list. If it's there, use it, otherwise pick whatever the device wanted (#0) + int wantedAlpha = 8; + // Requiring alpha seems to be a problem on older devices. Let's see if this helps... + if (attribs[1] == EGL_OPENGL_ES2_BIT) + wantedAlpha = 0; + for (int i = 0; i < num_configs; i++) { + EGL_ILOG("Config %d:", i); + LogEGLConfig(egl_dpy, configs[i]); + int red, green, blue, alpha, depth, stencil; + eglGetConfigAttrib(egl_dpy, configs[i], EGL_RED_SIZE, &red); + eglGetConfigAttrib(egl_dpy, configs[i], EGL_GREEN_SIZE, &green); + eglGetConfigAttrib(egl_dpy, configs[i], EGL_BLUE_SIZE, &blue); + eglGetConfigAttrib(egl_dpy, configs[i], EGL_ALPHA_SIZE, &alpha); + eglGetConfigAttrib(egl_dpy, configs[i], EGL_DEPTH_SIZE, &depth); + eglGetConfigAttrib(egl_dpy, configs[i], EGL_STENCIL_SIZE, &stencil); + if (chosenConfig == -1 && red == 8 && green == 8 && blue == 8 && alpha == wantedAlpha && depth == 24 && stencil == 8) { + chosenConfig = i; + } + } + if (chosenConfig == -1) + chosenConfig = 0; + + EGL_ILOG("eglChooseConfig successful: num_configs=%d, choosing config %d", num_configs, chosenConfig); + + if (s_opengl_mode == MODE_OPENGL) { + EGL_ILOG("eglBindAPI(OPENGL)"); + eglBindAPI(EGL_OPENGL_API); + } else { + EGL_ILOG("eglBindAPI(OPENGL_ES)"); + eglBindAPI(EGL_OPENGL_ES_API); + } + + EGLNativeWindowType host_window = (EGLNativeWindowType)window_handle; + EGLNativeWindowType native_window = InitializePlatform(host_window, configs[chosenConfig]); + + const char *s = eglQueryString(egl_dpy, EGL_VERSION); + EGL_ILOG("EGL_VERSION = %s\n", s); + + s = eglQueryString(egl_dpy, EGL_VENDOR); + EGL_ILOG("EGL_VENDOR = %s\n", s); + + s = eglQueryString(egl_dpy, EGL_EXTENSIONS); + EGL_ILOG("EGL_EXTENSIONS = %s\n", s); + + s = eglQueryString(egl_dpy, EGL_CLIENT_APIS); + EGL_ILOG("EGL_CLIENT_APIS = %s\n", s); + + + if (s_opengl_mode == MODE_OPENGL) { + EGL_ILOG("Finding a good GL version"); + egl_ctx = nullptr; + for (int minor = 6; minor >= 0 && !egl_ctx; --minor) { + ctx_attribs[1] = 4; + ctx_attribs[3] = minor; + egl_ctx = eglCreateContext(egl_dpy, configs[chosenConfig], EGL_NO_CONTEXT, ctx_attribs); + } + if (!egl_ctx) { + ctx_attribs[1] = 3; + ctx_attribs[3] = 3; + egl_ctx = eglCreateContext(egl_dpy, configs[chosenConfig], EGL_NO_CONTEXT, ctx_attribs); + } + } else { + egl_ctx = eglCreateContext(egl_dpy, configs[chosenConfig], EGL_NO_CONTEXT, ctx_attribs); + } + if (!egl_ctx) { + EGL_ILOG("Error: eglCreateContext failed: %s\n", EGLGetErrorString(eglGetError())); + delete[] configs; + return false; + } + EGL_ILOG("Successfully created EGL context.\n"); + + egl_surf = eglCreateWindowSurface(egl_dpy, configs[chosenConfig], native_window, nullptr); + if (!egl_surf) { + EGL_ILOG("Error: eglCreateWindowSurface failed: native_window=%p error=%s ctx_attribs[1]==%d\n", native_window, EGLGetErrorString(eglGetError()), ctx_attribs[1]); + eglDestroyContext(egl_dpy, egl_ctx); + delete[] configs; + return false; + } + EGL_ILOG("Successfully created EGL window surface (window=%p).\n", native_window); + + delete[] configs; + return true; +} + +// Create rendering window. +bool cInterfaceEGL::Create(void *window_handle, bool core, bool use565) { + EGLint egl_major, egl_minor; + + egl_dpy = OpenDisplay(); + + if (!egl_dpy) { + EGL_ILOG("Error: eglGetDisplay() failed\n"); + return false; + } + + if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) { + EGL_ILOG("Error: eglInitialize() failed\n"); + return false; + } + EGL_ILOG("eglInitialize() succeeded (use565=%d)\n", (int)use565); + + if (s_opengl_mode == MODE_DETECT || s_opengl_mode == MODE_DETECT_ES) + DetectMode(); + + if (!ChooseAndCreate(window_handle, core, use565) && (s_opengl_mode == MODE_OPENGLES3 || s_opengl_mode == MODE_OPENGL)) { + // Fallback to ES 2.0 and try again. + s_opengl_mode = MODE_OPENGLES2; + if (!ChooseAndCreate(window_handle, core, use565)) { + eglTerminate(egl_dpy); + egl_dpy = nullptr; + return false; + } + } + + return true; +} + +bool cInterfaceEGL::MakeCurrent() { + return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx); +} + +bool cInterfaceEGL::ClearCurrent() { + return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +void cInterfaceEGL::Shutdown() { + ShutdownPlatform(); + if (egl_ctx && !eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) { + NOTICE_LOG(G3D, "Could not release drawing context."); + } + if (egl_ctx) { + eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!eglDestroySurface(egl_dpy, egl_surf)) + NOTICE_LOG(G3D, "Could not destroy window surface."); + if (!eglDestroyContext(egl_dpy, egl_ctx)) + NOTICE_LOG(G3D, "Could not destroy drawing context."); + if (!eglTerminate(egl_dpy)) + NOTICE_LOG(G3D, "Could not destroy display connection."); + egl_ctx = nullptr; + egl_dpy = nullptr; + egl_surf = nullptr; + } +} diff --git a/Common/GL/GLInterface/EGL.h b/Common/GL/GLInterface/EGL.h new file mode 100644 index 000000000..e9d789748 --- /dev/null +++ b/Common/GL/GLInterface/EGL.h @@ -0,0 +1,42 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/Log.h" +#include "Common/GL/GLInterfaceBase.h" + +#define EGL_ILOG(...) INFO_LOG(G3D, __VA_ARGS__) +#define EGL_ELOG(...) INFO_LOG(G3D, __VA_ARGS__) + + +class cInterfaceEGL : public cInterfaceBase { +public: + void SwapInterval(int Interval) override; + void Swap() override; + void SetMode(u32 mode) override { s_opengl_mode = mode; } + void* GetFuncAddress(const std::string& name) override; + bool Create(void *window_handle, bool core, bool use565) override; + bool MakeCurrent() override; + bool ClearCurrent() override; + void Shutdown() override; + +protected: + EGLSurface egl_surf; + EGLContext egl_ctx; + EGLDisplay egl_dpy; + + virtual EGLDisplay OpenDisplay() = 0; + virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) = 0; + virtual void ShutdownPlatform() = 0; + virtual void SetInternalResolution(int internalWidth, int internalHeight) {} + const char *EGLGetErrorString(EGLint error); + +private: + bool ChooseAndCreate(void *window_handle, bool core, bool use565); + void DetectMode(); +}; diff --git a/Common/GL/GLInterface/EGLAndroid.cpp b/Common/GL/GLInterface/EGLAndroid.cpp new file mode 100644 index 000000000..8d2065a0a --- /dev/null +++ b/Common/GL/GLInterface/EGLAndroid.cpp @@ -0,0 +1,31 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include "Common/Log.h" +#include "Common/GL/GLInterface/EGLAndroid.h" + +EGLDisplay cInterfaceEGLAndroid::OpenDisplay() { + return eglGetDisplay(EGL_DEFAULT_DISPLAY); +} + +EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) { + EGLint format; + if (EGL_FALSE == eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format)) { + EGL_ELOG("Failed getting EGL_NATIVE_VISUAL_ID: error %s", EGLGetErrorString(eglGetError())); + return NULL; + } + + int32_t result = ANativeWindow_setBuffersGeometry(host_window, internalWidth_, internalHeight_, format); + EGL_ILOG("ANativeWindow_setBuffersGeometry returned %d", result); + + const int width = ANativeWindow_getWidth(host_window); + const int height = ANativeWindow_getHeight(host_window); + SetBackBufferDimensions(width, height); + + return host_window; +} + +void cInterfaceEGLAndroid::ShutdownPlatform() { +} diff --git a/Common/GL/GLInterface/EGLAndroid.h b/Common/GL/GLInterface/EGLAndroid.h new file mode 100644 index 000000000..811485d91 --- /dev/null +++ b/Common/GL/GLInterface/EGLAndroid.h @@ -0,0 +1,24 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Common/GL/GLInterface/EGL.h" + +class cInterfaceEGLAndroid : public cInterfaceEGL { +public: + cInterfaceEGLAndroid() : internalWidth_(0), internalHeight_(0) {} +protected: + EGLDisplay OpenDisplay() override; + EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override; + void ShutdownPlatform() override; + void OverrideBackbufferDimensions(int internalWidth, int internalHeight) override { + internalWidth_ = internalWidth; + internalHeight_ = internalHeight; + } + +private: + int internalWidth_; + int internalHeight_; +}; diff --git a/Common/GL/GLInterface/EGLSwitch.cpp b/Common/GL/GLInterface/EGLSwitch.cpp new file mode 100644 index 000000000..4cd670c67 --- /dev/null +++ b/Common/GL/GLInterface/EGLSwitch.cpp @@ -0,0 +1,21 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "ppsspp_config.h" +#if PPSSPP_PLATFORM(SWITCH) +#include +#include "Common/Log.h" +#include "Common/GL/GLInterface/EGLSwitch.h" + +EGLDisplay cInterfaceEGLSwitch::OpenDisplay() { + return eglGetDisplay(EGL_DEFAULT_DISPLAY); +} + +EGLNativeWindowType cInterfaceEGLSwitch::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) { + return nwindowGetDefault(); +} + +void cInterfaceEGLSwitch::ShutdownPlatform() { +} +#endif diff --git a/Common/GL/GLInterface/EGLSwitch.h b/Common/GL/GLInterface/EGLSwitch.h new file mode 100644 index 000000000..b31315842 --- /dev/null +++ b/Common/GL/GLInterface/EGLSwitch.h @@ -0,0 +1,24 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Common/GL/GLInterface/EGL.h" + +class cInterfaceEGLSwitch : public cInterfaceEGL { +public: + cInterfaceEGLSwitch() {} +protected: + EGLDisplay OpenDisplay() override; + EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override; + void ShutdownPlatform() override; + void OverrideBackbufferDimensions(int internalWidth, int internalHeight) override { + internalWidth_ = internalWidth; + internalHeight_ = internalHeight; + } + +private: + int internalWidth_ = 0; + int internalHeight_ = 0; +}; diff --git a/Common/GL/GLInterface/GLInterface.cpp b/Common/GL/GLInterface/GLInterface.cpp new file mode 100644 index 000000000..ad2e78120 --- /dev/null +++ b/Common/GL/GLInterface/GLInterface.cpp @@ -0,0 +1,44 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "ppsspp_config.h" +#include "Common/GL/GLInterfaceBase.h" + +#ifdef __ANDROID__ +#include "Common/GL/GLInterface/EGLAndroid.h" +#elif PPSSPP_PLATFORM(SWITCH) +#include "Common/GL/GLInterface/EGLSwitch.h" +#elif defined(__APPLE__) +#include "Common/GL/GLInterface/AGL.h" +#elif defined(_WIN32) +#include "Common/GL/GLInterface/WGL.h" +#elif HAVE_X11 +#if defined(USE_EGL) && USE_EGL +#include "Common/GL/GLInterface/EGLX11.h" +#else +#include "Common/GL/GLInterface/GLX.h" +#endif +#else +#error Platform doesnt have a GLInterface +#endif + +cInterfaceBase* HostGL_CreateGLInterface(){ + #ifdef __ANDROID__ + return new cInterfaceEGLAndroid; + #elif PPSSPP_PLATFORM(SWITCH) + return new cInterfaceEGLSwitch; + #elif defined(__APPLE__) + return new cInterfaceAGL; + #elif defined(_WIN32) + return new cInterfaceWGL; + #elif defined(HAVE_X11) && HAVE_X11 + #if defined(USE_EGL) && USE_EGL + return new cInterfaceEGLX11; + #else + return new cInterfaceGLX; + #endif + #else + return nullptr; + #endif +} diff --git a/Common/GL/GLInterfaceBase.h b/Common/GL/GLInterfaceBase.h new file mode 100644 index 000000000..250f0f35e --- /dev/null +++ b/Common/GL/GLInterfaceBase.h @@ -0,0 +1,50 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "Common/CommonTypes.h" + +enum GLInterfaceMode { + MODE_DETECT = 0, + MODE_DETECT_ES, + MODE_OPENGL, + MODE_OPENGLES2, + MODE_OPENGLES3, +}; + +class cInterfaceBase { +protected: + // Window dimensions. + u32 s_backbuffer_width; + u32 s_backbuffer_height; + + u32 s_opengl_mode; +public: + cInterfaceBase() : s_backbuffer_width(0), s_backbuffer_height(0), s_opengl_mode(MODE_DETECT) {} + virtual ~cInterfaceBase() {} + virtual void Swap() {} + virtual void SetMode(u32 mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; } + virtual u32 GetMode() { return s_opengl_mode; } + virtual void* GetFuncAddress(const std::string& name) { return nullptr; } + virtual bool Create(void *window_handle, bool core = true, bool use16bit = false) = 0; + virtual bool MakeCurrent() { return true; } + virtual bool ClearCurrent() { return true; } + virtual void Shutdown() {} + + virtual void SwapInterval(int Interval) { } + virtual u32 GetBackBufferWidth() { return s_backbuffer_width; } + virtual u32 GetBackBufferHeight() { return s_backbuffer_height; } + + virtual void OverrideBackbufferDimensions(int w, int h) = 0; + + virtual void SetBackBufferDimensions(u32 W, u32 H) {s_backbuffer_width = W; s_backbuffer_height = H; } + virtual void Update() { } + virtual bool PeekMessages() { return false; } +}; + + +cInterfaceBase* HostGL_CreateGLInterface(); diff --git a/Common/GPU/D3D11/D3D11Loader.cpp b/Common/GPU/D3D11/D3D11Loader.cpp index 6268f99ed..0dbea8099 100644 --- a/Common/GPU/D3D11/D3D11Loader.cpp +++ b/Common/GPU/D3D11/D3D11Loader.cpp @@ -11,6 +11,7 @@ static HMODULE g_D3DCompileModule; LPCREATEDXGIFACTORY ptr_CreateDXGIFactory; LPD3D11CREATEDEVICE ptr_D3D11CreateDevice; +LPD3D11CREATEDEVICEANDSWAPCHAIN ptr_D3D11CreateDeviceAndSwapChain; pD3DCompile ptr_D3DCompile; LoadD3D11Error LoadD3D11() { @@ -21,6 +22,7 @@ LoadD3D11Error LoadD3D11() { g_D3D11Module = LoadLibrary(L"d3d11.dll"); if (g_D3D11Module) { ptr_D3D11CreateDevice = (LPD3D11CREATEDEVICE)GetProcAddress(g_D3D11Module, "D3D11CreateDevice"); + ptr_D3D11CreateDeviceAndSwapChain = (LPD3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(g_D3D11Module, "D3D11CreateDeviceAndSwapChain"); } else { return LoadD3D11Error::FAIL_NO_D3D11; } diff --git a/Common/GPU/D3D11/D3D11Loader.h b/Common/GPU/D3D11/D3D11Loader.h index 080f761c5..750d1da98 100644 --- a/Common/GPU/D3D11/D3D11Loader.h +++ b/Common/GPU/D3D11/D3D11Loader.h @@ -14,10 +14,12 @@ #endif typedef HRESULT (WINAPI *LPCREATEDXGIFACTORY)(REFIID, void **); +typedef HRESULT (WINAPI *LPD3D11CREATEDEVICEANDSWAPCHAIN)(__in_opt IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, __in_opt CONST DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, __out_opt IDXGISwapChain **ppSwapChain, __out_opt ID3D11Device **ppDevice, __out_opt D3D_FEATURE_LEVEL *pFeatureLevel, __out_opt ID3D11DeviceContext **ppImmediateContext); typedef HRESULT (WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL *, UINT, UINT32, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); extern LPCREATEDXGIFACTORY ptr_CreateDXGIFactory; extern LPD3D11CREATEDEVICE ptr_D3D11CreateDevice; +extern LPD3D11CREATEDEVICEANDSWAPCHAIN ptr_D3D11CreateDeviceAndSwapChain; extern pD3DCompile ptr_D3DCompile; enum class LoadD3D11Error { diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 1559a3cbe..4a90c318c 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -11,7 +11,6 @@ #include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Data/Encoding/Utf8.h" -#include "Common/TimeUtil.h" #include "Common/Log.h" #include @@ -63,7 +62,7 @@ public: class D3D11DrawContext : public DrawContext { public: - D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, IDXGISwapChain *swapChain, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList, int maxInflightFrames); + D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList); ~D3D11DrawContext(); const DeviceCaps &GetDeviceCaps() const override { @@ -76,6 +75,10 @@ public: return (uint32_t)ShaderLanguage::HLSL_D3D11; } uint32_t GetDataFormatSupport(DataFormat fmt) const override; + PresentationMode GetPresentationMode() const override { + // TODO: Fix. Not yet used. + return PresentationMode::FIFO; + } InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override; DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override; @@ -89,7 +92,6 @@ public: Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override; void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override; void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; @@ -106,7 +108,7 @@ public: void BindTextures(int start, int count, Texture **textures, TextureBindFlags flags) override; void BindNativeTexture(int index, void *nativeTexture) override; void BindSamplerStates(int start, int count, SamplerState **states) override; - void BindVertexBuffer(Buffer *buffers, int offset) override; + void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override; void BindIndexBuffer(Buffer *indexBuffer, int offset) override; void BindPipeline(Pipeline *pipeline) override; @@ -128,17 +130,14 @@ public: stencilDirty_ = true; } + void EndFrame() override; void Draw(int vertexCount, int offset) override; void DrawIndexed(int vertexCount, int offset) override; void DrawUP(const void *vdata, int vertexCount) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; - void BeginFrame(DebugFlags debugFlags) override; - void EndFrame() override; - void Present(PresentMode presentMode, int vblanks) override; - - int GetFrameCount() override { return frameCount_; } + void BeginFrame() override; std::string GetInfoString(InfoField info) const override { switch (info) { @@ -179,10 +178,9 @@ private: HWND hWnd_; ID3D11Device *device_; - ID3D11Device1 *device1_; ID3D11DeviceContext *context_; + ID3D11Device1 *device1_; ID3D11DeviceContext1 *context1_; - IDXGISwapChain *swapChain_; ID3D11Texture2D *bbRenderTargetTex_ = nullptr; // NOT OWNED ID3D11RenderTargetView *bbRenderTargetView_ = nullptr; @@ -214,15 +212,14 @@ private: ID3D11GeometryShader *curGS_ = nullptr; D3D11_PRIMITIVE_TOPOLOGY curTopology_ = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; - ID3D11Buffer *nextVertexBuffer_ = nullptr; - UINT nextVertexBufferOffset_ = 0; + ID3D11Buffer *nextVertexBuffers_[4]{}; + int nextVertexBufferOffsets_[4]{}; bool dirtyIndexBuffer_ = false; ID3D11Buffer *nextIndexBuffer_ = nullptr; - UINT nextIndexBufferOffset_ = 0; + int nextIndexBufferOffset_ = 0; InvalidationCallback invalidationCallback_; - int frameCount_ = FRAME_TIME_HISTORY_LENGTH; // Dynamic state float blendFactor_[4]{}; @@ -243,14 +240,13 @@ private: std::vector deviceList_; }; -D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, IDXGISwapChain *swapChain, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList, int maxInflightFrames) +D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList) : hWnd_(hWnd), device_(device), context_(deviceContext1), device1_(device1), context1_(deviceContext1), featureLevel_(featureLevel), - swapChain_(swapChain), deviceList_(deviceList) { // We no longer support Windows Phone. @@ -281,10 +277,6 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.blendMinMaxSupported = true; caps_.multiSampleLevelsMask = 1; // More could be supported with some work. - caps_.presentInstantModeChange = true; - caps_.presentMaxInterval = 4; - caps_.presentModesSupported = PresentMode::FIFO | PresentMode::IMMEDIATE; - D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options)); if (SUCCEEDED(result)) { @@ -350,13 +342,6 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de const size_t UP_MAX_BYTES = 65536 * 24; upBuffer_ = CreateBuffer(UP_MAX_BYTES, BufferUsageFlag::DYNAMIC | BufferUsageFlag::VERTEXDATA); - - IDXGIDevice1 *dxgiDevice1 = nullptr; - hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice1)); - if (SUCCEEDED(hr)) { - caps_.setMaxFrameLatencySupported = true; - dxgiDevice1->SetMaximumFrameLatency(maxInflightFrames); - } } D3D11DrawContext::~D3D11DrawContext() { @@ -427,31 +412,18 @@ void D3D11DrawContext::HandleEvent(Event ev, int width, int height, void *param1 curRTHeight_ = height; break; } + case Event::PRESENTED: + // Make sure that we don't eliminate the next time the render target is set. + curRenderTargetView_ = nullptr; + curDepthStencilView_ = nullptr; + break; } } void D3D11DrawContext::EndFrame() { - // Fake a submit time. - frameTimeHistory_[frameCount_].firstSubmit = time_now_d(); curPipeline_ = nullptr; } -void D3D11DrawContext::Present(PresentMode presentMode, int vblanks) { - frameTimeHistory_[frameCount_].queuePresent = time_now_d(); - - int interval = vblanks; - if (presentMode != PresentMode::FIFO) { - interval = 0; - } - // Safety for libretro - if (swapChain_) { - swapChain_->Present(interval, 0); - } - curRenderTargetView_ = nullptr; - curDepthStencilView_ = nullptr; - frameCount_++; -} - void D3D11DrawContext::SetViewport(const Viewport &viewport) { DisplayRect rc{ viewport.TopLeftX , viewport.TopLeftY, viewport.Width, viewport.Height }; if (curRenderTargetView_ == bbRenderTargetView_) // Only the backbuffer is actually rotated wrong! @@ -725,7 +697,7 @@ public: D3D11InputLayout() {} InputLayoutDesc desc; std::vector elements; - UINT stride; // type to match function parameter + std::vector strides; }; const char *semanticToD3D11(int semantic, UINT *index) { @@ -752,13 +724,15 @@ InputLayout *D3D11DrawContext::CreateInputLayout(const InputLayoutDesc &desc) { D3D11_INPUT_ELEMENT_DESC el; el.AlignedByteOffset = desc.attributes[i].offset; el.Format = dataFormatToD3D11(desc.attributes[i].format); - el.InstanceDataStepRate = 0; - el.InputSlot = 0; + el.InstanceDataStepRate = desc.bindings[desc.attributes[i].binding].instanceRate ? 1 : 0; + el.InputSlot = desc.attributes[i].binding; el.SemanticName = semanticToD3D11(desc.attributes[i].location, &el.SemanticIndex); - el.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + el.InputSlotClass = desc.bindings[desc.attributes[i].binding].instanceRate ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; inputLayout->elements.push_back(el); } - inputLayout->stride = desc.stride; + for (size_t i = 0; i < desc.bindings.size(); i++) { + inputLayout->strides.push_back(desc.bindings[i].stride); + } return inputLayout; } @@ -821,83 +795,35 @@ public: width_ = desc.width; height_ = desc.height; depth_ = desc.depth; - format_ = desc.format; - mipLevels_ = desc.mipLevels; } ~D3D11Texture() { - if (tex_) - tex_->Release(); - if (stagingTex_) - stagingTex_->Release(); - if (view_) - view_->Release(); + if (tex) + tex->Release(); + if (stagingTex) + stagingTex->Release(); + if (view) + view->Release(); } - bool Create(ID3D11DeviceContext *context, ID3D11Device *device, const TextureDesc &desc, bool generateMips); - - bool CreateStagingTexture(ID3D11Device *device); - void UpdateTextureLevels(ID3D11DeviceContext *context, ID3D11Device *device, Texture *texture, const uint8_t *const *data, TextureCallback initDataCallback, int numLevels); - - ID3D11ShaderResourceView *View() { return view_; } - -private: - bool FillLevel(ID3D11DeviceContext *context, int level, int w, int h, int d, const uint8_t *const *data, TextureCallback initDataCallback); - - ID3D11Texture2D *tex_ = nullptr; - ID3D11Texture2D *stagingTex_ = nullptr; - ID3D11ShaderResourceView *view_ = nullptr; - int mipLevels_ = 0; + ID3D11Texture2D *tex = nullptr; + ID3D11Texture2D *stagingTex = nullptr; + ID3D11ShaderResourceView *view = nullptr; }; -bool D3D11Texture::FillLevel(ID3D11DeviceContext *context, int level, int w, int h, int d, const uint8_t *const *data, TextureCallback initDataCallback) { - D3D11_MAPPED_SUBRESOURCE mapped; - HRESULT hr = context->Map(stagingTex_, level, D3D11_MAP_WRITE, 0, &mapped); - if (!SUCCEEDED(hr)) { - tex_->Release(); - tex_ = nullptr; - return false; +Texture *D3D11DrawContext::CreateTexture(const TextureDesc &desc) { + if (!(GetDataFormatSupport(desc.format) & FMT_TEXTURE)) { + // D3D11 does not support this format as a texture format. + return nullptr; } - if (!initDataCallback((uint8_t *)mapped.pData, data[level], w, h, d, mapped.RowPitch, mapped.DepthPitch)) { - for (int s = 0; s < d; ++s) { - for (int y = 0; y < h; ++y) { - void *dest = (uint8_t *)mapped.pData + mapped.DepthPitch * s + mapped.RowPitch * y; - uint32_t byteStride = w * (uint32_t)DataFormatSizeInBytes(format_); - const void *src = data[level] + byteStride * (y + h * s); - memcpy(dest, src, byteStride); - } - } + D3D11Texture *tex = new D3D11Texture(desc); + + bool generateMips = desc.generateMips; + if (desc.generateMips && !(GetDataFormatSupport(desc.format) & FMT_AUTOGEN_MIPS)) { + // D3D11 does not support autogenerating mipmaps for this format. + generateMips = false; } - context->Unmap(stagingTex_, level); - return true; -} -bool D3D11Texture::CreateStagingTexture(ID3D11Device *device) { - if (stagingTex_) - return true; - D3D11_TEXTURE2D_DESC descColor{}; - descColor.Width = width_; - descColor.Height = height_; - descColor.MipLevels = mipLevels_; - descColor.ArraySize = 1; - descColor.Format = dataFormatToD3D11(format_); - descColor.SampleDesc.Count = 1; - descColor.SampleDesc.Quality = 0; - descColor.Usage = D3D11_USAGE_STAGING; - descColor.BindFlags = 0; - descColor.MiscFlags = 0; - descColor.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - - HRESULT hr = device->CreateTexture2D(&descColor, nullptr, &stagingTex_); - if (!SUCCEEDED(hr)) { - stagingTex_->Release(); - stagingTex_ = nullptr; - return false; - } - return true; -} - -bool D3D11Texture::Create(ID3D11DeviceContext *context, ID3D11Device *device, const TextureDesc &desc, bool generateMips) { D3D11_TEXTURE2D_DESC descColor{}; descColor.Width = desc.width; descColor.Height = desc.height; @@ -906,16 +832,25 @@ bool D3D11Texture::Create(ID3D11DeviceContext *context, ID3D11Device *device, co descColor.Format = dataFormatToD3D11(desc.format); descColor.SampleDesc.Count = 1; descColor.SampleDesc.Quality = 0; + + if (desc.initDataCallback) { + descColor.Usage = D3D11_USAGE_STAGING; + descColor.BindFlags = 0; + descColor.MiscFlags = 0; + descColor.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + HRESULT hr = device_->CreateTexture2D(&descColor, nullptr, &tex->stagingTex); + if (!SUCCEEDED(hr)) { + delete tex; + return nullptr; + } + } + descColor.Usage = D3D11_USAGE_DEFAULT; descColor.BindFlags = generateMips ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : D3D11_BIND_SHADER_RESOURCE; descColor.MiscFlags = generateMips ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; descColor.CPUAccessFlags = 0; - // Make sure we have a staging texture if we'll need it. - if (desc.initDataCallback && !CreateStagingTexture(device)) { - return false; - } - D3D11_SUBRESOURCE_DATA *initDataParam = nullptr; D3D11_SUBRESOURCE_DATA initData[12]{}; std::vector initDataBuffer[12]; @@ -935,39 +870,62 @@ bool D3D11Texture::Create(ID3D11DeviceContext *context, ID3D11Device *device, co initDataParam = initData; } - HRESULT hr = device->CreateTexture2D(&descColor, initDataParam, &tex_); + HRESULT hr = device_->CreateTexture2D(&descColor, initDataParam, &tex->tex); if (!SUCCEEDED(hr)) { - tex_ = nullptr; - return false; + delete tex; + return nullptr; } - hr = device->CreateShaderResourceView(tex_, nullptr, &view_); + hr = device_->CreateShaderResourceView(tex->tex, nullptr, &tex->view); if (!SUCCEEDED(hr)) { - return false; + delete tex; + return nullptr; } + auto populateLevelCallback = [&](int level, int w, int h, int d) { + D3D11_MAPPED_SUBRESOURCE mapped; + hr = context_->Map(tex->stagingTex, level, D3D11_MAP_WRITE, 0, &mapped); + if (!SUCCEEDED(hr)) { + return false; + } + + if (!desc.initDataCallback((uint8_t *)mapped.pData, desc.initData[level], w, h, d, mapped.RowPitch, mapped.DepthPitch)) { + for (int s = 0; s < d; ++s) { + for (int y = 0; y < h; ++y) { + void *dest = (uint8_t *)mapped.pData + mapped.DepthPitch * s + mapped.RowPitch * y; + uint32_t byteStride = w * (uint32_t)DataFormatSizeInBytes(desc.format); + const void *src = desc.initData[level] + byteStride * (y + h * d); + memcpy(dest, src, byteStride); + } + } + } + context_->Unmap(tex->stagingTex, level); + return true; + }; + if (generateMips && desc.initData.size() >= 1) { if (desc.initDataCallback) { - if (!FillLevel(context, 0, desc.width, desc.height, desc.depth, desc.initData.data(), desc.initDataCallback)) { - tex_->Release(); - return false; + if (!populateLevelCallback(0, desc.width, desc.height, desc.depth)) { + delete tex; + return nullptr; } - context->CopyResource(tex_, stagingTex_); - stagingTex_->Release(); - stagingTex_ = nullptr; + context_->CopyResource(tex->stagingTex, tex->stagingTex); + tex->stagingTex->Release(); + tex->stagingTex = nullptr; } else { uint32_t byteStride = desc.width * (uint32_t)DataFormatSizeInBytes(desc.format); - context->UpdateSubresource(tex_, 0, nullptr, desc.initData[0], byteStride, 0); + context_->UpdateSubresource(tex->tex, 0, nullptr, desc.initData[0], byteStride, 0); } - context->GenerateMips(view_); + context_->GenerateMips(tex->view); } else if (desc.initDataCallback) { int w = desc.width; int h = desc.height; int d = desc.depth; for (int i = 0; i < (int)desc.initData.size(); i++) { - if (!FillLevel(context, i, w, h, d, desc.initData.data(), desc.initDataCallback)) { + if (!populateLevelCallback(i, desc.width, desc.height, desc.depth)) { if (i == 0) { - return false; + delete tex; + return nullptr; } else { break; } @@ -978,62 +936,13 @@ bool D3D11Texture::Create(ID3D11DeviceContext *context, ID3D11Device *device, co d = (d + 1) / 2; } - context->CopyResource(tex_, stagingTex_); - stagingTex_->Release(); - stagingTex_ = nullptr; + context_->CopyResource(tex->tex, tex->stagingTex); + tex->stagingTex->Release(); + tex->stagingTex = nullptr; } - return true; -} - -void D3D11Texture::UpdateTextureLevels(ID3D11DeviceContext *context, ID3D11Device *device, Texture *texture, const uint8_t * const*data, TextureCallback initDataCallback, int numLevels) { - if (!CreateStagingTexture(device)) { - return; - } - - int w = width_; - int h = height_; - int d = depth_; - for (int i = 0; i < (int)numLevels; i++) { - if (!FillLevel(context, i, w, h, d, data, initDataCallback)) { - break; - } - - w = (w + 1) / 2; - h = (h + 1) / 2; - d = (d + 1) / 2; - } - - context->CopyResource(tex_, stagingTex_); - stagingTex_->Release(); - stagingTex_ = nullptr; -} - -Texture *D3D11DrawContext::CreateTexture(const TextureDesc &desc) { - if (!(GetDataFormatSupport(desc.format) & FMT_TEXTURE)) { - // D3D11 does not support this format as a texture format. - return nullptr; - } - - D3D11Texture *tex = new D3D11Texture(desc); - bool generateMips = desc.generateMips; - if (desc.generateMips && !(GetDataFormatSupport(desc.format) & FMT_AUTOGEN_MIPS)) { - // D3D11 does not support autogenerating mipmaps for this format. - generateMips = false; - } - if (!tex->Create(context_, device_, desc, generateMips)) { - tex->Release(); - return nullptr; - } - return tex; } - -void D3D11DrawContext::UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) { - D3D11Texture *tex = (D3D11Texture *)texture; - tex->UpdateTextureLevels(context_, device_, texture, data, initDataCallback, numLevels); -} - ShaderModule *D3D11DrawContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const char *tag) { if (language != ShaderLanguage::HLSL_D3D11) { ERROR_LOG(G3D, "Unsupported shader language"); @@ -1251,7 +1160,8 @@ void D3D11DrawContext::ApplyCurrentState() { } if (curPipeline_->input != nullptr) { - context_->IASetVertexBuffers(0, 1, &nextVertexBuffer_, &curPipeline_->input->stride, &nextVertexBufferOffset_); + int numVBs = (int)curPipeline_->input->strides.size(); + context_->IASetVertexBuffers(0, numVBs, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_); } if (dirtyIndexBuffer_) { context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R16_UINT, nextIndexBufferOffset_); @@ -1320,11 +1230,14 @@ void D3D11DrawContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t context_->UpdateSubresource(buf->buf, 0, &box, data, 0, 0); } -void D3D11DrawContext::BindVertexBuffer(Buffer *buffer, int offset) { +void D3D11DrawContext::BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) { + _assert_(start + count <= ARRAY_SIZE(nextVertexBuffers_)); // Lazy application - D3D11Buffer *buf = (D3D11Buffer *)buffer; - nextVertexBuffer_ = buf->buf; - nextVertexBufferOffset_ = offset; + for (int i = 0; i < count; i++) { + D3D11Buffer *buf = (D3D11Buffer *)buffers[i]; + nextVertexBuffers_[start + i] = buf->buf; + nextVertexBufferOffsets_[start + i] = offsets ? offsets[i] : 0; + } } void D3D11DrawContext::BindIndexBuffer(Buffer *indexBuffer, int offset) { @@ -1348,10 +1261,10 @@ void D3D11DrawContext::DrawIndexed(int indexCount, int offset) { void D3D11DrawContext::DrawUP(const void *vdata, int vertexCount) { ApplyCurrentState(); - int byteSize = vertexCount * curPipeline_->input->stride; + int byteSize = vertexCount * curPipeline_->input->strides[0]; UpdateBuffer(upBuffer_, (const uint8_t *)vdata, 0, byteSize, Draw::UPDATE_DISCARD); - BindVertexBuffer(upBuffer_, 0); + BindVertexBuffers(0, 1, &upBuffer_, nullptr); int offset = 0; Draw(vertexCount, offset); } @@ -1498,7 +1411,7 @@ void D3D11DrawContext::BindTextures(int start, int count, Texture **textures, Te _assert_(start + count <= ARRAY_SIZE(views)); for (int i = 0; i < count; i++) { D3D11Texture *tex = (D3D11Texture *)textures[i]; - views[i] = tex ? tex->View() : nullptr; + views[i] = tex ? tex->view : nullptr; } context_->PSSetShaderResources(start, count, views); } @@ -1535,11 +1448,7 @@ void D3D11DrawContext::Clear(int mask, uint32_t colorval, float depthVal, int st } } -void D3D11DrawContext::BeginFrame(DebugFlags debugFlags) { - FrameTimeData &frameTimeData = frameTimeHistory_.Add(frameCount_); - frameTimeData.afterFenceWait = time_now_d(); - frameTimeData.frameBegin = frameTimeData.afterFenceWait; - +void D3D11DrawContext::BeginFrame() { context_->OMSetRenderTargets(1, &curRenderTargetView_, curDepthStencilView_); if (curBlend_ != nullptr) { @@ -1559,7 +1468,7 @@ void D3D11DrawContext::BeginFrame(DebugFlags debugFlags) { context_->IASetPrimitiveTopology(curTopology_); } if (curPipeline_ != nullptr) { - context_->IASetVertexBuffers(0, 1, &nextVertexBuffer_, &curPipeline_->input->stride, &nextVertexBufferOffset_); + context_->IASetVertexBuffers(0, 1, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_); context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R16_UINT, nextIndexBufferOffset_); if (curPipeline_->dynamicUniforms) { context_->VSSetConstantBuffers(0, 1, &curPipeline_->dynamicUniforms); @@ -1862,7 +1771,7 @@ uint64_t D3D11DrawContext::GetNativeObject(NativeObject obj, void *srcObject) { case NativeObject::FEATURE_LEVEL: return (uint64_t)(uintptr_t)featureLevel_; case NativeObject::TEXTURE_VIEW: - return (uint64_t)(((D3D11Texture *)srcObject)->View()); + return (uint64_t)(((D3D11Texture *)srcObject)->view); default: return 0; } @@ -1879,8 +1788,8 @@ void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h } } -DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, IDXGISwapChain *swapChain, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames, int maxInflightFrames) { - return new D3D11DrawContext(device, context, device1, context1, swapChain, featureLevel, hWnd, adapterNames, maxInflightFrames); +DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames) { + return new D3D11DrawContext(device, context, device1, context1, featureLevel, hWnd, adapterNames); } } // namespace Draw diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index dadf67eaa..32152c698 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -25,7 +25,6 @@ #include "Common/GPU/D3D9/D3D9StateCache.h" #include "Common/OSVersion.h" #include "Common/StringUtils.h" -#include "Common/TimeUtil.h" #include "Common/Log.h" @@ -231,14 +230,14 @@ public: decl_->Release(); } } - int GetStride() const { return stride_; } + int GetStride(int binding) const { return stride_[binding]; } void Apply(LPDIRECT3DDEVICE9 device) { device->SetVertexDeclaration(decl_); } private: LPDIRECT3DVERTEXDECLARATION9 decl_; - int stride_; + int stride_[4]; }; class D3D9ShaderModule : public ShaderModule { @@ -309,14 +308,14 @@ public: return nullptr; } } - void UpdateTextureLevels(const uint8_t * const *data, int numLevels, TextureCallback initDataCallback); private: - void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback initDataCallback); + void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback); bool Create(const TextureDesc &desc); LPDIRECT3DDEVICE9 device_; LPDIRECT3DDEVICE9EX deviceEx_; TextureType type_; + DataFormat format_; D3DFORMAT d3dfmt_; LPDIRECT3DTEXTURE9 tex_ = nullptr; LPDIRECT3DVOLUMETEXTURE9 volTex_ = nullptr; @@ -375,31 +374,27 @@ bool D3D9Texture::Create(const TextureDesc &desc) { break; } if (FAILED(hr)) { - ERROR_LOG(G3D, "D3D9 Texture creation failed"); + ERROR_LOG(G3D, "Texture creation failed"); return false; } if (desc.initData.size()) { // In D3D9, after setting D3DUSAGE_AUTOGENMIPS, we can only access the top layer. The rest will be // automatically generated. - int numLevels = desc.generateMips ? 1 : (int)desc.initData.size(); - UpdateTextureLevels(desc.initData.data(), numLevels, desc.initDataCallback); + int maxLevel = desc.generateMips ? 1 : (int)desc.initData.size(); + int w = desc.width; + int h = desc.height; + int d = desc.depth; + for (int i = 0; i < maxLevel; i++) { + SetImageData(0, 0, 0, w, h, d, i, 0, desc.initData[i], desc.initDataCallback); + w = (w + 1) / 2; + h = (h + 1) / 2; + d = (d + 1) / 2; + } } return true; } -void D3D9Texture::UpdateTextureLevels(const uint8_t * const *data, int numLevels, TextureCallback initDataCallback) { - int w = width_; - int h = height_; - int d = depth_; - for (int i = 0; i < numLevels; i++) { - SetImageData(0, 0, 0, w, h, d, i, 0, data[i], initDataCallback); - w = (w + 1) / 2; - h = (h + 1) / 2; - d = (d + 1) / 2; - } -} - // Just switches R and G. inline uint32_t Shuffle8888(uint32_t x) { return (x & 0xFF00FF00) | ((x >> 16) & 0xFF) | ((x << 16) & 0xFF0000); @@ -519,6 +514,10 @@ public: return (uint32_t)ShaderLanguage::HLSL_D3D9; } uint32_t GetDataFormatSupport(DataFormat fmt) const override; + PresentationMode GetPresentationMode() const override { + // TODO: Fix. Not yet used. + return PresentationMode::FIFO; + } ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const char *tag) override; DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override; @@ -533,7 +532,6 @@ public: Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override; void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override; void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override { // Not implemented @@ -560,9 +558,12 @@ public: s->Apply(device_, start + i); } } - void BindVertexBuffer(Buffer *vertexBuffer, int offset) override { - curVBuffer_ = (D3D9Buffer *)vertexBuffer; - curVBufferOffset_ = offset; + void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override { + _assert_(start + count <= ARRAY_SIZE(curVBuffers_)); + for (int i = 0; i < count; i++) { + curVBuffers_[i + start] = (D3D9Buffer *)buffers[i]; + curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0; + } } void BindIndexBuffer(Buffer *indexBuffer, int offset) override { curIBuffer_ = (D3D9Buffer *)indexBuffer; @@ -573,11 +574,7 @@ public: curPipeline_ = (D3D9Pipeline *)pipeline; } - void BeginFrame(Draw::DebugFlags debugFlags) override; void EndFrame() override; - void Present(PresentMode presentMode, int vblanks) override; - - int GetFrameCount() override { return frameCount_; } void UpdateDynamicUniformBuffer(const void *ub, size_t size) override; @@ -638,12 +635,11 @@ private: D3DCAPS9 d3dCaps_; char shadeLangVersion_[64]{}; DeviceCaps caps_{}; - int frameCount_ = FRAME_TIME_HISTORY_LENGTH; // Bound state AutoRef curPipeline_; - AutoRef curVBuffer_; - int curVBufferOffset_ = 0; + AutoRef curVBuffers_[4]; + int curVBufferOffsets_[4]{}; AutoRef curIBuffer_; int curIBufferOffset_ = 0; AutoRef curRenderTarget_; @@ -780,9 +776,6 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID caps_.multiSampleLevelsMask = 1; // More could be supported with some work. caps_.clipPlanesSupported = caps.MaxUserClipPlanes; - caps_.presentInstantModeChange = false; - caps_.presentMaxInterval = 1; - caps_.presentModesSupported = PresentMode::FIFO; if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1) { caps_.anisoSupported = true; @@ -941,12 +934,6 @@ Texture *D3D9Context::CreateTexture(const TextureDesc &desc) { return tex; } -void D3D9Context::UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) { - D3D9Texture *tex = (D3D9Texture *)texture; - tex->UpdateTextureLevels(data, numLevels, initDataCallback); -} - - void D3D9Context::BindTextures(int start, int count, Texture **textures, TextureBindFlags flags) { _assert_(start + count <= MAX_BOUND_TEXTURES); for (int i = start; i < start + count; i++) { @@ -964,31 +951,10 @@ void D3D9Context::BindNativeTexture(int index, void *nativeTexture) { device_->SetTexture(index, texture); } -void D3D9Context::BeginFrame(Draw::DebugFlags debugFlags) { - FrameTimeData frameTimeData = frameTimeHistory_.Add(frameCount_); - frameTimeData.frameBegin = time_now_d(); - frameTimeData.afterFenceWait = frameTimeData.frameBegin; // no fence wait -} - void D3D9Context::EndFrame() { - frameTimeHistory_[frameCount_].firstSubmit = time_now_d(); curPipeline_ = nullptr; } -void D3D9Context::Present(PresentMode presentMode, int vblanks) { - frameTimeHistory_[frameCount_].queuePresent = time_now_d(); - if (deviceEx_) { - deviceEx_->EndScene(); - deviceEx_->PresentEx(NULL, NULL, NULL, NULL, 0); - deviceEx_->BeginScene(); - } else { - device_->EndScene(); - device_->Present(NULL, NULL, NULL, NULL); - device_->BeginScene(); - } - frameCount_++; -} - static void SemanticToD3D9UsageAndIndex(int semantic, BYTE *usage, BYTE *index) { *index = 0; switch (semantic) { @@ -1025,7 +991,7 @@ D3D9InputLayout::D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[desc.attributes.size() + 1]; size_t i; for (i = 0; i < desc.attributes.size(); i++) { - elements[i].Stream = 0; + elements[i].Stream = desc.attributes[i].binding; elements[i].Offset = desc.attributes[i].offset; elements[i].Method = D3DDECLMETHOD_DEFAULT; SemanticToD3D9UsageAndIndex(desc.attributes[i].location, &elements[i].Usage, &elements[i].UsageIndex); @@ -1035,7 +1001,9 @@ D3D9InputLayout::D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc // Zero the last one. memcpy(&elements[i], &end, sizeof(elements[i])); - stride_ = desc.stride; + for (i = 0; i < desc.bindings.size(); i++) { + stride_[i] = desc.bindings[i].stride; + } HRESULT hr = device->CreateVertexDeclaration(elements, &decl_); if (FAILED(hr)) { @@ -1169,7 +1137,7 @@ inline int D3DPrimCount(D3DPRIMITIVETYPE prim, int size) { } void D3D9Context::Draw(int vertexCount, int offset) { - device_->SetStreamSource(0, curVBuffer_->vbuffer_, curVBufferOffset_, curPipeline_->inputLayout->GetStride()); + device_->SetStreamSource(0, curVBuffers_[0]->vbuffer_, curVBufferOffsets_[0], curPipeline_->inputLayout->GetStride(0)); curPipeline_->inputLayout->Apply(device_); curPipeline_->Apply(device_, stencilRef_, stencilWriteMask_, stencilCompareMask_); ApplyDynamicState(); @@ -1180,7 +1148,7 @@ void D3D9Context::DrawIndexed(int vertexCount, int offset) { curPipeline_->inputLayout->Apply(device_); curPipeline_->Apply(device_, stencilRef_, stencilWriteMask_, stencilCompareMask_); ApplyDynamicState(); - device_->SetStreamSource(0, curVBuffer_->vbuffer_, curVBufferOffset_, curPipeline_->inputLayout->GetStride()); + device_->SetStreamSource(0, curVBuffers_[0]->vbuffer_, curVBufferOffsets_[0], curPipeline_->inputLayout->GetStride(0)); device_->SetIndices(curIBuffer_->ibuffer_); device_->DrawIndexedPrimitive(curPipeline_->prim, 0, 0, vertexCount, offset, D3DPrimCount(curPipeline_->prim, vertexCount)); } @@ -1190,7 +1158,7 @@ void D3D9Context::DrawUP(const void *vdata, int vertexCount) { curPipeline_->Apply(device_, stencilRef_, stencilWriteMask_, stencilCompareMask_); ApplyDynamicState(); - device_->DrawPrimitiveUP(curPipeline_->prim, D3DPrimCount(curPipeline_->prim, vertexCount), vdata, curPipeline_->inputLayout->GetStride()); + device_->DrawPrimitiveUP(curPipeline_->prim, D3DPrimCount(curPipeline_->prim, vertexCount), vdata, curPipeline_->inputLayout->GetStride(0)); } static uint32_t SwapRB(uint32_t c) { diff --git a/Common/GPU/GPUBackendCommon.cpp b/Common/GPU/GPUBackendCommon.cpp deleted file mode 100644 index b53001484..000000000 --- a/Common/GPU/GPUBackendCommon.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -#include "Common/GPU/GPUBackendCommon.h" - -// Global push buffer tracker for GPU memory profiling. -// Don't want to manually dig up all the active push buffers. -static std::mutex g_pushBufferListMutex; -static std::set g_pushBuffers; - -std::vector GetActiveGPUMemoryManagers() { - std::vector buffers; - std::lock_guard guard(g_pushBufferListMutex); - for (auto iter : g_pushBuffers) { - buffers.push_back(iter); - } - return buffers; -} - -void RegisterGPUMemoryManager(GPUMemoryManager *manager) { - std::lock_guard guard(g_pushBufferListMutex); - g_pushBuffers.insert(manager); -} - -void UnregisterGPUMemoryManager(GPUMemoryManager *manager) { - std::lock_guard guard(g_pushBufferListMutex); - g_pushBuffers.erase(manager); -} diff --git a/Common/GPU/GPUBackendCommon.h b/Common/GPU/GPUBackendCommon.h deleted file mode 100644 index e465b75df..000000000 --- a/Common/GPU/GPUBackendCommon.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -// Just an abstract thing to get debug information. -class GPUMemoryManager { -public: - virtual ~GPUMemoryManager() {} - - virtual void GetDebugString(char *buffer, size_t bufSize) const = 0; - virtual const char *Name() const = 0; // for sorting -}; - -std::vector GetActiveGPUMemoryManagers(); - -void RegisterGPUMemoryManager(GPUMemoryManager *manager); -void UnregisterGPUMemoryManager(GPUMemoryManager *manager); diff --git a/Common/GPU/MiscTypes.h b/Common/GPU/MiscTypes.h index 834db32f1..0db111a73 100644 --- a/Common/GPU/MiscTypes.h +++ b/Common/GPU/MiscTypes.h @@ -2,8 +2,6 @@ #include "Common/Common.h" -// Flags and structs shared between backends that haven't found a good home. - enum class InvalidationFlags { CACHED_RENDER_STATE = 1, }; @@ -16,22 +14,3 @@ enum class InvalidationCallbackFlags { ENUM_CLASS_BITOPS(InvalidationCallbackFlags); typedef std::function InvalidationCallback; - -// These are separate from FrameData because we store some history of these. -// Also, this might be joined with more non-GPU timing information later. -struct FrameTimeData { - uint64_t frameId; - - int waitCount; - - double frameBegin; - double afterFenceWait; - double firstSubmit; - double queuePresent; - - double actualPresent; - double desiredPresentTime; - double earliestPresentTime; - double presentMargin; -}; -constexpr size_t FRAME_TIME_HISTORY_LENGTH = 32; diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp index ea690d86a..be3b8d8aa 100644 --- a/Common/GPU/OpenGL/DataFormatGL.cpp +++ b/Common/GPU/OpenGL/DataFormatGL.cpp @@ -55,7 +55,7 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin internalFormat = GL_RGB; format = GL_RGB; type = GL_UNSIGNED_BYTE; - alignment = 3; + alignment = 1; break; case DataFormat::R4G4B4A4_UNORM_PACK16: @@ -146,14 +146,12 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin alignment = 16; break; -#ifdef GL_COMPRESSED_RGBA_ASTC_4x4_KHR case DataFormat::ASTC_4x4_UNORM_BLOCK: internalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; format = GL_RGBA; type = GL_FLOAT; alignment = 16; break; -#endif default: return false; diff --git a/Common/GPU/OpenGL/GLFeatures.cpp b/Common/GPU/OpenGL/GLFeatures.cpp index fa3463e5d..9b1e31337 100644 --- a/Common/GPU/OpenGL/GLFeatures.cpp +++ b/Common/GPU/OpenGL/GLFeatures.cpp @@ -592,9 +592,7 @@ bool CheckGLExtensions() { for (int i = 0; i < numCompressedFormats; i++) { switch (compressedFormats[i]) { case GL_COMPRESSED_RGB8_ETC2: gl_extensions.supportsETC2 = true; break; -#ifdef GL_COMPRESSED_RGBA_ASTC_4x4_KHR case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: gl_extensions.supportsASTC = true; break; -#endif #ifndef USING_GLES2 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: gl_extensions.supportsBC123 = true; break; case GL_COMPRESSED_RGBA_BPTC_UNORM: gl_extensions.supportsBC7 = true; break; @@ -628,13 +626,11 @@ bool CheckGLExtensions() { } void SetGLCoreContext(bool flag) { - if (!extensionsDone) { - useCoreContext = flag; - // For convenience, it'll get reset later. - gl_extensions.IsCoreContext = useCoreContext; - } else { - _assert_(flag == useCoreContext); - } + _assert_msg_(!extensionsDone, "SetGLCoreContext() after CheckGLExtensions()"); + + useCoreContext = flag; + // For convenience, it'll get reset later. + gl_extensions.IsCoreContext = useCoreContext; } void ResetGLExtensions() { diff --git a/Common/GPU/OpenGL/GLFeatures.h b/Common/GPU/OpenGL/GLFeatures.h index e8849f681..f2aa33805 100644 --- a/Common/GPU/OpenGL/GLFeatures.h +++ b/Common/GPU/OpenGL/GLFeatures.h @@ -18,7 +18,6 @@ enum { GPU_VENDOR_BROADCOM = 7, // Raspberry PI etc GPU_VENDOR_VIVANTE = 8, GPU_VENDOR_APPLE = 9, - GPU_VENDOR_MESA = 10, GPU_VENDOR_UNKNOWN = 0, }; diff --git a/Common/GPU/OpenGL/GLFrameData.cpp b/Common/GPU/OpenGL/GLFrameData.cpp index a82669dc8..fa5a051d3 100644 --- a/Common/GPU/OpenGL/GLFrameData.cpp +++ b/Common/GPU/OpenGL/GLFrameData.cpp @@ -32,25 +32,25 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) { } pushBuffers.clear(); for (auto shader : shaders) { - if (skipGLCalls && shader) + if (skipGLCalls) shader->shader = 0; // prevent the glDeleteShader delete shader; } shaders.clear(); for (auto program : programs) { - if (skipGLCalls && program) + if (skipGLCalls) program->program = 0; // prevent the glDeleteProgram delete program; } programs.clear(); for (auto buffer : buffers) { - if (skipGLCalls && buffer) + if (skipGLCalls) buffer->buffer_ = 0; delete buffer; } buffers.clear(); for (auto texture : textures) { - if (skipGLCalls && texture) + if (skipGLCalls) texture->texture = 0; delete texture; } diff --git a/Common/GPU/OpenGL/GLFrameData.h b/Common/GPU/OpenGL/GLFrameData.h index 16756f152..7d8d61c6c 100644 --- a/Common/GPU/OpenGL/GLFrameData.h +++ b/Common/GPU/OpenGL/GLFrameData.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "Common/GPU/OpenGL/GLCommon.h" @@ -40,8 +39,7 @@ struct GLQueueProfileContext { bool enabled; double cpuStartTime; double cpuEndTime; - std::string passesString; - int commandCounts[25]; // Can't grab count from the enum as it would mean a circular include. Might clean this up later. + int drawArraysRebindsAvoided; }; @@ -49,10 +47,6 @@ struct GLQueueProfileContext { struct GLFrameData { bool skipSwap = false; - // Frames need unique IDs to wait for present on, let's keep them here. - // Also used for indexing into the frame timing history buffer. - uint64_t frameId; - std::mutex fenceMutex; std::condition_variable fenceCondVar; bool readyForFence = true; diff --git a/Common/GPU/OpenGL/GLMemory.cpp b/Common/GPU/OpenGL/GLMemory.cpp deleted file mode 100644 index 4f93c6a79..000000000 --- a/Common/GPU/OpenGL/GLMemory.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "Common/MemoryUtil.h" -#include "Common/GPU/OpenGL/GLMemory.h" -#include "Common/GPU/OpenGL/GLRenderManager.h" -#include "Common/GPU/OpenGL/GLFeatures.h" -#include "Common/Data/Text/Parsers.h" - -extern std::thread::id renderThreadId; -#if MAX_LOGLEVEL >= DEBUG_LEVEL -static bool OnRenderThread() { - return std::this_thread::get_id() == renderThreadId; -} -#endif - -void *GLRBuffer::Map(GLBufferStrategy strategy) { - _assert_(buffer_ != 0); - - GLbitfield access = GL_MAP_WRITE_BIT; - if ((strategy & GLBufferStrategy::MASK_FLUSH) != 0) { - access |= GL_MAP_FLUSH_EXPLICIT_BIT; - } - if ((strategy & GLBufferStrategy::MASK_INVALIDATE) != 0) { - access |= GL_MAP_INVALIDATE_BUFFER_BIT; - } - - void *p = nullptr; - bool allowNativeBuffer = strategy != GLBufferStrategy::SUBDATA; - if (allowNativeBuffer) { - glBindBuffer(target_, buffer_); - - if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { -#if !PPSSPP_PLATFORM(IOS) - if (!hasStorage_) { - GLbitfield storageFlags = access & ~(GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); -#ifdef USING_GLES2 -#ifdef GL_EXT_buffer_storage - glBufferStorageEXT(target_, size_, nullptr, storageFlags); -#endif -#else - glBufferStorage(target_, size_, nullptr, storageFlags); -#endif - hasStorage_ = true; - } -#endif - p = glMapBufferRange(target_, 0, size_, access); - } else if (gl_extensions.VersionGEThan(3, 0, 0)) { - // GLES3 or desktop 3. - p = glMapBufferRange(target_, 0, size_, access); - } else if (!gl_extensions.IsGLES) { -#ifndef USING_GLES2 - p = glMapBuffer(target_, GL_READ_WRITE); -#endif - } - } - - mapped_ = p != nullptr; - return p; -} - -bool GLRBuffer::Unmap() { - glBindBuffer(target_, buffer_); - mapped_ = false; - return glUnmapBuffer(target_) == GL_TRUE; -} - -GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size, const char *tag) : render_(render), size_(size), target_(target), tag_(tag) { - bool res = AddBuffer(); - _assert_(res); - RegisterGPUMemoryManager(this); -} - -GLPushBuffer::~GLPushBuffer() { - UnregisterGPUMemoryManager(this); - Destroy(true); -} - -void GLPushBuffer::Map() { - _assert_(!writePtr_); - auto &info = buffers_[buf_]; - writePtr_ = info.deviceMemory ? info.deviceMemory : info.localMemory; - info.flushOffset = 0; - // Force alignment. This is needed for PushAligned() to work as expected. - while ((intptr_t)writePtr_ & 15) { - writePtr_++; - offset_++; - info.flushOffset++; - } - _assert_(writePtr_); -} - -void GLPushBuffer::Unmap() { - _assert_(writePtr_); - if (!buffers_[buf_].deviceMemory) { - // Here we simply upload the data to the last buffer. - // Might be worth trying with size_ instead of offset_, so the driver can replace - // the whole buffer. At least if it's close. - render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].localMemory, false); - } else { - buffers_[buf_].flushOffset = offset_; - } - writePtr_ = nullptr; -} - -void GLPushBuffer::Flush() { - // Must be called from the render thread. - _dbg_assert_(OnRenderThread()); - - if (buf_ >= buffers_.size()) { - _dbg_assert_msg_(false, "buf_ somehow got out of sync: %d vs %d", (int)buf_, (int)buffers_.size()); - return; - } - - buffers_[buf_].flushOffset = offset_; - if (!buffers_[buf_].deviceMemory && writePtr_) { - auto &info = buffers_[buf_]; - if (info.flushOffset != 0) { - _assert_(info.buffer->buffer_); - glBindBuffer(target_, info.buffer->buffer_); - glBufferSubData(target_, 0, info.flushOffset, info.localMemory); - } - - // Here we will submit all the draw calls, with the already known buffer and offsets. - // Might as well reset the write pointer here and start over the current buffer. - writePtr_ = info.localMemory; - offset_ = 0; - info.flushOffset = 0; - } - - // For device memory, we flush all buffers here. - if ((strategy_ & GLBufferStrategy::MASK_FLUSH) != 0) { - for (auto &info : buffers_) { - if (info.flushOffset == 0 || !info.deviceMemory) - continue; - - glBindBuffer(target_, info.buffer->buffer_); - glFlushMappedBufferRange(target_, 0, info.flushOffset); - info.flushOffset = 0; - } - } -} - -bool GLPushBuffer::AddBuffer() { - // INFO_LOG(G3D, "GLPushBuffer(%s): Allocating %d bytes", tag_, size_); - BufInfo info; - info.localMemory = (uint8_t *)AllocateAlignedMemory(size_, 16); - if (!info.localMemory) - return false; - info.buffer = render_->CreateBuffer(target_, size_, GL_DYNAMIC_DRAW); - info.size = size_; - buf_ = buffers_.size(); - buffers_.push_back(info); - return true; -} - -void GLPushBuffer::Destroy(bool onRenderThread) { - if (buf_ == -1) - return; // Already destroyed - for (BufInfo &info : buffers_) { - // This will automatically unmap device memory, if needed. - // NOTE: We immediately delete the buffer, don't go through the deleter, if we're on the render thread. - if (onRenderThread) { - delete info.buffer; - } else { - render_->DeleteBuffer(info.buffer); - } - FreeAlignedMemory(info.localMemory); - } - buffers_.clear(); - buf_ = -1; -} - -void GLPushBuffer::NextBuffer(size_t minSize) { - // First, unmap the current memory. - Unmap(); - - buf_++; - if (buf_ >= buffers_.size() || minSize > size_) { - // Before creating the buffer, adjust to the new size_ if necessary. - while (size_ < minSize) { - size_ <<= 1; - } - - bool res = AddBuffer(); - _assert_(res); - if (!res) { - // Let's try not to crash at least? - buf_ = 0; - } - } - - // Now, move to the next buffer and map it. - offset_ = 0; - Map(); -} - -void GLPushBuffer::Defragment() { - _dbg_assert_msg_(!OnRenderThread(), "Defragment must not run on the render thread"); - - if (buffers_.size() <= 1) { - // Let's take this opportunity to jettison any localMemory we don't need. - for (auto &info : buffers_) { - if (info.deviceMemory) { - FreeAlignedMemory(info.localMemory); - info.localMemory = nullptr; - } - } - - return; - } - - // Okay, we have more than one. Destroy them all and start over with a larger one. - - // When calling AddBuffer, we sometimes increase size_. So if we allocated multiple buffers in a frame, - // they won't all have the same size. Sum things up properly. - size_t newSize = 0; - for (int i = 0; i < (int)buffers_.size(); i++) { - newSize += buffers_[i].size; - } - - Destroy(false); - - // Set some sane but very free limits. If there's another spike, we'll just allocate more anyway. - size_ = std::min(std::max(newSize, (size_t)65536), (size_t)(512 * 1024 * 1024)); - bool res = AddBuffer(); - _assert_msg_(res, "AddBuffer failed"); -} - -size_t GLPushBuffer::GetTotalSize() const { - size_t sum = 0; - // When calling AddBuffer, we sometimes increase size_. So if we allocated multiple buffers in a frame, - // they won't all have the same size. Sum things up properly. - if (buffers_.size() > 1) { - for (int i = 0; i < (int)buffers_.size() - 1; i++) { - sum += buffers_[i].size; - } - } - sum += offset_; - return sum; -} - -void GLPushBuffer::MapDevice(GLBufferStrategy strategy) { - _dbg_assert_msg_(OnRenderThread(), "MapDevice must run on render thread"); - - strategy_ = strategy; - if (strategy_ == GLBufferStrategy::SUBDATA) { - return; - } - - bool mapChanged = false; - for (auto &info : buffers_) { - if (!info.buffer->buffer_ || info.deviceMemory) { - // Can't map - no device buffer associated yet or already mapped. - continue; - } - - info.deviceMemory = (uint8_t *)info.buffer->Map(strategy_); - mapChanged = mapChanged || info.deviceMemory != nullptr; - - if (!info.deviceMemory && !info.localMemory) { - // Somehow it failed, let's dodge crashing. - info.localMemory = (uint8_t *)AllocateAlignedMemory(info.buffer->size_, 16); - mapChanged = true; - } - - _dbg_assert_msg_(info.localMemory || info.deviceMemory, "Local or device memory must succeed"); - } - - if (writePtr_ && mapChanged) { - // This can happen during a sync. Remap. - writePtr_ = nullptr; - Map(); - } -} - -void GLPushBuffer::UnmapDevice() { - _dbg_assert_msg_(OnRenderThread(), "UnmapDevice must run on render thread"); - - for (auto &info : buffers_) { - if (info.deviceMemory) { - // TODO: Technically this can return false? - info.buffer->Unmap(); - info.deviceMemory = nullptr; - } - } -} - -void GLPushBuffer::GetDebugString(char *buffer, size_t bufSize) const { - snprintf(buffer, bufSize, "%s: %s/%s (%d)", tag_, NiceSizeFormat(this->offset_).c_str(), NiceSizeFormat(this->size_).c_str(), (int)buffers_.size()); -} diff --git a/Common/GPU/OpenGL/GLMemory.h b/Common/GPU/OpenGL/GLMemory.h deleted file mode 100644 index cb0fa509a..000000000 --- a/Common/GPU/OpenGL/GLMemory.h +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "Common/GPU/GPUBackendCommon.h" -#include "Common/GPU/OpenGL/GLCommon.h" -#include "Common/Log.h" - -enum class GLBufferStrategy { - SUBDATA = 0, - - MASK_FLUSH = 0x10, - MASK_INVALIDATE = 0x20, - - // Map/unmap the buffer each frame. - FRAME_UNMAP = 1, - // Map/unmap and also invalidate the buffer on map. - INVALIDATE_UNMAP = MASK_INVALIDATE, - // Map/unmap and explicitly flushed changed ranges. - FLUSH_UNMAP = MASK_FLUSH, - // Map/unmap, invalidate on map, and explicit flush. - FLUSH_INVALIDATE_UNMAP = MASK_FLUSH | MASK_INVALIDATE, -}; - -static inline int operator &(const GLBufferStrategy &lhs, const GLBufferStrategy &rhs) { - return (int)lhs & (int)rhs; -} - -class GLRBuffer { -public: - GLRBuffer(GLuint target, size_t size) : target_(target), size_((int)size) {} - ~GLRBuffer() { - if (buffer_) { - glDeleteBuffers(1, &buffer_); - } - } - - void *Map(GLBufferStrategy strategy); - bool Unmap(); - - bool Mapped() const { - return mapped_; - } - - GLuint buffer_ = 0; - GLuint target_; - int size_; - -private: - bool mapped_ = false; - bool hasStorage_ = false; -}; - -class GLRenderManager; - -// Similar to VulkanPushBuffer but is currently less efficient - it collects all the data in -// RAM then does a big memcpy/buffer upload at the end of the frame. This is at least a lot -// faster than the hundreds of buffer uploads or memory array buffers we used before. -// On modern GL we could avoid the copy using glBufferStorage but not sure it's worth the -// trouble. -// We need to manage the lifetime of this together with the other resources so its destructor -// runs on the render thread. -class GLPushBuffer : public GPUMemoryManager { -public: - friend class GLRenderManager; - - struct BufInfo { - GLRBuffer *buffer = nullptr; - uint8_t *localMemory = nullptr; - uint8_t *deviceMemory = nullptr; - size_t flushOffset = 0; - size_t size; - }; - - GLPushBuffer(GLRenderManager *render, GLuint target, size_t size, const char *tag); - ~GLPushBuffer(); - - void Reset() { offset_ = 0; } - - void GetDebugString(char *buffer, size_t bufSize) const override; - - const char *Name() const override { return tag_; }; // for sorting - - // Utility for users of this class, not used internally. - enum { INVALID_OFFSET = 0xFFFFFFFF }; - -private: - // Needs context in case of defragment. - void Begin() { - buf_ = 0; - offset_ = 0; - // Note: we must defrag because some buffers may be smaller than size_. - Defragment(); - Map(); - _dbg_assert_(writePtr_); - } - - void BeginNoReset() { - Map(); - } - - void End() { - Unmap(); - } - -public: - void Map(); - void Unmap(); - - bool IsReady() const { - return writePtr_ != nullptr; - } - - // Recommended - lets you write directly into the buffer through the returned pointer. - // If you didn't end up using all the memory you grabbed here, then before calling Allocate or Push - // again, call Rewind (see below). - uint8_t *Allocate(uint32_t numBytes, uint32_t alignment, GLRBuffer **buf, uint32_t *bindOffset) { - uint32_t offset = ((uint32_t)offset_ + alignment - 1) & ~(alignment - 1); - if (offset + numBytes <= size_) { - // Common path. - offset_ = offset + numBytes; - *buf = buffers_[buf_].buffer; - *bindOffset = offset; - return writePtr_ + offset; - } - - NextBuffer(numBytes); - *bindOffset = 0; - *buf = buffers_[buf_].buffer; - // Need to mark the allocated range used in the new buffer. How did things work before this? - offset_ = numBytes; - return writePtr_; - } - - // For convenience if all you'll do is to copy. - uint32_t Push(const void *data, uint32_t numBytes, int alignment, GLRBuffer **buf) { - uint32_t bindOffset; - uint8_t *ptr = Allocate(numBytes, alignment, buf, &bindOffset); - memcpy(ptr, data, numBytes); - return bindOffset; - } - - uint8_t *GetPtr(uint32_t offset) { - return writePtr_ + offset; - } - - // If you didn't use all of the previous allocation you just made (obviously can't be another one), - // you can return memory to the buffer by specifying the offset up until which you wrote data. - // Pass in the buffer you got last time. If that buffer has been filled already, no rewind can be safely done. - // (well technically would be possible but not worth the trouble). - void Rewind(GLRBuffer *buffer, uint32_t offset) { - if (buffer == buffers_[buf_].buffer) { - _dbg_assert_(offset != INVALID_OFFSET); - _dbg_assert_(offset <= offset_); - offset_ = offset; - } - } - - size_t GetOffset() const { return offset_; } - size_t GetTotalSize() const; - - void Destroy(bool onRenderThread); - void Flush(); - -protected: - void MapDevice(GLBufferStrategy strategy); - void UnmapDevice(); - -private: - bool AddBuffer(); - void NextBuffer(size_t minSize); - void Defragment(); - - GLRenderManager *render_; - std::vector buffers_; - size_t buf_ = 0; - size_t offset_ = 0; - size_t size_ = 0; - uint8_t *writePtr_ = nullptr; - GLuint target_; - GLBufferStrategy strategy_ = GLBufferStrategy::SUBDATA; - const char *tag_; -}; diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index c4b5533b3..9c0e19e7e 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -73,9 +73,7 @@ void GLQueueRunner::CreateDeviceObjects() { populate(GL_SHADING_LANGUAGE_VERSION); CHECK_GL_ERROR_IF_DEBUG(); -#if !PPSSPP_ARCH(X86) // Doesn't work on AMD for some reason. See issue #17787 useDebugGroups_ = !gl_extensions.IsGLES && gl_extensions.VersionGEThan(4, 3); -#endif } void GLQueueRunner::DestroyDeviceObjects() { @@ -120,7 +118,7 @@ static std::string GetStereoBufferLayout(const char *uniformName) { else return "undefined"; } -void GLQueueRunner::RunInitSteps(const FastVec &steps, bool skipGLCalls) { +void GLQueueRunner::RunInitSteps(const std::vector &steps, bool skipGLCalls) { if (skipGLCalls) { // Some bookkeeping still needs to be done. for (size_t i = 0; i < steps.size(); i++) { @@ -334,10 +332,10 @@ void GLQueueRunner::RunInitSteps(const FastVec &steps, bool skipGLC step.create_shader.shader->desc.c_str(), infoLog.c_str(), LineNumberString(code).c_str()); - std::vector lines; + std::vector lines; SplitString(errorString, '\n', lines); - for (auto line : lines) { - ERROR_LOG(G3D, "%.*s", (int)line.size(), line.data()); + for (auto &line : lines) { + ERROR_LOG(G3D, "%s", line.c_str()); } if (errorCallback_) { std::string desc = StringFromFormat("Shader compilation failed: %s", step.create_shader.stage == GL_VERTEX_SHADER ? "vertex" : "fragment"); @@ -653,7 +651,7 @@ retry_depth: currentReadHandle_ = fbo->handle; } -void GLQueueRunner::RunSteps(const std::vector &steps, GLFrameData &frameData, bool skipGLCalls, bool keepSteps, bool useVR) { +void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps, bool useVR, GLQueueProfileContext &profile) { if (skipGLCalls) { if (keepSteps) { return; @@ -702,7 +700,7 @@ void GLQueueRunner::RunSteps(const std::vector &steps, GLFrameData &f CHECK_GL_ERROR_IF_DEBUG(); size_t renderCount = 0; for (size_t i = 0; i < steps.size(); i++) { - GLRStep &step = *steps[i]; + const GLRStep &step = *steps[i]; #if !defined(USING_GLES2) if (useDebugGroups_) @@ -713,10 +711,11 @@ void GLQueueRunner::RunSteps(const std::vector &steps, GLFrameData &f case GLRStepType::RENDER: renderCount++; if (IsVREnabled()) { - PreprocessStepVR(&step); - PerformRenderPass(step, renderCount == 1, renderCount == totalRenderCount, frameData.profile); + GLRStep vrStep = step; + PreprocessStepVR(&vrStep); + PerformRenderPass(vrStep, renderCount == 1, renderCount == totalRenderCount, profile); } else { - PerformRenderPass(step, renderCount == 1, renderCount == totalRenderCount, frameData.profile); + PerformRenderPass(step, renderCount == 1, renderCount == totalRenderCount, profile); } break; case GLRStepType::COPY: @@ -742,14 +741,11 @@ void GLQueueRunner::RunSteps(const std::vector &steps, GLFrameData &f if (useDebugGroups_) glPopDebugGroup(); #endif - if (frameData.profile.enabled) { - frameData.profile.passesString += StepToString(step); - } + if (!keepSteps) { delete steps[i]; } } - CHECK_GL_ERROR_IF_DEBUG(); } @@ -838,45 +834,19 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last bool logicEnabled = false; #endif bool clipDistanceEnabled[8]{}; + + bool lastDrawIsArray = false; + int lastBindOffset = 0; + GLRInputLayout *lastDrawLayout = nullptr; + GLuint blendEqColor = (GLuint)-1; GLuint blendEqAlpha = (GLuint)-1; - GLenum blendSrcColor = (GLenum)-1; - GLenum blendDstColor = (GLenum)-1; - GLenum blendSrcAlpha = (GLenum)-1; - GLenum blendDstAlpha = (GLenum)-1; - GLuint stencilWriteMask = (GLuint)-1; - GLenum stencilFunc = (GLenum)-1; - GLuint stencilRef = (GLuint)-1; - GLuint stencilCompareMask = (GLuint)-1; - GLenum stencilSFail = (GLenum)-1; - GLenum stencilZFail = (GLenum)-1; - GLenum stencilPass = (GLenum)-1; - GLenum frontFace = (GLenum)-1; - GLenum cullFace = (GLenum)-1; GLRTexture *curTex[MAX_GL_TEXTURE_SLOTS]{}; - GLRViewport viewport = { - -1000000000.0f, - -1000000000.0f, - -1000000000.0f, - -1000000000.0f, - -1000000000.0f, - -1000000000.0f, - }; - - GLRect2D scissorRc = { -1, -1, -1, -1 }; - CHECK_GL_ERROR_IF_DEBUG(); auto &commands = step.commands; for (const auto &c : commands) { -#ifdef _DEBUG - if (profile.enabled) { - if ((size_t)c.cmd < ARRAY_SIZE(profile.commandCounts)) { - profile.commandCounts[(size_t)c.cmd]++; - } - } -#endif switch (c.cmd) { case GLRRenderCommand::DEPTH: if (c.depth.enabled) { @@ -897,34 +867,23 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last depthEnabled = false; } break; - case GLRRenderCommand::STENCIL: - if (c.stencil.enabled) { + case GLRRenderCommand::STENCILFUNC: + if (c.stencilFunc.enabled) { if (!stencilEnabled) { glEnable(GL_STENCIL_TEST); stencilEnabled = true; } - if (c.stencil.func != stencilFunc || c.stencil.ref != stencilRef || c.stencil.compareMask != stencilCompareMask) { - glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask); - stencilFunc = c.stencil.func; - stencilRef = c.stencil.ref; - stencilCompareMask = c.stencil.compareMask; - } - if (c.stencil.sFail != stencilSFail || c.stencil.zFail != stencilZFail || c.stencil.pass != stencilPass) { - glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass); - stencilSFail = c.stencil.sFail; - stencilZFail = c.stencil.zFail; - stencilPass = c.stencil.pass; - } - if (c.stencil.writeMask != stencilWriteMask) { - glStencilMask(c.stencil.writeMask); - stencilWriteMask = c.stencil.writeMask; - } + glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); } else if (/* !c.stencilFunc.enabled && */stencilEnabled) { glDisable(GL_STENCIL_TEST); stencilEnabled = false; } CHECK_GL_ERROR_IF_DEBUG(); break; + case GLRRenderCommand::STENCILOP: + glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass); + glStencilMask(c.stencilOp.writeMask); + break; case GLRRenderCommand::BLEND: if (c.blend.enabled) { if (!blendEnabled) { @@ -936,13 +895,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last blendEqColor = c.blend.funcColor; blendEqAlpha = c.blend.funcAlpha; } - if (blendSrcColor != c.blend.srcColor || blendDstColor != c.blend.dstColor || blendSrcAlpha != c.blend.srcAlpha || blendDstAlpha != c.blend.dstAlpha) { - glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha); - blendSrcColor = c.blend.srcColor; - blendDstColor = c.blend.dstColor; - blendSrcAlpha = c.blend.srcAlpha; - blendDstAlpha = c.blend.dstAlpha; - } + glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha); } else if (/* !c.blend.enabled && */ blendEnabled) { glDisable(GL_BLEND); blendEnabled = false; @@ -1020,27 +973,16 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last y = curFBHeight_ - y - c.viewport.vp.h; // TODO: Support FP viewports through glViewportArrays - if (viewport.x != c.viewport.vp.x || viewport.y != y || viewport.w != c.viewport.vp.w || viewport.h != c.viewport.vp.h) { - glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h); - viewport.x = c.viewport.vp.x; - viewport.y = y; - viewport.w = c.viewport.vp.w; - viewport.h = c.viewport.vp.h; - } - - if (viewport.minZ != c.viewport.vp.minZ || viewport.maxZ != c.viewport.vp.maxZ) { - viewport.minZ = c.viewport.vp.minZ; - viewport.maxZ = c.viewport.vp.maxZ; + glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h); #if !defined(USING_GLES2) - if (gl_extensions.IsGLES) { - glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ); - } else { - glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ); - } -#else + if (gl_extensions.IsGLES) { glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ); -#endif + } else { + glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ); } +#else + glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ); +#endif CHECK_GL_ERROR_IF_DEBUG(); break; } @@ -1049,13 +991,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last int y = c.scissor.rc.y; if (!curFB_) y = curFBHeight_ - y - c.scissor.rc.h; - if (scissorRc.x != c.scissor.rc.x || scissorRc.y != y || scissorRc.w != c.scissor.rc.w || scissorRc.h != c.scissor.rc.h) { - glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h); - scissorRc.x = c.scissor.rc.x; - scissorRc.y = y; - scissorRc.w = c.scissor.rc.w; - scissorRc.h = c.scissor.rc.h; - } + glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h); CHECK_GL_ERROR_IF_DEBUG(); break; } @@ -1238,36 +1174,63 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last } case GLRRenderCommand::DRAW: { + // TODO: Add fast path for glBindVertexBuffer GLRInputLayout *layout = c.draw.inputLayout; - GLuint buf = c.draw.vertexBuffer->buffer_; - _dbg_assert_(!c.draw.vertexBuffer->Mapped()); + GLuint buf = c.draw.buffer ? c.draw.buffer->buffer_ : 0; + _dbg_assert_(!c.draw.buffer || !c.draw.buffer->Mapped()); if (buf != curArrayBuffer) { glBindBuffer(GL_ARRAY_BUFFER, buf); curArrayBuffer = buf; + // Invalidate any draw offset caching. + lastDrawLayout = nullptr; } + if (attrMask != layout->semanticsMask_) { EnableDisableVertexArrays(attrMask, layout->semanticsMask_); attrMask = layout->semanticsMask_; } - for (size_t i = 0; i < layout->entries.size(); i++) { - auto &entry = layout->entries[i]; - glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, layout->stride, (const void *)(c.draw.vertexOffset + entry.offset)); - } if (c.draw.indexBuffer) { + for (size_t i = 0; i < layout->entries.size(); i++) { + auto &entry = layout->entries[i]; + glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, layout->stride, (const void *)(c.draw.offset + entry.offset)); + } GLuint buf = c.draw.indexBuffer->buffer_; - _dbg_assert_(!c.draw.indexBuffer->Mapped()); + _dbg_assert_(!(c.draw.indexBuffer && c.draw.indexBuffer->Mapped())); if (buf != curElemArrayBuffer) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); curElemArrayBuffer = buf; } if (c.draw.instances == 1) { - glDrawElements(c.draw.mode, c.draw.count, c.draw.indexType, (void *)(intptr_t)c.draw.indexOffset); + glDrawElements(c.draw.mode, c.draw.count, c.draw.indexType, c.draw.indices); } else { - glDrawElementsInstanced(c.draw.mode, c.draw.count, c.draw.indexType, (void *)(intptr_t)c.draw.indexOffset, c.draw.instances); + glDrawElementsInstanced(c.draw.mode, c.draw.count, c.draw.indexType, c.draw.indices, c.draw.instances); } + lastDrawIsArray = false; } else { - glDrawArrays(c.draw.mode, c.draw.first, c.draw.count); + // See if we can avoid calling glVertexAttribPointer. + int offset = 0; + bool rebind = true; + if (lastDrawIsArray && layout == lastDrawLayout) { + unsigned int diff = (unsigned int)c.draw.offset - (unsigned int)lastBindOffset; + if (diff % layout->stride == 0) { + // Compatible draws. + offset = diff / layout->stride; + rebind = false; + profile.drawArraysRebindsAvoided++; + } + } + if (rebind) { + // Rebind. + for (size_t i = 0; i < layout->entries.size(); i++) { + auto &entry = layout->entries[i]; + glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, layout->stride, (const void *)(c.draw.offset + entry.offset)); + } + lastBindOffset = (int)c.draw.offset; + } + glDrawArrays(c.draw.mode, c.draw.first + offset, c.draw.count); + lastDrawIsArray = true; } + lastDrawLayout = layout; CHECK_GL_ERROR_IF_DEBUG(); break; } @@ -1378,14 +1341,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last glEnable(GL_CULL_FACE); cullEnabled = true; } - if (frontFace != c.raster.frontFace) { - glFrontFace(c.raster.frontFace); - frontFace = c.raster.frontFace; - } - if (cullFace != c.raster.cullFace) { - glCullFace(c.raster.cullFace); - cullFace = c.raster.cullFace; - } + glFrontFace(c.raster.frontFace); + glCullFace(c.raster.cullFace); } else if (/* !c.raster.cullEnable && */ cullEnabled) { glDisable(GL_CULL_FACE); cullEnabled = false; @@ -1853,74 +1810,3 @@ GLRFramebuffer::~GLRFramebuffer() { glDeleteRenderbuffers(1, &stencil_buffer); CHECK_GL_ERROR_IF_DEBUG(); } - -std::string GLQueueRunner::StepToString(const GLRStep &step) const { - char buffer[256]; - switch (step.stepType) { - case GLRStepType::RENDER: - { - int w = step.render.framebuffer ? step.render.framebuffer->width : targetWidth_; - int h = step.render.framebuffer ? step.render.framebuffer->height : targetHeight_; - snprintf(buffer, sizeof(buffer), "RENDER %s %s (commands: %d, %dx%d)\n", step.tag, step.render.framebuffer ? step.render.framebuffer->Tag() : "", (int)step.commands.size(), w, h); - break; - } - case GLRStepType::COPY: - snprintf(buffer, sizeof(buffer), "COPY '%s' %s -> %s (%dx%d, %s)\n", step.tag, step.copy.src->Tag(), step.copy.dst->Tag(), step.copy.srcRect.w, step.copy.srcRect.h, GLRAspectToString((GLRAspect)step.copy.aspectMask)); - break; - case GLRStepType::BLIT: - snprintf(buffer, sizeof(buffer), "BLIT '%s' %s -> %s (%dx%d->%dx%d, %s)\n", step.tag, step.copy.src->Tag(), step.copy.dst->Tag(), step.blit.srcRect.w, step.blit.srcRect.h, step.blit.dstRect.w, step.blit.dstRect.h, GLRAspectToString((GLRAspect)step.blit.aspectMask)); - break; - case GLRStepType::READBACK: - snprintf(buffer, sizeof(buffer), "READBACK '%s' %s (%dx%d, %s)\n", step.tag, step.readback.src ? step.readback.src->Tag() : "(backbuffer)", step.readback.srcRect.w, step.readback.srcRect.h, GLRAspectToString((GLRAspect)step.readback.aspectMask)); - break; - case GLRStepType::READBACK_IMAGE: - snprintf(buffer, sizeof(buffer), "READBACK_IMAGE '%s' (%dx%d)\n", step.tag, step.readback_image.srcRect.w, step.readback_image.srcRect.h); - break; - case GLRStepType::RENDER_SKIP: - snprintf(buffer, sizeof(buffer), "(RENDER_SKIP) %s\n", step.tag); - break; - default: - buffer[0] = 0; - break; - } - return std::string(buffer); -} - -const char *GLRAspectToString(GLRAspect aspect) { - switch (aspect) { - case GLR_ASPECT_COLOR: return "COLOR"; - case GLR_ASPECT_DEPTH: return "DEPTH"; - case GLR_ASPECT_STENCIL: return "STENCIL"; - default: return "N/A"; - } -} - -const char *RenderCommandToString(GLRRenderCommand cmd) { - switch (cmd) { - case GLRRenderCommand::DEPTH: return "DEPTH"; - case GLRRenderCommand::STENCIL: return "STENCIL"; - case GLRRenderCommand::BLEND: return "BLEND"; - case GLRRenderCommand::BLENDCOLOR: return "BLENDCOLOR"; - case GLRRenderCommand::LOGICOP: return "LOGICOP"; - case GLRRenderCommand::UNIFORM4I: return "UNIFORM4I"; - case GLRRenderCommand::UNIFORM4UI: return "UNIFORM4UI"; - case GLRRenderCommand::UNIFORM4F: return "UNIFORM4F"; - case GLRRenderCommand::UNIFORMMATRIX: return "UNIFORMMATRIX"; - case GLRRenderCommand::UNIFORMSTEREOMATRIX: return "UNIFORMSTEREOMATRIX"; - case GLRRenderCommand::TEXTURESAMPLER: return "TEXTURESAMPLER"; - case GLRRenderCommand::TEXTURELOD: return "TEXTURELOD"; - case GLRRenderCommand::VIEWPORT: return "VIEWPORT"; - case GLRRenderCommand::SCISSOR: return "SCISSOR"; - case GLRRenderCommand::RASTER: return "RASTER"; - case GLRRenderCommand::CLEAR: return "CLEAR"; - case GLRRenderCommand::INVALIDATE: return "INVALIDATE"; - case GLRRenderCommand::BINDPROGRAM: return "BINDPROGRAM"; - case GLRRenderCommand::BINDTEXTURE: return "BINDTEXTURE"; - case GLRRenderCommand::BIND_FB_TEXTURE: return "BIND_FB_TEXTURE"; - case GLRRenderCommand::BIND_VERTEX_BUFFER: return "BIND_VERTEX_BUFFER"; - case GLRRenderCommand::GENMIPS: return "GENMIPS"; - case GLRRenderCommand::DRAW: return "DRAW"; - case GLRRenderCommand::TEXTURE_SUBIMAGE: return "TEXTURE_SUBIMAGE"; - default: return "N/A"; - } -} diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index df86b9565..1aa7398ea 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -11,7 +11,7 @@ #include "Common/GPU/Shader.h" #include "Common/GPU/thin3d.h" #include "Common/Data/Collections/TinySet.h" -#include "Common/Data/Collections/FastVec.h" + struct GLRViewport { float x, y, w, h, minZ, maxZ; @@ -40,7 +40,8 @@ class GLRInputLayout; enum class GLRRenderCommand : uint8_t { DEPTH, - STENCIL, + STENCILFUNC, + STENCILOP, BLEND, BLENDCOLOR, LOGICOP, @@ -69,7 +70,6 @@ enum class GLRRenderCommand : uint8_t { // type field, smashed right after each other?) // Also, all GLenums are really only 16 bits. struct GLRRenderData { - GLRRenderData(GLRRenderCommand _cmd) : cmd(_cmd) {} GLRRenderCommand cmd; union { struct { @@ -99,21 +99,23 @@ struct GLRRenderData { GLenum func; uint8_t ref; uint8_t compareMask; + } stencilFunc; + struct { GLenum sFail; GLenum zFail; GLenum pass; uint8_t writeMask; - } stencil; + } stencilOp; // also write mask struct { GLRInputLayout *inputLayout; - GLRBuffer *vertexBuffer; + GLRBuffer *buffer; + size_t offset; GLRBuffer *indexBuffer; - uint32_t vertexOffset; - uint32_t indexOffset; GLenum mode; // primitive GLint first; GLint count; GLint indexType; + void *indices; GLint instances; } draw; struct { @@ -290,17 +292,16 @@ enum class GLRRenderPassAction { class GLRFramebuffer; -enum GLRAspect { +enum { GLR_ASPECT_COLOR = 1, GLR_ASPECT_DEPTH = 2, GLR_ASPECT_STENCIL = 3, }; -const char *GLRAspectToString(GLRAspect aspect); struct GLRStep { GLRStep(GLRStepType _type) : stepType(_type) {} GLRStepType stepType; - FastVec commands; + std::vector commands; TinySet dependencies; const char *tag; union { @@ -309,6 +310,8 @@ struct GLRStep { GLRRenderPassAction color; GLRRenderPassAction depth; GLRRenderPassAction stencil; + // Note: not accurate. + int numDraws; } render; struct { GLRFramebuffer *src; @@ -352,9 +355,9 @@ public: caps_ = caps; } - void RunInitSteps(const FastVec &steps, bool skipGLCalls); + void RunInitSteps(const std::vector &steps, bool skipGLCalls); - void RunSteps(const std::vector &steps, GLFrameData &frameData, bool skipGLCalls, bool keepSteps, bool useVR); + void RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps, bool useVR, GLQueueProfileContext &profile); void CreateDeviceObjects(); void DestroyDeviceObjects(); @@ -390,8 +393,6 @@ private: GLenum fbo_get_fb_target(bool read, GLuint **cached); void fbo_unbind(); - std::string StepToString(const GLRStep &step) const; - GLRFramebuffer *curFB_ = nullptr; GLuint globalVAO_ = 0; @@ -423,5 +424,3 @@ private: ErrorCallbackFn errorCallback_ = nullptr; void *errorCallbackUserData_ = nullptr; }; - -const char *RenderCommandToString(GLRRenderCommand cmd); diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index d6adbff77..7cfcce91c 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -17,7 +17,12 @@ #define VLOG(...) #endif -std::thread::id renderThreadId; +static std::thread::id renderThreadId; +#if MAX_LOGLEVEL >= DEBUG_LEVEL +static bool OnRenderThread() { + return std::this_thread::get_id() == renderThreadId; +} +#endif GLRTexture::GLRTexture(const Draw::DeviceCaps &caps, int width, int height, int depth, int numMips) { if (caps.textureNPOTFullySupported) { @@ -37,7 +42,7 @@ GLRTexture::~GLRTexture() { } } -GLRenderManager::GLRenderManager(HistoryBuffer &frameTimeHistory) : frameTimeHistory_(frameTimeHistory) { +GLRenderManager::GLRenderManager() { // size_t sz = sizeof(GLRRenderData); // _dbg_assert_(sz == 88); } @@ -129,25 +134,25 @@ bool GLRenderManager::ThreadFrame() { return false; } - GLRRenderThreadTask *task = nullptr; + GLRRenderThreadTask task; // In case of syncs or other partial completion, we keep going until we complete a frame. while (true) { // Pop a task of the queue and execute it. // NOTE: We need to actually wait for a task, we can't just bail! + { std::unique_lock lock(pushMutex_); while (renderThreadQueue_.empty()) { pushCondVar_.wait(lock); } - task = std::move(renderThreadQueue_.front()); + task = renderThreadQueue_.front(); renderThreadQueue_.pop(); } // We got a task! We can now have pushMutex_ unlocked, allowing the host to // push more work when it feels like it, and just start working. - if (task->runType == GLRRunType::EXIT) { - delete task; + if (task.runType == GLRRunType::EXIT) { // Oh, host wanted out. Let's leave, and also let's notify the host. // This is unlike Vulkan too which can just block on the thread existing. std::unique_lock lock(syncMutex_); @@ -157,13 +162,11 @@ bool GLRenderManager::ThreadFrame() { } // Render the scene. - VLOG(" PULL: Frame %d RUN (%0.3f)", task->frame, time_now_d()); - if (Run(*task)) { + VLOG(" PULL: Frame %d RUN (%0.3f)", task.frame, time_now_d()); + if (Run(task)) { // Swap requested, so we just bail the loop. - delete task; break; } - delete task; }; return true; @@ -176,7 +179,9 @@ void GLRenderManager::StopThread() { run_ = false; std::unique_lock lock(pushMutex_); - renderThreadQueue_.push(new GLRRenderThreadTask(GLRRunType::EXIT)); + GLRRenderThreadTask exitTask{}; + exitTask.runType = GLRRunType::EXIT; + renderThreadQueue_.push(exitTask); pushCondVar_.notify_one(); } else { WARN_LOG(G3D, "GL submission thread was already paused."); @@ -184,11 +189,15 @@ void GLRenderManager::StopThread() { } std::string GLRenderManager::GetGpuProfileString() const { - int curFrame = curFrame_; + int curFrame = GetCurFrame(); const GLQueueProfileContext &profile = frameData_[curFrame].profile; float cputime_ms = 1000.0f * (profile.cpuEndTime - profile.cpuStartTime); - return StringFromFormat("CPU time to run the list: %0.2f ms\n\n%s", cputime_ms, profilePassesString_.c_str()); + return StringFromFormat( + "CPU time to run the list: %0.2f ms\n" + "Avoided DrawArrays rebinds: %d", + cputime_ms, + profile.drawArraysRebindsAvoided); } void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) { @@ -215,11 +224,13 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende step->render.color = color; step->render.depth = depth; step->render.stencil = stencil; + step->render.numDraws = 0; step->tag = tag; steps_.push_back(step); GLuint clearMask = 0; - GLRRenderData data(GLRRenderCommand::CLEAR); + GLRRenderData data; + data.cmd = GLRRenderCommand::CLEAR; if (color == GLRRenderPassAction::CLEAR) { clearMask |= GL_COLOR_BUFFER_BIT; data.clear.clearColor = clearColor; @@ -350,18 +361,11 @@ void GLRenderManager::BeginFrame(bool enableProfiling) { int curFrame = GetCurFrame(); - FrameTimeData &frameTimeData = frameTimeHistory_.Add(frameIdGen_); - frameTimeData.frameBegin = time_now_d(); - frameTimeData.afterFenceWait = frameTimeData.frameBegin; - GLFrameData &frameData = frameData_[curFrame]; - frameData.frameId = frameIdGen_; frameData.profile.enabled = enableProfiling; - - frameIdGen_++; { - std::unique_lock lock(frameData.fenceMutex); VLOG("PUSH: BeginFrame (curFrame = %d, readyForFence = %d, time=%0.3f)", curFrame, (int)frameData.readyForFence, time_now_d()); + std::unique_lock lock(frameData.fenceMutex); while (!frameData.readyForFence) { frameData.fenceCondVar.wait(lock); } @@ -378,100 +382,37 @@ void GLRenderManager::BeginFrame(bool enableProfiling) { void GLRenderManager::Finish() { curRenderStep_ = nullptr; // EndCurRenderStep is this simple here. - int curFrame = curFrame_; + int curFrame = GetCurFrame(); GLFrameData &frameData = frameData_[curFrame]; - frameTimeHistory_[frameData.frameId].firstSubmit = time_now_d(); - frameData_[curFrame].deleter.Take(deleter_); - if (frameData.profile.enabled) { - profilePassesString_ = std::move(frameData.profile.passesString); - -#ifdef _DEBUG - std::string cmdString; - for (int i = 0; i < ARRAY_SIZE(frameData.profile.commandCounts); i++) { - if (frameData.profile.commandCounts[i] > 0) { - cmdString += StringFromFormat("%s: %d\n", RenderCommandToString((GLRRenderCommand)i), frameData.profile.commandCounts[i]); - } - } - memset(frameData.profile.commandCounts, 0, sizeof(frameData.profile.commandCounts)); - profilePassesString_ = cmdString + profilePassesString_; -#endif - - frameData.profile.passesString.clear(); - } - VLOG("PUSH: Finish, pushing task. curFrame = %d", curFrame); - GLRRenderThreadTask *task = new GLRRenderThreadTask(GLRRunType::SUBMIT); - task->frame = curFrame; + GLRRenderThreadTask task; + task.frame = curFrame; + task.runType = GLRRunType::PRESENT; + { std::unique_lock lock(pushMutex_); renderThreadQueue_.push(task); - renderThreadQueue_.back()->initSteps = std::move(initSteps_); - renderThreadQueue_.back()->steps = std::move(steps_); + renderThreadQueue_.back().initSteps = std::move(initSteps_); + renderThreadQueue_.back().steps = std::move(steps_); initSteps_.clear(); steps_.clear(); pushCondVar_.notify_one(); } -} -void GLRenderManager::Present() { - GLRRenderThreadTask *presentTask = new GLRRenderThreadTask(GLRRunType::PRESENT); - presentTask->frame = curFrame_; - { - std::unique_lock lock(pushMutex_); - renderThreadQueue_.push(presentTask); - pushCondVar_.notify_one(); - } - - int newCurFrame = curFrame_ + 1; - if (newCurFrame >= inflightFrames_) { - newCurFrame = 0; - } - curFrame_ = newCurFrame; + curFrame_++; + if (curFrame_ >= inflightFrames_) + curFrame_ = 0; insideFrame_ = false; } // Render thread. Returns true if the caller should handle a swap. bool GLRenderManager::Run(GLRRenderThreadTask &task) { - _dbg_assert_(task.frame >= 0); - GLFrameData &frameData = frameData_[task.frame]; - if (task.runType == GLRRunType::PRESENT) { - bool swapRequest = false; - if (!frameData.skipSwap) { - frameTimeHistory_[frameData.frameId].queuePresent = time_now_d(); - if (swapIntervalChanged_) { - swapIntervalChanged_ = false; - if (swapIntervalFunction_) { - swapIntervalFunction_(swapInterval_); - } - } - // This is the swapchain framebuffer flip. - if (swapFunction_) { - VLOG(" PULL: SwapFunction()"); - swapFunction_(); - } - swapRequest = true; - } else { - frameData.skipSwap = false; - } - frameData.hasBegun = false; - - VLOG(" PULL: Frame %d.readyForFence = true", task.frame); - - { - std::lock_guard lock(frameData.fenceMutex); - frameData.readyForFence = true; - frameData.fenceCondVar.notify_one(); - // At this point, we're done with this framedata (for now). - } - return swapRequest; - } - if (!frameData.hasBegun) { frameData.hasBegun = true; @@ -492,17 +433,18 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) { if (frameData.profile.enabled) { frameData.profile.cpuStartTime = time_now_d(); + frameData.profile.drawArraysRebindsAvoided = 0; } if (IsVREnabled()) { int passes = GetVRPassesCount(); for (int i = 0; i < passes; i++) { PreVRFrameRender(i); - queueRunner_.RunSteps(task.steps, frameData, skipGLCalls_, i < passes - 1, true); + queueRunner_.RunSteps(task.steps, skipGLCalls_, i < passes - 1, true, frameData.profile); PostVRFrameRender(); } } else { - queueRunner_.RunSteps(task.steps, frameData, skipGLCalls_, false, false); + queueRunner_.RunSteps(task.steps, skipGLCalls_, false, false, frameData.profile); } if (frameData.profile.enabled) { @@ -515,8 +457,43 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) { } } + bool swapRequest = false; + switch (task.runType) { - case GLRRunType::SUBMIT: + case GLRRunType::PRESENT: + if (!frameData.skipSwap) { + if (swapIntervalChanged_) { + swapIntervalChanged_ = false; + if (swapIntervalFunction_) { + swapIntervalFunction_(swapInterval_); + } + } + // This is the swapchain framebuffer flip. + if (swapFunction_) { + VLOG(" PULL: SwapFunction()"); + swapFunction_(); + if (!retainControl_) { + // get out of here. + swapRequest = true; + } + } else { + VLOG(" PULL: SwapRequested"); + swapRequest = true; + } + } else { + frameData.skipSwap = false; + } + frameData.hasBegun = false; + + VLOG(" PULL: Frame %d.readyForFence = true", task.frame); + + { + std::lock_guard lock(frameData.fenceMutex); + frameData.readyForFence = true; + frameData.fenceCondVar.notify_one(); + // At this point, we're done with this framedata (for now). + } + break; case GLRRunType::SYNC: @@ -525,7 +502,7 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) { // glFinish is not actually necessary here, and won't be unless we start using // glBufferStorage. Then we need to use fences. { - std::lock_guard lock(syncMutex_); + std::unique_lock lock(syncMutex_); syncDone_ = true; syncCondVar_.notify_one(); } @@ -535,20 +512,21 @@ bool GLRenderManager::Run(GLRRenderThreadTask &task) { _assert_(false); } VLOG(" PULL: ::Run(): Done running tasks"); - return false; + return swapRequest; } void GLRenderManager::FlushSync() { { VLOG("PUSH: Frame[%d].readyForRun = true (sync)", curFrame_); - GLRRenderThreadTask *task = new GLRRenderThreadTask(GLRRunType::SYNC); - task->frame = curFrame_; + GLRRenderThreadTask task; + task.frame = curFrame_; + task.runType = GLRRunType::SYNC; std::unique_lock lock(pushMutex_); renderThreadQueue_.push(task); - renderThreadQueue_.back()->initSteps = std::move(initSteps_); - renderThreadQueue_.back()->steps = std::move(steps_); + renderThreadQueue_.back().initSteps = std::move(initSteps_); + renderThreadQueue_.back().steps = std::move(steps_); pushCondVar_.notify_one(); steps_.clear(); } @@ -563,3 +541,272 @@ void GLRenderManager::FlushSync() { syncDone_ = false; } } + +GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size) : render_(render), size_(size), target_(target) { + bool res = AddBuffer(); + _assert_(res); +} + +GLPushBuffer::~GLPushBuffer() { + Destroy(true); +} + +void GLPushBuffer::Map() { + _assert_(!writePtr_); + auto &info = buffers_[buf_]; + writePtr_ = info.deviceMemory ? info.deviceMemory : info.localMemory; + info.flushOffset = 0; + // Force alignment. This is needed for PushAligned() to work as expected. + while ((intptr_t)writePtr_ & 15) { + writePtr_++; + offset_++; + info.flushOffset++; + } + _assert_(writePtr_); +} + +void GLPushBuffer::Unmap() { + _assert_(writePtr_); + if (!buffers_[buf_].deviceMemory) { + // Here we simply upload the data to the last buffer. + // Might be worth trying with size_ instead of offset_, so the driver can replace + // the whole buffer. At least if it's close. + render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].localMemory, false); + } else { + buffers_[buf_].flushOffset = offset_; + } + writePtr_ = nullptr; +} + +void GLPushBuffer::Flush() { + // Must be called from the render thread. + _dbg_assert_(OnRenderThread()); + + if (buf_ >= buffers_.size()) { + _dbg_assert_msg_(false, "buf_ somehow got out of sync: %d vs %d", (int)buf_, (int)buffers_.size()); + return; + } + + buffers_[buf_].flushOffset = offset_; + if (!buffers_[buf_].deviceMemory && writePtr_) { + auto &info = buffers_[buf_]; + if (info.flushOffset != 0) { + _assert_(info.buffer->buffer_); + glBindBuffer(target_, info.buffer->buffer_); + glBufferSubData(target_, 0, info.flushOffset, info.localMemory); + } + + // Here we will submit all the draw calls, with the already known buffer and offsets. + // Might as well reset the write pointer here and start over the current buffer. + writePtr_ = info.localMemory; + offset_ = 0; + info.flushOffset = 0; + } + + // For device memory, we flush all buffers here. + if ((strategy_ & GLBufferStrategy::MASK_FLUSH) != 0) { + for (auto &info : buffers_) { + if (info.flushOffset == 0 || !info.deviceMemory) + continue; + + glBindBuffer(target_, info.buffer->buffer_); + glFlushMappedBufferRange(target_, 0, info.flushOffset); + info.flushOffset = 0; + } + } +} + +bool GLPushBuffer::AddBuffer() { + BufInfo info; + info.localMemory = (uint8_t *)AllocateAlignedMemory(size_, 16); + if (!info.localMemory) + return false; + info.buffer = render_->CreateBuffer(target_, size_, GL_DYNAMIC_DRAW); + info.size = size_; + buf_ = buffers_.size(); + buffers_.push_back(info); + return true; +} + +void GLPushBuffer::Destroy(bool onRenderThread) { + if (buf_ == -1) + return; // Already destroyed + for (BufInfo &info : buffers_) { + // This will automatically unmap device memory, if needed. + // NOTE: We immediately delete the buffer, don't go through the deleter, if we're on the render thread. + if (onRenderThread) { + delete info.buffer; + } else { + render_->DeleteBuffer(info.buffer); + } + FreeAlignedMemory(info.localMemory); + } + buffers_.clear(); + buf_ = -1; +} + +void GLPushBuffer::NextBuffer(size_t minSize) { + // First, unmap the current memory. + Unmap(); + + buf_++; + if (buf_ >= buffers_.size() || minSize > size_) { + // Before creating the buffer, adjust to the new size_ if necessary. + while (size_ < minSize) { + size_ <<= 1; + } + + bool res = AddBuffer(); + _assert_(res); + if (!res) { + // Let's try not to crash at least? + buf_ = 0; + } + } + + // Now, move to the next buffer and map it. + offset_ = 0; + Map(); +} + +void GLPushBuffer::Defragment() { + _dbg_assert_msg_(!OnRenderThread(), "Defragment must not run on the render thread"); + + if (buffers_.size() <= 1) { + // Let's take this opportunity to jettison any localMemory we don't need. + for (auto &info : buffers_) { + if (info.deviceMemory) { + FreeAlignedMemory(info.localMemory); + info.localMemory = nullptr; + } + } + + return; + } + + // Okay, we have more than one. Destroy them all and start over with a larger one. + + // When calling AddBuffer, we sometimes increase size_. So if we allocated multiple buffers in a frame, + // they won't all have the same size. Sum things up properly. + size_t newSize = 0; + for (int i = 0; i < (int)buffers_.size(); i++) { + newSize += buffers_[i].size; + } + + Destroy(false); + + // Set some sane but very free limits. If there's another spike, we'll just allocate more anyway. + size_ = std::min(std::max(newSize, (size_t)65536), (size_t)(512 * 1024 * 1024)); + bool res = AddBuffer(); + _assert_msg_(res, "AddBuffer failed"); +} + +size_t GLPushBuffer::GetTotalSize() const { + size_t sum = 0; + // When calling AddBuffer, we sometimes increase size_. So if we allocated multiple buffers in a frame, + // they won't all have the same size. Sum things up properly. + if (buffers_.size() > 1) { + for (int i = 0; i < (int)buffers_.size() - 1; i++) { + sum += buffers_[i].size; + } + } + sum += offset_; + return sum; +} + +void GLPushBuffer::MapDevice(GLBufferStrategy strategy) { + _dbg_assert_msg_(OnRenderThread(), "MapDevice must run on render thread"); + + strategy_ = strategy; + if (strategy_ == GLBufferStrategy::SUBDATA) { + return; + } + + bool mapChanged = false; + for (auto &info : buffers_) { + if (!info.buffer->buffer_ || info.deviceMemory) { + // Can't map - no device buffer associated yet or already mapped. + continue; + } + + info.deviceMemory = (uint8_t *)info.buffer->Map(strategy_); + mapChanged = mapChanged || info.deviceMemory != nullptr; + + if (!info.deviceMemory && !info.localMemory) { + // Somehow it failed, let's dodge crashing. + info.localMemory = (uint8_t *)AllocateAlignedMemory(info.buffer->size_, 16); + mapChanged = true; + } + + _dbg_assert_msg_(info.localMemory || info.deviceMemory, "Local or device memory must succeed"); + } + + if (writePtr_ && mapChanged) { + // This can happen during a sync. Remap. + writePtr_ = nullptr; + Map(); + } +} + +void GLPushBuffer::UnmapDevice() { + _dbg_assert_msg_(OnRenderThread(), "UnmapDevice must run on render thread"); + + for (auto &info : buffers_) { + if (info.deviceMemory) { + // TODO: Technically this can return false? + info.buffer->Unmap(); + info.deviceMemory = nullptr; + } + } +} + +void *GLRBuffer::Map(GLBufferStrategy strategy) { + _assert_(buffer_ != 0); + + GLbitfield access = GL_MAP_WRITE_BIT; + if ((strategy & GLBufferStrategy::MASK_FLUSH) != 0) { + access |= GL_MAP_FLUSH_EXPLICIT_BIT; + } + if ((strategy & GLBufferStrategy::MASK_INVALIDATE) != 0) { + access |= GL_MAP_INVALIDATE_BUFFER_BIT; + } + + void *p = nullptr; + bool allowNativeBuffer = strategy != GLBufferStrategy::SUBDATA; + if (allowNativeBuffer) { + glBindBuffer(target_, buffer_); + + if (gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage) { +#if !PPSSPP_PLATFORM(IOS) + if (!hasStorage_) { + GLbitfield storageFlags = access & ~(GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); +#ifdef USING_GLES2 +#ifdef GL_EXT_buffer_storage + glBufferStorageEXT(target_, size_, nullptr, storageFlags); +#endif +#else + glBufferStorage(target_, size_, nullptr, storageFlags); +#endif + hasStorage_ = true; + } +#endif + p = glMapBufferRange(target_, 0, size_, access); + } else if (gl_extensions.VersionGEThan(3, 0, 0)) { + // GLES3 or desktop 3. + p = glMapBufferRange(target_, 0, size_, access); + } else if (!gl_extensions.IsGLES) { +#ifndef USING_GLES2 + p = glMapBuffer(target_, GL_READ_WRITE); +#endif + } + } + + mapped_ = p != nullptr; + return p; +} + +bool GLRBuffer::Unmap() { + glBindBuffer(target_, buffer_); + mapped_ = false; + return glUnmapBuffer(target_) == GL_TRUE; +} diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index fb31fdfe3..d5f6e88d0 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -16,7 +16,6 @@ #include "Common/GPU/OpenGL/GLQueueRunner.h" #include "Common/GPU/OpenGL/GLFrameData.h" #include "Common/GPU/OpenGL/GLCommon.h" -#include "Common/GPU/OpenGL/GLMemory.h" class GLRInputLayout; class GLPushBuffer; @@ -53,13 +52,12 @@ public: class GLRFramebuffer { public: - GLRFramebuffer(const Draw::DeviceCaps &caps, int _width, int _height, bool z_stencil, const char *tag) + GLRFramebuffer(const Draw::DeviceCaps &caps, int _width, int _height, bool z_stencil) : color_texture(caps, _width, _height, 1, 1), z_stencil_texture(caps, _width, _height, 1, 1), width(_width), height(_height), z_stencil_(z_stencil) { } - ~GLRFramebuffer(); - const char *Tag() const { return tag_.c_str(); } + ~GLRFramebuffer(); GLuint handle = 0; GLRTexture color_texture; @@ -72,10 +70,8 @@ public: int width; int height; GLuint colorDepth = 0; - bool z_stencil_; -private: - std::string tag_; + bool z_stencil_; }; // We need to create some custom heap-allocated types so we can forward things that need to be created on the GL thread, before @@ -183,6 +179,179 @@ private: std::unordered_map uniformCache_; }; +enum class GLBufferStrategy { + SUBDATA = 0, + + MASK_FLUSH = 0x10, + MASK_INVALIDATE = 0x20, + + // Map/unmap the buffer each frame. + FRAME_UNMAP = 1, + // Map/unmap and also invalidate the buffer on map. + INVALIDATE_UNMAP = MASK_INVALIDATE, + // Map/unmap and explicitly flushed changed ranges. + FLUSH_UNMAP = MASK_FLUSH, + // Map/unmap, invalidate on map, and explicit flush. + FLUSH_INVALIDATE_UNMAP = MASK_FLUSH | MASK_INVALIDATE, +}; + +static inline int operator &(const GLBufferStrategy &lhs, const GLBufferStrategy &rhs) { + return (int)lhs & (int)rhs; +} + +class GLRBuffer { +public: + GLRBuffer(GLuint target, size_t size) : target_(target), size_((int)size) {} + ~GLRBuffer() { + if (buffer_) { + glDeleteBuffers(1, &buffer_); + } + } + + void *Map(GLBufferStrategy strategy); + bool Unmap(); + + bool Mapped() const { + return mapped_; + } + + GLuint buffer_ = 0; + GLuint target_; + int size_; + +private: + bool mapped_ = false; + bool hasStorage_ = false; +}; + +class GLRenderManager; + +// Similar to VulkanPushBuffer but is currently less efficient - it collects all the data in +// RAM then does a big memcpy/buffer upload at the end of the frame. This is at least a lot +// faster than the hundreds of buffer uploads or memory array buffers we used before. +// On modern GL we could avoid the copy using glBufferStorage but not sure it's worth the +// trouble. +// We need to manage the lifetime of this together with the other resources so its destructor +// runs on the render thread. +class GLPushBuffer { +public: + friend class GLRenderManager; + + struct BufInfo { + GLRBuffer *buffer = nullptr; + uint8_t *localMemory = nullptr; + uint8_t *deviceMemory = nullptr; + size_t flushOffset = 0; + size_t size; + }; + + GLPushBuffer(GLRenderManager *render, GLuint target, size_t size); + ~GLPushBuffer(); + + void Reset() { offset_ = 0; } + +private: + // Needs context in case of defragment. + void Begin() { + buf_ = 0; + offset_ = 0; + // Note: we must defrag because some buffers may be smaller than size_. + Defragment(); + Map(); + _dbg_assert_(writePtr_); + } + + void BeginNoReset() { + Map(); + } + + void End() { + Unmap(); + } + +public: + void Map(); + void Unmap(); + + bool IsReady() const { + return writePtr_ != nullptr; + } + + // When using the returned memory, make sure to bind the returned vkbuf. + // This will later allow for handling overflow correctly. + size_t Allocate(size_t numBytes, GLRBuffer **vkbuf) { + size_t out = offset_; + if (offset_ + ((numBytes + 3) & ~3) >= size_) { + NextBuffer(numBytes); + out = offset_; + offset_ += (numBytes + 3) & ~3; + } else { + offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes. + } + *vkbuf = buffers_[buf_].buffer; + return out; + } + + // Returns the offset that should be used when binding this buffer to get this data. + size_t Push(const void *data, size_t size, GLRBuffer **vkbuf) { + _dbg_assert_(writePtr_); + size_t off = Allocate(size, vkbuf); + memcpy(writePtr_ + off, data, size); + return off; + } + + uint32_t PushAligned(const void *data, size_t size, int align, GLRBuffer **vkbuf) { + _dbg_assert_(writePtr_); + offset_ = (offset_ + align - 1) & ~(align - 1); + size_t off = Allocate(size, vkbuf); + memcpy(writePtr_ + off, data, size); + return (uint32_t)off; + } + + size_t GetOffset() const { + return offset_; + } + + // "Zero-copy" variant - you can write the data directly as you compute it. + // Recommended. + void *Push(size_t size, uint32_t *bindOffset, GLRBuffer **vkbuf) { + _dbg_assert_(writePtr_); + size_t off = Allocate(size, vkbuf); + *bindOffset = (uint32_t)off; + return writePtr_ + off; + } + void *PushAligned(size_t size, uint32_t *bindOffset, GLRBuffer **vkbuf, int align) { + _dbg_assert_(writePtr_); + offset_ = (offset_ + align - 1) & ~(align - 1); + size_t off = Allocate(size, vkbuf); + *bindOffset = (uint32_t)off; + return writePtr_ + off; + } + + size_t GetTotalSize() const; + + void Destroy(bool onRenderThread); + void Flush(); + +protected: + void MapDevice(GLBufferStrategy strategy); + void UnmapDevice(); + +private: + bool AddBuffer(); + void NextBuffer(size_t minSize); + void Defragment(); + + GLRenderManager *render_; + std::vector buffers_; + size_t buf_ = 0; + size_t offset_ = 0; + size_t size_ = 0; + uint8_t *writePtr_ = nullptr; + GLuint target_; + GLBufferStrategy strategy_ = GLBufferStrategy::SUBDATA; +}; + class GLRInputLayout { public: struct Entry { @@ -193,12 +362,11 @@ public: intptr_t offset; }; std::vector entries; - int stride; + unsigned int stride; int semanticsMask_ = 0; }; enum class GLRRunType { - SUBMIT, PRESENT, SYNC, EXIT, @@ -207,19 +375,14 @@ enum class GLRRunType { class GLRenderManager; class GLPushBuffer; -// These are enqueued from the main thread, and the render thread pops them off +// These are enqueued from the main thread, +// and the render thread pops them off struct GLRRenderThreadTask { - GLRRenderThreadTask(GLRRunType _runType) : runType(_runType) {} - std::vector steps; - FastVec initSteps; + std::vector initSteps; - int frame = -1; + int frame; GLRRunType runType; - - // Avoid copying these by accident. - GLRRenderThreadTask(GLRRenderThreadTask &) = delete; - GLRRenderThreadTask& operator =(GLRRenderThreadTask &) = delete; }; // Note: The GLRenderManager is created and destroyed on the render thread, and the latter @@ -227,12 +390,9 @@ struct GLRRenderThreadTask { // directly in the destructor. class GLRenderManager { public: - GLRenderManager(HistoryBuffer &frameTimeHistory); + GLRenderManager(); ~GLRenderManager(); - GLRenderManager(GLRenderManager &) = delete; - GLRenderManager &operator=(GLRenderManager &) = delete; - void SetInvalidationCallback(InvalidationCallback callback) { invalidationCallback_ = callback; } @@ -254,47 +414,43 @@ public: // Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again. void BeginFrame(bool enableProfiling); // Can run on a different thread! - void Finish(); - void Present(); + void Finish(); // Creation commands. These were not needed in Vulkan since there we can do that on the main thread. // We pass in width/height here even though it's not strictly needed until we support glTextureStorage // and then we'll also need formats and stuff. GLRTexture *CreateTexture(GLenum target, int width, int height, int depth, int numMips) { - _dbg_assert_(target != 0); - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::CREATE_TEXTURE; + GLRInitStep step { GLRInitStepType::CREATE_TEXTURE }; step.create_texture.texture = new GLRTexture(caps_, width, height, depth, numMips); step.create_texture.texture->target = target; + initSteps_.push_back(step); return step.create_texture.texture; } GLRBuffer *CreateBuffer(GLuint target, size_t size, GLuint usage) { - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::CREATE_BUFFER; + GLRInitStep step{ GLRInitStepType::CREATE_BUFFER }; step.create_buffer.buffer = new GLRBuffer(target, size); step.create_buffer.size = (int)size; step.create_buffer.usage = usage; + initSteps_.push_back(step); return step.create_buffer.buffer; } GLRShader *CreateShader(GLuint stage, const std::string &code, const std::string &desc) { - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::CREATE_SHADER; + GLRInitStep step{ GLRInitStepType::CREATE_SHADER }; step.create_shader.shader = new GLRShader(); step.create_shader.shader->desc = desc; step.create_shader.stage = stage; step.create_shader.code = new char[code.size() + 1]; memcpy(step.create_shader.code, code.data(), code.size() + 1); + initSteps_.push_back(step); return step.create_shader.shader; } - GLRFramebuffer *CreateFramebuffer(int width, int height, bool z_stencil, const char *tag) { - _dbg_assert_(width > 0 && height > 0 && tag != nullptr); - - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::CREATE_FRAMEBUFFER; - step.create_framebuffer.framebuffer = new GLRFramebuffer(caps_, width, height, z_stencil, tag); + GLRFramebuffer *CreateFramebuffer(int width, int height, bool z_stencil) { + GLRInitStep step{ GLRInitStepType::CREATE_FRAMEBUFFER }; + step.create_framebuffer.framebuffer = new GLRFramebuffer(caps_, width, height, z_stencil); + initSteps_.push_back(step); return step.create_framebuffer.framebuffer; } @@ -303,8 +459,7 @@ public: GLRProgram *CreateProgram( std::vector shaders, std::vector semantics, std::vector queries, std::vector initializers, GLRProgramLocData *locData, const GLRProgramFlags &flags) { - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::CREATE_PROGRAM; + GLRInitStep step{ GLRInitStepType::CREATE_PROGRAM }; _assert_(shaders.size() <= ARRAY_SIZE(step.create_program.shaders)); step.create_program.program = new GLRProgram(); step.create_program.program->semantics_ = semantics; @@ -328,53 +483,47 @@ public: } #endif step.create_program.num_shaders = (int)shaders.size(); + initSteps_.push_back(step); return step.create_program.program; } GLRInputLayout *CreateInputLayout(const std::vector &entries, int stride) { - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::CREATE_INPUT_LAYOUT; + GLRInitStep step{ GLRInitStepType::CREATE_INPUT_LAYOUT }; step.create_input_layout.inputLayout = new GLRInputLayout(); step.create_input_layout.inputLayout->entries = entries; step.create_input_layout.inputLayout->stride = stride; for (auto &iter : step.create_input_layout.inputLayout->entries) { step.create_input_layout.inputLayout->semanticsMask_ |= 1 << iter.location; } + initSteps_.push_back(step); return step.create_input_layout.inputLayout; } - GLPushBuffer *CreatePushBuffer(int frame, GLuint target, size_t size, const char *tag) { - GLPushBuffer *push = new GLPushBuffer(this, target, size, tag); + GLPushBuffer *CreatePushBuffer(int frame, GLuint target, size_t size) { + GLPushBuffer *push = new GLPushBuffer(this, target, size); RegisterPushBuffer(frame, push); return push; } void DeleteShader(GLRShader *shader) { - _dbg_assert_(shader != nullptr); deleter_.shaders.push_back(shader); } void DeleteProgram(GLRProgram *program) { - _dbg_assert_(program != nullptr); deleter_.programs.push_back(program); } void DeleteBuffer(GLRBuffer *buffer) { - _dbg_assert_(buffer != nullptr); deleter_.buffers.push_back(buffer); } void DeleteTexture(GLRTexture *texture) { - _dbg_assert_(texture != nullptr); deleter_.textures.push_back(texture); } void DeleteInputLayout(GLRInputLayout *inputLayout) { - _dbg_assert_(inputLayout != nullptr); deleter_.inputLayouts.push_back(inputLayout); } void DeleteFramebuffer(GLRFramebuffer *framebuffer) { - _dbg_assert_(framebuffer != nullptr); deleter_.framebuffers.push_back(framebuffer); } void DeletePushBuffer(GLPushBuffer *pushbuffer) { - _dbg_assert_(pushbuffer != nullptr); deleter_.pushBuffers.push_back(pushbuffer); } @@ -419,8 +568,7 @@ public: void BufferSubdata(GLRBuffer *buffer, size_t offset, size_t size, uint8_t *data, bool deleteData = true) { // TODO: Maybe should be a render command instead of an init command? When possible it's better as // an init command, that's for sure. - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::BUFFER_SUBDATA; + GLRInitStep step{ GLRInitStepType::BUFFER_SUBDATA }; _dbg_assert_(offset >= 0); _dbg_assert_(offset <= buffer->size_ - size); step.buffer_subdata.buffer = buffer; @@ -428,12 +576,12 @@ public: step.buffer_subdata.size = (int)size; step.buffer_subdata.data = data; step.buffer_subdata.deleteData = deleteData; + initSteps_.push_back(step); } // Takes ownership over the data pointer and delete[]-s it. void TextureImage(GLRTexture *texture, int level, int width, int height, int depth, Draw::DataFormat format, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW, bool linearFilter = false) { - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::TEXTURE_IMAGE; + GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE }; step.texture_image.texture = texture; step.texture_image.data = data; step.texture_image.format = format; @@ -443,11 +591,12 @@ public: step.texture_image.depth = depth; step.texture_image.allocType = allocType; step.texture_image.linearFilter = linearFilter; + initSteps_.push_back(step); } void TextureSubImage(int slot, GLRTexture *texture, int level, int x, int y, int width, int height, Draw::DataFormat format, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData _data(GLRRenderCommand::TEXTURE_SUBIMAGE); + GLRRenderData _data{ GLRRenderCommand::TEXTURE_SUBIMAGE }; _data.texture_subimage.texture = texture; _data.texture_subimage.data = data; _data.texture_subimage.format = format; @@ -462,11 +611,11 @@ public: } void FinalizeTexture(GLRTexture *texture, int loadedLevels, bool genMips) { - GLRInitStep &step = initSteps_.push_uninitialized(); - step.stepType = GLRInitStepType::TEXTURE_FINALIZE; + GLRInitStep step{ GLRInitStepType::TEXTURE_FINALIZE }; step.texture_finalize.texture = texture; step.texture_finalize.loadedLevels = loadedLevels; step.texture_finalize.genMips = genMips; + initSteps_.push_back(step); } void BindTexture(int slot, GLRTexture *tex) { @@ -477,18 +626,18 @@ public: } _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); _dbg_assert_(slot < MAX_GL_TEXTURE_SLOTS); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::BINDTEXTURE; + GLRRenderData data{ GLRRenderCommand::BINDTEXTURE }; data.texture.slot = slot; data.texture.texture = tex; + curRenderStep_->commands.push_back(data); } void BindProgram(GLRProgram *program) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::BINDPROGRAM; + GLRRenderData data{ GLRRenderCommand::BINDPROGRAM }; _dbg_assert_(program != nullptr); data.program.program = program; + curRenderStep_->commands.push_back(data); #ifdef _DEBUG curProgram_ = program; #endif @@ -496,25 +645,25 @@ public: void SetDepth(bool enabled, bool write, GLenum func) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::DEPTH; + GLRRenderData data{ GLRRenderCommand::DEPTH }; data.depth.enabled = enabled; data.depth.write = write; data.depth.func = func; + curRenderStep_->commands.push_back(data); } void SetViewport(const GLRViewport &vp) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::VIEWPORT; + GLRRenderData data{ GLRRenderCommand::VIEWPORT }; data.viewport.vp = vp; + curRenderStep_->commands.push_back(data); } void SetScissor(const GLRect2D &rc) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::SCISSOR; + GLRRenderData data{ GLRRenderCommand::SCISSOR }; data.scissor.rc = rc; + curRenderStep_->commands.push_back(data); } void SetUniformI(const GLint *loc, int count, const int *udata) { @@ -522,12 +671,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4I; - data.uniform4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORM4I }; data.uniform4.loc = loc; data.uniform4.count = count; memcpy(data.uniform4.v, udata, sizeof(int) * count); + curRenderStep_->commands.push_back(data); } void SetUniformI1(const GLint *loc, int udata) { @@ -535,12 +683,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4I; - data.uniform4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORM4I }; data.uniform4.loc = loc; data.uniform4.count = 1; memcpy(data.uniform4.v, &udata, sizeof(udata)); + curRenderStep_->commands.push_back(data); } void SetUniformUI(const GLint *loc, int count, const uint32_t *udata) { @@ -548,12 +695,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4UI; - data.uniform4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORM4UI }; data.uniform4.loc = loc; data.uniform4.count = count; memcpy(data.uniform4.v, udata, sizeof(uint32_t) * count); + curRenderStep_->commands.push_back(data); } void SetUniformUI1(const GLint *loc, uint32_t udata) { @@ -561,12 +707,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4UI; - data.uniform4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORM4UI }; data.uniform4.loc = loc; data.uniform4.count = 1; memcpy(data.uniform4.v, &udata, sizeof(udata)); + curRenderStep_->commands.push_back(data); } void SetUniformF(const GLint *loc, int count, const float *udata) { @@ -574,12 +719,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4F; - data.uniform4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; data.uniform4.loc = loc; data.uniform4.count = count; memcpy(data.uniform4.v, udata, sizeof(float) * count); + curRenderStep_->commands.push_back(data); } void SetUniformF1(const GLint *loc, const float udata) { @@ -587,12 +731,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4F; - data.uniform4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; data.uniform4.loc = loc; data.uniform4.count = 1; memcpy(data.uniform4.v, &udata, sizeof(float)); + curRenderStep_->commands.push_back(data); } void SetUniformF(const char *name, int count, const float *udata) { @@ -600,12 +743,11 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORM4F; + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; data.uniform4.name = name; - data.uniform4.loc = nullptr; data.uniform4.count = count; memcpy(data.uniform4.v, udata, sizeof(float) * count); + curRenderStep_->commands.push_back(data); } void SetUniformM4x4(const GLint *loc, const float *udata) { @@ -613,11 +755,10 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORMMATRIX; - data.uniformMatrix4.name = nullptr; + GLRRenderData data{ GLRRenderCommand::UNIFORMMATRIX }; data.uniformMatrix4.loc = loc; memcpy(data.uniformMatrix4.m, udata, sizeof(float) * 16); + curRenderStep_->commands.push_back(data); } void SetUniformM4x4Stereo(const char *name, const GLint *loc, const float *left, const float *right) { @@ -625,13 +766,13 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORMSTEREOMATRIX; + GLRRenderData data{ GLRRenderCommand::UNIFORMSTEREOMATRIX }; data.uniformStereoMatrix4.name = name; data.uniformStereoMatrix4.loc = loc; data.uniformStereoMatrix4.mData = new float[32]; memcpy(&data.uniformStereoMatrix4.mData[0], left, sizeof(float) * 16); memcpy(&data.uniformStereoMatrix4.mData[16], right, sizeof(float) * 16); + curRenderStep_->commands.push_back(data); } void SetUniformM4x4(const char *name, const float *udata) { @@ -639,19 +780,17 @@ public: #ifdef _DEBUG _dbg_assert_(curProgram_); #endif - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::UNIFORMMATRIX; + GLRRenderData data{ GLRRenderCommand::UNIFORMMATRIX }; data.uniformMatrix4.name = name; - data.uniformMatrix4.loc = nullptr; memcpy(data.uniformMatrix4.m, udata, sizeof(float) * 16); + curRenderStep_->commands.push_back(data); } void SetBlendAndMask(int colorMask, bool blendEnabled, GLenum srcColor, GLenum dstColor, GLenum srcAlpha, GLenum dstAlpha, GLenum funcColor, GLenum funcAlpha) { // Make this one only a non-debug _assert_, since it often comes first. // Lets us collect info about this potential crash through assert extra data. _assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::BLEND; + GLRRenderData data{ GLRRenderCommand::BLEND }; data.blend.mask = colorMask; data.blend.enabled = blendEnabled; data.blend.srcColor = srcColor; @@ -660,88 +799,96 @@ public: data.blend.dstAlpha = dstAlpha; data.blend.funcColor = funcColor; data.blend.funcAlpha = funcAlpha; + curRenderStep_->commands.push_back(data); } void SetNoBlendAndMask(int colorMask) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::BLEND; + GLRRenderData data{ GLRRenderCommand::BLEND }; data.blend.mask = colorMask; data.blend.enabled = false; + curRenderStep_->commands.push_back(data); } #ifndef USING_GLES2 void SetLogicOp(bool enabled, GLenum logicOp) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::LOGICOP; + GLRRenderData data{ GLRRenderCommand::LOGICOP }; data.logic.enabled = enabled; data.logic.logicOp = logicOp; + curRenderStep_->commands.push_back(data); } #endif - void SetStencil(bool enabled, GLenum func, uint8_t refValue, uint8_t compareMask, uint8_t writeMask, GLenum sFail, GLenum zFail, GLenum pass) { + void SetStencilFunc(bool enabled, GLenum func, uint8_t refValue, uint8_t compareMask) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::STENCIL; - data.stencil.enabled = enabled; - data.stencil.func = func; - data.stencil.ref = refValue; - data.stencil.compareMask = compareMask; - data.stencil.writeMask = writeMask; - data.stencil.sFail = sFail; - data.stencil.zFail = zFail; - data.stencil.pass = pass; + GLRRenderData data{ GLRRenderCommand::STENCILFUNC }; + data.stencilFunc.enabled = enabled; + data.stencilFunc.func = func; + data.stencilFunc.ref = refValue; + data.stencilFunc.compareMask = compareMask; + curRenderStep_->commands.push_back(data); + } + + void SetStencilOp(uint8_t writeMask, GLenum sFail, GLenum zFail, GLenum pass) { + _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::STENCILOP }; + data.stencilOp.writeMask = writeMask; + data.stencilOp.sFail = sFail; + data.stencilOp.zFail = zFail; + data.stencilOp.pass = pass; + curRenderStep_->commands.push_back(data); } void SetStencilDisabled() { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::STENCIL; - data.stencil.enabled = false; + GLRRenderData data; + data.cmd = GLRRenderCommand::STENCILFUNC; + data.stencilFunc.enabled = false; + curRenderStep_->commands.push_back(data); } void SetBlendFactor(const float color[4]) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::BLENDCOLOR; + GLRRenderData data{ GLRRenderCommand::BLENDCOLOR }; CopyFloat4(data.blendColor.color, color); + curRenderStep_->commands.push_back(data); } void SetRaster(GLboolean cullEnable, GLenum frontFace, GLenum cullFace, GLboolean ditherEnable, GLboolean depthClamp) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::RASTER; + GLRRenderData data{ GLRRenderCommand::RASTER }; data.raster.cullEnable = cullEnable; data.raster.frontFace = frontFace; data.raster.cullFace = cullFace; data.raster.ditherEnable = ditherEnable; data.raster.depthClampEnable = depthClamp; + curRenderStep_->commands.push_back(data); } // Modifies the current texture as per GL specs, not global state. void SetTextureSampler(int slot, GLenum wrapS, GLenum wrapT, GLenum magFilter, GLenum minFilter, float anisotropy) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); _dbg_assert_(slot < MAX_GL_TEXTURE_SLOTS); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::TEXTURESAMPLER; + GLRRenderData data{ GLRRenderCommand::TEXTURESAMPLER }; data.textureSampler.slot = slot; data.textureSampler.wrapS = wrapS; data.textureSampler.wrapT = wrapT; data.textureSampler.magFilter = magFilter; data.textureSampler.minFilter = minFilter; data.textureSampler.anisotropy = anisotropy; + curRenderStep_->commands.push_back(data); } void SetTextureLod(int slot, float minLod, float maxLod, float lodBias) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); _dbg_assert_(slot < MAX_GL_TEXTURE_SLOTS); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::TEXTURELOD; + GLRRenderData data{ GLRRenderCommand::TEXTURELOD}; data.textureLod.slot = slot; data.textureLod.minLod = minLod; data.textureLod.maxLod = maxLod; data.textureLod.lodBias = lodBias; + curRenderStep_->commands.push_back(data); } // If scissorW == 0, no scissor is applied (the whole render target is cleared). @@ -749,8 +896,7 @@ public: _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); if (!clearMask) return; - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::CLEAR; + GLRRenderData data{ GLRRenderCommand::CLEAR }; data.clear.clearMask = clearMask; data.clear.clearColor = clearColor; data.clear.clearZ = clearZ; @@ -760,36 +906,38 @@ public: data.clear.scissorY = scissorY; data.clear.scissorW = scissorW; data.clear.scissorH = scissorH; + curRenderStep_->commands.push_back(data); } - void Draw(GLRInputLayout *inputLayout, GLRBuffer *vertexBuffer, uint32_t vertexOffset, GLenum mode, int first, int count) { - _dbg_assert_(vertexBuffer && curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::DRAW; + void Draw(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset, GLenum mode, int first, int count) { + _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::DRAW }; data.draw.inputLayout = inputLayout; - data.draw.vertexOffset = vertexOffset; - data.draw.vertexBuffer = vertexBuffer; + data.draw.offset = offset; + data.draw.buffer = buffer; data.draw.indexBuffer = nullptr; data.draw.mode = mode; data.draw.first = first; data.draw.count = count; data.draw.indexType = 0; + curRenderStep_->commands.push_back(data); + curRenderStep_->render.numDraws++; } - // Would really love to have a basevertex parameter, but impossible in unextended GLES, without glDrawElementsBaseVertex, unfortunately. - void DrawIndexed(GLRInputLayout *inputLayout, GLRBuffer *vertexBuffer, uint32_t vertexOffset, GLRBuffer *indexBuffer, uint32_t indexOffset, GLenum mode, int count, GLenum indexType, int instances = 1) { - _dbg_assert_(vertexBuffer && indexBuffer && curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = GLRRenderCommand::DRAW; + void DrawIndexed(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset, GLRBuffer *indexBuffer, GLenum mode, int count, GLenum indexType, void *indices, int instances = 1) { + _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::DRAW }; data.draw.inputLayout = inputLayout; - data.draw.vertexOffset = vertexOffset; - data.draw.vertexBuffer = vertexBuffer; + data.draw.offset = offset; + data.draw.buffer = buffer; data.draw.indexBuffer = indexBuffer; - data.draw.indexOffset = indexOffset; data.draw.mode = mode; data.draw.count = count; data.draw.indexType = indexType; + data.draw.indices = indices; data.draw.instances = instances; + curRenderStep_->commands.push_back(data); + curRenderStep_->render.numDraws++; } enum { MAX_INFLIGHT_FRAMES = 3 }; @@ -820,8 +968,9 @@ public: _dbg_assert_(foundCount == 1); } - void SetSwapFunction(std::function swapFunction) { + void SetSwapFunction(std::function swapFunction, bool retainControl) { swapFunction_ = swapFunction; + retainControl_ = retainControl; } void SetSwapIntervalFunction(std::function swapIntervalFunction) { @@ -871,7 +1020,7 @@ private: GLRStep *curRenderStep_ = nullptr; std::vector steps_; - FastVec initSteps_; + std::vector initSteps_; // Execution time state bool run_ = true; @@ -883,7 +1032,7 @@ private: std::mutex pushMutex_; std::condition_variable pushCondVar_; - std::queue renderThreadQueue_; + std::queue renderThreadQueue_; // For readbacks and other reasons we need to sync with the render thread. std::mutex syncMutex_; @@ -900,6 +1049,7 @@ private: std::function swapFunction_; std::function swapIntervalFunction_; + bool retainControl_ = false; GLBufferStrategy bufferStrategy_ = GLBufferStrategy::SUBDATA; int inflightFrames_ = MAX_INFLIGHT_FRAMES; @@ -916,9 +1066,5 @@ private: #endif Draw::DeviceCaps caps_{}; - std::string profilePassesString_; InvalidationCallback invalidationCallback_; - - uint64_t frameIdGen_ = FRAME_TIME_HISTORY_LENGTH; - HistoryBuffer &frameTimeHistory_; }; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 47f63d02c..d9b8a189f 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -180,9 +180,8 @@ public: void Apply(GLRenderManager *render, uint8_t stencilRef, uint8_t stencilWriteMask, uint8_t stencilCompareMask) { render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp); - render->SetStencil( - stencilEnabled, stencilCompareOp, stencilRef, stencilCompareMask, - stencilWriteMask, stencilFail, stencilZFail, stencilPass); + render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilRef, stencilCompareMask); + render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass); } }; @@ -322,13 +321,16 @@ class OpenGLTexture; class OpenGLContext : public DrawContext { public: - OpenGLContext(bool canChangeSwapInterval); + OpenGLContext(); ~OpenGLContext(); void SetTargetSize(int w, int h) override { DrawContext::SetTargetSize(w, h); renderManager_.Resize(w, h); } + void SetDebugFlags(DebugFlags flags) override { + debugFlags_ = flags; + } const DeviceCaps &GetDeviceCaps() const override { return caps_; @@ -347,6 +349,11 @@ public: renderManager_.SetErrorCallback(callback, userdata); } + PresentationMode GetPresentationMode() const override { + // TODO: Fix. Not yet used. + return PresentationMode::FIFO; + } + DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override; BlendState *CreateBlendState(const BlendStateDesc &desc) override; SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override; @@ -359,16 +366,10 @@ public: Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override; - void BeginFrame(DebugFlags debugFlags) override; + void BeginFrame() override; void EndFrame() override; - void Present(PresentMode mode, int vblanks) override; - - int GetFrameCount() override { - return frameCount_; - } void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override; void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; @@ -406,11 +407,12 @@ public: stencilWriteMask_ = writeMask; stencilCompareMask_ = compareMask; // Do we need to update on the fly here? - renderManager_.SetStencil( + renderManager_.SetStencilFunc( curPipeline_->depthStencil->stencilEnabled, curPipeline_->depthStencil->stencilCompareOp, refValue, - compareMask, + compareMask); + renderManager_.SetStencilOp( writeMask, curPipeline_->depthStencil->stencilFail, curPipeline_->depthStencil->stencilZFail, @@ -421,9 +423,12 @@ public: void BindNativeTexture(int sampler, void *nativeTexture) override; void BindPipeline(Pipeline *pipeline) override; - void BindVertexBuffer(Buffer *buffer, int offset) override { - curVBuffer_ = (OpenGLBuffer *)buffer; - curVBufferOffset_ = offset; + void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override { + _assert_(start + count <= ARRAY_SIZE(curVBuffers_)); + for (int i = 0; i < count; i++) { + curVBuffers_[i + start] = (OpenGLBuffer *)buffers[i]; + curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0; + } } void BindIndexBuffer(Buffer *indexBuffer, int offset) override { curIBuffer_ = (OpenGLBuffer *)indexBuffer; @@ -460,7 +465,6 @@ public: case GPUVendor::VENDOR_BROADCOM: return "VENDOR_BROADCOM"; case GPUVendor::VENDOR_VIVANTE: return "VENDOR_VIVANTE"; case GPUVendor::VENDOR_APPLE: return "VENDOR_APPLE"; - case GPUVendor::VENDOR_MESA: return "VENDOR_MESA"; case GPUVendor::VENDOR_UNKNOWN: default: return "VENDOR_UNKNOWN"; @@ -483,15 +487,10 @@ public: renderManager_.SetInvalidationCallback(callback); } - std::string GetGpuProfileString() const override { - return renderManager_.GetGpuProfileString(); - } - private: void ApplySamplers(); GLRenderManager renderManager_; - int frameCount_ = 0; DeviceCaps caps_{}; @@ -502,9 +501,9 @@ private: const GLRTexture *boundTextures_[MAX_TEXTURE_SLOTS]{}; AutoRef curPipeline_; - AutoRef curVBuffer_; + AutoRef curVBuffers_[4]{}; + int curVBufferOffsets_[4]{}; AutoRef curIBuffer_; - int curVBufferOffset_ = 0; int curIBufferOffset_ = 0; AutoRef curRenderTarget_; @@ -518,6 +517,8 @@ private: GLPushBuffer *push; }; FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]{}; + + DebugFlags debugFlags_ = DebugFlags::NONE; }; static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) { @@ -540,7 +541,7 @@ static bool HasIntelDualSrcBug(const int versions[4]) { } } -OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameTimeHistory_) { +OpenGLContext::OpenGLContext() { if (gl_extensions.IsGLES) { if (gl_extensions.OES_packed_depth_stencil || gl_extensions.OES_depth24) { caps_.preferredDepthBufferFormat = DataFormat::D24_S8; @@ -564,7 +565,6 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT caps_.textureDepthSupported = true; } - caps_.setMaxFrameLatencySupported = true; caps_.dualSourceBlend = gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended; caps_.anisoSupported = gl_extensions.EXT_texture_filter_anisotropic; caps_.framebufferCopySupported = gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image || gl_extensions.ARB_copy_image; @@ -613,7 +613,6 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT case GPU_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break; case GPU_VENDOR_VIVANTE: caps_.vendor = GPUVendor::VENDOR_VIVANTE; break; case GPU_VENDOR_APPLE: caps_.vendor = GPUVendor::VENDOR_APPLE; break; - case GPU_VENDOR_MESA: caps_.vendor = GPUVendor::VENDOR_MESA; break; case GPU_VENDOR_UNKNOWN: default: caps_.vendor = GPUVendor::VENDOR_UNKNOWN; @@ -632,7 +631,7 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT caps_.isTilingGPU = gl_extensions.IsGLES && caps_.vendor != GPUVendor::VENDOR_NVIDIA && caps_.vendor != GPUVendor::VENDOR_INTEL; for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { - frameData_[i].push = renderManager_.CreatePushBuffer(i, GL_ARRAY_BUFFER, 64 * 1024, "thin3d_vbuf"); + frameData_[i].push = renderManager_.CreatePushBuffer(i, GL_ARRAY_BUFFER, 64 * 1024); } if (!gl_extensions.VersionGEThan(3, 0, 0)) { @@ -772,16 +771,6 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT } } - if (canChangeSwapInterval) { - caps_.presentInstantModeChange = true; - caps_.presentMaxInterval = 4; - caps_.presentModesSupported = PresentMode::FIFO | PresentMode::IMMEDIATE; - } else { - caps_.presentInstantModeChange = false; - caps_.presentModesSupported = PresentMode::FIFO; - caps_.presentMaxInterval = 1; - } - renderManager_.SetDeviceCaps(caps_); } @@ -793,8 +782,8 @@ OpenGLContext::~OpenGLContext() { } } -void OpenGLContext::BeginFrame(DebugFlags debugFlags) { - renderManager_.BeginFrame(debugFlags & DebugFlags::PROFILE_TIMESTAMPS); +void OpenGLContext::BeginFrame() { + renderManager_.BeginFrame(debugFlags_ & DebugFlags::PROFILE_TIMESTAMPS); FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; renderManager_.BeginPushBuffer(frameData.push); } @@ -803,12 +792,8 @@ void OpenGLContext::EndFrame() { FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; renderManager_.EndPushBuffer(frameData.push); // upload the data! renderManager_.Finish(); - Invalidate(InvalidationFlags::CACHED_RENDER_STATE); -} -void OpenGLContext::Present(PresentMode presentMode, int vblanks) { - renderManager_.Present(); - frameCount_++; + Invalidate(InvalidationFlags::CACHED_RENDER_STATE); } void OpenGLContext::Invalidate(InvalidationFlags flags) { @@ -830,7 +815,7 @@ InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) { return fmt; } -static GLuint TypeToTarget(TextureType type) { +GLuint TypeToTarget(TextureType type) { switch (type) { #ifndef USING_GLES2 case TextureType::LINEAR1D: return GL_TEXTURE_1D; @@ -868,33 +853,25 @@ public: return tex_; } - void UpdateTextureLevels(GLRenderManager *render, const uint8_t *const *data, int numLevels, TextureCallback initDataCallback); - private: - void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback initDataCallback); + void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback); GLRenderManager *render_; GLRTexture *tex_; + DataFormat format_; TextureType type_; int mipLevels_; - bool generateMips_; // Generate mips requested - bool generatedMips_; // Has generated mips + bool generatedMips_; }; OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : render_(render) { - _dbg_assert_(desc.format != Draw::DataFormat::UNDEFINED); - _dbg_assert_(desc.width > 0 && desc.height > 0 && desc.depth > 0); - _dbg_assert_(desc.type != Draw::TextureType::UNKNOWN); - generatedMips_ = false; - generateMips_ = desc.generateMips; width_ = desc.width; height_ = desc.height; depth_ = desc.depth; format_ = desc.format; type_ = desc.type; - GLenum target = TypeToTarget(desc.type); tex_ = render->CreateTexture(target, desc.width, desc.height, 1, desc.mipLevels); @@ -902,25 +879,21 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : if (desc.initData.empty()) return; - UpdateTextureLevels(render, desc.initData.data(), (int)desc.initData.size(), desc.initDataCallback); -} - -void OpenGLTexture::UpdateTextureLevels(GLRenderManager *render, const uint8_t * const *data, int numLevels, TextureCallback initDataCallback) { int level = 0; int width = width_; int height = height_; int depth = depth_; - for (int i = 0; i < numLevels; i++) { - SetImageData(0, 0, 0, width, height, depth, level, 0, data[i], initDataCallback); + for (auto data : desc.initData) { + SetImageData(0, 0, 0, width, height, depth, level, 0, data, desc.initDataCallback); width = (width + 1) / 2; height = (height + 1) / 2; depth = (depth + 1) / 2; level++; } - mipLevels_ = generateMips_ ? mipLevels_ : level; + mipLevels_ = desc.generateMips ? desc.mipLevels : level; bool genMips = false; - if (numLevels < mipLevels_ && generateMips_) { + if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) { // Assumes the texture is bound for editing genMips = true; generatedMips_ = true; @@ -931,7 +904,7 @@ void OpenGLTexture::UpdateTextureLevels(GLRenderManager *render, const uint8_t * OpenGLTexture::~OpenGLTexture() { if (tex_) { render_->DeleteTexture(tex_); - tex_ = nullptr; + tex_ = 0; generatedMips_ = false; } } @@ -950,7 +923,7 @@ public: GLRFramebuffer *framebuffer_ = nullptr; }; -void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback initDataCallback) { +void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback) { if ((width != width_ || height != height_ || depth != depth_) && level == 0) { // When switching to texStorage we need to handle this correctly. width_ = width; @@ -966,8 +939,8 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int uint8_t *texData = new uint8_t[(size_t)(width * height * depth * alignment)]; bool texDataPopulated = false; - if (initDataCallback) { - texDataPopulated = initDataCallback(texData, data, width, height, depth, width * (int)alignment, height * width * (int)alignment); + if (callback) { + texDataPopulated = callback(texData, data, width, height, depth, width * (int)alignment, height * width * (int)alignment); } if (texDataPopulated) { if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) { @@ -1048,11 +1021,6 @@ Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) { return new OpenGLTexture(&renderManager_, desc); } -void OpenGLContext::UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) { - OpenGLTexture *tex = (OpenGLTexture *)texture; - tex->UpdateTextureLevels(&renderManager_, data, numLevels, initDataCallback); -} - DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) { OpenGLDepthStencilState *ds = new OpenGLDepthStencilState(); ds->depthTestEnabled = desc.depthTestEnabled; @@ -1367,35 +1335,31 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { } void OpenGLContext::Draw(int vertexCount, int offset) { - _dbg_assert_msg_(curVBuffer_ != nullptr, "Can't call Draw without a vertex buffer"); + _dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call Draw without a vertex buffer"); ApplySamplers(); _assert_(curPipeline_->inputLayout); - renderManager_.Draw(curPipeline_->inputLayout->inputLayout_, curVBuffer_->buffer_, curVBufferOffset_, curPipeline_->prim, offset, vertexCount); + renderManager_.Draw(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0], curPipeline_->prim, offset, vertexCount); } void OpenGLContext::DrawIndexed(int vertexCount, int offset) { - _dbg_assert_msg_(curVBuffer_ != nullptr, "Can't call DrawIndexed without a vertex buffer"); + _dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call DrawIndexed without a vertex buffer"); _dbg_assert_msg_(curIBuffer_ != nullptr, "Can't call DrawIndexed without an index buffer"); ApplySamplers(); _assert_(curPipeline_->inputLayout); renderManager_.DrawIndexed( - curPipeline_->inputLayout->inputLayout_, - curVBuffer_->buffer_, curVBufferOffset_, - curIBuffer_->buffer_, curIBufferOffset_ + offset * sizeof(uint32_t), - curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT); + curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0], curIBuffer_->buffer_, + curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT, (void *)((intptr_t)curIBufferOffset_ + offset * sizeof(uint32_t))); } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { _assert_(curPipeline_->inputLayout != nullptr); int stride = curPipeline_->inputLayout->stride; - uint32_t dataSize = stride * vertexCount; + size_t dataSize = stride * vertexCount; FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; GLRBuffer *buf; - uint32_t offset; - uint8_t *dest = frameData.push->Allocate(dataSize, 4, &buf, &offset); - memcpy(dest, vdata, dataSize); + size_t offset = frameData.push->Push(vdata, dataSize, &buf); ApplySamplers(); _assert_(curPipeline_->inputLayout); @@ -1418,8 +1382,8 @@ void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stenc renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_); } -DrawContext *T3DCreateGLContext(bool canChangeSwapInterval) { - return new OpenGLContext(canChangeSwapInterval); +DrawContext *T3DCreateGLContext() { + return new OpenGLContext(); } OpenGLInputLayout::~OpenGLInputLayout() { @@ -1429,7 +1393,8 @@ OpenGLInputLayout::~OpenGLInputLayout() { void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) { // TODO: This is only accurate if there's only one stream. But whatever, for now we // never use multiple streams anyway. - stride = desc.stride; + _dbg_assert_(desc.bindings.size() == 1); + stride = (GLsizei)desc.bindings[0].stride; std::vector entries; for (auto &attr : desc.attributes) { @@ -1478,7 +1443,7 @@ Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) { // TODO: Support multiview later. (It's our only use case for multi layers). _dbg_assert_(desc.numLayers == 1); - GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil, desc.tag); + GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil); OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_, framebuffer); return fbo; } diff --git a/Common/GPU/ShaderTranslation.cpp b/Common/GPU/ShaderTranslation.cpp index 0977a089f..dc9492b31 100644 --- a/Common/GPU/ShaderTranslation.cpp +++ b/Common/GPU/ShaderTranslation.cpp @@ -63,10 +63,15 @@ static EShLanguage GetShLanguageFromStage(const ShaderStage stage) { } void ShaderTranslationInit() { + // TODO: We have TLS issues on UWP +#if !PPSSPP_PLATFORM(UWP) glslang::InitializeProcess(); +#endif } void ShaderTranslationShutdown() { +#if !PPSSPP_PLATFORM(UWP) glslang::FinalizeProcess(); +#endif } struct Builtin { @@ -224,6 +229,11 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, const ShaderLan return result; } +#if PPSSPP_PLATFORM(UWP) + *errorMessage = "No shader translation available (UWP)"; + return false; +#endif + errorMessage->clear(); glslang::TProgram program; diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 05607469c..e57345cfa 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -57,7 +57,6 @@ std::string VulkanVendorString(uint32_t vendorId) { case VULKAN_VENDOR_QUALCOMM: return "Qualcomm"; case VULKAN_VENDOR_IMGTEC: return "Imagination"; case VULKAN_VENDOR_APPLE: return "Apple"; - case VULKAN_VENDOR_MESA: return "Mesa"; default: return StringFromFormat("%08x", vendorId); } @@ -550,13 +549,12 @@ void VulkanContext::ChooseDevice(int physical_device) { vkGetPhysicalDeviceQueueFamilyProperties(physical_devices_[physical_device_], &queue_count, queueFamilyProperties_.data()); _dbg_assert_(queue_count >= 1); - // Detect preferred depth/stencil formats, in this order. All supported devices will support at least one of these. + // Detect preferred formats, in this order. static const VkFormat depthStencilFormats[] = { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, }; - deviceInfo_.preferredDepthStencilFormat = VK_FORMAT_UNDEFINED; for (size_t i = 0; i < ARRAY_SIZE(depthStencilFormats); i++) { VkFormatProperties props; @@ -575,8 +573,7 @@ void VulkanContext::ChooseDevice(int physical_device) { deviceInfo_.canBlitToPreferredDepthStencilFormat = true; } - // This is as good a place as any to do this. Though, we don't use this much anymore after we added - // support for VMA. + // This is as good a place as any to do this. vkGetPhysicalDeviceMemoryProperties(physical_devices_[physical_device_], &memory_properties_); INFO_LOG(G3D, "Memory Types (%d):", memory_properties_.memoryTypeCount); for (int i = 0; i < (int)memory_properties_.memoryTypeCount; i++) { @@ -595,24 +592,31 @@ void VulkanContext::ChooseDevice(int physical_device) { VkPhysicalDeviceFeatures2 features2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR}; // Add to chain even if not supported, GetPhysicalDeviceFeatures is supposed to ignore unknown structs. VkPhysicalDeviceMultiviewFeatures multiViewFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES }; - VkPhysicalDevicePresentWaitFeaturesKHR presentWaitFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR }; - VkPhysicalDevicePresentIdFeaturesKHR presentIdFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR }; - features2.pNext = &multiViewFeatures; - multiViewFeatures.pNext = &presentWaitFeatures; - presentWaitFeatures.pNext = &presentIdFeatures; - presentIdFeatures.pNext = nullptr; - vkGetPhysicalDeviceFeatures2KHR(physical_devices_[physical_device_], &features2); deviceFeatures_.available.standard = features2.features; deviceFeatures_.available.multiview = multiViewFeatures; - deviceFeatures_.available.presentWait = presentWaitFeatures; - deviceFeatures_.available.presentId = presentIdFeatures; } else { vkGetPhysicalDeviceFeatures(physical_devices_[physical_device_], &deviceFeatures_.available.standard); deviceFeatures_.available.multiview = {}; } + deviceFeatures_.enabled = {}; + // Enable a few safe ones if they are available. + deviceFeatures_.enabled.standard.dualSrcBlend = deviceFeatures_.available.standard.dualSrcBlend; + deviceFeatures_.enabled.standard.logicOp = deviceFeatures_.available.standard.logicOp; + deviceFeatures_.enabled.standard.depthClamp = deviceFeatures_.available.standard.depthClamp; + deviceFeatures_.enabled.standard.depthBounds = deviceFeatures_.available.standard.depthBounds; + deviceFeatures_.enabled.standard.samplerAnisotropy = deviceFeatures_.available.standard.samplerAnisotropy; + deviceFeatures_.enabled.standard.shaderClipDistance = deviceFeatures_.available.standard.shaderClipDistance; + deviceFeatures_.enabled.standard.shaderCullDistance = deviceFeatures_.available.standard.shaderCullDistance; + deviceFeatures_.enabled.standard.geometryShader = deviceFeatures_.available.standard.geometryShader; + deviceFeatures_.enabled.standard.sampleRateShading = deviceFeatures_.available.standard.sampleRateShading; + + deviceFeatures_.enabled.multiview = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES }; + deviceFeatures_.enabled.multiview.multiview = deviceFeatures_.available.multiview.multiview; + // deviceFeatures_.enabled.multiview.multiviewGeometryShader = deviceFeatures_.available.multiview.multiviewGeometryShader; + GetDeviceLayerExtensionList(nullptr, device_extension_properties_); device_extensions_enabled_.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); @@ -644,8 +648,8 @@ VkResult VulkanContext::CreateDevice() { return VK_ERROR_INITIALIZATION_FAILED; } - VkDeviceQueueCreateInfo queue_info{ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; - float queue_priorities[1] = { 1.0f }; + VkDeviceQueueCreateInfo queue_info{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}; + float queue_priorities[1] = {1.0f}; queue_info.queueCount = 1; queue_info.pQueuePriorities = queue_priorities; bool found = false; @@ -677,41 +681,6 @@ VkResult VulkanContext::CreateDevice() { extensionsLookup_.EXT_fragment_shader_interlock = EnableDeviceExtension(VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME); extensionsLookup_.ARM_rasterization_order_attachment_access = EnableDeviceExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME); -#if !PPSSPP_PLATFORM(MAC) && !PPSSPP_PLATFORM(IOS) - extensionsLookup_.GOOGLE_display_timing = EnableDeviceExtension(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME); -#endif - if (!extensionsLookup_.GOOGLE_display_timing) { - extensionsLookup_.KHR_present_id = EnableDeviceExtension(VK_KHR_PRESENT_ID_EXTENSION_NAME); - extensionsLookup_.KHR_present_wait = EnableDeviceExtension(VK_KHR_PRESENT_WAIT_EXTENSION_NAME); - } - - deviceFeatures_.enabled = {}; - // Enable a few safe ones if they are available. - deviceFeatures_.enabled.standard.dualSrcBlend = deviceFeatures_.available.standard.dualSrcBlend; - deviceFeatures_.enabled.standard.logicOp = deviceFeatures_.available.standard.logicOp; - deviceFeatures_.enabled.standard.depthClamp = deviceFeatures_.available.standard.depthClamp; - deviceFeatures_.enabled.standard.depthBounds = deviceFeatures_.available.standard.depthBounds; - deviceFeatures_.enabled.standard.samplerAnisotropy = deviceFeatures_.available.standard.samplerAnisotropy; - deviceFeatures_.enabled.standard.shaderClipDistance = deviceFeatures_.available.standard.shaderClipDistance; - deviceFeatures_.enabled.standard.shaderCullDistance = deviceFeatures_.available.standard.shaderCullDistance; - deviceFeatures_.enabled.standard.geometryShader = deviceFeatures_.available.standard.geometryShader; - deviceFeatures_.enabled.standard.sampleRateShading = deviceFeatures_.available.standard.sampleRateShading; - - deviceFeatures_.enabled.multiview = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES }; - if (extensionsLookup_.KHR_multiview) { - deviceFeatures_.enabled.multiview.multiview = deviceFeatures_.available.multiview.multiview; - } - // Strangely, on Intel, it reports these as available even though the extension isn't in the list. - deviceFeatures_.enabled.presentId = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR }; - if (extensionsLookup_.KHR_present_id) { - deviceFeatures_.enabled.presentId.presentId = deviceFeatures_.available.presentId.presentId; - } - deviceFeatures_.enabled.presentWait = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR }; - if (extensionsLookup_.KHR_present_wait) { - deviceFeatures_.enabled.presentWait.presentWait = deviceFeatures_.available.presentWait.presentWait; - } - // deviceFeatures_.enabled.multiview.multiviewGeometryShader = deviceFeatures_.available.multiview.multiviewGeometryShader; - VkPhysicalDeviceFeatures2 features2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; VkDeviceCreateInfo device_info{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; @@ -726,9 +695,6 @@ VkResult VulkanContext::CreateDevice() { device_info.pNext = &features2; features2.features = deviceFeatures_.enabled.standard; features2.pNext = &deviceFeatures_.enabled.multiview; - deviceFeatures_.enabled.multiview.pNext = &deviceFeatures_.enabled.presentWait; - deviceFeatures_.enabled.presentWait.pNext = &deviceFeatures_.enabled.presentId; - deviceFeatures_.enabled.presentId.pNext = nullptr; } else { device_info.pEnabledFeatures = &deviceFeatures_.enabled.standard; } @@ -1290,9 +1256,9 @@ bool VulkanContext::InitSwapchain() { for (size_t i = 0; i < presentModeCount; i++) { bool match = false; match = match || ((flags_ & VULKAN_FLAG_PRESENT_MAILBOX) && presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR); - match = match || ((flags_ & VULKAN_FLAG_PRESENT_IMMEDIATE) && presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR); match = match || ((flags_ & VULKAN_FLAG_PRESENT_FIFO_RELAXED) && presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR); match = match || ((flags_ & VULKAN_FLAG_PRESENT_FIFO) && presentModes[i] == VK_PRESENT_MODE_FIFO_KHR); + match = match || ((flags_ & VULKAN_FLAG_PRESENT_IMMEDIATE) && presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR); // Default to the first present mode from the list. if (match || swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) { @@ -1302,6 +1268,10 @@ bool VulkanContext::InitSwapchain() { break; } } +#ifdef __ANDROID__ + // HACK + swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; +#endif delete[] presentModes; // Determine the number of VkImage's to use in the swap chain (we desire to // own only 1 image at a time, besides the images being displayed and @@ -1666,101 +1636,80 @@ void VulkanDeleteList::Take(VulkanDeleteList &del) { } void VulkanDeleteList::PerformDeletes(VulkanContext *vulkan, VmaAllocator allocator) { - int deleteCount = 0; - for (auto &callback : callbacks_) { callback.func(vulkan, callback.userdata); - deleteCount++; } callbacks_.clear(); VkDevice device = vulkan->GetDevice(); for (auto &cmdPool : cmdPools_) { vkDestroyCommandPool(device, cmdPool, nullptr); - deleteCount++; } cmdPools_.clear(); for (auto &descPool : descPools_) { vkDestroyDescriptorPool(device, descPool, nullptr); - deleteCount++; } descPools_.clear(); for (auto &module : modules_) { vkDestroyShaderModule(device, module, nullptr); - deleteCount++; } modules_.clear(); for (auto &buf : buffers_) { vkDestroyBuffer(device, buf, nullptr); - deleteCount++; } buffers_.clear(); for (auto &buf : buffersWithAllocs_) { vmaDestroyBuffer(allocator, buf.buffer, buf.alloc); - deleteCount++; } buffersWithAllocs_.clear(); for (auto &bufView : bufferViews_) { vkDestroyBufferView(device, bufView, nullptr); - deleteCount++; } bufferViews_.clear(); for (auto &imageWithAlloc : imagesWithAllocs_) { vmaDestroyImage(allocator, imageWithAlloc.image, imageWithAlloc.alloc); - deleteCount++; } imagesWithAllocs_.clear(); for (auto &imageView : imageViews_) { vkDestroyImageView(device, imageView, nullptr); - deleteCount++; } imageViews_.clear(); for (auto &mem : deviceMemory_) { vkFreeMemory(device, mem, nullptr); - deleteCount++; } deviceMemory_.clear(); for (auto &sampler : samplers_) { vkDestroySampler(device, sampler, nullptr); - deleteCount++; } samplers_.clear(); for (auto &pipeline : pipelines_) { vkDestroyPipeline(device, pipeline, nullptr); - deleteCount++; } pipelines_.clear(); for (auto &pcache : pipelineCaches_) { vkDestroyPipelineCache(device, pcache, nullptr); - deleteCount++; } pipelineCaches_.clear(); for (auto &renderPass : renderPasses_) { vkDestroyRenderPass(device, renderPass, nullptr); - deleteCount++; } renderPasses_.clear(); for (auto &framebuffer : framebuffers_) { vkDestroyFramebuffer(device, framebuffer, nullptr); - deleteCount++; } framebuffers_.clear(); for (auto &pipeLayout : pipelineLayouts_) { vkDestroyPipelineLayout(device, pipeLayout, nullptr); - deleteCount++; } pipelineLayouts_.clear(); for (auto &descSetLayout : descSetLayouts_) { vkDestroyDescriptorSetLayout(device, descSetLayout, nullptr); - deleteCount++; } descSetLayouts_.clear(); for (auto &queryPool : queryPools_) { vkDestroyQueryPool(device, queryPool, nullptr); - deleteCount++; } queryPools_.clear(); - deleteCount_ = deleteCount; } void VulkanContext::GetImageMemoryRequirements(VkImage image, VkMemoryRequirements *mem_reqs, bool *dedicatedAllocation) { diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index 0d0e93417..de760b934 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -36,7 +36,6 @@ enum { VULKAN_VENDOR_QUALCOMM = 0x00005143, VULKAN_VENDOR_IMGTEC = 0x00001010, // PowerVR VULKAN_VENDOR_APPLE = 0x0000106b, // Apple through MoltenVK - VULKAN_VENDOR_MESA = 0x00010005, // lavapipe }; VK_DEFINE_HANDLE(VmaAllocator); @@ -138,10 +137,6 @@ public: void Take(VulkanDeleteList &del); void PerformDeletes(VulkanContext *vulkan, VmaAllocator allocator); - int GetLastDeleteCount() const { - return deleteCount_; - } - private: std::vector cmdPools_; std::vector descPools_; @@ -161,7 +156,6 @@ private: std::vector descSetLayouts_; std::vector queryPools_; std::vector callbacks_; - int deleteCount_ = 0; }; // VulkanContext manages the device and swapchain, and deferred deletion of objects. @@ -270,8 +264,6 @@ public: struct AllPhysicalDeviceFeatures { VkPhysicalDeviceFeatures standard; VkPhysicalDeviceMultiviewFeatures multiview; - VkPhysicalDevicePresentWaitFeaturesKHR presentWait; - VkPhysicalDevicePresentIdFeaturesKHR presentId; }; const PhysicalDeviceProps &GetPhysicalDeviceProperties(int i = -1) const { @@ -297,13 +289,6 @@ public: return device_extensions_enabled_; } - const std::vector &GetInstanceExtensionsAvailable() const { - return instance_extension_properties_; - } - const std::vector &GetInstanceExtensionsEnabled() const { - return instance_extensions_enabled_; - } - const VkPhysicalDeviceMemoryProperties &GetMemoryProperties() const { return memory_properties_; } @@ -327,6 +312,7 @@ public: for (const auto &iter : instance_layer_properties_) { for (const auto &ext : iter.extensions) { if (!strcmp(extensionName, ext.extensionName)) { + INFO_LOG(G3D, "%s found in layer extensions: %s", extensionName, iter.properties.layerName); return true; } } @@ -397,10 +383,6 @@ public: return availablePresentModes_; } - int GetLastDeleteCount() const { - return frame_[curFrame_].deleteList.GetLastDeleteCount(); - } - private: bool ChooseQueue(); diff --git a/Common/GPU/Vulkan/VulkanDebug.cpp b/Common/GPU/Vulkan/VulkanDebug.cpp index 0bda4815c..00a226897 100644 --- a/Common/GPU/Vulkan/VulkanDebug.cpp +++ b/Common/GPU/Vulkan/VulkanDebug.cpp @@ -21,7 +21,6 @@ #include #include "Common/Log.h" -#include "Common/System/System.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanDebug.h" @@ -54,14 +53,8 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( return false; case 1303270965: // Benign perf warning, image blit using GENERAL layout. - // TODO: Oops, turns out we filtered out a bit too much here! - // We really need that performance flag check to sort out the stuff that matters. - // Will enable it soon, but it'll take some fixing. - // - if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) - return false; - break; - + // UNASSIGNED + return false; case 606910136: case -392708513: case -384083808: @@ -83,27 +76,10 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( // Extended validation (ARM best practices) // Non-fifo validation not recommended return false; - case 337425955: - // False positive - // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3615 - return false; default: break; } - /* - // Can be used to temporarily turn errors into info for easier debugging. - switch (messageCode) { - case 1544472022: - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { - messageSeverity = (VkDebugUtilsMessageSeverityFlagBitsEXT)((messageSeverity & ~VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT); - } - break; - default: - break; - } - */ - int count; { std::lock_guard lock(g_errorCountMutex); @@ -140,7 +116,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( #ifdef _WIN32 OutputDebugStringA(msg.c_str()); if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { - if (options->breakOnError && System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) { + if (options->breakOnError && IsDebuggerPresent()) { DebugBreak(); } if (options->msgBoxOnError) { @@ -148,7 +124,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( } } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { // Don't break on perf warnings for now, even with a debugger. We log them at least. - if (options->breakOnWarning && System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT) && 0 == (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) { + if (options->breakOnWarning && IsDebuggerPresent() && 0 == (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) { DebugBreak(); } } diff --git a/Common/GPU/Vulkan/VulkanDescSet.cpp b/Common/GPU/Vulkan/VulkanDescSet.cpp deleted file mode 100644 index 640f034d3..000000000 --- a/Common/GPU/Vulkan/VulkanDescSet.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "Common/GPU/Vulkan/VulkanDescSet.h" - -VulkanDescSetPool::~VulkanDescSetPool() { - _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool %s never destroyed", tag_); -} - -void VulkanDescSetPool::Create(VulkanContext *vulkan, const BindingType *bindingTypes, uint32_t bindingTypesCount, uint32_t descriptorCount) { - _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool::Create when already exists"); - - vulkan_ = vulkan; - info_ = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - info_.maxSets = descriptorCount; - _dbg_assert_(sizes_.empty()); - - uint32_t storageImageCount = 0; - uint32_t storageBufferCount = 0; - uint32_t combinedImageSamplerCount = 0; - uint32_t uniformBufferDynamicCount = 0; - for (uint32_t i = 0; i < bindingTypesCount; i++) { - switch (bindingTypes[i]) { - case BindingType::COMBINED_IMAGE_SAMPLER: combinedImageSamplerCount++; break; - case BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX: - case BindingType::UNIFORM_BUFFER_DYNAMIC_ALL: uniformBufferDynamicCount++; break; - case BindingType::STORAGE_BUFFER_VERTEX: - case BindingType::STORAGE_BUFFER_COMPUTE: storageBufferCount++; break; - case BindingType::STORAGE_IMAGE_COMPUTE: storageImageCount++; break; - } - } - if (combinedImageSamplerCount) { - sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, combinedImageSamplerCount * descriptorCount }); - } - if (uniformBufferDynamicCount) { - sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBufferDynamicCount * descriptorCount }); - } - if (storageBufferCount) { - sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufferCount * descriptorCount }); - } - if (storageImageCount) { - sizes_.push_back(VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, storageImageCount * descriptorCount }); - } - VkResult res = Recreate(false); - _assert_msg_(res == VK_SUCCESS, "Could not create VulkanDescSetPool %s", tag_); -} - -bool VulkanDescSetPool::Allocate(VkDescriptorSet *descriptorSets, int count, const VkDescriptorSetLayout *layouts) { - if (descPool_ == VK_NULL_HANDLE || usage_ + count >= info_.maxSets) { - // Missing or out of space, need to recreate. - VkResult res = Recreate(grow_); - _assert_msg_(res == VK_SUCCESS, "Could not grow VulkanDescSetPool %s on usage %d", tag_, (int)usage_); - } - - VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; - descAlloc.descriptorPool = descPool_; - descAlloc.descriptorSetCount = count; - descAlloc.pSetLayouts = layouts; - VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, descriptorSets); - - if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) { - WARN_LOG(G3D, "Pool %s %s - recreating", tag_, result == VK_ERROR_FRAGMENTED_POOL ? "fragmented" : "full"); - // There seems to have been a spec revision. Here we should apparently recreate the descriptor pool, - // so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html - // Fragmentation shouldn't really happen though since we wipe the pool every frame. - VkResult res = Recreate(false); - _assert_msg_(res == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to recreate a descriptor pool. sz=%d res=%d", usage_, (int)res); - - // Need to update this pointer since we have allocated a new one. - descAlloc.descriptorPool = descPool_; - result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, descriptorSets); - _assert_msg_(result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result); - } - - if (result != VK_SUCCESS) { - return false; - } - - usage_ += count; - return true; -} - -void VulkanDescSetPool::Reset() { - _assert_msg_(descPool_ != VK_NULL_HANDLE, "VulkanDescSetPool::Reset without valid pool"); - vkResetDescriptorPool(vulkan_->GetDevice(), descPool_, 0); - - usage_ = 0; -} - -void VulkanDescSetPool::Destroy() { - if (descPool_ != VK_NULL_HANDLE) { - vulkan_->Delete().QueueDeleteDescriptorPool(descPool_); - usage_ = 0; - } - sizes_.clear(); -} - -void VulkanDescSetPool::DestroyImmediately() { - if (descPool_ != VK_NULL_HANDLE) { - vkDestroyDescriptorPool(vulkan_->GetDevice(), descPool_, nullptr); - descPool_ = VK_NULL_HANDLE; - usage_ = 0; - } - sizes_.clear(); -} - -VkResult VulkanDescSetPool::Recreate(bool grow) { - _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Recreate without VulkanContext"); - - uint32_t prevSize = info_.maxSets; - if (grow) { - info_.maxSets *= 2; - for (auto &size : sizes_) - size.descriptorCount *= 2; - } - - // Delete the pool if it already exists. - if (descPool_ != VK_NULL_HANDLE) { - INFO_LOG(G3D, "Reallocating %s desc pool from %d to %d", tag_, prevSize, info_.maxSets); - vulkan_->Delete().QueueDeleteDescriptorPool(descPool_); - usage_ = 0; - } - - info_.pPoolSizes = &sizes_[0]; - info_.poolSizeCount = (uint32_t)sizes_.size(); - - VkResult result = vkCreateDescriptorPool(vulkan_->GetDevice(), &info_, nullptr, &descPool_); - if (result == VK_SUCCESS) { - vulkan_->SetDebugName(descPool_, VK_OBJECT_TYPE_DESCRIPTOR_POOL, tag_); - } - return result; -} diff --git a/Common/GPU/Vulkan/VulkanDescSet.h b/Common/GPU/Vulkan/VulkanDescSet.h deleted file mode 100644 index 9133f99f9..000000000 --- a/Common/GPU/Vulkan/VulkanDescSet.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "Common/Data/Collections/FastVec.h" -#include "Common/GPU/Vulkan/VulkanContext.h" - -#include - -enum class BindingType { - COMBINED_IMAGE_SAMPLER, - UNIFORM_BUFFER_DYNAMIC_VERTEX, - UNIFORM_BUFFER_DYNAMIC_ALL, - STORAGE_BUFFER_VERTEX, - STORAGE_BUFFER_COMPUTE, - STORAGE_IMAGE_COMPUTE, -}; - -// Only appropriate for use in a per-frame pool. -class VulkanDescSetPool { -public: - VulkanDescSetPool(const char *tag, bool grow = true) : tag_(tag), grow_(grow) {} - ~VulkanDescSetPool(); - - void Create(VulkanContext *vulkan, const BindingType *bindingTypes, uint32_t bindingTypesCount, uint32_t descriptorCount); - // Allocate a new set, which may resize and empty the current sets. - // Use only for the current frame. - bool Allocate(VkDescriptorSet *descriptorSets, int count, const VkDescriptorSetLayout *layouts); - void Reset(); - - // This queues up destruction. - void Destroy(); - // This actually destroys immediately. - void DestroyImmediately(); - - bool IsDestroyed() const { - return !descPool_; - } - -private: - VkResult Recreate(bool grow); - - const char *tag_; - VulkanContext *vulkan_ = nullptr; - VkDescriptorPool descPool_ = VK_NULL_HANDLE; - VkDescriptorPoolCreateInfo info_{}; - std::vector sizes_; - uint32_t usage_ = 0; - bool grow_; -}; diff --git a/Common/GPU/Vulkan/VulkanFrameData.cpp b/Common/GPU/Vulkan/VulkanFrameData.cpp index 3f1ee5113..90d2c4348 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.cpp +++ b/Common/GPU/Vulkan/VulkanFrameData.cpp @@ -4,12 +4,6 @@ #include "Common/Log.h" #include "Common/StringUtils.h" -#if 0 // def _DEBUG -#define VLOG(...) NOTICE_LOG(G3D, __VA_ARGS__) -#else -#define VLOG(...) -#endif - void CachedReadback::Destroy(VulkanContext *vulkan) { if (buffer) { vulkan->Delete().QueueDeleteBufferAllocation(buffer, allocation); @@ -90,10 +84,6 @@ void FrameData::AcquireNextImage(VulkanContext *vulkan, FrameDataShared &shared) WARN_LOG(G3D, "%s returned from AcquireNextImage - processing the frame, but not presenting", VulkanResultToString(res)); skipSwap = true; break; - case VK_ERROR_SURFACE_LOST_KHR: - ERROR_LOG(G3D, "%s returned from AcquireNextImage - ignoring, but this better be during shutdown", VulkanResultToString(res)); - skipSwap = true; - break; default: // Weird, shouldn't get any other values. Maybe lost device? _assert_msg_(false, "vkAcquireNextImageKHR failed! result=%s", VulkanResultToString(res)); @@ -114,25 +104,6 @@ VkResult FrameData::QueuePresent(VulkanContext *vulkan, FrameDataShared &shared) present.pWaitSemaphores = &shared.renderingCompleteSemaphore; present.waitSemaphoreCount = 1; - // Can't move these into the if. - VkPresentIdKHR presentID{ VK_STRUCTURE_TYPE_PRESENT_ID_KHR }; - VkPresentTimesInfoGOOGLE presentGOOGLE{ VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE }; - - uint64_t frameId = this->frameId; - VkPresentTimeGOOGLE presentTimeGOOGLE{ (uint32_t)frameId, 0 }; // it's ok to truncate this. it'll wrap around and work (if we ever reach 4 billion frames..) - - if (shared.measurePresentTime) { - if (vulkan->Extensions().KHR_present_id && vulkan->GetDeviceFeatures().enabled.presentId.presentId) { - presentID.pPresentIds = &frameId; - presentID.swapchainCount = 1; - present.pNext = &presentID; - } else if (vulkan->Extensions().GOOGLE_display_timing) { - presentGOOGLE.pTimes = &presentTimeGOOGLE; - presentGOOGLE.swapchainCount = 1; - present.pNext = &presentGOOGLE; - } - } - return vkQueuePresentKHR(vulkan->GetGraphicsQueue(), &present); } @@ -150,7 +121,7 @@ VkCommandBuffer FrameData::GetInitCmd(VulkanContext *vulkan) { } // Good spot to reset the query pool. - if (profile.enabled) { + if (profilingEnabled_) { vkCmdResetQueryPool(initCmd, profile.queryPool, 0, MAX_TIMESTAMP_QUERIES); vkCmdWriteTimestamp(initCmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, profile.queryPool, 0); } @@ -167,7 +138,7 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame VkFence fenceToTrigger = VK_NULL_HANDLE; if (hasInitCommands) { - if (profile.enabled) { + if (profilingEnabled_) { // Pre-allocated query ID 1 - end of init cmdbuf. vkCmdWriteTimestamp(initCmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, profile.queryPool, 1); } @@ -225,16 +196,12 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame VkResult res; if (fenceToTrigger == fence) { - VLOG("Doing queue submit, fencing frame %d", this->index); // The fence is waited on by the main thread, they are not allowed to access it simultaneously. res = vkQueueSubmit(vulkan->GetGraphicsQueue(), 1, &submit_info, fenceToTrigger); - if (sharedData.useMultiThreading) { - std::lock_guard lock(fenceMutex); - readyForFence = true; - fenceCondVar.notify_one(); - } + std::lock_guard lock(fenceMutex); + readyForFence = true; + fenceCondVar.notify_one(); } else { - VLOG("Doing queue submit, fencing something (%p)", fenceToTrigger); res = vkQueueSubmit(vulkan->GetGraphicsQueue(), 1, &submit_info, fenceToTrigger); } @@ -252,7 +219,7 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame } } -void FrameDataShared::Init(VulkanContext *vulkan, bool useMultiThreading, bool measurePresentTime) { +void FrameDataShared::Init(VulkanContext *vulkan) { VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; semaphoreCreateInfo.flags = 0; VkResult res = vkCreateSemaphore(vulkan->GetDevice(), &semaphoreCreateInfo, nullptr, &acquireSemaphore); @@ -263,9 +230,6 @@ void FrameDataShared::Init(VulkanContext *vulkan, bool useMultiThreading, bool m // This fence is used for synchronizing readbacks. Does not need preinitialization. readbackFence = vulkan->CreateFence(false); vulkan->SetDebugName(readbackFence, VK_OBJECT_TYPE_FENCE, "readbackFence"); - - this->useMultiThreading = useMultiThreading; - this->measurePresentTime = measurePresentTime; } void FrameDataShared::Destroy(VulkanContext *vulkan) { diff --git a/Common/GPU/Vulkan/VulkanFrameData.h b/Common/GPU/Vulkan/VulkanFrameData.h index 0085c3ed9..0e1344f24 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.h +++ b/Common/GPU/Vulkan/VulkanFrameData.h @@ -13,22 +13,17 @@ enum { }; enum class VKRRunType { - SUBMIT, PRESENT, SYNC, EXIT, }; struct QueueProfileContext { - bool enabled = false; - bool timestampsEnabled = false; VkQueryPool queryPool; std::vector timestampDescriptions; std::string profileSummary; double cpuStartTime; double cpuEndTime; - double descWriteTime; - int descriptorsWritten; }; class VKRFramebuffer; @@ -55,10 +50,8 @@ struct FrameDataShared { // For synchronous readbacks. VkFence readbackFence = VK_NULL_HANDLE; - bool useMultiThreading; - bool measurePresentTime; - void Init(VulkanContext *vulkan, bool useMultiThreading, bool measurePresentTime); + void Init(VulkanContext *vulkan); void Destroy(VulkanContext *vulkan); }; @@ -98,15 +91,12 @@ struct FrameData { // Swapchain. uint32_t curSwapchainImage = -1; - // Frames need unique IDs to wait for present on, let's keep them here. - // Also used for indexing into the frame timing history buffer. - uint64_t frameId = 0; - // Profiling. - QueueProfileContext profile{}; + QueueProfileContext profile; + bool profilingEnabled_ = false; // Async readback cache. - DenseHashMap readbacks_; + DenseHashMap readbacks_; FrameData() : readbacks_(8) {} diff --git a/Common/GPU/Vulkan/VulkanFramebuffer.cpp b/Common/GPU/Vulkan/VulkanFramebuffer.cpp index d36aa44f1..17167e36e 100644 --- a/Common/GPU/Vulkan/VulkanFramebuffer.cpp +++ b/Common/GPU/Vulkan/VulkanFramebuffer.cpp @@ -2,27 +2,6 @@ #include "Common/GPU/Vulkan/VulkanFramebuffer.h" #include "Common/GPU/Vulkan/VulkanQueueRunner.h" -static const char *rpTypeDebugNames[] = { - "RENDER", - "RENDER_DEPTH", - "MV_RENDER", - "MV_RENDER_DEPTH", - "MS_RENDER", - "MS_RENDER_DEPTH", - "MS_MV_RENDER", - "MS_MV_RENDER_DEPTH", - "BACKBUF", -}; - -const char *GetRPTypeName(RenderPassType rpType) { - uint32_t index = (uint32_t)rpType; - if (index < ARRAY_SIZE(rpTypeDebugNames)) { - return rpTypeDebugNames[index]; - } else { - return "N/A"; - } -} - VkSampleCountFlagBits MultiSampleLevelToFlagBits(int count) { // TODO: Check hardware support here, or elsewhere? // Some hardware only supports 4x. @@ -286,17 +265,12 @@ static VkAttachmentStoreOp ConvertStoreAction(VKRRenderPassStoreAction action) { // Also see https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#synchronization-pipeline-barriers-subpass-self-dependencies VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPassType rpType, VkSampleCountFlagBits sampleCount) { + bool selfDependency = RenderPassTypeHasInput(rpType); bool isBackbuffer = rpType == RenderPassType::BACKBUFFER; bool hasDepth = RenderPassTypeHasDepth(rpType); bool multiview = RenderPassTypeHasMultiView(rpType); bool multisample = RenderPassTypeHasMultisample(rpType); - _dbg_assert_(!(isBackbuffer && multisample)); - - if (isBackbuffer) { - _dbg_assert_(key.depthLoadAction == VKRRenderPassLoadAction::CLEAR); - } - if (multiview) { // TODO: Assert that the device has multiview support enabled. } @@ -323,7 +297,7 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas attachments[attachmentCount].storeOp = ConvertStoreAction(key.depthStoreAction); attachments[attachmentCount].stencilLoadOp = multisample ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : ConvertLoadAction(key.stencilLoadAction); attachments[attachmentCount].stencilStoreOp = ConvertStoreAction(key.stencilStoreAction); - attachments[attachmentCount].initialLayout = isBackbuffer ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[attachmentCount].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments[attachmentCount].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachmentCount++; } @@ -356,7 +330,7 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas VkAttachmentReference colorReference{}; colorReference.attachment = colorAttachmentIndex; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorReference.layout = selfDependency ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkAttachmentReference depthReference{}; depthReference.attachment = depthAttachmentIndex; @@ -365,15 +339,20 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas VkSubpassDescription subpass{}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.flags = 0; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; + if (selfDependency) { + subpass.inputAttachmentCount = 1; + subpass.pInputAttachments = &colorReference; + } else { + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + } subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorReference; VkAttachmentReference colorResolveReference; if (multisample) { colorResolveReference.attachment = 0; // the non-msaa color buffer. - colorResolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorResolveReference.layout = selfDependency ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; subpass.pResolveAttachments = &colorResolveReference; } else { subpass.pResolveAttachments = nullptr; @@ -408,25 +387,23 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas } if (isBackbuffer) { - // We don't specify any explicit transitions for these, so let's use subpass dependencies. - // This makes sure that writes to the depth image are done before we try to write to it again. - // From Sascha's examples. deps[numDeps].srcSubpass = VK_SUBPASS_EXTERNAL; deps[numDeps].dstSubpass = 0; - deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - deps[numDeps].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - deps[numDeps].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - deps[numDeps].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - numDeps++; - // Dependencies for the color image. - deps[numDeps].srcSubpass = VK_SUBPASS_EXTERNAL; - deps[numDeps].dstSubpass = 0; - deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - deps[numDeps].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + deps[numDeps].srcAccessMask = 0; deps[numDeps].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + numDeps++; + } + + if (selfDependency) { deps[numDeps].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + deps[numDeps].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + deps[numDeps].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + deps[numDeps].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + deps[numDeps].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + deps[numDeps].srcSubpass = 0; + deps[numDeps].dstSubpass = 0; numDeps++; } @@ -486,6 +463,10 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas VkSubpassDescription2KHR subpass2{ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR }; subpass2.colorAttachmentCount = subpass.colorAttachmentCount; subpass2.flags = subpass.flags; + if (selfDependency) { + subpass2.inputAttachmentCount = subpass.inputAttachmentCount; + subpass2.pInputAttachments = &colorReference2; + } subpass2.pColorAttachments = &colorReference2; if (hasDepth) { subpass2.pDepthStencilAttachment = &depthReference2; @@ -495,7 +476,7 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas if (multisample) { colorResolveReference2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorResolveReference2.attachment = colorResolveReference.attachment; // the non-msaa color buffer. - colorResolveReference2.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorResolveReference2.layout = selfDependency ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; subpass2.pResolveAttachments = &colorResolveReference2; } else { subpass2.pResolveAttachments = nullptr; @@ -528,10 +509,6 @@ VkRenderPass CreateRenderPass(VulkanContext *vulkan, const RPKey &key, RenderPas res = vkCreateRenderPass(vulkan->GetDevice(), &rp, nullptr, &pass); } - if (pass) { - vulkan->SetDebugName(pass, VK_OBJECT_TYPE_RENDER_PASS, GetRPTypeName(rpType)); - } - _assert_(res == VK_SUCCESS); _assert_(pass != VK_NULL_HANDLE); return pass; diff --git a/Common/GPU/Vulkan/VulkanFramebuffer.h b/Common/GPU/Vulkan/VulkanFramebuffer.h index 97ff9e367..fc584f4b8 100644 --- a/Common/GPU/Vulkan/VulkanFramebuffer.h +++ b/Common/GPU/Vulkan/VulkanFramebuffer.h @@ -13,14 +13,15 @@ enum class RenderPassType { // These eight are organized so that bit 0 is DEPTH and bit 1 is INPUT and bit 2 is MULTIVIEW, so // they can be OR-ed together in MergeRPTypes. HAS_DEPTH = 1, - MULTIVIEW = 2, - MULTISAMPLE = 4, + COLOR_INPUT = 2, // input attachment + MULTIVIEW = 4, + MULTISAMPLE = 8, // This is the odd one out, and gets special handling in MergeRPTypes. // If this flag is set, none of the other flags can be set. // For the backbuffer we can always use CLEAR/DONT_CARE, so bandwidth cost for a depth channel is negligible // so we don't bother with a non-depth version. - BACKBUFFER = 8, + BACKBUFFER = 16, TYPE_COUNT = BACKBUFFER + 1, }; @@ -106,6 +107,10 @@ inline bool RenderPassTypeHasDepth(RenderPassType type) { return (type & RenderPassType::HAS_DEPTH) || type == RenderPassType::BACKBUFFER; } +inline bool RenderPassTypeHasInput(RenderPassType type) { + return (type & RenderPassType::COLOR_INPUT) != 0; +} + inline bool RenderPassTypeHasMultiView(RenderPassType type) { return (type & RenderPassType::MULTIVIEW) != 0; } @@ -157,5 +162,3 @@ private: VkSampleCountFlagBits sampleCounts[(size_t)RenderPassType::TYPE_COUNT]; RPKey key_; }; - -const char *GetRPTypeName(RenderPassType rpType); diff --git a/Common/GPU/Vulkan/VulkanImage.cpp b/Common/GPU/Vulkan/VulkanImage.cpp index cc498c938..dbc76e32d 100644 --- a/Common/GPU/Vulkan/VulkanImage.cpp +++ b/Common/GPU/Vulkan/VulkanImage.cpp @@ -130,12 +130,9 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int depth, i res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view_); if (res != VK_SUCCESS) { - ERROR_LOG(G3D, "vkCreateImageView failed: %s. Destroying image.", VulkanResultToString(res)); + ERROR_LOG(G3D, "vkCreateImageView failed: %s", VulkanResultToString(res)); + // This leaks the image. _assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS); - vmaDestroyImage(vulkan_->Allocator(), image_, allocation_); - view_ = VK_NULL_HANDLE; - image_ = VK_NULL_HANDLE; - allocation_ = VK_NULL_HANDLE; return false; } vulkan_->SetDebugName(view_, VK_OBJECT_TYPE_IMAGE_VIEW, tag_); @@ -144,7 +141,6 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int depth, i if (view_info.viewType == VK_IMAGE_VIEW_TYPE_2D) { view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &arrayView_); - // Assume that if the above view creation succeeded, so will this. _assert_(res == VK_SUCCESS); vulkan_->SetDebugName(arrayView_, VK_OBJECT_TYPE_IMAGE_VIEW, tag_); } @@ -262,22 +258,6 @@ void VulkanTexture::EndCreate(VkCommandBuffer cmd, bool vertexTexture, VkPipelin prevStage == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); } -void VulkanTexture::PrepareForTransferDst(VkCommandBuffer cmd, int levels) { - TransitionImageLayout2(cmd, image_, 0, levels, 1, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); -} - -void VulkanTexture::RestoreAfterTransferDst(VkCommandBuffer cmd, int levels) { - TransitionImageLayout2(cmd, image_, 0, levels, 1, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); -} - VkImageView VulkanTexture::CreateViewForMip(int mip) { VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; view_info.image = image_; diff --git a/Common/GPU/Vulkan/VulkanImage.h b/Common/GPU/Vulkan/VulkanImage.h index 41d7fe72c..580e66371 100644 --- a/Common/GPU/Vulkan/VulkanImage.h +++ b/Common/GPU/Vulkan/VulkanImage.h @@ -37,10 +37,6 @@ public: void GenerateMips(VkCommandBuffer cmd, int firstMipToGenerate, bool fromCompute); void EndCreate(VkCommandBuffer cmd, bool vertexTexture, VkPipelineStageFlags prevStage, VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - // For updating levels after creation. Careful with the timelines! - void PrepareForTransferDst(VkCommandBuffer cmd, int levels); - void RestoreAfterTransferDst(VkCommandBuffer cmd, int levels); - // When loading mips from compute shaders, you need to pass VK_IMAGE_LAYOUT_GENERAL to the above function. // In addition, ignore UploadMip and GenerateMip, and instead use GetViewForMip. Make sure to delete the returned views when used. VkImageView CreateViewForMip(int mip); diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 3c7069c4a..23f664ba9 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -223,16 +223,11 @@ PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; -// Assorted other extensions. PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; -PFN_vkWaitForPresentKHR vkWaitForPresentKHR; -PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; -PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; - } // namespace PPSSPP_VK using namespace PPSSPP_VK; @@ -314,7 +309,7 @@ static void VulkanFreeLibrary(VulkanLibraryHandle &h) { } void VulkanSetAvailable(bool available) { - INFO_LOG(G3D, "Setting Vulkan availability to true"); + INFO_LOG(G3D, "Forcing Vulkan availability to true"); g_vulkanAvailabilityChecked = true; g_vulkanMayBeAvailable = available; } @@ -731,13 +726,6 @@ void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledE LOAD_DEVICE_FUNC(device, vkCmdEndRenderPass); LOAD_DEVICE_FUNC(device, vkCmdExecuteCommands); - if (enabledExtensions.KHR_present_wait) { - LOAD_DEVICE_FUNC(device, vkWaitForPresentKHR); - } - if (enabledExtensions.GOOGLE_display_timing) { - LOAD_DEVICE_FUNC(device, vkGetPastPresentationTimingGOOGLE); - LOAD_DEVICE_FUNC(device, vkGetRefreshCycleDurationGOOGLE); - } if (enabledExtensions.KHR_dedicated_allocation) { LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements2KHR); LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements2KHR); diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index 0e631ba71..0358db70e 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -235,9 +235,6 @@ extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesE extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; extern PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; -extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR; -extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; -extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; } // namespace PPSSPP_VK // For fast extension-enabled checks. @@ -256,9 +253,6 @@ struct VulkanExtensions { bool EXT_swapchain_colorspace; bool ARM_rasterization_order_attachment_access; bool EXT_fragment_shader_interlock; - bool KHR_present_id; // Should probably check the feature flags instead. - bool KHR_present_wait; // Same - bool GOOGLE_display_timing; // bool EXT_depth_range_unrestricted; // Allows depth outside [0.0, 1.0] in 32-bit float depth buffers. }; diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index 83588c917..1a718c95a 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -35,9 +35,252 @@ using namespace PPSSPP_VK; // Always keep around push buffers at least this long (seconds). static const double PUSH_GARBAGE_COLLECTION_DELAY = 10.0; +// Global push buffer tracker for vulkan memory profiling. +// Don't want to manually dig up all the active push buffers. +static std::mutex g_pushBufferListMutex; +static std::set g_pushBuffers; + +std::vector GetActiveVulkanMemoryManagers() { + std::vector buffers; + std::lock_guard guard(g_pushBufferListMutex); + for (auto iter : g_pushBuffers) { + buffers.push_back(iter); + } + return buffers; +} + +VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage) + : vulkan_(vulkan), name_(name), size_(size), usage_(usage) { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.insert(this); + } + + bool res = AddBuffer(); + _assert_(res); +} + +VulkanPushBuffer::~VulkanPushBuffer() { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.erase(this); + } + + _dbg_assert_(!writePtr_); + _assert_(buffers_.empty()); +} + +bool VulkanPushBuffer::AddBuffer() { + BufInfo info; + VkDevice device = vulkan_->GetDevice(); + + VkBufferCreateInfo b{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + b.size = size_; + b.flags = 0; + b.usage = usage_; + b.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + b.queueFamilyIndexCount = 0; + b.pQueueFamilyIndices = nullptr; + + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + VmaAllocationInfo allocInfo{}; + + VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &b, &allocCreateInfo, &info.buffer, &info.allocation, &allocInfo); + if (VK_SUCCESS != res) { + _assert_msg_(false, "vkCreateBuffer failed! result=%d", (int)res); + return false; + } + + vulkan_->SetDebugName(info.buffer, VK_OBJECT_TYPE_BUFFER, name_); + + buffers_.push_back(info); + buf_ = buffers_.size() - 1; + return true; +} + +void VulkanPushBuffer::Destroy(VulkanContext *vulkan) { + _dbg_assert_(!writePtr_); + for (BufInfo &info : buffers_) { + vulkan->Delete().QueueDeleteBufferAllocation(info.buffer, info.allocation); + } + buffers_.clear(); +} + +void VulkanPushBuffer::NextBuffer(size_t minSize) { + // First, unmap the current memory. + Unmap(); + + buf_++; + if (buf_ >= buffers_.size() || minSize > size_) { + // Before creating the buffer, adjust to the new size_ if necessary. + while (size_ < minSize) { + size_ <<= 1; + } + + bool res = AddBuffer(); + _assert_(res); + if (!res) { + // Let's try not to crash at least? + buf_ = 0; + } + } + + // Now, move to the next buffer and map it. + offset_ = 0; + Map(); +} + +void VulkanPushBuffer::Defragment(VulkanContext *vulkan) { + if (buffers_.size() <= 1) { + return; + } + + // Okay, we have more than one. Destroy them all and start over with a larger one. + size_t newSize = size_ * buffers_.size(); + Destroy(vulkan); + + size_ = newSize; + bool res = AddBuffer(); + _assert_(res); +} + +size_t VulkanPushBuffer::GetTotalSize() const { + size_t sum = 0; + if (buffers_.size() > 1) + sum += size_ * (buffers_.size() - 1); + sum += offset_; + return sum; +} + +void VulkanPushBuffer::GetDebugString(char *buffer, size_t bufSize) const { + size_t sum = 0; + if (buffers_.size() > 1) + sum += size_ * (buffers_.size() - 1); + sum += offset_; + size_t capacity = size_ * buffers_.size(); + snprintf(buffer, bufSize, "Push %s: %s / %s", name_, NiceSizeFormat(sum).c_str(), NiceSizeFormat(capacity).c_str()); +} + +void VulkanPushBuffer::Map() { + _dbg_assert_(!writePtr_); + VkResult res = vmaMapMemory(vulkan_->Allocator(), buffers_[buf_].allocation, (void **)(&writePtr_)); + _dbg_assert_(writePtr_); + _assert_(VK_SUCCESS == res); +} + +void VulkanPushBuffer::Unmap() { + _dbg_assert_msg_(writePtr_ != nullptr, "VulkanPushBuffer::Unmap: writePtr_ null here means we have a bug (map/unmap mismatch)"); + if (!writePtr_) + return; + + vmaUnmapMemory(vulkan_->Allocator(), buffers_[buf_].allocation); + writePtr_ = nullptr; +} + +VulkanDescSetPool::~VulkanDescSetPool() { + _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool %s never destroyed", tag_); +} + +void VulkanDescSetPool::Create(VulkanContext *vulkan, const VkDescriptorPoolCreateInfo &info, const std::vector &sizes) { + _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool::Create when already exists"); + + vulkan_ = vulkan; + info_ = info; + sizes_ = sizes; + + VkResult res = Recreate(false); + _assert_msg_(res == VK_SUCCESS, "Could not create VulkanDescSetPool %s", tag_); +} + +VkDescriptorSet VulkanDescSetPool::Allocate(int n, const VkDescriptorSetLayout *layouts, const char *tag) { + if (descPool_ == VK_NULL_HANDLE || usage_ + n >= info_.maxSets) { + // Missing or out of space, need to recreate. + VkResult res = Recreate(grow_); + _assert_msg_(res == VK_SUCCESS, "Could not grow VulkanDescSetPool %s on usage %d", tag_, (int)usage_); + } + + VkDescriptorSet desc; + VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + descAlloc.descriptorPool = descPool_; + descAlloc.descriptorSetCount = n; + descAlloc.pSetLayouts = layouts; + VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc); + + if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) { + // There seems to have been a spec revision. Here we should apparently recreate the descriptor pool, + // so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html + // Fragmentation shouldn't really happen though since we wipe the pool every frame. + VkResult res = Recreate(false); + _assert_msg_(res == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to recreate a descriptor pool. sz=%d res=%d", usage_, (int)res); + + // Need to update this pointer since we have allocated a new one. + descAlloc.descriptorPool = descPool_; + result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc); + _assert_msg_(result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result); + } + + if (result != VK_SUCCESS) { + return VK_NULL_HANDLE; + } + + vulkan_->SetDebugName(desc, VK_OBJECT_TYPE_DESCRIPTOR_SET, tag); + return desc; +} + +void VulkanDescSetPool::Reset() { + _assert_msg_(descPool_ != VK_NULL_HANDLE, "VulkanDescSetPool::Reset without valid pool"); + vkResetDescriptorPool(vulkan_->GetDevice(), descPool_, 0); + + clear_(); + usage_ = 0; +} + +void VulkanDescSetPool::Destroy() { + _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Destroy without VulkanContext"); + + if (descPool_ != VK_NULL_HANDLE) { + vulkan_->Delete().QueueDeleteDescriptorPool(descPool_); + clear_(); + usage_ = 0; + } +} + +VkResult VulkanDescSetPool::Recreate(bool grow) { + _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Recreate without VulkanContext"); + + uint32_t prevSize = info_.maxSets; + if (grow) { + info_.maxSets *= 2; + for (auto &size : sizes_) + size.descriptorCount *= 2; + } + + // Delete the pool if it already exists. + if (descPool_ != VK_NULL_HANDLE) { + DEBUG_LOG(G3D, "Reallocating %s desc pool from %d to %d", tag_, prevSize, info_.maxSets); + vulkan_->Delete().QueueDeleteDescriptorPool(descPool_); + clear_(); + usage_ = 0; + } + + info_.pPoolSizes = &sizes_[0]; + info_.poolSizeCount = (uint32_t)sizes_.size(); + + VkResult result = vkCreateDescriptorPool(vulkan_->GetDevice(), &info_, nullptr, &descPool_); + if (result == VK_SUCCESS) { + vulkan_->SetDebugName(descPool_, VK_OBJECT_TYPE_DESCRIPTOR_POOL, tag_); + } + return result; +} + VulkanPushPool::VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage) : vulkan_(vulkan), name_(name), originalBlockSize_(originalBlockSize), usage_(usage) { - RegisterGPUMemoryManager(this); + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.insert(this); + } + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { blocks_.push_back(CreateBlock(originalBlockSize)); blocks_.back().original = true; @@ -46,7 +289,11 @@ VulkanPushPool::VulkanPushPool(VulkanContext *vulkan, const char *name, size_t o } VulkanPushPool::~VulkanPushPool() { - UnregisterGPUMemoryManager(this); + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.erase(this); + } + _dbg_assert_(blocks_.empty()); } @@ -74,7 +321,7 @@ VulkanPushPool::Block VulkanPushPool::CreateBlock(size_t size) { _assert_(result == VK_SUCCESS); result = vmaMapMemory(vulkan_->Allocator(), block.allocation, (void **)(&block.writePtr)); - _assert_msg_(result == VK_SUCCESS, "VulkanPushPool: Failed to map memory (result = %s)", VulkanResultToString(result)); + _assert_(result == VK_SUCCESS); _assert_msg_(block.writePtr != nullptr, "VulkanPushPool: Failed to map memory on block of size %d", (int)block.size); return block; diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index 14e3b7843..766f497a7 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -5,9 +5,7 @@ #include #include -#include "Common/Data/Collections/FastVec.h" #include "Common/GPU/Vulkan/VulkanContext.h" -#include "Common/GPU/GPUBackendCommon.h" // Forward declaration VK_DEFINE_HANDLE(VmaAllocation); @@ -16,10 +14,101 @@ VK_DEFINE_HANDLE(VmaAllocation); // // Vulkan memory management utils. +// Just an abstract thing to get debug information. +class VulkanMemoryManager { +public: + virtual ~VulkanMemoryManager() {} + + virtual void GetDebugString(char *buffer, size_t bufSize) const = 0; + virtual const char *Name() const = 0; // for sorting +}; + +// VulkanPushBuffer +// Simple incrementing allocator. +// Use these to push vertex, index and uniform data. Generally you'll have two or three of these +// and alternate on each frame. Make sure not to reset until the fence from the last time you used it +// has completed. +// NOTE: This has now been replaced with VulkanPushPool for all uses except the vertex cache. +class VulkanPushBuffer : public VulkanMemoryManager { + struct BufInfo { + VkBuffer buffer; + VmaAllocation allocation; + }; + +public: + // NOTE: If you create a push buffer with PushBufferType::GPU_ONLY, + // then you can't use any of the push functions as pointers will not be reachable from the CPU. + // You must in this case use Allocate() only, and pass the returned offset and the VkBuffer to Vulkan APIs. + VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage); + ~VulkanPushBuffer(); + + void Destroy(VulkanContext *vulkan); + + void Reset() { offset_ = 0; } + + void GetDebugString(char *buffer, size_t bufSize) const override; + const char *Name() const override { + return name_; + } + + // Needs context in case of defragment. + void Begin(VulkanContext *vulkan) { + buf_ = 0; + offset_ = 0; + // Note: we must defrag because some buffers may be smaller than size_. + Defragment(vulkan); + Map(); + } + + void BeginNoReset() { Map(); } + void End() { Unmap(); } + + void Map(); + void Unmap(); + + // When using the returned memory, make sure to bind the returned vkbuf. + uint8_t *Allocate(VkDeviceSize numBytes, VkDeviceSize alignment, VkBuffer *vkbuf, uint32_t *bindOffset) { + size_t offset = (offset_ + alignment - 1) & ~(alignment - 1); + if (offset + numBytes > size_) { + NextBuffer(numBytes); + offset = offset_; + } + offset_ = offset + numBytes; + *bindOffset = (uint32_t)offset; + *vkbuf = buffers_[buf_].buffer; + return writePtr_ + offset; + } + + VkDeviceSize Push(const void *data, VkDeviceSize numBytes, int alignment, VkBuffer *vkbuf) { + uint32_t bindOffset; + uint8_t *ptr = Allocate(numBytes, alignment, vkbuf, &bindOffset); + memcpy(ptr, data, numBytes); + return bindOffset; + } + + size_t GetOffset() const { return offset_; } + size_t GetTotalSize() const; + +private: + bool AddBuffer(); + void NextBuffer(size_t minSize); + void Defragment(VulkanContext *vulkan); + + VulkanContext *vulkan_; + + std::vector buffers_; + size_t buf_ = 0; + size_t offset_ = 0; + size_t size_ = 0; + uint8_t *writePtr_ = nullptr; + VkBufferUsageFlags usage_; + const char *name_; +}; + // Simple memory pushbuffer pool that can share blocks between the "frames", to reduce the impact of push memory spikes - // a later frame can gobble up redundant buffers from an earlier frame even if they don't share frame index. // NOT thread safe! Can only be used from one thread (our main thread). -class VulkanPushPool : public GPUMemoryManager { +class VulkanPushPool : public VulkanMemoryManager { public: VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage); ~VulkanPushPool(); @@ -54,8 +143,6 @@ public: return blocks_[curBlockIndex_].writePtr; } - // NOTE: If you can avoid this by writing the data directly into memory returned from Allocate, - // do so. Savings from avoiding memcpy can be significant. VkDeviceSize Push(const void *data, VkDeviceSize numBytes, int alignment, VkBuffer *vkbuf) { uint32_t bindOffset; uint8_t *ptr = Allocate(numBytes, alignment, vkbuf, &bindOffset); @@ -94,3 +181,36 @@ private: int curBlockIndex_ = -1; const char *name_; }; + +// Only appropriate for use in a per-frame pool. +class VulkanDescSetPool { +public: + VulkanDescSetPool(const char *tag, bool grow) : tag_(tag), grow_(grow) {} + ~VulkanDescSetPool(); + + // Must call this before use: defines how to clear cache of ANY returned values from Allocate(). + void Setup(const std::function &clear) { + clear_ = clear; + } + void Create(VulkanContext *vulkan, const VkDescriptorPoolCreateInfo &info, const std::vector &sizes); + // Allocate a new set, which may resize and empty the current sets. + // Use only for the current frame, unless in a cache cleared by clear_. + VkDescriptorSet Allocate(int n, const VkDescriptorSetLayout *layouts, const char *tag); + void Reset(); + void Destroy(); + +private: + VkResult Recreate(bool grow); + + const char *tag_; + VulkanContext *vulkan_ = nullptr; + VkDescriptorPool descPool_ = VK_NULL_HANDLE; + VkDescriptorPoolCreateInfo info_{}; + std::vector sizes_; + std::function clear_; + uint32_t usage_ = 0; + bool grow_; +}; + +std::vector GetActiveVulkanMemoryManagers(); + diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 6c6fb9f66..3e2c26934 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -129,6 +129,7 @@ bool VulkanQueueRunner::CreateSwapchain(VkCommandBuffer cmdInit) { return true; } + bool VulkanQueueRunner::InitBackbufferFramebuffers(int width, int height) { VkResult res; // We share the same depth buffer but have multiple color buffers, see the loop below. @@ -172,7 +173,7 @@ bool VulkanQueueRunner::InitDepthStencilBuffer(VkCommandBuffer cmd) { image_info.queueFamilyIndexCount = 0; image_info.pQueueFamilyIndices = nullptr; image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; + image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; image_info.flags = 0; depth_.format = depth_format; @@ -250,8 +251,8 @@ void VulkanQueueRunner::DestroyBackBuffers() { // Self-dependency: https://github.com/gpuweb/gpuweb/issues/442#issuecomment-547604827 // Also see https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#synchronization-pipeline-barriers-subpass-self-dependencies VKRRenderPass *VulkanQueueRunner::GetRenderPass(const RPKey &key) { - VKRRenderPass *foundPass; - if (renderPasses_.Get(key, &foundPass)) { + auto foundPass = renderPasses_.Get(key); + if (foundPass) { return foundPass; } @@ -260,6 +261,31 @@ VKRRenderPass *VulkanQueueRunner::GetRenderPass(const RPKey &key) { return pass; } +// Must match the subpass self-dependency declared above. +void VulkanQueueRunner::SelfDependencyBarrier(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier) { + if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + VkAccessFlags srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkAccessFlags dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + recordBarrier->TransitionImage( + img.image, + 0, + 1, + img.numLayers, + aspect, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_GENERAL, + srcAccessMask, + dstAccessMask, + srcStageMask, + dstStageMask + ); + } else { + _assert_msg_(false, "Depth self-dependencies not yet supported"); + } +} + void VulkanQueueRunner::PreprocessSteps(std::vector &steps) { // Optimizes renderpasses, then sequences them. // Planned optimizations: @@ -337,8 +363,8 @@ void VulkanQueueRunner::PreprocessSteps(std::vector &steps) { } } -void VulkanQueueRunner::RunSteps(std::vector &steps, int curFrame, FrameData &frameData, FrameDataShared &frameDataShared, bool keepSteps) { - QueueProfileContext *profile = frameData.profile.enabled ? &frameData.profile : nullptr; +void VulkanQueueRunner::RunSteps(std::vector &steps, FrameData &frameData, FrameDataShared &frameDataShared, bool keepSteps) { + QueueProfileContext *profile = frameData.profilingEnabled_ ? &frameData.profile : nullptr; if (profile) profile->cpuStartTime = time_now_d(); @@ -393,7 +419,7 @@ void VulkanQueueRunner::RunSteps(std::vector &steps, int curFrame, Fr vkCmdBeginDebugUtilsLabelEXT(cmd, &labelInfo); } } - PerformRenderPass(step, cmd, curFrame); + PerformRenderPass(step, cmd); break; case VKRStepType::COPY: PerformCopy(step, cmd); @@ -411,9 +437,9 @@ void VulkanQueueRunner::RunSteps(std::vector &steps, int curFrame, Fr break; } - if (profile && profile->timestampsEnabled && profile->timestampDescriptions.size() + 1 < MAX_TIMESTAMP_QUERIES) { + if (profile && profile->timestampDescriptions.size() + 1 < MAX_TIMESTAMP_QUERIES) { vkCmdWriteTimestamp(cmd, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, profile->queryPool, (uint32_t)profile->timestampDescriptions.size()); - profile->timestampDescriptions.push_back(StepToString(vulkan_, step)); + profile->timestampDescriptions.push_back(StepToString(step)); } if (emitLabels) { @@ -455,7 +481,7 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector &steps) { last = j - 1; // should really also check descriptor sets... if (steps[j]->commands.size()) { - const VkRenderData &cmd = steps[j]->commands.back(); + VkRenderData &cmd = steps[j]->commands.back(); if (cmd.cmd == VKRRenderCommand::DRAW_INDEXED && cmd.draw.count != 6) last = j - 1; } @@ -673,16 +699,36 @@ const char *AspectToString(VkImageAspectFlags aspect) { } } -std::string VulkanQueueRunner::StepToString(VulkanContext *vulkan, const VKRStep &step) { +static const char *rpTypeDebugNames[] = { + "RENDER", + "RENDER_DEPTH", + "RENDER_INPUT", + "RENDER_DEPTH_INPUT", + "MV_RENDER", + "MV_RENDER_DEPTH", + "MV_RENDER_INPUT", + "MV_RENDER_DEPTH_INPUT", + "MS_RENDER", + "MS_RENDER_DEPTH", + "MS_RENDER_INPUT", + "MS_RENDER_DEPTH_INPUT", + "MS_MV_RENDER", + "MS_MV_RENDER_DEPTH", + "MS_MV_RENDER_INPUT", + "MS_MV_RENDER_DEPTH_INPUT", + "BACKBUF", +}; + +std::string VulkanQueueRunner::StepToString(const VKRStep &step) const { char buffer[256]; switch (step.stepType) { case VKRStepType::RENDER: { - int w = step.render.framebuffer ? step.render.framebuffer->width : vulkan->GetBackbufferWidth(); - int h = step.render.framebuffer ? step.render.framebuffer->height : vulkan->GetBackbufferHeight(); + int w = step.render.framebuffer ? step.render.framebuffer->width : vulkan_->GetBackbufferWidth(); + int h = step.render.framebuffer ? step.render.framebuffer->height : vulkan_->GetBackbufferHeight(); int actual_w = step.render.renderArea.extent.width; int actual_h = step.render.renderArea.extent.height; - const char *renderCmd = GetRPTypeName(step.render.renderPassType); + const char *renderCmd = rpTypeDebugNames[(size_t)step.render.renderPassType]; snprintf(buffer, sizeof(buffer), "%s %s %s (draws: %d, %dx%d/%dx%d)", renderCmd, step.tag, step.render.framebuffer ? step.render.framebuffer->Tag() : "", step.render.numDraws, actual_w, actual_h, w, h); break; } @@ -872,9 +918,15 @@ void VulkanQueueRunner::LogRenderPass(const VKRStep &pass, bool verbose) { case VKRRenderCommand::REMOVED: INFO_LOG(G3D, " (Removed)"); break; + case VKRRenderCommand::SELF_DEPENDENCY_BARRIER: + INFO_LOG(G3D, " SelfBarrier()"); + break; case VKRRenderCommand::BIND_GRAPHICS_PIPELINE: INFO_LOG(G3D, " BindGraphicsPipeline(%x)", (int)(intptr_t)cmd.graphics_pipeline.pipeline); break; + case VKRRenderCommand::BIND_COMPUTE_PIPELINE: + INFO_LOG(G3D, " BindComputePipeline(%x)", (int)(intptr_t)cmd.compute_pipeline.pipeline); + break; case VKRRenderCommand::BLEND: INFO_LOG(G3D, " BlendColor(%08x)", cmd.blendColor.color); break; @@ -914,19 +966,19 @@ void VulkanQueueRunner::LogRenderPass(const VKRStep &pass, bool verbose) { } void VulkanQueueRunner::LogCopy(const VKRStep &step) { - INFO_LOG(G3D, "%s", StepToString(vulkan_, step).c_str()); + INFO_LOG(G3D, "%s", StepToString(step).c_str()); } void VulkanQueueRunner::LogBlit(const VKRStep &step) { - INFO_LOG(G3D, "%s", StepToString(vulkan_, step).c_str()); + INFO_LOG(G3D, "%s", StepToString(step).c_str()); } void VulkanQueueRunner::LogReadback(const VKRStep &step) { - INFO_LOG(G3D, "%s", StepToString(vulkan_, step).c_str()); + INFO_LOG(G3D, "%s", StepToString(step).c_str()); } void VulkanQueueRunner::LogReadbackImage(const VKRStep &step) { - INFO_LOG(G3D, "%s", StepToString(vulkan_, step).c_str()); + INFO_LOG(G3D, "%s", StepToString(step).c_str()); } void TransitionToOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayout colorLayout, VkImage depthStencilImage, VkImageLayout depthStencilLayout, int numLayers, VulkanBarrier *recordBarrier) { @@ -1099,7 +1151,7 @@ void TransitionFromOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayou } } -void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd, int curFrame) { +void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd) { for (size_t i = 0; i < step.preTransitions.size(); i++) { const TransitionRequest &iter = step.preTransitions[i]; if (iter.aspect == VK_IMAGE_ASPECT_COLOR_BIT && iter.fb->color.layout != iter.targetLayout) { @@ -1189,13 +1241,12 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c VKRGraphicsPipeline *lastGraphicsPipeline = nullptr; VKRComputePipeline *lastComputePipeline = nullptr; - const auto &commands = step.commands; + auto &commands = step.commands; // We can do a little bit of state tracking here to eliminate some calls into the driver. // The stencil ones are very commonly mostly redundant so let's eliminate them where possible. // Might also want to consider scissor and viewport. VkPipeline lastPipeline = VK_NULL_HANDLE; - FastVec *descSets = nullptr; VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; bool pipelineOK = false; @@ -1238,9 +1289,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c if (pipeline != VK_NULL_HANDLE) { vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - descSets = &c.graphics_pipeline.pipelineLayout->frameData[curFrame].descSets_; - pipelineLayout = c.graphics_pipeline.pipelineLayout->pipelineLayout; - _dbg_assert_(pipelineLayout != VK_NULL_HANDLE); + pipelineLayout = c.pipeline.pipelineLayout; lastGraphicsPipeline = graphicsPipeline; pipelineOK = true; } else { @@ -1255,6 +1304,20 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c break; } + case VKRRenderCommand::BIND_COMPUTE_PIPELINE: + { + VKRComputePipeline *computePipeline = c.compute_pipeline.pipeline; + if (computePipeline != lastComputePipeline) { + VkPipeline pipeline = computePipeline->pipeline->BlockUntilReady(); + if (pipeline != VK_NULL_HANDLE) { + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); + pipelineLayout = c.pipeline.pipelineLayout; + lastComputePipeline = computePipeline; + } + } + break; + } + case VKRRenderCommand::VIEWPORT: if (fb != nullptr) { vkCmdSetViewport(cmd, 0, 1, &c.viewport.vp); @@ -1298,6 +1361,21 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c break; } + case VKRRenderCommand::SELF_DEPENDENCY_BARRIER: + { + _assert_(step.render.pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT); + _assert_(fb); + VulkanBarrier barrier; + if (fb->sampleCount != VK_SAMPLE_COUNT_1_BIT) { + // Rendering is happening to the multisample buffer, not the color buffer. + SelfDependencyBarrier(fb->msaaColor, VK_IMAGE_ASPECT_COLOR_BIT, &barrier); + } else { + SelfDependencyBarrier(fb->color, VK_IMAGE_ASPECT_COLOR_BIT, &barrier); + } + barrier.Flush(cmd); + break; + } + case VKRRenderCommand::PUSH_CONSTANTS: if (pipelineOK) { vkCmdPushConstants(cmd, pipelineLayout, c.push.stages, c.push.offset, c.push.size, c.push.data); @@ -1321,10 +1399,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::DRAW_INDEXED: if (pipelineOK) { - VkDescriptorSet set = (*descSets)[c.drawIndexed.descSetIndex].set; - _dbg_assert_(set != VK_NULL_HANDLE); - vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets); - vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &c.drawIndexed.ds, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets); + vkCmdBindIndexBuffer(cmd, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, (VkIndexType)c.drawIndexed.indexType); VkDeviceSize voffset = c.drawIndexed.voffset; vkCmdBindVertexBuffers(cmd, 0, 1, &c.drawIndexed.vbuffer, &voffset); vkCmdDrawIndexed(cmd, c.drawIndexed.count, c.drawIndexed.instances, 0, 0, 0); @@ -1333,9 +1409,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::DRAW: if (pipelineOK) { - VkDescriptorSet set = (*descSets)[c.drawIndexed.descSetIndex].set; - _dbg_assert_(set != VK_NULL_HANDLE); - vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, c.draw.numUboOffsets, c.draw.uboOffsets); + vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets); if (c.draw.vbuffer) { vkCmdBindVertexBuffers(cmd, 0, 1, &c.draw.vbuffer, &c.draw.voffset); } @@ -1953,7 +2027,8 @@ void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd key.height = step.readback.srcRect.extent.height; // See if there's already a buffer we can reuse - if (!frameData.readbacks_.Get(key, &cached)) { + cached = frameData.readbacks_.Get(key); + if (!cached) { cached = new CachedReadback(); cached->bufferSize = 0; frameData.readbacks_.Insert(key, cached); @@ -2033,8 +2108,8 @@ bool VulkanQueueRunner::CopyReadbackBuffer(FrameData &frameData, VKRFramebuffer key.framebuf = src; key.width = width; key.height = height; - CachedReadback *cached; - if (frameData.readbacks_.Get(key, &cached)) { + CachedReadback *cached = frameData.readbacks_.Get(key); + if (cached) { readback = cached; } else { // Didn't have a cached image ready yet diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index a7676c466..6df7dfc68 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -6,7 +6,6 @@ #include "Common/Thread/Promise.h" #include "Common/Data/Collections/Hashmaps.h" -#include "Common/Data/Collections/FastVec.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanBarrier.h" #include "Common/GPU/Vulkan/VulkanFrameData.h" @@ -19,7 +18,6 @@ class VKRFramebuffer; struct VKRGraphicsPipeline; struct VKRComputePipeline; struct VKRImage; -struct VKRPipelineLayout; struct FrameData; enum { @@ -31,6 +29,7 @@ enum { enum class VKRRenderCommand : uint8_t { REMOVED, BIND_GRAPHICS_PIPELINE, // async + BIND_COMPUTE_PIPELINE, // async STENCIL, BLEND, VIEWPORT, @@ -39,6 +38,7 @@ enum class VKRRenderCommand : uint8_t { DRAW, DRAW_INDEXED, PUSH_CONSTANTS, + SELF_DEPENDENCY_BARRIER, DEBUG_ANNOTATION, NUM_RENDER_COMMANDS, }; @@ -47,21 +47,30 @@ enum class PipelineFlags : u8 { NONE = 0, USES_BLEND_CONSTANT = (1 << 1), USES_DEPTH_STENCIL = (1 << 2), // Reads or writes the depth or stencil buffers. - USES_GEOMETRY_SHADER = (1 << 3), - USES_MULTIVIEW = (1 << 4), // Inherited from the render pass it was created with. - USES_DISCARD = (1 << 5), + USES_INPUT_ATTACHMENT = (1 << 3), + USES_GEOMETRY_SHADER = (1 << 4), + USES_MULTIVIEW = (1 << 5), // Inherited from the render pass it was created with. + USES_DISCARD = (1 << 6), }; ENUM_CLASS_BITOPS(PipelineFlags); struct VkRenderData { VKRRenderCommand cmd; union { + struct { + VkPipeline pipeline; + VkPipelineLayout pipelineLayout; + } pipeline; struct { VKRGraphicsPipeline *pipeline; - VKRPipelineLayout *pipelineLayout; + VkPipelineLayout pipelineLayout; } graphics_pipeline; struct { - uint32_t descSetIndex; + VKRComputePipeline *pipeline; + VkPipelineLayout pipelineLayout; + } compute_pipeline; + struct { + VkDescriptorSet ds; int numUboOffsets; uint32_t uboOffsets[3]; VkBuffer vbuffer; @@ -70,15 +79,16 @@ struct VkRenderData { uint32_t offset; } draw; struct { - uint32_t descSetIndex; + VkDescriptorSet ds; + int numUboOffsets; uint32_t uboOffsets[3]; - uint16_t numUboOffsets; - uint16_t instances; VkBuffer vbuffer; VkBuffer ibuffer; uint32_t voffset; uint32_t ioffset; uint32_t count; + int16_t instances; + int16_t indexType; } drawIndexed; struct { uint32_t clearColor; @@ -110,7 +120,9 @@ struct VkRenderData { const char *annotation; } debugAnnotation; struct { - int setIndex; + int setNumber; + VkDescriptorSet set; + VkPipelineLayout pipelineLayout; } bindDescSet; }; }; @@ -141,7 +153,7 @@ struct VKRStep { ~VKRStep() {} VKRStepType stepType; - FastVec commands; + std::vector commands; TinySet preTransitions; TinySet dependencies; const char *tag; @@ -200,14 +212,9 @@ struct VKRStep { // These are enqueued from the main thread, // and the render thread pops them off struct VKRRenderThreadTask { - VKRRenderThreadTask(VKRRunType _runType) : runType(_runType) {} std::vector steps; - int frame = -1; + int frame; VKRRunType runType; - - // Avoid copying these by accident. - VKRRenderThreadTask(VKRRenderThreadTask &) = delete; - VKRRenderThreadTask &operator =(VKRRenderThreadTask &) = delete; }; class VulkanQueueRunner { @@ -220,10 +227,10 @@ public: } void PreprocessSteps(std::vector &steps); - void RunSteps(std::vector &steps, int curFrame, FrameData &frameData, FrameDataShared &frameDataShared, bool keepSteps = false); + void RunSteps(std::vector &steps, FrameData &frameData, FrameDataShared &frameDataShared, bool keepSteps = false); void LogSteps(const std::vector &steps, bool verbose); - static std::string StepToString(VulkanContext *vulkan, const VKRStep &step); + std::string StepToString(const VKRStep &step) const; void CreateDeviceObjects(); void DestroyDeviceObjects(); @@ -280,7 +287,7 @@ private: bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering. VKRRenderPass *PerformBindFramebufferAsRenderTarget(const VKRStep &pass, VkCommandBuffer cmd); - void PerformRenderPass(const VKRStep &pass, VkCommandBuffer cmd, int curFrame); + void PerformRenderPass(const VKRStep &pass, VkCommandBuffer cmd); void PerformCopy(const VKRStep &pass, VkCommandBuffer cmd); void PerformBlit(const VKRStep &pass, VkCommandBuffer cmd); void PerformReadback(const VKRStep &pass, VkCommandBuffer cmd, FrameData &frameData); @@ -302,6 +309,8 @@ private: static void SetupTransitionToTransferDst(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier); static void SetupTransferDstWriteAfterWrite(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier); + static void SelfDependencyBarrier(VKRImage &img, VkImageAspectFlags aspect, VulkanBarrier *recordBarrier); + VulkanContext *vulkan_; VkFramebuffer backbuffer_ = VK_NULL_HANDLE; @@ -312,7 +321,7 @@ private: // Renderpasses, all combinations of preserving or clearing or dont-care-ing fb contents. // Each VKRRenderPass contains all compatibility classes (which attachments they have, etc). - DenseHashMap renderPasses_; + DenseHashMap renderPasses_; // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 9a4f4e1aa..7ab778d8c 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -12,7 +12,6 @@ #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanRenderManager.h" -#include "Common/LogReporting.h" #include "Common/Thread/ThreadUtil.h" #include "Common/VR/PPSSPPVR.h" @@ -30,10 +29,6 @@ using namespace PPSSPP_VK; // renderPass is an example of the "compatibility class" or RenderPassType type. bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleRenderPass, RenderPassType rpType, VkSampleCountFlagBits sampleCount, double scheduleTime, int countToCompile) { - // Good torture test to test the shutdown-while-precompiling-shaders issue on PC where it's normally - // hard to catch because shaders compile so fast. - // sleep_ms(200); - bool multisample = RenderPassTypeHasMultisample(rpType); if (multisample) { if (sampleCount_ != VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM) { @@ -116,7 +111,7 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR pipe.pDynamicState = &desc->ds; pipe.pInputAssemblyState = &inputAssembly; pipe.pMultisampleState = &ms; - pipe.layout = desc->pipelineLayout->pipelineLayout; + pipe.layout = desc->pipelineLayout; pipe.basePipelineHandle = VK_NULL_HANDLE; pipe.basePipelineIndex = 0; pipe.subpass = 0; @@ -192,7 +187,7 @@ void VKRGraphicsPipeline::DestroyVariantsInstant(VkDevice device) { VKRGraphicsPipeline::~VKRGraphicsPipeline() { // This is called from the callbacked queued in QueueForDeletion. - // When we reach here, we should already be empty, so let's assert on that. + // Here we are free to directly delete stuff, don't need to queue. for (size_t i = 0; i < (size_t)RenderPassType::TYPE_COUNT; i++) { _assert_(!pipeline[i]); } @@ -200,14 +195,6 @@ VKRGraphicsPipeline::~VKRGraphicsPipeline() { desc->Release(); } -void VKRGraphicsPipeline::BlockUntilCompiled() { - for (size_t i = 0; i < (size_t)RenderPassType::TYPE_COUNT; i++) { - if (pipeline[i]) { - pipeline[i]->BlockUntilReady(); - } - } -} - void VKRGraphicsPipeline::QueueForDeletion(VulkanContext *vulkan) { // Can't destroy variants here, the pipeline still lives for a while. vulkan->Delete().QueueCallback([](VulkanContext *vulkan, void *p) { @@ -260,21 +247,15 @@ bool VKRComputePipeline::CreateAsync(VulkanContext *vulkan) { return true; } -VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan, bool useThread, HistoryBuffer &frameTimeHistory) +VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan), queueRunner_(vulkan), initTimeMs_("initTimeMs"), totalGPUTimeMs_("totalGPUTimeMs"), - renderCPUTimeMs_("renderCPUTimeMs"), - descUpdateTimeMs_("descUpdateCPUTimeMs"), - useRenderThread_(useThread), - frameTimeHistory_(frameTimeHistory) + renderCPUTimeMs_("renderCPUTimeMs") { inflightFramesAtStart_ = vulkan_->GetInflightFrames(); - // For present timing experiments. Disabled for now. - measurePresentTime_ = false; - - frameDataShared_.Init(vulkan, useThread, measurePresentTime_); + frameDataShared_.Init(vulkan); for (int i = 0; i < inflightFramesAtStart_; i++) { frameData_[i].Init(vulkan, i); @@ -289,6 +270,7 @@ bool VulkanRenderManager::CreateBackbuffers() { return false; } + VkCommandBuffer cmdInit = GetInitCmd(); if (!queueRunner_.CreateSwapchain(cmdInit)) { @@ -310,53 +292,35 @@ bool VulkanRenderManager::CreateBackbuffers() { outOfDateFrames_ = 0; - for (int i = 0; i < vulkan_->GetInflightFrames(); i++) { - auto &frameData = frameData_[i]; - frameData.readyForFence = true; // Just in case. - } - - // Start the thread(s). + // Start the thread. if (HasBackbuffers()) { run_ = true; // For controlling the compiler thread's exit - if (useRenderThread_) { - INFO_LOG(G3D, "Starting Vulkan submission thread"); - thread_ = std::thread(&VulkanRenderManager::ThreadFunc, this); - } + INFO_LOG(G3D, "Starting Vulkan submission thread"); + thread_ = std::thread(&VulkanRenderManager::ThreadFunc, this); INFO_LOG(G3D, "Starting Vulkan compiler thread"); compileThread_ = std::thread(&VulkanRenderManager::CompileThreadFunc, this); - - if (measurePresentTime_ && vulkan_->Extensions().KHR_present_wait && vulkan_->GetPresentMode() == VK_PRESENT_MODE_FIFO_KHR) { - INFO_LOG(G3D, "Starting Vulkan present wait thread"); - presentWaitThread_ = std::thread(&VulkanRenderManager::PresentWaitThreadFunc, this); - } } return true; } // Called from main thread. void VulkanRenderManager::StopThread() { - if (useRenderThread_) { - _dbg_assert_(thread_.joinable()); + { // Tell the render thread to quit when it's done. - VKRRenderThreadTask *task = new VKRRenderThreadTask(VKRRunType::EXIT); - task->frame = vulkan_->GetCurFrame(); + VKRRenderThreadTask task; + task.frame = vulkan_->GetCurFrame(); + task.runType = VKRRunType::EXIT; std::unique_lock lock(pushMutex_); renderThreadQueue_.push(task); pushCondVar_.notify_one(); } - // Compiler and present thread still relies on this. + // Compiler thread still relies on this. run_ = false; - if (presentWaitThread_.joinable()) { - presentWaitThread_.join(); - } - // Stop the thread. - if (useRenderThread_) { - thread_.join(); - } + thread_.join(); for (int i = 0; i < vulkan_->GetInflightFrames(); i++) { auto &frameData = frameData_[i]; @@ -413,8 +377,6 @@ VulkanRenderManager::~VulkanRenderManager() { vulkan_->WaitUntilQueueIdle(); - _dbg_assert_(pipelineLayouts_.empty()); - VkDevice device = vulkan_->GetDevice(); frameDataShared_.Destroy(vulkan_); for (int i = 0; i < inflightFramesAtStart_; i++) { @@ -515,32 +477,24 @@ void VulkanRenderManager::CompileThreadFunc() { Task *task = new CreateMultiPipelinesTask(vulkan_, entries); g_threadManager.EnqueueTask(task); } - + queueRunner_.NotifyCompileDone(); } } -void VulkanRenderManager::DrainAndBlockCompileQueue() { +void VulkanRenderManager::DrainCompileQueue() { std::unique_lock lock(compileMutex_); - compileBlocked_ = true; compileCond_.notify_all(); while (!compileQueue_.empty()) { queueRunner_.WaitForCompileNotification(); } } -void VulkanRenderManager::ReleaseCompileQueue() { - std::unique_lock lock(compileMutex_); - compileBlocked_ = false; -} - void VulkanRenderManager::ThreadFunc() { SetCurrentThreadName("RenderMan"); while (true) { - _dbg_assert_(useRenderThread_); - // Pop a task of the queue and execute it. - VKRRenderThreadTask *task = nullptr; + VKRRenderThreadTask task; { std::unique_lock lock(pushMutex_); while (renderThreadQueue_.empty()) { @@ -552,15 +506,12 @@ void VulkanRenderManager::ThreadFunc() { // Oh, we got a task! We can now have pushMutex_ unlocked, allowing the host to // push more work when it feels like it, and just start working. - if (task->runType == VKRRunType::EXIT) { + if (task.runType == VKRRunType::EXIT) { // Oh, host wanted out. Let's leave. - delete task; - // In this case, there should be no more tasks. break; } - Run(*task); - delete task; + Run(task); } // Wait for the device to be done with everything, before tearing stuff down. @@ -570,66 +521,18 @@ void VulkanRenderManager::ThreadFunc() { VLOG("PULL: Quitting"); } -void VulkanRenderManager::PresentWaitThreadFunc() { - SetCurrentThreadName("PresentWait"); - - _dbg_assert_(vkWaitForPresentKHR != nullptr); - - uint64_t waitedId = frameIdGen_; - while (run_) { - const uint64_t timeout = 1000000000ULL; // 1 sec - if (VK_SUCCESS == vkWaitForPresentKHR(vulkan_->GetDevice(), vulkan_->GetSwapchain(), waitedId, timeout)) { - frameTimeHistory_[waitedId].actualPresent = time_now_d(); - frameTimeHistory_[waitedId].waitCount++; - waitedId++; - } else { - // We caught up somehow, which is a bad sign (we should have blocked, right?). Maybe we should break out of the loop? - sleep_ms(1); - frameTimeHistory_[waitedId].waitCount++; - } - _dbg_assert_(waitedId <= frameIdGen_); - } - - INFO_LOG(G3D, "Leaving PresentWaitThreadFunc()"); -} - -void VulkanRenderManager::PollPresentTiming() { - // For VK_GOOGLE_display_timing, we need to poll. - - // Poll for information about completed frames. - // NOTE: We seem to get the information pretty late! Like after 6 frames, which is quite weird. - // Tested on POCO F4. - if (vulkan_->Extensions().GOOGLE_display_timing) { - uint32_t count = 0; - vkGetPastPresentationTimingGOOGLE(vulkan_->GetDevice(), vulkan_->GetSwapchain(), &count, nullptr); - if (count > 0) { - VkPastPresentationTimingGOOGLE *timings = new VkPastPresentationTimingGOOGLE[count]; - vkGetPastPresentationTimingGOOGLE(vulkan_->GetDevice(), vulkan_->GetSwapchain(), &count, timings); - for (uint32_t i = 0; i < count; i++) { - uint64_t presentId = timings[i].presentID; - frameTimeHistory_[presentId].actualPresent = from_time_raw(timings[i].actualPresentTime); - frameTimeHistory_[presentId].desiredPresentTime = from_time_raw(timings[i].desiredPresentTime); - frameTimeHistory_[presentId].earliestPresentTime = from_time_raw(timings[i].earliestPresentTime); - double presentMargin = from_time_raw_relative(timings[i].presentMargin); - frameTimeHistory_[presentId].presentMargin = presentMargin; - } - delete[] timings; - } - } -} - void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfiler) { - double frameBeginTime = time_now_d() VLOG("BeginFrame"); VkDevice device = vulkan_->GetDevice(); int curFrame = vulkan_->GetCurFrame(); FrameData &frameData = frameData_[curFrame]; + VLOG("PUSH: Fencing %d", curFrame); // Makes sure the submission from the previous time around has happened. Otherwise // we are not allowed to wait from another thread here.. - if (useRenderThread_) { + { std::unique_lock lock(frameData.fenceMutex); while (!frameData.readyForFence) { frameData.fenceCondVar.wait(lock); @@ -644,29 +547,16 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile } vkResetFences(device, 1, &frameData.fence); - uint64_t frameId = frameIdGen_++; - - PollPresentTiming(); - - ResetDescriptorLists(curFrame); - int validBits = vulkan_->GetQueueFamilyProperties(vulkan_->GetGraphicsQueueFamilyIndex()).timestampValidBits; - FrameTimeData &frameTimeData = frameTimeHistory_.Add(frameId); - frameTimeData.frameId = frameId; - frameTimeData.frameBegin = frameBeginTime; - frameTimeData.afterFenceWait = time_now_d(); - // Can't set this until after the fence. - frameData.profile.enabled = enableProfiling; - frameData.profile.timestampsEnabled = enableProfiling && validBits > 0; - frameData.frameId = frameId; + frameData.profilingEnabled_ = enableProfiling && validBits > 0; uint64_t queryResults[MAX_TIMESTAMP_QUERIES]; - if (enableProfiling) { + if (frameData.profilingEnabled_) { // Pull the profiling results from last time and produce a summary! - if (!frameData.profile.timestampDescriptions.empty() && frameData.profile.timestampsEnabled) { + if (!frameData.profile.timestampDescriptions.empty()) { int numQueries = (int)frameData.profile.timestampDescriptions.size(); VkResult res = vkGetQueryPoolResults( vulkan_->GetDevice(), @@ -684,13 +574,6 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile renderCPUTimeMs_.Update((frameData.profile.cpuEndTime - frameData.profile.cpuStartTime) * 1000.0); renderCPUTimeMs_.Format(line, sizeof(line)); str << line; - descUpdateTimeMs_.Update(frameData.profile.descWriteTime * 1000.0); - descUpdateTimeMs_.Format(line, sizeof(line)); - str << line; - snprintf(line, sizeof(line), "Descriptors written: %d\n", frameData.profile.descriptorsWritten); - str << line; - snprintf(line, sizeof(line), "Resource deletions: %d\n", vulkan_->GetLastDeleteCount()); - str << line; for (int i = 0; i < numQueries - 1; i++) { uint64_t diff = (queryResults[i + 1] - queryResults[i]) & timestampDiffMask; double milliseconds = (double)diff * timestampConversionFactor; @@ -711,22 +594,10 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile frameData.profile.profileSummary = "(error getting GPU profile - not ready?)"; } } else { - std::stringstream str; - char line[256]; - renderCPUTimeMs_.Update((frameData.profile.cpuEndTime - frameData.profile.cpuStartTime) * 1000.0); - renderCPUTimeMs_.Format(line, sizeof(line)); - str << line; - descUpdateTimeMs_.Update(frameData.profile.descWriteTime * 1000.0); - descUpdateTimeMs_.Format(line, sizeof(line)); - str << line; - snprintf(line, sizeof(line), "Descriptors written: %d\n", frameData.profile.descriptorsWritten); - str << line; - frameData.profile.profileSummary = str.str(); + frameData.profile.profileSummary = "(no GPU profile data collected)"; } } - frameData.profile.descriptorsWritten = 0; - // Must be after the fence - this performs deletes. VLOG("PUSH: BeginFrame %d", curFrame); @@ -734,7 +605,7 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile vulkan_->BeginFrame(enableLogProfiler ? GetInitCmd() : VK_NULL_HANDLE); frameData.profile.timestampDescriptions.clear(); - if (frameData.profile.timestampsEnabled) { + if (frameData.profilingEnabled_) { // For various reasons, we need to always use an init cmd buffer in this case to perform the vkCmdResetQueryPool, // unless we want to limit ourselves to only measure the main cmd buffer. // Later versions of Vulkan have support for clearing queries on the CPU timeline, but we don't want to rely on that. @@ -750,28 +621,14 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() { return frameData_[curFrame].GetInitCmd(vulkan_); } -void VulkanRenderManager::ReportBadStateForDraw() { - const char *cause1 = ""; - char cause2[256]; - cause2[0] = '\0'; - if (!curRenderStep_) { - cause1 = "No current render step"; - } - if (curRenderStep_ && curRenderStep_->stepType != VKRStepType::RENDER) { - cause1 = "Not a render step: "; - std::string str = VulkanQueueRunner::StepToString(vulkan_, *curRenderStep_); - truncate_cpy(cause2, str.c_str()); - } - ERROR_LOG_REPORT_ONCE(baddraw, G3D, "Can't draw: %s%s. Step count: %d", cause1, cause2, (int)steps_.size()); -} - VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, PipelineFlags pipelineFlags, uint32_t variantBitmask, VkSampleCountFlagBits sampleCount, bool cacheLoad, const char *tag) { + VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline(pipelineFlags, tag); + if (!desc->vertexShader || !desc->fragmentShader) { ERROR_LOG(G3D, "Can't create graphics pipeline with missing vs/ps: %p %p", desc->vertexShader, desc->fragmentShader); return nullptr; } - VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline(pipelineFlags, tag); pipeline->desc = desc; pipeline->desc->AddRef(); if (curRenderStep_ && !cacheLoad) { @@ -788,11 +645,7 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe VKRRenderPassStoreAction::STORE, VKRRenderPassStoreAction::DONT_CARE, VKRRenderPassStoreAction::DONT_CARE, }; VKRRenderPass *compatibleRenderPass = queueRunner_.GetRenderPass(key); - std::lock_guard lock(compileMutex_); - if (compileBlocked_) { - delete pipeline; - return nullptr; - } + compileMutex_.lock(); bool needsCompile = false; for (size_t i = 0; i < (size_t)RenderPassType::TYPE_COUNT; i++) { if (!(variantBitmask & (1 << i))) @@ -804,6 +657,10 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe WARN_LOG(G3D, "Not compiling pipeline that requires depth, for non depth renderpass type"); continue; } + if ((pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT) && !RenderPassTypeHasInput(rpType)) { + WARN_LOG(G3D, "Not compiling pipeline that requires input attachment, for non input renderpass type"); + continue; + } // Shouldn't hit this, these should have been filtered elsewhere. However, still a good check to do. if (sampleCount == VK_SAMPLE_COUNT_1_BIT && RenderPassTypeHasMultisample(rpType)) { WARN_LOG(G3D, "Not compiling single sample pipeline for a multisampled render pass type"); @@ -816,19 +673,18 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe } if (needsCompile) compileCond_.notify_one(); + compileMutex_.unlock(); } return pipeline; } VKRComputePipeline *VulkanRenderManager::CreateComputePipeline(VKRComputePipelineDesc *desc) { - std::lock_guard lock(compileMutex_); - if (compileBlocked_) { - return nullptr; - } VKRComputePipeline *pipeline = new VKRComputePipeline(); pipeline->desc = desc; + compileMutex_.lock(); compileQueue_.push_back(CompileQueueEntry(pipeline)); compileCond_.notify_one(); + compileMutex_.unlock(); return pipeline; } @@ -854,6 +710,10 @@ void VulkanRenderManager::EndCurRenderStep() { if (!curRenderStep_->render.framebuffer) { rpType = RenderPassType::BACKBUFFER; } else { + if (curPipelineFlags_ & PipelineFlags::USES_INPUT_ATTACHMENT) { + // Not allowed on backbuffers. + rpType = depthStencil ? (RenderPassType::HAS_DEPTH | RenderPassType::COLOR_INPUT) : RenderPassType::COLOR_INPUT; + } // Framebuffers can be stereo, and if so, will control the render pass type to match. // Pipelines can be mono and render fine to stereo etc, so not checking them here. // Note that we don't support rendering to just one layer of a multilayer framebuffer! @@ -874,7 +734,7 @@ void VulkanRenderManager::EndCurRenderStep() { compileMutex_.lock(); bool needsCompile = false; for (VKRGraphicsPipeline *pipeline : pipelinesToCheck_) { - if (!pipeline || compileBlocked_) { + if (!pipeline) { // Not good, but let's try not to crash. continue; } @@ -904,6 +764,11 @@ void VulkanRenderManager::EndCurRenderStep() { curPipelineFlags_ = (PipelineFlags)0; } +void VulkanRenderManager::BindCurrentFramebufferAsInputAttachment0(VkImageAspectFlags aspectBits) { + _dbg_assert_(curRenderStep_); + curRenderStep_->commands.push_back(VkRenderData{ VKRRenderCommand::SELF_DEPENDENCY_BARRIER }); +} + void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth, VKRRenderPassLoadAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) { _dbg_assert_(insideFrame_); // Eliminate dupes (bind of the framebuffer we already are rendering to), instantly convert to a clear if possible. @@ -1134,7 +999,7 @@ void VulkanRenderManager::CopyImageToMemorySync(VkImage image, int mipLevel, int queueRunner_.CopyReadbackBuffer(frameData_[vulkan_->GetCurFrame()], nullptr, w, h, destFormat, destFormat, pixelStride, pixels); } -static void RemoveDrawCommands(FastVec *cmds) { +static void RemoveDrawCommands(std::vector *cmds) { // Here we remove any DRAW type commands when we hit a CLEAR. for (auto &c : *cmds) { if (c.cmd == VKRRenderCommand::DRAW || c.cmd == VKRRenderCommand::DRAW_INDEXED) { @@ -1143,7 +1008,7 @@ static void RemoveDrawCommands(FastVec *cmds) { } } -static void CleanupRenderCommands(FastVec *cmds) { +static void CleanupRenderCommands(std::vector *cmds) { size_t lastCommand[(int)VKRRenderCommand::NUM_RENDER_COMMANDS]; memset(lastCommand, -1, sizeof(lastCommand)); @@ -1401,38 +1266,17 @@ void VulkanRenderManager::Finish() { FrameData &frameData = frameData_[curFrame]; VLOG("PUSH: Frame[%d]", curFrame); - VKRRenderThreadTask *task = new VKRRenderThreadTask(VKRRunType::SUBMIT); - task->frame = curFrame; - if (useRenderThread_) { + VKRRenderThreadTask task; + task.frame = curFrame; + task.runType = VKRRunType::PRESENT; + { std::unique_lock lock(pushMutex_); renderThreadQueue_.push(task); - renderThreadQueue_.back()->steps = std::move(steps_); + renderThreadQueue_.back().steps = std::move(steps_); pushCondVar_.notify_one(); - } else { - // Just do it! - task->steps = std::move(steps_); - Run(*task); - delete task; } steps_.clear(); -} - -void VulkanRenderManager::Present() { - int curFrame = vulkan_->GetCurFrame(); - - VKRRenderThreadTask *task = new VKRRenderThreadTask(VKRRunType::PRESENT); - task->frame = curFrame; - if (useRenderThread_) { - std::unique_lock lock(pushMutex_); - renderThreadQueue_.push(task); - pushCondVar_.notify_one(); - } else { - // Just do it! - Run(*task); - delete task; - } - vulkan_->EndFrame(); insideFrame_ = false; } @@ -1450,42 +1294,9 @@ void VulkanRenderManager::Wipe() { void VulkanRenderManager::Run(VKRRenderThreadTask &task) { FrameData &frameData = frameData_[task.frame]; - if (task.runType == VKRRunType::PRESENT) { - if (!frameData.skipSwap) { - VkResult res = frameData.QueuePresent(vulkan_, frameDataShared_); - frameTimeHistory_[frameData.frameId].queuePresent = time_now_d(); - if (res == VK_ERROR_OUT_OF_DATE_KHR) { - // We clearly didn't get this in vkAcquireNextImageKHR because of the skipSwap check above. - // Do the increment. - outOfDateFrames_++; - } else if (res == VK_SUBOPTIMAL_KHR) { - outOfDateFrames_++; - } else if (res != VK_SUCCESS) { - _assert_msg_(false, "vkQueuePresentKHR failed! result=%s", VulkanResultToString(res)); - } else { - // Success - outOfDateFrames_ = 0; - } - } else { - // We only get here if vkAcquireNextImage returned VK_ERROR_OUT_OF_DATE. - outOfDateFrames_++; - frameData.skipSwap = false; - } - return; - } - _dbg_assert_(!frameData.hasPresentCommands); - - if (!frameTimeHistory_[frameData.frameId].firstSubmit) { - frameTimeHistory_[frameData.frameId].firstSubmit = time_now_d(); - } frameData.SubmitPending(vulkan_, FrameSubmitType::Pending, frameDataShared_); - // Flush descriptors. - double descStart = time_now_d(); - FlushDescriptors(task.frame); - frameData.profile.descWriteTime = time_now_d() - descStart; - if (!frameData.hasMainCommands) { // Effectively resets both main and present command buffers, since they both live in this pool. // We always record main commands first, so we don't need to reset the present command buffer separately. @@ -1507,23 +1318,43 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { int passes = GetVRPassesCount(); for (int i = 0; i < passes; i++) { PreVRFrameRender(i); - queueRunner_.RunSteps(task.steps, task.frame, frameData, frameDataShared_, i < passes - 1); + queueRunner_.RunSteps(task.steps, frameData, frameDataShared_, i < passes - 1); PostVRFrameRender(); } } else { - queueRunner_.RunSteps(task.steps, task.frame, frameData, frameDataShared_); + queueRunner_.RunSteps(task.steps, frameData, frameDataShared_); } switch (task.runType) { - case VKRRunType::SUBMIT: + case VKRRunType::PRESENT: frameData.SubmitPending(vulkan_, FrameSubmitType::Present, frameDataShared_); + + if (!frameData.skipSwap) { + VkResult res = frameData.QueuePresent(vulkan_, frameDataShared_); + if (res == VK_ERROR_OUT_OF_DATE_KHR) { + // We clearly didn't get this in vkAcquireNextImageKHR because of the skipSwap check above. + // Do the increment. + outOfDateFrames_++; + } else if (res == VK_SUBOPTIMAL_KHR) { + outOfDateFrames_++; + } else if (res != VK_SUCCESS) { + _assert_msg_(false, "vkQueuePresentKHR failed! result=%s", VulkanResultToString(res)); + } else { + // Success + outOfDateFrames_ = 0; + } + } else { + // We only get here if vkAcquireNextImage returned VK_ERROR_OUT_OF_DATE. + outOfDateFrames_++; + frameData.skipSwap = false; + } break; case VKRRunType::SYNC: // The submit will trigger the readbackFence, and also do the wait for it. frameData.SubmitPending(vulkan_, FrameSubmitType::Sync, frameDataShared_); - if (useRenderThread_) { + { std::unique_lock lock(syncMutex_); syncCondVar_.notify_one(); } @@ -1542,8 +1373,6 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { // Called from main thread. void VulkanRenderManager::FlushSync() { - _dbg_assert_(!curRenderStep_); - if (invalidationCallback_) { invalidationCallback_(InvalidationCallbackFlags::COMMAND_BUFFER_STATE); } @@ -1551,34 +1380,25 @@ void VulkanRenderManager::FlushSync() { int curFrame = vulkan_->GetCurFrame(); FrameData &frameData = frameData_[curFrame]; - if (useRenderThread_) { - { - VLOG("PUSH: Frame[%d]", curFrame); - VKRRenderThreadTask *task = new VKRRenderThreadTask(VKRRunType::SYNC); - task->frame = curFrame; - std::unique_lock lock(pushMutex_); - renderThreadQueue_.push(task); - renderThreadQueue_.back()->steps = std::move(steps_); - pushCondVar_.notify_one(); - steps_.clear(); - } + { + VLOG("PUSH: Frame[%d]", curFrame); + VKRRenderThreadTask task; + task.frame = curFrame; + task.runType = VKRRunType::SYNC; + std::unique_lock lock(pushMutex_); + renderThreadQueue_.push(task); + renderThreadQueue_.back().steps = std::move(steps_); + pushCondVar_.notify_one(); + } - { - std::unique_lock lock(syncMutex_); - // Wait for the flush to be hit, since we're syncing. - while (!frameData.syncDone) { - VLOG("PUSH: Waiting for frame[%d].syncDone = 1 (sync)", curFrame); - syncCondVar_.wait(lock); - } - frameData.syncDone = false; + { + std::unique_lock lock(syncMutex_); + // Wait for the flush to be hit, since we're syncing. + while (!frameData.syncDone) { + VLOG("PUSH: Waiting for frame[%d].syncDone = 1 (sync)", curFrame); + syncCondVar_.wait(lock); } - } else { - VKRRenderThreadTask *task = new VKRRenderThreadTask(VKRRunType::SYNC); - task->frame = curFrame; - task->steps = std::move(steps_); - Run(*task); - delete task; - steps_.clear(); + frameData.syncDone = false; } } @@ -1587,238 +1407,3 @@ void VulkanRenderManager::ResetStats() { totalGPUTimeMs_.Reset(); renderCPUTimeMs_.Reset(); } - -VKRPipelineLayout *VulkanRenderManager::CreatePipelineLayout(BindingType *bindingTypes, size_t bindingTypesCount, bool geoShadersEnabled, const char *tag) { - VKRPipelineLayout *layout = new VKRPipelineLayout(); - layout->tag = tag; - layout->bindingTypesCount = (uint32_t)bindingTypesCount; - - _dbg_assert_(bindingTypesCount <= ARRAY_SIZE(layout->bindingTypes)); - memcpy(layout->bindingTypes, bindingTypes, sizeof(BindingType) * bindingTypesCount); - - VkDescriptorSetLayoutBinding bindings[VKRPipelineLayout::MAX_DESC_SET_BINDINGS]; - for (int i = 0; i < bindingTypesCount; i++) { - bindings[i].binding = i; - bindings[i].descriptorCount = 1; - bindings[i].pImmutableSamplers = nullptr; - - switch (bindingTypes[i]) { - case BindingType::COMBINED_IMAGE_SAMPLER: - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - break; - case BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX: - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - bindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - break; - case BindingType::UNIFORM_BUFFER_DYNAMIC_ALL: - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - bindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - if (geoShadersEnabled) { - bindings[i].stageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT; - } - break; - case BindingType::STORAGE_BUFFER_VERTEX: - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - break; - case BindingType::STORAGE_BUFFER_COMPUTE: - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - break; - case BindingType::STORAGE_IMAGE_COMPUTE: - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - break; - default: - _dbg_assert_(false); - break; - } - } - - VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; - dsl.bindingCount = (uint32_t)bindingTypesCount; - dsl.pBindings = bindings; - VkResult res = vkCreateDescriptorSetLayout(vulkan_->GetDevice(), &dsl, nullptr, &layout->descriptorSetLayout); - _assert_(VK_SUCCESS == res && layout->descriptorSetLayout); - - VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; - VkDescriptorSetLayout setLayouts[1] = { layout->descriptorSetLayout }; - pl.setLayoutCount = ARRAY_SIZE(setLayouts); - pl.pSetLayouts = setLayouts; - res = vkCreatePipelineLayout(vulkan_->GetDevice(), &pl, nullptr, &layout->pipelineLayout); - _assert_(VK_SUCCESS == res && layout->pipelineLayout); - - vulkan_->SetDebugName(layout->descriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, tag); - vulkan_->SetDebugName(layout->pipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, tag); - - for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { - // Some games go beyond 1024 and end up having to resize like GTA, but most stay below so we start there. - layout->frameData[i].pool.Create(vulkan_, bindingTypes, (uint32_t)bindingTypesCount, 1024); - } - - pipelineLayouts_.push_back(layout); - return layout; -} - -void VulkanRenderManager::DestroyPipelineLayout(VKRPipelineLayout *layout) { - for (auto iter = pipelineLayouts_.begin(); iter != pipelineLayouts_.end(); iter++) { - if (*iter == layout) { - pipelineLayouts_.erase(iter); - break; - } - } - vulkan_->Delete().QueueCallback([](VulkanContext *vulkan, void *userdata) { - VKRPipelineLayout *layout = (VKRPipelineLayout *)userdata; - for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { - layout->frameData[i].pool.DestroyImmediately(); - } - vkDestroyPipelineLayout(vulkan->GetDevice(), layout->pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(vulkan->GetDevice(), layout->descriptorSetLayout, nullptr); - - delete layout; - }, layout); -} - -void VulkanRenderManager::FlushDescriptors(int frame) { - for (auto iter : pipelineLayouts_) { - iter->FlushDescSets(vulkan_, frame, &frameData_[frame].profile); - } -} - -void VulkanRenderManager::ResetDescriptorLists(int frame) { - for (auto iter : pipelineLayouts_) { - VKRPipelineLayout::FrameData &data = iter->frameData[frame]; - - data.flushedDescriptors_ = 0; - data.descSets_.clear(); - data.descData_.clear(); - } -} - -VKRPipelineLayout::~VKRPipelineLayout() { - _assert_(frameData[0].pool.IsDestroyed()); -} - -void VKRPipelineLayout::FlushDescSets(VulkanContext *vulkan, int frame, QueueProfileContext *profile) { - _dbg_assert_(frame < VulkanContext::MAX_INFLIGHT_FRAMES); - - FrameData &data = frameData[frame]; - - VulkanDescSetPool &pool = data.pool; - FastVec &descData = data.descData_; - FastVec &descSets = data.descSets_; - - pool.Reset(); - - VkDescriptorSet setCache[8]; - VkDescriptorSetLayout layoutsForAlloc[ARRAY_SIZE(setCache)]; - for (int i = 0; i < ARRAY_SIZE(setCache); i++) { - layoutsForAlloc[i] = descriptorSetLayout; - } - int setsUsed = ARRAY_SIZE(setCache); // To allocate immediately. - - // This will write all descriptors. - // Initially, we just do a simple look-back comparing to the previous descriptor to avoid sequential dupes. - - // Initially, let's do naive single desc set writes. - VkWriteDescriptorSet writes[MAX_DESC_SET_BINDINGS]; - VkDescriptorImageInfo imageInfo[MAX_DESC_SET_BINDINGS]; // just picked a practical number - VkDescriptorBufferInfo bufferInfo[MAX_DESC_SET_BINDINGS]; - - size_t start = data.flushedDescriptors_; - int writeCount = 0; - - for (size_t index = start; index < descSets.size(); index++) { - auto &d = descSets[index]; - - // This is where we look up to see if we already have an identical descriptor previously in the array. - // We could do a simple custom hash map here that doesn't handle collisions, since those won't matter. - // Instead, for now we just check history one item backwards. Good enough, it seems. - if (index > start + 1) { - if (descSets[index - 1].count == d.count) { - if (!memcmp(descData.data() + d.offset, descData.data() + descSets[index - 1].offset, d.count * sizeof(PackedDescriptor))) { - d.set = descSets[index - 1].set; - continue; - } - } - } - - if (setsUsed < ARRAY_SIZE(setCache)) { - d.set = setCache[setsUsed++]; - } else { - // Allocate in small batches. - bool success = pool.Allocate(setCache, ARRAY_SIZE(setCache), layoutsForAlloc); - _dbg_assert_(success); - d.set = setCache[0]; - setsUsed = 1; - } - - // TODO: Build up bigger batches of writes. - const PackedDescriptor *data = descData.begin() + d.offset; - int numWrites = 0; - int numBuffers = 0; - int numImages = 0; - for (int i = 0; i < d.count; i++) { - if (!data[i].image.view) { // This automatically also checks for an null buffer due to the union. - continue; - } - switch (this->bindingTypes[i]) { - case BindingType::COMBINED_IMAGE_SAMPLER: - _dbg_assert_(data[i].image.sampler != VK_NULL_HANDLE); - imageInfo[numImages].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo[numImages].imageView = data[i].image.view; - imageInfo[numImages].sampler = data[i].image.sampler; - writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writes[numWrites].pImageInfo = &imageInfo[numImages]; - writes[numWrites].pBufferInfo = nullptr; - numImages++; - break; - case BindingType::STORAGE_IMAGE_COMPUTE: - imageInfo[numImages].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo[numImages].imageView = data[i].image.view; - imageInfo[numImages].sampler = VK_NULL_HANDLE; - writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - writes[numWrites].pImageInfo = &imageInfo[numImages]; - writes[numWrites].pBufferInfo = nullptr; - numImages++; - break; - case BindingType::STORAGE_BUFFER_VERTEX: - case BindingType::STORAGE_BUFFER_COMPUTE: - bufferInfo[numBuffers].buffer = data[i].buffer.buffer; - bufferInfo[numBuffers].offset = data[i].buffer.offset; - bufferInfo[numBuffers].range = data[i].buffer.range; - writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - writes[numWrites].pBufferInfo = &bufferInfo[numBuffers]; - writes[numWrites].pImageInfo = nullptr; - numBuffers++; - break; - case BindingType::UNIFORM_BUFFER_DYNAMIC_ALL: - case BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX: - bufferInfo[numBuffers].buffer = data[i].buffer.buffer; - bufferInfo[numBuffers].offset = 0; - bufferInfo[numBuffers].range = data[i].buffer.range; - writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - writes[numWrites].pBufferInfo = &bufferInfo[numBuffers]; - writes[numWrites].pImageInfo = nullptr; - numBuffers++; - break; - } - writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[numWrites].pNext = nullptr; - writes[numWrites].descriptorCount = 1; - writes[numWrites].dstArrayElement = 0; - writes[numWrites].dstBinding = i; - writes[numWrites].dstSet = d.set; - writes[numWrites].pTexelBufferView = nullptr; - numWrites++; - } - - vkUpdateDescriptorSets(vulkan->GetDevice(), numWrites, writes, 0, nullptr); - - writeCount++; - } - - data.flushedDescriptors_ = (int)descSets.size(); - profile->descriptorsWritten += writeCount; -} diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index 8f9c7120d..b0ca50d4b 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -17,13 +17,11 @@ #include "Common/System/Display.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/Data/Convert/SmallDataConvert.h" -#include "Common/Data/Collections/FastVec.h" #include "Common/Math/math_util.h" #include "Common/GPU/DataFormat.h" #include "Common/GPU/MiscTypes.h" #include "Common/GPU/Vulkan/VulkanQueueRunner.h" #include "Common/GPU/Vulkan/VulkanFramebuffer.h" -#include "Common/GPU/Vulkan/VulkanDescSet.h" #include "Common/GPU/thin3d.h" // Forward declaration @@ -78,10 +76,7 @@ struct BoundingRect { // All the data needed to create a graphics pipeline. // TODO: Compress this down greatly. -class VKRGraphicsPipelineDesc : public Draw::RefCountedObject { -public: - VKRGraphicsPipelineDesc() : Draw::RefCountedObject("VKRGraphicsPipelineDesc") {} - +struct VKRGraphicsPipelineDesc : Draw::RefCountedObject { VkPipelineCache pipelineCache = VK_NULL_HANDLE; VkPipelineColorBlendStateCreateInfo cbs{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; VkPipelineColorBlendAttachmentState blend0{}; @@ -107,7 +102,7 @@ public: VkPipelineVertexInputStateCreateInfo vis{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; VkPipelineViewportStateCreateInfo views{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; - VKRPipelineLayout *pipelineLayout = nullptr; + VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; // Does not include the render pass type, it's passed in separately since the // desc is persistent. @@ -132,10 +127,6 @@ struct VKRGraphicsPipeline { // This deletes the whole VKRGraphicsPipeline, you must remove your last pointer to it when doing this. void QueueForDeletion(VulkanContext *vulkan); - // This blocks until any background compiles are finished. - // Used during game shutdown before we clear out shaders that these compiles depend on. - void BlockUntilCompiled(); - u32 GetVariantsBitmask() const; void LogCreationFailure() const; @@ -185,66 +176,15 @@ struct CompileQueueEntry { VkSampleCountFlagBits sampleCount; }; -// Pending descriptor sets. -// TODO: Sort these by VKRPipelineLayout to avoid storing it for each element. -struct PendingDescSet { - int offset; // probably enough with a u16. - u8 count; - VkDescriptorSet set; -}; - -struct PackedDescriptor { - union { - struct { - VkImageView view; - VkSampler sampler; - } image; - struct { - VkBuffer buffer; - uint32_t offset; - uint32_t range; - } buffer; - }; -}; - -// Note that we only support a single descriptor set due to compatibility with some ancient devices. -// We should probably eventually give that up. -struct VKRPipelineLayout { - ~VKRPipelineLayout(); - enum { MAX_DESC_SET_BINDINGS = 10 }; - BindingType bindingTypes[MAX_DESC_SET_BINDINGS]; - - uint32_t bindingTypesCount = 0; - VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; - VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; // only support 1 for now. - int pushConstSize = 0; - const char *tag = nullptr; - - struct FrameData { - FrameData() : pool("GameDescPool", true) {} - VulkanDescSetPool pool; - FastVec descData_; - FastVec descSets_; - // TODO: We should be able to get away with a single descData_/descSets_ and then send it along, - // but it's easier to just segregate by frame id. - int flushedDescriptors_ = 0; - }; - - FrameData frameData[VulkanContext::MAX_INFLIGHT_FRAMES]; - - void FlushDescSets(VulkanContext *vulkan, int frame, QueueProfileContext *profile); -}; - class VulkanRenderManager { public: - VulkanRenderManager(VulkanContext *vulkan, bool useThread, HistoryBuffer &frameTimeHistory); + VulkanRenderManager(VulkanContext *vulkan); ~VulkanRenderManager(); // Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again. void BeginFrame(bool enableProfiling, bool enableLogProfiler); - // These can run on a different thread! + // Can run on a different thread! void Finish(); - void Present(); // Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown. void Wipe(); @@ -275,6 +215,8 @@ public: // get an array texture view. VkImageView BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, VkImageAspectFlags aspectBits, int layer); + void BindCurrentFramebufferAsInputAttachment0(VkImageAspectFlags aspectBits); + bool CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag); void CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag); @@ -289,27 +231,16 @@ public: VKRGraphicsPipeline *CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, PipelineFlags pipelineFlags, uint32_t variantBitmask, VkSampleCountFlagBits sampleCount, bool cacheLoad, const char *tag); VKRComputePipeline *CreateComputePipeline(VKRComputePipelineDesc *desc); - VKRPipelineLayout *CreatePipelineLayout(BindingType *bindingTypes, size_t bindingCount, bool geoShadersEnabled, const char *tag); - void DestroyPipelineLayout(VKRPipelineLayout *pipelineLayout); - - void ReportBadStateForDraw(); - void NudgeCompilerThread() { compileMutex_.lock(); compileCond_.notify_one(); compileMutex_.unlock(); } - // This is the first call in a draw operation. Instead of asserting like we used to, you can now check the - // return value and skip the draw if we're in a bad state. In that case, call ReportBadState. - // The old assert wasn't very helpful in figuring out what caused it anyway... - bool BindPipeline(VKRGraphicsPipeline *pipeline, PipelineFlags flags, VKRPipelineLayout *pipelineLayout) { - _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER && pipeline != nullptr); - if (!curRenderStep_ || curRenderStep_->stepType != VKRStepType::RENDER) { - return false; - } - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::BIND_GRAPHICS_PIPELINE; + void BindPipeline(VKRGraphicsPipeline *pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) { + _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); + _dbg_assert_(pipeline != nullptr); + VkRenderData data{ VKRRenderCommand::BIND_GRAPHICS_PIPELINE }; pipelinesToCheck_.push_back(pipeline); data.graphics_pipeline.pipeline = pipeline; data.graphics_pipeline.pipelineLayout = pipelineLayout; @@ -318,16 +249,24 @@ public: // DebugBreak(); // } curPipelineFlags_ |= flags; - curPipelineLayout_ = pipelineLayout; - return true; + curRenderStep_->commands.push_back(data); + } + + void BindPipeline(VKRComputePipeline *pipeline, PipelineFlags flags, VkPipelineLayout pipelineLayout) { + _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); + _dbg_assert_(pipeline != nullptr); + VkRenderData data{ VKRRenderCommand::BIND_COMPUTE_PIPELINE }; + data.compute_pipeline.pipeline = pipeline; + data.compute_pipeline.pipelineLayout = pipelineLayout; + curPipelineFlags_ |= flags; + curRenderStep_->commands.push_back(data); } void SetViewport(const VkViewport &vp) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); _dbg_assert_((int)vp.width >= 0); _dbg_assert_((int)vp.height >= 0); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::VIEWPORT; + VkRenderData data{ VKRRenderCommand::VIEWPORT }; data.viewport.vp.x = vp.x; data.viewport.vp.y = vp.y; data.viewport.vp.width = vp.width; @@ -337,6 +276,7 @@ public: // TODO: This should be fixed at the source. data.viewport.vp.minDepth = clamp_value(vp.minDepth, 0.0f, 1.0f); data.viewport.vp.maxDepth = clamp_value(vp.maxDepth, 0.0f, 1.0f); + curRenderStep_->commands.push_back(data); curStepHasViewport_ = true; } @@ -378,37 +318,37 @@ public: curRenderArea_.Apply(rc); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::SCISSOR; + VkRenderData data{ VKRRenderCommand::SCISSOR }; data.scissor.scissor = rc; + curRenderStep_->commands.push_back(data); curStepHasScissor_ = true; } void SetStencilParams(uint8_t writeMask, uint8_t compareMask, uint8_t refValue) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::STENCIL; + VkRenderData data{ VKRRenderCommand::STENCIL }; data.stencil.stencilWriteMask = writeMask; data.stencil.stencilCompareMask = compareMask; data.stencil.stencilRef = refValue; + curRenderStep_->commands.push_back(data); } void SetBlendFactor(uint32_t color) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::BLEND; + VkRenderData data{ VKRRenderCommand::BLEND }; data.blendColor.color = color; + curRenderStep_->commands.push_back(data); } void PushConstants(VkPipelineLayout pipelineLayout, VkShaderStageFlags stages, int offset, int size, void *constants) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); _dbg_assert_(size + offset < 40); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::PUSH_CONSTANTS; + VkRenderData data{ VKRRenderCommand::PUSH_CONSTANTS }; data.push.stages = stages; data.push.offset = offset; data.push.size = size; memcpy(data.push.data, constants, size); + curRenderStep_->commands.push_back(data); } void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask); @@ -438,52 +378,28 @@ public: curRenderStep_->render.stencilStore = VKRRenderPassStoreAction::DONT_CARE; } - // Descriptors will match the current pipeline layout, set by the last call to BindPipeline. - // Count is the count of void*s. Two are needed for COMBINED_IMAGE_SAMPLER, everything else is a single one. - // The goal is to keep this function very small and fast, and do the expensive work on the render thread or - // another thread. - PackedDescriptor *PushDescriptorSet(int count, int *descSetIndex) { - _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER); - - int curFrame = vulkan_->GetCurFrame(); - - VKRPipelineLayout::FrameData &data = curPipelineLayout_->frameData[curFrame]; - - size_t offset = data.descData_.size(); - PackedDescriptor *retval = data.descData_.extend_uninitialized(count); - - int setIndex = (int)data.descSets_.size(); - PendingDescSet &descSet = data.descSets_.push_uninitialized(); - descSet.offset = (uint32_t)offset; - descSet.count = count; - // descSet.set = VK_NULL_HANDLE; // to be filled in - *descSetIndex = setIndex; - return retval; - } - - void Draw(int descSetIndex, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, int count, int offset = 0) { + void Draw(VkDescriptorSet descSet, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, int count, int offset = 0) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER && curStepHasViewport_ && curStepHasScissor_); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::DRAW; + VkRenderData data{ VKRRenderCommand::DRAW }; data.draw.count = count; data.draw.offset = offset; - data.draw.descSetIndex = descSetIndex; + data.draw.ds = descSet; data.draw.vbuffer = vbuffer; data.draw.voffset = voffset; data.draw.numUboOffsets = numUboOffsets; _dbg_assert_(numUboOffsets <= ARRAY_SIZE(data.draw.uboOffsets)); for (int i = 0; i < numUboOffsets; i++) data.draw.uboOffsets[i] = uboOffsets[i]; + curRenderStep_->commands.push_back(data); curRenderStep_->render.numDraws++; } - void DrawIndexed(int descSetIndex, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, int numInstances) { + void DrawIndexed(VkDescriptorSet descSet, int numUboOffsets, const uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, int numInstances, VkIndexType indexType) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER && curStepHasViewport_ && curStepHasScissor_); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::DRAW_INDEXED; + VkRenderData data{ VKRRenderCommand::DRAW_INDEXED }; data.drawIndexed.count = count; data.drawIndexed.instances = numInstances; - data.drawIndexed.descSetIndex = descSetIndex; + data.drawIndexed.ds = descSet; data.drawIndexed.vbuffer = vbuffer; data.drawIndexed.voffset = voffset; data.drawIndexed.ibuffer = ibuffer; @@ -492,6 +408,8 @@ public: _dbg_assert_(numUboOffsets <= ARRAY_SIZE(data.drawIndexed.uboOffsets)); for (int i = 0; i < numUboOffsets; i++) data.drawIndexed.uboOffsets[i] = uboOffsets[i]; + data.drawIndexed.indexType = indexType; + curRenderStep_->commands.push_back(data); curRenderStep_->render.numDraws++; } @@ -499,9 +417,9 @@ public: // in the debugger. void DebugAnnotate(const char *annotation) { _dbg_assert_(curRenderStep_); - VkRenderData &data = curRenderStep_->commands.push_uninitialized(); - data.cmd = VKRRenderCommand::DEBUG_ANNOTATION; + VkRenderData data{ VKRRenderCommand::DEBUG_ANNOTATION }; data.debugAnnotation.annotation = annotation; + curRenderStep_->commands.push_back(data); } VkCommandBuffer GetInitCmd(); @@ -535,9 +453,10 @@ public: return outOfDateFrames_ > VulkanContext::MAX_INFLIGHT_FRAMES; } + void Invalidate(InvalidationFlags flags); + void ResetStats(); - void DrainAndBlockCompileQueue(); - void ReleaseCompileQueue(); + void DrainCompileQueue(); private: void EndCurRenderStep(); @@ -551,12 +470,6 @@ private: void FlushSync(); void StopThread(); - void PresentWaitThreadFunc(); - void PollPresentTiming(); - - void ResetDescriptorLists(int frame); - void FlushDescriptors(int frame); - FrameDataShared frameDataShared_; FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; @@ -578,9 +491,6 @@ private: bool insideFrame_ = false; bool run_ = false; - bool useRenderThread_ = true; - bool measurePresentTime_ = false; - // This is the offset within this frame, in case of a mid-frame sync. VKRStep *curRenderStep_ = nullptr; bool curStepHasViewport_ = false; @@ -599,7 +509,7 @@ private: std::mutex pushMutex_; std::condition_variable pushCondVar_; - std::queue renderThreadQueue_; + std::queue renderThreadQueue_; // For readbacks and other reasons we need to sync with the render thread. std::mutex syncMutex_; @@ -612,10 +522,6 @@ private: std::condition_variable compileCond_; std::mutex compileMutex_; std::vector compileQueue_; - bool compileBlocked_ = false; - - // Thread for measuring presentation delay. - std::thread presentWaitThread_; // pipelines to check and possibly create at the end of the current render pass. std::vector pipelinesToCheck_; @@ -624,13 +530,6 @@ private: SimpleStat initTimeMs_; SimpleStat totalGPUTimeMs_; SimpleStat renderCPUTimeMs_; - SimpleStat descUpdateTimeMs_; std::function invalidationCallback_; - - uint64_t frameIdGen_ = FRAME_TIME_HISTORY_LENGTH; - HistoryBuffer &frameTimeHistory_; - - VKRPipelineLayout *curPipelineLayout_ = nullptr; - std::vector pipelineLayouts_; }; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index ee6cf399d..45601416e 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -20,20 +20,27 @@ #include #include -#include "Common/Log.h" -#include "Common/StringUtils.h" #include "Common/System/Display.h" #include "Common/Math/lin/matrix4x4.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/GPU/thin3d.h" #include "Common/GPU/Vulkan/VulkanRenderManager.h" + +#include "Common/Log.h" +#include "Common/StringUtils.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanImage.h" #include "Common/GPU/Vulkan/VulkanMemory.h" -#include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/Thread/Promise.h" -// For descriptor set 0 (the only one), we use a simple descriptor set for all thin3d rendering: 1 UBO binding point, 3 combined texture/samples. +#include "Common/GPU/Vulkan/VulkanLoader.h" + +// We support a frame-global descriptor set, which can be optionally used by other code, +// but is not directly used by thin3d. It has to be defined here though, be in set 0 +// and specified in every pipeline layout, otherwise it can't sit undisturbed when other +// descriptor sets are bound on top. + +// For descriptor set 1, we use a simple descriptor set for all thin3d rendering: 1 UBO binding point, 3 combined texture/samples. // // binding 0 - uniform buffer // binding 1 - texture/sampler @@ -247,7 +254,7 @@ bool VKShaderModule::Compile(VulkanContext *vulkan, ShaderLanguage language, con class VKInputLayout : public InputLayout { public: - VkVertexInputBindingDescription binding; + std::vector bindings; std::vector attributes; VkPipelineVertexInputStateCreateInfo visc; }; @@ -290,7 +297,7 @@ public: std::vector deps; - int stride = 0; + int stride[4]{}; int dynamicUniformSize = 0; bool usesStencil = false; @@ -328,11 +335,8 @@ struct DescriptorSetKey { class VKTexture : public Texture { public: VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const TextureDesc &desc) - : vulkan_(vulkan), mipLevels_(desc.mipLevels) { - format_ = desc.format; - } + : vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {} bool Create(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const TextureDesc &desc); - void Update(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const uint8_t *const *data, TextureCallback callback, int numLevels); ~VKTexture() { Destroy(); @@ -352,13 +356,7 @@ public: return VK_NULL_HANDLE; // This would be bad. } - int NumLevels() const { - return mipLevels_; - } - private: - void UpdateInternal(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const uint8_t *const *data, TextureCallback callback, int numLevels); - void Destroy() { if (vkTex_) { vkTex_->Destroy(); @@ -371,16 +369,19 @@ private: VulkanTexture *vkTex_ = nullptr; int mipLevels_ = 0; + + DataFormat format_ = DataFormat::UNDEFINED; }; class VKFramebuffer; class VKContext : public DrawContext { public: - VKContext(VulkanContext *vulkan, bool useRenderThread); + VKContext(VulkanContext *vulkan); ~VKContext(); void DebugAnnotate(const char *annotation) override; + void SetDebugFlags(DebugFlags flags) override; const DeviceCaps &GetDeviceCaps() const override { return caps_; @@ -397,13 +398,13 @@ public: } uint32_t GetDataFormatSupport(DataFormat fmt) const override; - PresentMode GetPresentMode() const { + PresentationMode GetPresentationMode() const override { switch (vulkan_->GetPresentMode()) { - case VK_PRESENT_MODE_FIFO_KHR: return PresentMode::FIFO; - case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return PresentMode::FIFO; // We treat is as FIFO for now (and won't ever enable it anyway...) - case VK_PRESENT_MODE_IMMEDIATE_KHR: return PresentMode::IMMEDIATE; - case VK_PRESENT_MODE_MAILBOX_KHR: return PresentMode::MAILBOX; - default: return PresentMode::FIFO; + case VK_PRESENT_MODE_FIFO_KHR: return PresentationMode::FIFO; + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return PresentationMode::FIFO_RELAXED; + case VK_PRESENT_MODE_IMMEDIATE_KHR: return PresentationMode::IMMEDIATE; + case VK_PRESENT_MODE_MAILBOX_KHR: return PresentationMode::MAILBOX; + default: return PresentationMode::FIFO; } } @@ -420,7 +421,6 @@ public: Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override; void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override; void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; @@ -430,6 +430,7 @@ public: // These functions should be self explanatory. void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override; void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override; + void BindCurrentFramebufferForColorInput() override; void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; @@ -446,9 +447,13 @@ public: curPipeline_ = (VKPipeline *)pipeline; } - void BindVertexBuffer(Buffer *vertexBuffer, int offset) override { - curVBuffer_ = (VKBuffer *)vertexBuffer; - curVBufferOffset_ = offset; + // TODO: Make VKBuffers proper buffers, and do a proper binding model. This is just silly. + void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override { + _assert_(start + count <= ARRAY_SIZE(curVBuffers_)); + for (int i = 0; i < count; i++) { + curVBuffers_[i + start] = (VKBuffer *)buffers[i]; + curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0; + } } void BindIndexBuffer(Buffer *indexBuffer, int offset) override { curIBuffer_ = (VKBuffer *)indexBuffer; @@ -467,16 +472,10 @@ public: void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; - void BeginFrame(DebugFlags debugFlags) override; + void BeginFrame() override; void EndFrame() override; - void Present(PresentMode presentMode, int vblanks) override; - void WipeQueue() override; - int GetFrameCount() override { - return frameCount_; - } - void FlushState() override {} void ResetStats() override { @@ -500,10 +499,10 @@ public: } } - void BindDescriptors(VkBuffer buffer, PackedDescriptor descriptors[4]); + VkDescriptorSet GetOrCreateDescriptorSet(VkBuffer buffer); std::vector GetFeatureList() const override; - std::vector GetExtensionList(bool device, bool enabledOnly) const override; + std::vector GetExtensionList() const override; uint64_t GetNativeObject(NativeObject obj, void *srcObject) override; @@ -517,30 +516,27 @@ public: renderManager_.SetInvalidationCallback(callback); } - std::string GetGpuProfileString() const override { - return renderManager_.GetGpuProfileString(); - } - private: VulkanTexture *GetNullTexture(); VulkanContext *vulkan_ = nullptr; - int frameCount_ = 0; VulkanRenderManager renderManager_; VulkanTexture *nullTexture_ = nullptr; AutoRef curPipeline_; - AutoRef curVBuffer_; - int curVBufferOffset_ = 0; + AutoRef curVBuffers_[4]; + int curVBufferOffsets_[4]{}; AutoRef curIBuffer_; int curIBufferOffset_ = 0; - VKRPipelineLayout *pipelineLayout_ = nullptr; + VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE; + VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE; VkPipelineCache pipelineCache_ = VK_NULL_HANDLE; AutoRef curFramebuffer_; VkDevice device_; + DebugFlags debugFlags_ = DebugFlags::NONE; enum { MAX_FRAME_COMMAND_BUFFERS = 256, @@ -548,10 +544,23 @@ private: AutoRef boundTextures_[MAX_BOUND_TEXTURES]; AutoRef boundSamplers_[MAX_BOUND_TEXTURES]; VkImageView boundImageView_[MAX_BOUND_TEXTURES]{}; - TextureBindFlags boundTextureFlags_[MAX_BOUND_TEXTURES]{}; + TextureBindFlags boundTextureFlags_[MAX_BOUND_TEXTURES]; VulkanPushPool *push_ = nullptr; + struct FrameData { + FrameData() : descriptorPool("VKContext", false) { + descriptorPool.Setup([this] { descSets_.clear(); }); + } + // Per-frame descriptor set cache. As it's per frame and reset every frame, we don't need to + // worry about invalidating descriptors pointing to deleted textures. + // However! ARM is not a fan of doing it this way. + std::map descSets_; + VulkanDescSetPool descriptorPool; + }; + + FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; + DeviceCaps caps_{}; uint8_t stencilRef_ = 0; @@ -739,14 +748,14 @@ enum class TextureState { PENDING_DESTRUCTION, }; -bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const TextureDesc &desc) { +bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushPool *push, const TextureDesc &desc) { // Zero-sized textures not allowed. _assert_(desc.width * desc.height * desc.depth > 0); // remember to set depth to 1! if (desc.width * desc.height * desc.depth <= 0) { ERROR_LOG(G3D, "Bad texture dimensions %dx%dx%d", desc.width, desc.height, desc.depth); return false; } - _dbg_assert_(pushBuffer); + _assert_(push); format_ = desc.format; mipLevels_ = desc.mipLevels; width_ = desc.width; @@ -754,6 +763,8 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const Te depth_ = desc.depth; vkTex_ = new VulkanTexture(vulkan_, desc.tag); VkFormat vulkanFormat = DataFormatToVulkan(format_); + int bpp = GetBpp(vulkanFormat); + int bytesPerPixel = bpp / 8; int usageBits = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; if (mipLevels_ > (int)desc.initData.size()) { // Gonna have to generate some, which requires TRANSFER_SRC @@ -768,10 +779,33 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const Te } VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; if (desc.initData.size()) { - UpdateInternal(cmd, pushBuffer, desc.initData.data(), desc.initDataCallback, (int)desc.initData.size()); + int w = width_; + int h = height_; + int d = depth_; + int i; + for (i = 0; i < (int)desc.initData.size(); i++) { + uint32_t offset; + VkBuffer buf; + size_t size = w * h * d * bytesPerPixel; + if (desc.initDataCallback) { + uint8_t *dest = (uint8_t *)push->Allocate(size, 16, &buf, &offset); + _assert_(dest != nullptr); + if (!desc.initDataCallback(dest, desc.initData[i], w, h, d, w * bytesPerPixel, h * w * bytesPerPixel)) { + memcpy(dest, desc.initData[i], size); + } + } else { + offset = push->Push((const void *)desc.initData[i], size, 16, &buf); + } + TextureCopyBatch batch; + vkTex_->CopyBufferToMipLevel(cmd, &batch, i, w, h, 0, buf, offset, w); + vkTex_->FinishCopyBatch(cmd, &batch); + w = (w + 1) / 2; + h = (h + 1) / 2; + d = (d + 1) / 2; + } // Generate the rest of the mips automatically. - if (desc.initData.size() < mipLevels_) { - vkTex_->GenerateMips(cmd, (int)desc.initData.size(), false); + if (i < mipLevels_) { + vkTex_->GenerateMips(cmd, i, false); layout = VK_IMAGE_LAYOUT_GENERAL; } } @@ -779,45 +813,6 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const Te return true; } -void VKTexture::Update(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const uint8_t * const *data, TextureCallback initDataCallback, int numLevels) { - // Before we can use UpdateInternal, we need to transition the image to the same state as after CreateDirect, - // making it ready for writing. - vkTex_->PrepareForTransferDst(cmd, numLevels); - UpdateInternal(cmd, pushBuffer, data, initDataCallback, numLevels); - vkTex_->RestoreAfterTransferDst(cmd, numLevels); -} - -void VKTexture::UpdateInternal(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const uint8_t * const *data, TextureCallback initDataCallback, int numLevels) { - int w = width_; - int h = height_; - int d = depth_; - int i; - VkFormat vulkanFormat = DataFormatToVulkan(format_); - int bpp = GetBpp(vulkanFormat); - int bytesPerPixel = bpp / 8; - TextureCopyBatch batch; - batch.reserve(numLevels); - for (i = 0; i < numLevels; i++) { - uint32_t offset; - VkBuffer buf; - size_t size = w * h * d * bytesPerPixel; - uint8_t *dest = (uint8_t *)pushBuffer->Allocate(size, 16, &buf, &offset); - if (initDataCallback) { - _assert_(dest != nullptr); - if (!initDataCallback(dest, data[i], w, h, d, w * bytesPerPixel, h * w * bytesPerPixel)) { - memcpy(dest, data[i], size); - } - } else { - memcpy(dest, data[i], size); - } - vkTex_->CopyBufferToMipLevel(cmd, &batch, i, w, h, 0, buf, offset, w); - w = (w + 1) / 2; - h = (h + 1) / 2; - d = (d + 1) / 2; - } - vkTex_->FinishCopyBatch(cmd, &batch); -} - static DataFormat DataFormatFromVulkanDepth(VkFormat fmt) { switch (fmt) { case VK_FORMAT_D24_UNORM_S8_UINT: @@ -837,23 +832,19 @@ static DataFormat DataFormatFromVulkanDepth(VkFormat fmt) { return DataFormat::UNDEFINED; } -VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread) - : vulkan_(vulkan), renderManager_(vulkan, useRenderThread, frameTimeHistory_) { +VKContext::VKContext(VulkanContext *vulkan) + : vulkan_(vulkan), renderManager_(vulkan) { shaderLanguageDesc_.Init(GLSL_VULKAN); VkFormat depthStencilFormat = vulkan->GetDeviceInfo().preferredDepthStencilFormat; - caps_.setMaxFrameLatencySupported = true; caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.standard.samplerAnisotropy != 0; caps_.geometryShaderSupported = vulkan->GetDeviceFeatures().enabled.standard.geometryShader != 0; caps_.tesselationShaderSupported = vulkan->GetDeviceFeatures().enabled.standard.tessellationShader != 0; caps_.dualSourceBlend = vulkan->GetDeviceFeatures().enabled.standard.dualSrcBlend != 0; caps_.depthClampSupported = vulkan->GetDeviceFeatures().enabled.standard.depthClamp != 0; - - // Comment out these two to test geometry shader culling on any geometry shader-supporting hardware. caps_.clipDistanceSupported = vulkan->GetDeviceFeatures().enabled.standard.shaderClipDistance != 0; caps_.cullDistanceSupported = vulkan->GetDeviceFeatures().enabled.standard.shaderCullDistance != 0; - caps_.framebufferBlitSupported = true; caps_.framebufferCopySupported = true; caps_.framebufferDepthBlitSupported = vulkan->GetDeviceInfo().canBlitToPreferredDepthStencilFormat; @@ -872,20 +863,6 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread) caps_.logicOpSupported = vulkan->GetDeviceFeatures().enabled.standard.logicOp != 0; caps_.multiViewSupported = vulkan->GetDeviceFeatures().enabled.multiview.multiview != 0; caps_.sampleRateShadingSupported = vulkan->GetDeviceFeatures().enabled.standard.sampleRateShading != 0; - caps_.textureSwizzleSupported = true; - - // Present mode stuff - caps_.presentMaxInterval = 1; - caps_.presentInstantModeChange = false; // TODO: Fix this with some work in VulkanContext - caps_.presentModesSupported = (PresentMode)0; - for (auto mode : vulkan->GetAvailablePresentModes()) { - switch (mode) { - case VK_PRESENT_MODE_FIFO_KHR: caps_.presentModesSupported |= PresentMode::FIFO; break; - case VK_PRESENT_MODE_IMMEDIATE_KHR: caps_.presentModesSupported |= PresentMode::IMMEDIATE; break; - case VK_PRESENT_MODE_MAILBOX_KHR: caps_.presentModesSupported |= PresentMode::MAILBOX; break; - default: break; // Ignore any other modes. - } - } const auto &limits = vulkan->GetPhysicalDeviceProperties().properties.limits; @@ -899,7 +876,6 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread) case VULKAN_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break; case VULKAN_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break; case VULKAN_VENDOR_APPLE: caps_.vendor = GPUVendor::VENDOR_APPLE; break; - case VULKAN_VENDOR_MESA: caps_.vendor = GPUVendor::VENDOR_MESA; break; default: WARN_LOG(G3D, "Unknown vendor ID %08x", deviceProps.vendorID); caps_.vendor = GPUVendor::VENDOR_UNKNOWN; @@ -1009,29 +985,71 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread) } } - // Vulkan can support this through input attachments and various extensions, but not worth - // the trouble. - caps_.framebufferFetchSupported = false; + // Limited, through input attachments and self-dependencies. + // We turn it off here already if buggy. + caps_.framebufferFetchSupported = !bugs_.Has(Bugs::SUBPASS_FEEDBACK_BROKEN); caps_.deviceID = deviceProps.deviceID; device_ = vulkan->GetDevice(); + std::vector dpTypes; + dpTypes.resize(2); + dpTypes[0].descriptorCount = 200; + dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + dpTypes[1].descriptorCount = 200 * MAX_BOUND_TEXTURES; + dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + + VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + // Don't want to mess around with individually freeing these, let's go dynamic each frame. + dp.flags = 0; + // 200 textures per frame was not enough for the UI. + dp.maxSets = 4096; + VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; push_ = new VulkanPushPool(vulkan_, "pushBuffer", 4 * 1024 * 1024, usage); + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { + frame_[i].descriptorPool.Create(vulkan_, dp, dpTypes); + } + // binding 0 - uniform data // binding 1 - combined sampler/image 0 // binding 2 - combined sampler/image 1 - // ...etc - BindingType bindings[MAX_BOUND_TEXTURES + 1]; - bindings[0] = BindingType::UNIFORM_BUFFER_DYNAMIC_ALL; + VkDescriptorSetLayoutBinding bindings[MAX_BOUND_TEXTURES + 1]; + bindings[0].descriptorCount = 1; + bindings[0].pImmutableSamplers = nullptr; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[0].binding = 0; for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { - bindings[1 + i] = BindingType::COMBINED_IMAGE_SAMPLER; + bindings[i + 1].descriptorCount = 1; + bindings[i + 1].pImmutableSamplers = nullptr; + bindings[i + 1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[i + 1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[i + 1].binding = i + 1; } - pipelineLayout_ = renderManager_.CreatePipelineLayout(bindings, ARRAY_SIZE(bindings), caps_.geometryShaderSupported, "thin3d_layout"); + + VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + dsl.bindingCount = ARRAY_SIZE(bindings); + dsl.pBindings = bindings; + VkResult res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &descriptorSetLayout_); + _assert_(VK_SUCCESS == res); + + vulkan_->SetDebugName(descriptorSetLayout_, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, "thin3d_d_layout"); + + VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; + pl.pPushConstantRanges = nullptr; + pl.pushConstantRangeCount = 0; + VkDescriptorSetLayout setLayouts[1] = { descriptorSetLayout_ }; + pl.setLayoutCount = ARRAY_SIZE(setLayouts); + pl.pSetLayouts = setLayouts; + res = vkCreatePipelineLayout(device_, &pl, nullptr, &pipelineLayout_); + _assert_(VK_SUCCESS == res); + + vulkan_->SetDebugName(pipelineLayout_, VK_OBJECT_TYPE_PIPELINE_LAYOUT, "thin3d_p_layout"); VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; - VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); + res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); _assert_(VK_SUCCESS == res); } @@ -1039,32 +1057,35 @@ VKContext::~VKContext() { DestroyPresets(); delete nullTexture_; + // This also destroys all descriptor sets. + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { + frame_[i].descriptorPool.Destroy(); + } push_->Destroy(); delete push_; - renderManager_.DestroyPipelineLayout(pipelineLayout_); + vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); + vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_); vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_); } -void VKContext::BeginFrame(DebugFlags debugFlags) { - renderManager_.BeginFrame(debugFlags & DebugFlags::PROFILE_TIMESTAMPS, debugFlags & DebugFlags::PROFILE_SCOPES); +void VKContext::BeginFrame() { + // TODO: Bad dependency on g_Config here! + renderManager_.BeginFrame(debugFlags_ & DebugFlags::PROFILE_TIMESTAMPS, debugFlags_ & DebugFlags::PROFILE_SCOPES); + + FrameData &frame = frame_[vulkan_->GetCurFrame()]; + push_->BeginFrame(); + + frame.descriptorPool.Reset(); } void VKContext::EndFrame() { - // Do all the work to submit the command buffers etc. renderManager_.Finish(); + // Unbind stuff, to avoid accidentally relying on it across frames (and provide some protection against forgotten unbinds of deleted things). Invalidate(InvalidationFlags::CACHED_RENDER_STATE); } -void VKContext::Present(PresentMode presentMode, int vblanks) { - if (presentMode == PresentMode::FIFO) { - _dbg_assert_(vblanks == 0 || vblanks == 1); - } - renderManager_.Present(); - frameCount_++; -} - void VKContext::Invalidate(InvalidationFlags flags) { if (flags & InvalidationFlags::CACHED_RENDER_STATE) { curPipeline_ = nullptr; @@ -1085,30 +1106,81 @@ void VKContext::WipeQueue() { renderManager_.Wipe(); } -void VKContext::BindDescriptors(VkBuffer buf, PackedDescriptor descriptors[4]) { - descriptors[0].buffer.buffer = buf; - descriptors[0].buffer.offset = 0; // dynamic - descriptors[0].buffer.range = curPipeline_->GetUBOSize(); +VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { + DescriptorSetKey key{}; + + FrameData *frame = &frame_[vulkan_->GetCurFrame()]; - int numDescs = 1; for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { - VkImageView view; - VkSampler sampler; if (boundTextures_[i]) { - view = (boundTextureFlags_[i] & TextureBindFlags::VULKAN_BIND_ARRAY) ? boundTextures_[i]->GetImageArrayView() : boundTextures_[i]->GetImageView(); + key.imageViews_[i] = (boundTextureFlags_[i] & TextureBindFlags::VULKAN_BIND_ARRAY) ? boundTextures_[i]->GetImageArrayView() : boundTextures_[i]->GetImageView(); } else { - view = boundImageView_[i]; + key.imageViews_[i] = boundImageView_[i]; } - sampler = boundSamplers_[i] ? boundSamplers_[i]->GetSampler() : VK_NULL_HANDLE; + key.samplers_[i] = boundSamplers_[i]; + } + key.buffer_ = buf; - if (view && sampler) { - descriptors[i + 1].image.view = view; - descriptors[i + 1].image.sampler = sampler; - } else { - descriptors[i + 1].image.view = VK_NULL_HANDLE; - descriptors[i + 1].image.sampler = VK_NULL_HANDLE; + auto iter = frame->descSets_.find(key); + if (iter != frame->descSets_.end()) { + return iter->second; + } + + VkDescriptorSet descSet = frame->descriptorPool.Allocate(1, &descriptorSetLayout_, "thin3d_descset"); + if (descSet == VK_NULL_HANDLE) { + ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed"); + return VK_NULL_HANDLE; + } + + vulkan_->SetDebugName(descSet, VK_OBJECT_TYPE_DESCRIPTOR_SET, "(thin3d desc set)"); + + VkDescriptorBufferInfo bufferDesc; + bufferDesc.buffer = buf; + bufferDesc.offset = 0; + bufferDesc.range = curPipeline_->GetUBOSize(); + + VkDescriptorImageInfo imageDesc[MAX_BOUND_TEXTURES]{}; + VkWriteDescriptorSet writes[1 + MAX_BOUND_TEXTURES]{}; + + // If handles are NULL for whatever buggy reason, it's best to leave the descriptors + // unwritten instead of trying to write a zero, which is not legal. + + int numWrites = 0; + if (buf) { + writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[numWrites].dstSet = descSet; + writes[numWrites].dstArrayElement = 0; + writes[numWrites].dstBinding = 0; + writes[numWrites].pBufferInfo = &bufferDesc; + writes[numWrites].pImageInfo = nullptr; + writes[numWrites].pTexelBufferView = nullptr; + writes[numWrites].descriptorCount = 1; + writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + numWrites++; + } + + for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { + if (key.imageViews_[i] && key.samplers_[i] && key.samplers_[i]->GetSampler()) { + imageDesc[i].imageView = key.imageViews_[i]; + imageDesc[i].sampler = key.samplers_[i]->GetSampler(); + imageDesc[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[numWrites].dstSet = descSet; + writes[numWrites].dstArrayElement = 0; + writes[numWrites].dstBinding = i + 1; + writes[numWrites].pBufferInfo = nullptr; + writes[numWrites].pImageInfo = &imageDesc[i]; + writes[numWrites].pTexelBufferView = nullptr; + writes[numWrites].descriptorCount = 1; + writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + numWrites++; } } + + vkUpdateDescriptorSets(device_, numWrites, writes, 0, nullptr); + + frame->descSets_[key] = descSet; + return descSet; } Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc, const char *tag) { @@ -1145,11 +1217,13 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc, const char } } - _dbg_assert_(input); + _dbg_assert_(input && input->bindings.size() == 1); _dbg_assert_((int)input->attributes.size() == (int)input->visc.vertexAttributeDescriptionCount); - pipeline->stride = input->binding.stride; - gDesc.ibd = input->binding; + for (int i = 0; i < (int)input->bindings.size(); i++) { + pipeline->stride[i] = input->bindings[i].stride; + } + gDesc.ibd = input->bindings[0]; for (size_t i = 0; i < input->attributes.size(); i++) { gDesc.attrs[i] = input->attributes[i]; } @@ -1231,20 +1305,23 @@ InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) { VKInputLayout *vl = new VKInputLayout(); vl->visc = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; vl->visc.flags = 0; - vl->visc.vertexBindingDescriptionCount = 1; vl->visc.vertexAttributeDescriptionCount = (uint32_t)desc.attributes.size(); + vl->visc.vertexBindingDescriptionCount = (uint32_t)desc.bindings.size(); + vl->bindings.resize(vl->visc.vertexBindingDescriptionCount); vl->attributes.resize(vl->visc.vertexAttributeDescriptionCount); - vl->visc.pVertexBindingDescriptions = &vl->binding; + vl->visc.pVertexBindingDescriptions = vl->bindings.data(); vl->visc.pVertexAttributeDescriptions = vl->attributes.data(); for (size_t i = 0; i < desc.attributes.size(); i++) { - vl->attributes[i].binding = 0; + vl->attributes[i].binding = (uint32_t)desc.attributes[i].binding; vl->attributes[i].format = DataFormatToVulkan(desc.attributes[i].format); vl->attributes[i].location = desc.attributes[i].location; vl->attributes[i].offset = desc.attributes[i].offset; } - vl->binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - vl->binding.binding = 0; - vl->binding.stride = desc.stride; + for (size_t i = 0; i < desc.bindings.size(); i++) { + vl->bindings[i].inputRate = desc.bindings[i].instanceRate ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + vl->bindings[i].binding = (uint32_t)i; + vl->bindings[i].stride = desc.bindings[i].stride; + } return vl; } @@ -1265,20 +1342,6 @@ Texture *VKContext::CreateTexture(const TextureDesc &desc) { } } -void VKContext::UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) { - VkCommandBuffer initCmd = renderManager_.GetInitCmd(); - if (!push_ || !initCmd) { - // Too early! Fail. - ERROR_LOG(G3D, "Can't create textures before the first frame has started."); - return; - } - - VKTexture *tex = (VKTexture *)texture; - - _dbg_assert_(numLevels <= tex->NumLevels()); - tex->Update(initCmd, push_, data, initDataCallback, numLevels); -} - static inline void CopySide(VkStencilOpState &dest, const StencilSetup &src) { dest.compareOp = compToVK[(int)src.compareOp]; dest.failOp = stencilOpToVK[(int)src.failOp]; @@ -1353,7 +1416,7 @@ void VKContext::BindTextures(int start, int count, Texture **textures, TextureBi boundTextures_[i] = static_cast(textures[i - start]); boundTextureFlags_[i] = flags; if (boundTextures_[i]) { - // If a texture is bound, we set these up in BindDescriptors too. + // If a texture is bound, we set these up in GetOrCreateDescriptorSet too. // But we might need to set the view here anyway so it can be queried using GetNativeObject. if (flags & TextureBindFlags::VULKAN_BIND_ARRAY) { boundImageView_[i] = boundTextures_[i]->GetImageArrayView(); @@ -1399,36 +1462,42 @@ void VKContext::ApplyDynamicState() { } void VKContext::Draw(int vertexCount, int offset) { - VKBuffer *vbuf = curVBuffer_; + VKBuffer *vbuf = curVBuffers_[0]; VkBuffer vulkanVbuf; VkBuffer vulkanUBObuf; uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), 4, &vulkanVbuf); + VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf); + if (descSet == VK_NULL_HANDLE) { + ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed, skipping %s", __FUNCTION__); + return; + } + BindCurrentPipeline(); ApplyDynamicState(); - int descSetIndex; - PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex); - BindDescriptors(vulkanUBObuf, descriptors); - renderManager_.Draw(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffset_, vertexCount, offset); + renderManager_.Draw(descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount, offset); } void VKContext::DrawIndexed(int vertexCount, int offset) { VKBuffer *ibuf = curIBuffer_; - VKBuffer *vbuf = curVBuffer_; + VKBuffer *vbuf = curVBuffers_[0]; VkBuffer vulkanVbuf, vulkanIbuf, vulkanUBObuf; uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), 4, &vulkanVbuf); size_t ibBindOffset = push_->Push(ibuf->GetData(), ibuf->GetSize(), 4, &vulkanIbuf); + VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf); + if (descSet == VK_NULL_HANDLE) { + ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed, skipping %s", __FUNCTION__); + return; + } + BindCurrentPipeline(); ApplyDynamicState(); - int descSetIndex; - PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex); - BindDescriptors(vulkanUBObuf, descriptors); - renderManager_.DrawIndexed(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffset_, vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1); + renderManager_.DrawIndexed(descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1, VK_INDEX_TYPE_UINT16); } void VKContext::DrawUP(const void *vdata, int vertexCount) { @@ -1438,7 +1507,7 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) { } VkBuffer vulkanVbuf, vulkanUBObuf; - size_t dataSize = vertexCount * curPipeline_->stride; + size_t dataSize = vertexCount * curPipeline_->stride[0]; uint32_t vbBindOffset; uint8_t *dataPtr = push_->Allocate(dataSize, 4, &vulkanVbuf, &vbBindOffset); _assert_(dataPtr != nullptr); @@ -1446,12 +1515,15 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) { uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); + VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf); + if (descSet == VK_NULL_HANDLE) { + ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed, skipping %s", __FUNCTION__); + return; + } + BindCurrentPipeline(); ApplyDynamicState(); - int descSetIndex; - PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex); - BindDescriptors(vulkanUBObuf, descriptors); - renderManager_.Draw(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffset_, vertexCount); + renderManager_.Draw(descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount); } void VKContext::BindCurrentPipeline() { @@ -1469,8 +1541,8 @@ void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int sten renderManager_.Clear(colorval, depthVal, stencilVal, mask); } -DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan, bool useRenderThread) { - return new VKContext(vulkan, useRenderThread); +DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan) { + return new VKContext(vulkan); } void AddFeature(std::vector &features, const char *name, VkBool32 available, VkBool32 enabled) { @@ -1501,24 +1573,16 @@ std::vector VKContext::GetFeatureList() const { AddFeature(features, "multiview", vulkan_->GetDeviceFeatures().available.multiview.multiview, vulkan_->GetDeviceFeatures().enabled.multiview.multiview); AddFeature(features, "multiviewGeometryShader", vulkan_->GetDeviceFeatures().available.multiview.multiviewGeometryShader, vulkan_->GetDeviceFeatures().enabled.multiview.multiviewGeometryShader); - AddFeature(features, "presentId", vulkan_->GetDeviceFeatures().available.presentId.presentId, vulkan_->GetDeviceFeatures().enabled.presentId.presentId); - AddFeature(features, "presentWait", vulkan_->GetDeviceFeatures().available.presentWait.presentWait, vulkan_->GetDeviceFeatures().enabled.presentWait.presentWait); features.emplace_back(std::string("Preferred depth buffer format: ") + VulkanFormatToString(vulkan_->GetDeviceInfo().preferredDepthStencilFormat)); return features; } -std::vector VKContext::GetExtensionList(bool device, bool enabledOnly) const { +std::vector VKContext::GetExtensionList() const { std::vector extensions; - if (enabledOnly) { - for (auto &iter : (device ? vulkan_->GetDeviceExtensionsEnabled() : vulkan_->GetInstanceExtensionsEnabled())) { - extensions.push_back(iter); - } - } else { - for (auto &iter : (device ? vulkan_->GetDeviceExtensionsAvailable() : vulkan_->GetInstanceExtensionsAvailable())) { - extensions.push_back(iter.extensionName); - } + for (auto &iter : vulkan_->GetDeviceExtensionsAvailable()) { + extensions.push_back(iter.extensionName); } return extensions; } @@ -1671,6 +1735,10 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, layer); } +void VKContext::BindCurrentFramebufferForColorInput() { + renderManager_.BindCurrentFramebufferAsInputAttachment0(VK_IMAGE_ASPECT_COLOR_BIT); +} + void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { VKFramebuffer *fb = (VKFramebuffer *)fbo; if (fb) { @@ -1747,4 +1815,8 @@ void VKContext::DebugAnnotate(const char *annotation) { renderManager_.DebugAnnotate(annotation); } +void VKContext::SetDebugFlags(DebugFlags flags) { + debugFlags_ = flags; +} + } // namespace Draw diff --git a/Common/GPU/thin3d.cpp b/Common/GPU/thin3d.cpp index 85b910aef..f5dc4b452 100644 --- a/Common/GPU/thin3d.cpp +++ b/Common/GPU/thin3d.cpp @@ -119,8 +119,7 @@ bool DataFormatIsBlockCompressed(DataFormat fmt, int *blockSize) { } RefCountedObject::~RefCountedObject() { - const int rc = refcount_.load(); - _dbg_assert_msg_(rc == 0xDEDEDE, "Unexpected refcount %d in object of type '%s'", rc, name_); + _dbg_assert_(refcount_ == 0xDEDEDE); } bool RefCountedObject::Release() { @@ -132,7 +131,6 @@ bool RefCountedObject::Release() { return true; } } else { - // No point in printing the name here if the object has already been free-d, it'll be corrupt and dangerous to print. _dbg_assert_msg_(false, "Refcount (%d) invalid for object %p - corrupt?", refcount_.load(), this); } return false; @@ -140,10 +138,11 @@ bool RefCountedObject::Release() { bool RefCountedObject::ReleaseAssertLast() { bool released = Release(); - _dbg_assert_msg_(released, "RefCountedObject: Expected to be the last reference, but isn't! (%s)", name_); + _dbg_assert_msg_(released, "RefCountedObject: Expected to be the last reference, but isn't!"); return released; } + // ================================== PIXEL/FRAGMENT SHADERS // The Vulkan ones can be re-used with modern GL later if desired, as they're just GLSL. @@ -768,20 +767,4 @@ const char *Bugs::GetBugName(uint32_t bug) { } } -const char *PresentModeToString(PresentMode presentMode) { - // All 8 possible cases, with three flags, for simplicity. - switch ((int)presentMode) { - case 0: return "NONE"; - case (int)PresentMode::FIFO: return "FIFO"; - case (int)PresentMode::IMMEDIATE: return "IMMEDIATE"; - case (int)PresentMode::MAILBOX: return "MAILBOX"; - case ((int)PresentMode::FIFO | (int)PresentMode::MAILBOX) : return "FIFO|MAILBOX"; - case ((int)PresentMode::FIFO | (int)PresentMode::IMMEDIATE) : return "FIFO|IMMEDIATE"; - case ((int)PresentMode::MAILBOX | (int)PresentMode::IMMEDIATE) : return "MAILBOX|IMMEDIATE"; // Not gonna happen - case ((int)PresentMode::FIFO | (int)PresentMode::MAILBOX | (int)PresentMode::IMMEDIATE) : return "FIFO|MAILBOX|IMMEDIATE"; - default: - return "INVALID"; - } -} - } // namespace Draw diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index fb6f402e4..26f63c980 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -18,7 +18,6 @@ #include "Common/GPU/Shader.h" #include "Common/GPU/MiscTypes.h" #include "Common/Data/Collections/Slice.h" -#include "Common/Data/Collections/FastVec.h" namespace Lin { class Matrix4x4; @@ -231,7 +230,6 @@ enum class GPUVendor { VENDOR_BROADCOM, // Raspberry VENDOR_VIVANTE, VENDOR_APPLE, - VENDOR_MESA, }; enum class NativeObject { @@ -361,7 +359,7 @@ protected: class RefCountedObject { public: - explicit RefCountedObject(const char *name) : name_(name) { + RefCountedObject() { refcount_ = 1; } RefCountedObject(const RefCountedObject &other) = delete; @@ -374,7 +372,6 @@ public: private: std::atomic refcount_; - const char * const name_; }; template @@ -431,22 +428,18 @@ struct AutoRef { class BlendState : public RefCountedObject { public: - BlendState() : RefCountedObject("BlendState") {} }; class SamplerState : public RefCountedObject { public: - SamplerState() : RefCountedObject("SamplerState") {} }; class DepthStencilState : public RefCountedObject { public: - DepthStencilState() : RefCountedObject("DepthStencilState") {} }; class Framebuffer : public RefCountedObject { public: - Framebuffer() : RefCountedObject("Framebuffer") {} int Width() { return width_; } int Height() { return height_; } int Layers() { return layers_; } @@ -459,55 +452,46 @@ protected: class Buffer : public RefCountedObject { public: - Buffer() : RefCountedObject("Buffer") {} }; class Texture : public RefCountedObject { public: - Texture() : RefCountedObject("Texture") {} - int Width() const { return width_; } - int Height() const { return height_; } - int Depth() const { return depth_; } - DataFormat Format() const { return format_; } - + int Width() { return width_; } + int Height() { return height_; } + int Depth() { return depth_; } protected: int width_ = -1, height_ = -1, depth_ = -1; - DataFormat format_ = DataFormat::UNDEFINED; +}; + +struct BindingDesc { + int stride; + bool instanceRate; }; struct AttributeDesc { + int binding; int location; // corresponds to semantic DataFormat format; int offset; }; struct InputLayoutDesc { - int stride; + std::vector bindings; std::vector attributes; }; -class InputLayout : public RefCountedObject { -public: - InputLayout() : RefCountedObject("InputLayout") {} -}; +class InputLayout : public RefCountedObject { }; // Uniform types have moved to Shader.h. class ShaderModule : public RefCountedObject { public: - ShaderModule() : RefCountedObject("ShaderModule") {} virtual ShaderStage GetStage() const = 0; }; -class Pipeline : public RefCountedObject { -public: - Pipeline() : RefCountedObject("Pipeline") {} -}; +class Pipeline : public RefCountedObject { }; -class RasterState : public RefCountedObject { -public: - RasterState() : RefCountedObject("RasterState") {} -}; +class RasterState : public RefCountedObject {}; struct StencilSetup { StencilOp failOp; @@ -566,13 +550,6 @@ struct PipelineDesc { const Slice samplers; }; -enum class PresentMode { - FIFO = 1, - IMMEDIATE = 2, - MAILBOX = 4, -}; -ENUM_CLASS_BITOPS(PresentMode); - struct DeviceCaps { GPUVendor vendor; uint32_t deviceID; // use caution! @@ -606,8 +583,6 @@ struct DeviceCaps { bool multiViewSupported; bool isTilingGPU; // This means that it benefits from correct store-ops, msaa without backing memory, etc. bool sampleRateShadingSupported; - bool setMaxFrameLatencySupported; - bool textureSwizzleSupported; bool verySlowShaderCompiler; @@ -617,11 +592,6 @@ struct DeviceCaps { // Old style, for older GL or Direct3D 9. u32 clipPlanesSupported; - // Presentation caps - int presentMaxInterval; // 1 on many backends - bool presentInstantModeChange; - PresentMode presentModesSupported; - u32 multiSampleLevelsMask; // Bit n is set if (1 << n) is a valid multisample level. Bit 0 is always set. std::string deviceName; // The device name to use when creating the thin3d context, to get the same one. }; @@ -683,6 +653,13 @@ enum class DebugFlags { }; ENUM_CLASS_BITOPS(DebugFlags); +enum class PresentationMode { + FIFO, + FIFO_RELAXED, + IMMEDIATE, + MAILBOX, +}; + class DrawContext { public: virtual ~DrawContext(); @@ -694,9 +671,11 @@ public: virtual const DeviceCaps &GetDeviceCaps() const = 0; virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0; virtual std::vector GetFeatureList() const { return std::vector(); } - virtual std::vector GetExtensionList(bool device, bool enabledOnly) const { return std::vector(); } + virtual std::vector GetExtensionList() const { return std::vector(); } virtual std::vector GetDeviceList() const { return std::vector(); } + virtual PresentationMode GetPresentationMode() const = 0; + // Describes the primary shader language that this implementation prefers. const ShaderLanguageDesc &GetShaderLanguageDesc() { return shaderLanguageDesc_; @@ -707,6 +686,7 @@ public: virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {} virtual void DebugAnnotate(const char *annotation) {} + virtual void SetDebugFlags(DebugFlags flags) {} // Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly). // TODO: Possibly ditch these and just put the descs directly in PipelineDesc since only D3D11 benefits. @@ -733,11 +713,6 @@ public: // Copies data from the CPU over into the buffer, at a specific offset. This does not change the size of the buffer and cannot write outside it. virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0; - // Used to optimize DrawPixels by re-using previously allocated temp textures. - // Do not try to update a texture that might be used by an in-flight command buffer! In OpenGL and D3D, this will cause stalls - // while in Vulkan this might cause various strangeness like image corruption. - virtual void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) = 0; - virtual void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) = 0; virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) = 0; @@ -781,7 +756,7 @@ public: virtual void BindSamplerStates(int start, int count, SamplerState **state) = 0; virtual void BindTextures(int start, int count, Texture **textures, TextureBindFlags flags = TextureBindFlags::NONE) = 0; - virtual void BindVertexBuffer(Buffer *vertexBuffer, int offset) = 0; + virtual void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) = 0; virtual void BindIndexBuffer(Buffer *indexBuffer, int offset) = 0; // Sometimes it's necessary to bind a texture not created by thin3d, and use with a thin3d pipeline. @@ -812,13 +787,8 @@ public: virtual void DrawUP(const void *vdata, int vertexCount) = 0; // Frame management (for the purposes of sync and resource management, necessary with modern APIs). Default implementations here. - virtual void BeginFrame(DebugFlags debugFlags) = 0; + virtual void BeginFrame() {} virtual void EndFrame() = 0; - - // vblanks is only relevant in FIFO present mode. - // NOTE: Not all backends support vblanks > 1. Some backends also can't change presentation mode immediately. - virtual void Present(PresentMode presentMode, int vblanks) = 0; - virtual void WipeQueue() {} // This should be avoided as much as possible, in favor of clearing when binding a render target, which is native @@ -846,20 +816,7 @@ public: // Not very elegant, but more elegant than the old passId hack. virtual void SetInvalidationCallback(InvalidationCallback callback) = 0; - // Total amount of frames rendered. Unaffected by game pause, so more robust than gpuStats.numFlips - virtual int GetFrameCount() = 0; - - virtual std::string GetGpuProfileString() const { - return ""; - } - - const HistoryBuffer &FrameTimeHistory() const { - return frameTimeHistory_; - } - protected: - HistoryBuffer frameTimeHistory_; - ShaderModule *vsPresets_[VS_MAX_PRESET]; ShaderModule *fsPresets_[FS_MAX_PRESET]; @@ -899,6 +856,4 @@ struct ShaderSource { ShaderModule *CreateShader(DrawContext *draw, ShaderStage stage, const std::vector &sources); -const char *PresentModeToString(PresentMode presentMode); - } // namespace Draw diff --git a/Common/GPU/thin3d_create.h b/Common/GPU/thin3d_create.h index 603db13d7..fccb3b076 100644 --- a/Common/GPU/thin3d_create.h +++ b/Common/GPU/thin3d_create.h @@ -17,20 +17,20 @@ struct ID3D11Device; struct ID3D11DeviceContext; struct ID3D11Device1; struct ID3D11DeviceContext1; -struct IDXGISwapChain; + #endif class VulkanContext; namespace Draw { -DrawContext *T3DCreateGLContext(bool canChangeSwapInterval); +DrawContext *T3DCreateGLContext(); #ifdef _WIN32 DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx); -DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, IDXGISwapChain *swapChain, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames, int maxInflightFrames); +DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames); #endif -DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool useRenderThread); +DrawContext *T3DCreateVulkanContext(VulkanContext *context); } // namespace Draw diff --git a/Common/GraphicsContext.h b/Common/GraphicsContext.h index 91319d72e..873722764 100644 --- a/Common/GraphicsContext.h +++ b/Common/GraphicsContext.h @@ -14,6 +14,9 @@ public: virtual void ShutdownFromRenderThread() {} virtual void Shutdown() = 0; + virtual void SwapInterval(int interval) = 0; + + virtual void SwapBuffers() = 0; // Used during window resize. Must be called from the window thread, // not the rendering thread or CPU thread. diff --git a/Common/Input/GestureDetector.h b/Common/Input/GestureDetector.h index 3e5754a7a..39c95dbae 100644 --- a/Common/Input/GestureDetector.h +++ b/Common/Input/GestureDetector.h @@ -1,5 +1,3 @@ -#pragma once - #include #include "Common/Input/InputState.h" #include "Common/Math/geom2d.h" diff --git a/Common/Input/InputState.cpp b/Common/Input/InputState.cpp index 95282f7e2..3db6dc137 100644 --- a/Common/Input/InputState.cpp +++ b/Common/Input/InputState.cpp @@ -20,7 +20,7 @@ const char *GetDeviceName(int deviceId) { case DEVICE_ID_PAD_7: return "pad8"; case DEVICE_ID_PAD_8: return "pad9"; case DEVICE_ID_PAD_9: return "pad10"; - case DEVICE_ID_XINPUT_0: return "x360"; // keeping these strings for backward compat. Hm, what would break if we changed them to xbox? + case DEVICE_ID_XINPUT_0: return "x360"; // keeping these strings for backward compat case DEVICE_ID_XINPUT_1: return "x360_2"; case DEVICE_ID_XINPUT_2: return "x360_3"; case DEVICE_ID_XINPUT_3: return "x360_4"; @@ -37,10 +37,9 @@ const char *GetDeviceName(int deviceId) { std::vector dpadKeys; std::vector confirmKeys; std::vector cancelKeys; -std::vector infoKeys; std::vector tabLeftKeys; std::vector tabRightKeys; -static std::unordered_map uiFlipAnalogY; +static std::unordered_map uiFlipAnalogY; static void AppendKeys(std::vector &keys, const std::vector &newKeys) { for (auto iter = newKeys.begin(); iter != newKeys.end(); ++iter) { @@ -70,15 +69,11 @@ void SetTabLeftRightKeys(const std::vector &tabLeft, const std::ve tabRightKeys = tabRight; } -void SetInfoKeys(const std::vector &info) { - infoKeys = info; -} - -void SetAnalogFlipY(std::unordered_map flipYByDeviceId) { +void SetAnalogFlipY(std::unordered_map flipYByDeviceId) { uiFlipAnalogY = flipYByDeviceId; } -int GetAnalogYDirection(InputDeviceID deviceId) { +int GetAnalogYDirection(int deviceId) { auto configured = uiFlipAnalogY.find(deviceId); if (configured != uiFlipAnalogY.end()) return configured->second; @@ -86,12 +81,11 @@ int GetAnalogYDirection(InputDeviceID deviceId) { } // NOTE: Changing the format of FromConfigString/ToConfigString breaks controls.ini backwards compatibility. -InputMapping InputMapping::FromConfigString(const std::string_view str) { - std::vector parts; +InputMapping InputMapping::FromConfigString(const std::string &str) { + std::vector parts; SplitString(str, '-', parts); - // We only convert to std::string here to add null terminators for atoi. - InputDeviceID deviceId = (InputDeviceID)(atoi(std::string(parts[0]).c_str())); - InputKeyCode keyCode = (InputKeyCode)atoi(std::string(parts[1]).c_str()); + int deviceId = atoi(parts[0].c_str()); + int keyCode = atoi(parts[1].c_str()); InputMapping mapping; mapping.deviceId = deviceId; @@ -100,15 +94,15 @@ InputMapping InputMapping::FromConfigString(const std::string_view str) { } std::string InputMapping::ToConfigString() const { - return StringFromFormat("%d-%d", (int)deviceId, keyCode); + return StringFromFormat("%d-%d", deviceId, keyCode); } void InputMapping::FormatDebug(char *buffer, size_t bufSize) const { if (IsAxis()) { int direction; int axis = Axis(&direction); - snprintf(buffer, bufSize, "Device: %d Axis: %d (%d)", (int)deviceId, axis, direction); + snprintf(buffer, bufSize, "Device: %d Axis: %d (%d)", deviceId, axis, direction); } else { - snprintf(buffer, bufSize, "Device: %d Key: %d", (int)deviceId, keyCode); + snprintf(buffer, bufSize, "Device: %d Key: %d", deviceId, keyCode); } } diff --git a/Common/Input/InputState.h b/Common/Input/InputState.h index 0a0874de0..0d71bf5c3 100644 --- a/Common/Input/InputState.h +++ b/Common/Input/InputState.h @@ -12,7 +12,7 @@ // Default device IDs -enum InputDeviceID { +enum { DEVICE_ID_ANY = -1, // Represents any device ID DEVICE_ID_DEFAULT = 0, // Old Android DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards @@ -31,23 +31,50 @@ enum InputDeviceID { DEVICE_ID_XINPUT_1 = 21, DEVICE_ID_XINPUT_2 = 22, DEVICE_ID_XINPUT_3 = 23, - DEVICE_ID_ACCELEROMETER = 30, // no longer used + DEVICE_ID_ACCELEROMETER = 30, DEVICE_ID_XR_HMD = 39, DEVICE_ID_XR_CONTROLLER_LEFT = 40, DEVICE_ID_XR_CONTROLLER_RIGHT = 41, DEVICE_ID_TOUCH = 42, - DEVICE_ID_COUNT, }; -inline InputDeviceID operator +(InputDeviceID deviceID, int addend) { - return (InputDeviceID)((int)deviceID + addend); -} - //number of contiguous generic joypad IDs const int MAX_NUM_PADS = 10; const char *GetDeviceName(int deviceId); +enum { + PAD_BUTTON_A = 1, + PAD_BUTTON_B = 2, + PAD_BUTTON_X = 4, + PAD_BUTTON_Y = 8, + PAD_BUTTON_LBUMPER = 16, + PAD_BUTTON_RBUMPER = 32, + PAD_BUTTON_START = 64, + PAD_BUTTON_SELECT = 128, + PAD_BUTTON_UP = 256, + PAD_BUTTON_DOWN = 512, + PAD_BUTTON_LEFT = 1024, + PAD_BUTTON_RIGHT = 2048, + + PAD_BUTTON_MENU = 4096, + PAD_BUTTON_BACK = 8192, + + // For Qt + PAD_BUTTON_JOY_UP = 1<<14, + PAD_BUTTON_JOY_DOWN = 1<<15, + PAD_BUTTON_JOY_LEFT = 1<<16, + PAD_BUTTON_JOY_RIGHT = 1<<17, + + PAD_BUTTON_LEFT_THUMB = 1 << 18, // Click left thumb stick on X360 + PAD_BUTTON_RIGHT_THUMB = 1 << 19, // Click right thumb stick on X360 + + PAD_BUTTON_LEFT_TRIGGER = 1 << 21, // Click left thumb stick on X360 + PAD_BUTTON_RIGHT_TRIGGER = 1 << 22, // Click left thumb stick on X360 + + PAD_BUTTON_FASTFORWARD = 1 << 20, // Click Tab to unthrottle +}; + #ifndef MAX_KEYQUEUESIZE #define MAX_KEYQUEUESIZE 20 #endif @@ -71,18 +98,18 @@ private: return AXIS_BIND_NKCODE_START + axisId * 2 + (direction < 0 ? 1 : 0); } public: - InputMapping() : deviceId(DEVICE_ID_DEFAULT), keyCode(0) {} + InputMapping() : deviceId(0), keyCode(0) {} // From a key mapping - InputMapping(InputDeviceID _deviceId, int key) : deviceId(_deviceId), keyCode(key) {} + InputMapping(int _deviceId, int key) : deviceId(_deviceId), keyCode(key) {} // From an axis - InputMapping(InputDeviceID _deviceId, int axis, int direction) : deviceId(_deviceId), keyCode(TranslateKeyCodeFromAxis(axis, direction)) { + InputMapping(int _deviceId, int axis, int direction) : deviceId(_deviceId), keyCode(TranslateKeyCodeFromAxis(axis, direction)) { _dbg_assert_(direction != 0); } - static InputMapping FromConfigString(std::string_view str); + static InputMapping FromConfigString(const std::string &str); std::string ToConfigString() const; - InputDeviceID deviceId; + int deviceId; int keyCode; // Can also represent an axis with direction, if encoded properly. bool IsAxis() const { @@ -122,9 +149,6 @@ public: if (keyCode != other.keyCode) return false; return true; } - bool operator != (const InputMapping &other) const { - return !(*this == other); - } void FormatDebug(char *buffer, size_t bufSize) const; }; @@ -171,19 +195,15 @@ enum { struct KeyInput { KeyInput() {} - KeyInput(InputDeviceID devId, InputKeyCode code, int fl) : deviceId(devId), keyCode(code), flags(fl) {} - KeyInput(InputDeviceID devId, int unicode) : deviceId(devId), unicodeChar(unicode), flags(KEY_CHAR) {} - InputDeviceID deviceId; - union { - InputKeyCode keyCode; // Android keycodes are the canonical keycodes, everyone else map to them. - int unicodeChar; // for KEY_CHAR - }; + KeyInput(int devId, int code, int fl) : deviceId(devId), keyCode(code), flags(fl) {} + int deviceId; + int keyCode; // Android keycodes are the canonical keycodes, everyone else map to them. int flags; }; struct AxisInput { - InputDeviceID deviceId; - InputAxis axisId; + int deviceId; + int axisId; // Android axis Ids are the canonical ones. float value; }; @@ -191,15 +211,13 @@ struct AxisInput { extern std::vector dpadKeys; extern std::vector confirmKeys; extern std::vector cancelKeys; -extern std::vector infoKeys; extern std::vector tabLeftKeys; extern std::vector tabRightKeys; void SetDPadKeys(const std::vector &leftKey, const std::vector &rightKey, const std::vector &upKey, const std::vector &downKey); void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel); void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight); -void SetInfoKeys(const std::vector &info); // 0 means unknown (attempt autodetect), -1 means flip, 1 means original direction. -void SetAnalogFlipY(std::unordered_map flipYByDeviceId); -int GetAnalogYDirection(InputDeviceID deviceId); +void SetAnalogFlipY(std::unordered_map flipYByDeviceId); +int GetAnalogYDirection(int deviceId); diff --git a/Common/Input/KeyCodes.h b/Common/Input/KeyCodes.h index 8614e5a2d..690d4c2c0 100644 --- a/Common/Input/KeyCodes.h +++ b/Common/Input/KeyCodes.h @@ -1,7 +1,6 @@ #pragma once -// These mostly match Android keycodes. -enum InputKeyCode { +typedef enum _keycode_t { NKCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed NKCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed NKCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) @@ -260,10 +259,9 @@ enum InputKeyCode { NKCODE_EXT_ROTATION_RIGHT = 1114, NKCODE_MAX -}; +} keycode_t; -// These mostly match Android axis IDs. -enum InputAxis { +enum AndroidJoystickAxis { // Field descriptor #15 I JOYSTICK_AXIS_X = 0, JOYSTICK_AXIS_Y = 1, @@ -305,7 +303,7 @@ enum InputAxis { JOYSTICK_AXIS_MOUSE_REL_X = 26, JOYSTICK_AXIS_MOUSE_REL_Y = 27, - // Mobile device accelerometer/gyro. NOTE: These are no longer passed around internally, only used for the plugin API. + // Mobile device accelerometer/gyro JOYSTICK_AXIS_ACCELEROMETER_X = 40, JOYSTICK_AXIS_ACCELEROMETER_Y = 41, JOYSTICK_AXIS_ACCELEROMETER_Z = 42, diff --git a/Common/Log.cpp b/Common/Log.cpp index 988e51f43..28c2f821d 100644 --- a/Common/Log.cpp +++ b/Common/Log.cpp @@ -25,7 +25,6 @@ #include "StringUtils.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/Thread/ThreadUtil.h" -#include "Common/TimeUtil.h" #if PPSSPP_PLATFORM(ANDROID) #include @@ -39,12 +38,10 @@ static bool hitAnyAsserts = false; std::mutex g_extraAssertInfoMutex; std::string g_extraAssertInfo = "menu"; -double g_assertInfoTime = 0.0; void SetExtraAssertInfo(const char *info) { std::lock_guard guard(g_extraAssertInfoMutex); g_extraAssertInfo = info ? info : "menu"; - g_assertInfoTime = time_now_d(); } bool HandleAssert(const char *function, const char *file, int line, const char *expression, const char* format, ...) { @@ -60,8 +57,7 @@ bool HandleAssert(const char *function, const char *file, int line, const char * char formatted[LOG_BUF_SIZE + 128]; { std::lock_guard guard(g_extraAssertInfoMutex); - double delta = time_now_d() - g_assertInfoTime; - snprintf(formatted, sizeof(formatted), "(%s:%s:%d): [%s] (%s, %0.1fs) %s", file, function, line, expression, g_extraAssertInfo.c_str(), delta, text); + snprintf(formatted, sizeof(formatted), "(%s:%s:%d): [%s] (%s) %s", file, function, line, expression, g_extraAssertInfo.c_str(), text); } // Normal logging (will also log to Android log) diff --git a/Common/Log.h b/Common/Log.h index 91b834b7f..7913cb0b0 100644 --- a/Common/Log.h +++ b/Common/Log.h @@ -26,8 +26,9 @@ #define DEBUG_LEVEL 5 // Detailed debugging - might make things slow. #define VERBOSE_LEVEL 6 // Noisy debugging - sometimes needed but usually unimportant. -// NOTE: Needs to be kept in sync with the g_logTypeNames array. -enum class LogType { +namespace LogTypes { + +enum LOG_TYPE { SYSTEM = 0, // Catch-all for uncategorized things BOOT, COMMON, @@ -44,9 +45,6 @@ enum class LogType { FRAMEBUF, AUDIO, IO, - ACHIEVEMENTS, - HTTP, - PRINTF, SCEAUDIO, SCECTRL, @@ -66,7 +64,7 @@ enum class LogType { NUMBER_OF_LOGS, // Must be last }; -enum class LogLevel : int { +enum LOG_LEVELS : int { LNOTICE = NOTICE_LEVEL, LERROR = ERROR_LEVEL, LWARNING = WARNING_LEVEL, @@ -75,18 +73,18 @@ enum class LogLevel : int { LVERBOSE = VERBOSE_LEVEL, }; -void GenericLog(LogLevel level, LogType type, +} // namespace + +void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, ...) #ifdef __GNUC__ __attribute__((format(printf, 5, 6))) #endif ; -bool GenericLogEnabled(LogLevel level, LogType type); +bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type); -// Exception for Windows - enable more log levels in release mode than on other platforms. #if defined(_DEBUG) || defined(_WIN32) -// Needs to be an int (and not use the enum) because it's used by the preprocessor! #define MAX_LOGLEVEL DEBUG_LEVEL #else @@ -100,16 +98,16 @@ bool GenericLogEnabled(LogLevel level, LogType type); // Let the compiler optimize this out. // TODO: Compute a dynamic max level as well that can be checked here. #define GENERIC_LOG(t, v, ...) { \ - if ((int)v <= MAX_LOGLEVEL) \ + if (v <= MAX_LOGLEVEL) \ GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \ } -#define ERROR_LOG(t,...) do { GENERIC_LOG(LogType::t, LogLevel::LERROR, __VA_ARGS__) } while (false) -#define WARN_LOG(t,...) do { GENERIC_LOG(LogType::t, LogLevel::LWARNING, __VA_ARGS__) } while (false) -#define NOTICE_LOG(t,...) do { GENERIC_LOG(LogType::t, LogLevel::LNOTICE, __VA_ARGS__) } while (false) -#define INFO_LOG(t,...) do { GENERIC_LOG(LogType::t, LogLevel::LINFO, __VA_ARGS__) } while (false) -#define DEBUG_LOG(t,...) do { GENERIC_LOG(LogType::t, LogLevel::LDEBUG, __VA_ARGS__) } while (false) -#define VERBOSE_LOG(t,...) do { GENERIC_LOG(LogType::t, LogLevel::LVERBOSE, __VA_ARGS__) } while (false) +#define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (false) +#define WARN_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__) } while (false) +#define NOTICE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LNOTICE, __VA_ARGS__) } while (false) +#define INFO_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LINFO, __VA_ARGS__) } while (false) +#define DEBUG_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LDEBUG, __VA_ARGS__) } while (false) +#define VERBOSE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LVERBOSE, __VA_ARGS__) } while (false) // Currently only actually shows a dialog box on Windows. bool HandleAssert(const char *function, const char *file, int line, const char *expression, const char* format, ...) @@ -130,8 +128,8 @@ void SetExtraAssertInfo(const char *info); #define __FILENAME__ __FILE__ #endif -// If we're a debug build, _dbg_assert_ is active. Not otherwise, even on Windows. -#if defined(_DEBUG) +// If we're in "debug" assert mode +#if MAX_LOGLEVEL >= DEBUG_LEVEL #define _dbg_assert_(_a_) \ if (!(_a_)) {\ diff --git a/Common/LogManager.cpp b/Common/LogManager.cpp index 60396a6e2..13084098a 100644 --- a/Common/LogManager.cpp +++ b/Common/LogManager.cpp @@ -47,7 +47,7 @@ static const char level_to_char[8] = "-NEWIDV"; #define LOG_MSC_OUTPUTDEBUG false #endif -void GenericLog(LogLevel level, LogType type, const char *file, int line, const char* fmt, ...) { +void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char* fmt, ...) { if (g_bLogEnabledSetting && !(*g_bLogEnabledSetting)) return; va_list args; @@ -69,7 +69,7 @@ void GenericLog(LogLevel level, LogType type, const char *file, int line, const va_end(args); } -bool GenericLogEnabled(LogLevel level, LogType type) { +bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type) { if (LogManager::GetInstance()) return (*g_bLogEnabledSetting) && LogManager::GetInstance()->IsEnabled(level, type); return false; @@ -77,56 +77,56 @@ bool GenericLogEnabled(LogLevel level, LogType type) { LogManager *LogManager::logManager_ = NULL; -// NOTE: Needs to be kept in sync with the LogType enum. -static const char *g_logTypeNames[] = { - "SYSTEM", - "BOOT", - "COMMON", - "CPU", - "FILESYS", - "G3D", - "HLE", - "JIT", - "LOADER", - "ME", // Media Engine - "MEMMAP", - "SASMIX", - "SAVESTATE", - "FRAMEBUF", - "AUDIO", - "IO", - "ACHIEVEMENTS", - "HTTP", - "PRINTF", +struct LogNameTableEntry { + LogTypes::LOG_TYPE logType; + const char *name; +}; - "SCEAUDIO", - "SCECTRL", - "SCEDISP", - "SCEFONT", - "SCEGE", - "SCEINTC", - "SCEIO", - "SCEKERNEL", - "SCEMODULE", - "SCENET", - "SCERTC", - "SCESAS", - "SCEUTIL", - "SCEMISC", +static const LogNameTableEntry logTable[] = { + {LogTypes::SYSTEM, "SYSTEM"}, + {LogTypes::BOOT, "BOOT"}, + {LogTypes::COMMON, "COMMON"}, + {LogTypes::CPU, "CPU"}, + {LogTypes::FILESYS, "FILESYS"}, + {LogTypes::G3D, "G3D"}, + {LogTypes::HLE, "HLE"}, + {LogTypes::JIT, "JIT"}, + {LogTypes::LOADER, "LOADER"}, + {LogTypes::ME, "ME"}, // Media Engine + {LogTypes::MEMMAP, "MEMMAP"}, + {LogTypes::SASMIX, "SASMIX"}, + {LogTypes::SAVESTATE, "SAVESTATE"}, + {LogTypes::FRAMEBUF, "FRAMEBUF"}, + {LogTypes::AUDIO, "AUDIO"}, + {LogTypes::IO, "IO"}, + + {LogTypes::SCEAUDIO, "SCEAUDIO"}, + {LogTypes::SCECTRL, "SCECTRL"}, + {LogTypes::SCEDISPLAY, "SCEDISP"}, + {LogTypes::SCEFONT, "SCEFONT"}, + {LogTypes::SCEGE, "SCEGE"}, + {LogTypes::SCEINTC, "SCEINTC"}, + {LogTypes::SCEIO, "SCEIO"}, + {LogTypes::SCEKERNEL, "SCEKERNEL"}, + {LogTypes::SCEMODULE, "SCEMODULE"}, + {LogTypes::SCENET, "SCENET"}, + {LogTypes::SCERTC, "SCERTC"}, + {LogTypes::SCESAS, "SCESAS"}, + {LogTypes::SCEUTILITY, "SCEUTIL"}, + {LogTypes::SCEMISC, "SCEMISC"}, }; LogManager::LogManager(bool *enabledSetting) { g_bLogEnabledSetting = enabledSetting; - _dbg_assert_(ARRAY_SIZE(g_logTypeNames) == (size_t)LogType::NUMBER_OF_LOGS); - - for (size_t i = 0; i < ARRAY_SIZE(g_logTypeNames); i++) { - truncate_cpy(log_[i].m_shortName, g_logTypeNames[i]); - log_[i].enabled = true; + for (size_t i = 0; i < ARRAY_SIZE(logTable); i++) { + _assert_msg_(i == logTable[i].logType, "Bad logtable at %i", (int)i); + truncate_cpy(log_[logTable[i].logType].m_shortName, logTable[i].name); + log_[logTable[i].logType].enabled = true; #if defined(_DEBUG) - log_[i].level = LogLevel::LDEBUG; + log_[logTable[i].logType].level = LogTypes::LDEBUG; #else - log_[i].level = LogLevel::LINFO; + log_[logTable[i].logType].level = LogTypes::LINFO; #endif } @@ -158,7 +158,7 @@ LogManager::LogManager(bool *enabledSetting) { } LogManager::~LogManager() { - for (int i = 0; i < (int)LogType::NUMBER_OF_LOGS; ++i) { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { #if !defined(MOBILE_DEVICE) || defined(_DEBUG) RemoveListener(fileLog_); RemoveListener(consoleLog_); @@ -194,25 +194,25 @@ void LogManager::ChangeFileLog(const char *filename) { } void LogManager::SaveConfig(Section *section) { - for (int i = 0; i < (int)LogType::NUMBER_OF_LOGS; i++) { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { section->Set((std::string(log_[i].m_shortName) + "Enabled").c_str(), log_[i].enabled); section->Set((std::string(log_[i].m_shortName) + "Level").c_str(), (int)log_[i].level); } } void LogManager::LoadConfig(const Section *section, bool debugDefaults) { - for (int i = 0; i < (int)LogType::NUMBER_OF_LOGS; i++) { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { bool enabled = false; int level = 0; section->Get((std::string(log_[i].m_shortName) + "Enabled").c_str(), &enabled, true); - section->Get((std::string(log_[i].m_shortName) + "Level").c_str(), &level, (int)(debugDefaults ? LogLevel::LDEBUG : LogLevel::LERROR)); + section->Get((std::string(log_[i].m_shortName) + "Level").c_str(), &level, debugDefaults ? (int)LogTypes::LDEBUG : (int)LogTypes::LERROR); log_[i].enabled = enabled; - log_[i].level = (LogLevel)level; + log_[i].level = (LogTypes::LOG_LEVELS)level; } } -void LogManager::Log(LogLevel level, LogType type, const char *file, int line, const char *format, va_list args) { - const LogChannel &log = log_[(size_t)type]; +void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *format, va_list args) { + const LogChannel &log = log_[type]; if (level > log.level || !log.enabled) return; @@ -268,8 +268,8 @@ void LogManager::Log(LogLevel level, LogType type, const char *file, int line, c } } -bool LogManager::IsEnabled(LogLevel level, LogType type) { - LogChannel &log = log_[(size_t)type]; +bool LogManager::IsEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type) { + LogChannel &log = log_[type]; if (level > log.level || !log.enabled) return false; return true; diff --git a/Common/LogManager.h b/Common/LogManager.h index 715177406..3ee1347f4 100644 --- a/Common/LogManager.h +++ b/Common/LogManager.h @@ -37,7 +37,7 @@ extern const char *hleCurrentThreadName; struct LogMessage { char timestamp[16]; char header[64]; // Filename/thread/etc. in front. - LogLevel level; + LogTypes::LOG_LEVELS level; const char *log; std::string msg; // The actual log message. }; @@ -83,7 +83,7 @@ public: int GetCount() const { return count_ < MAX_LOGS ? count_ : MAX_LOGS; } const char *TextAt(int i) const { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)].msg.c_str(); } - LogLevel LevelAt(int i) const { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)].level; } + LogTypes::LOG_LEVELS LevelAt(int i) const { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)].level; } private: enum { MAX_LOGS = 128 }; @@ -99,7 +99,7 @@ private: struct LogChannel { char m_shortName[32]{}; - LogLevel level; + LogTypes::LOG_LEVELS level; bool enabled; }; @@ -114,7 +114,7 @@ private: LogManager(const LogManager &) = delete; void operator=(const LogManager &) = delete; - LogChannel log_[(size_t)LogType::NUMBER_OF_LOGS]; + LogChannel log_[LogTypes::NUMBER_OF_LOGS]; FileLogListener *fileLog_ = nullptr; ConsoleListener *consoleLog_ = nullptr; OutputDebugStringLogListener *debuggerLog_ = nullptr; @@ -128,33 +128,33 @@ public: void AddListener(LogListener *listener); void RemoveListener(LogListener *listener); - static u32 GetMaxLevel() { return (u32)MAX_LOGLEVEL; } - static int GetNumChannels() { return (int)LogType::NUMBER_OF_LOGS; } + static u32 GetMaxLevel() { return MAX_LOGLEVEL; } + static int GetNumChannels() { return LogTypes::NUMBER_OF_LOGS; } - void Log(LogLevel level, LogType type, + void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *fmt, va_list args); - bool IsEnabled(LogLevel level, LogType type); + bool IsEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type); - LogChannel *GetLogChannel(LogType type) { - return &log_[(size_t)type]; + LogChannel *GetLogChannel(LogTypes::LOG_TYPE type) { + return &log_[type]; } - void SetLogLevel(LogType type, LogLevel level) { - log_[(size_t)type].level = level; + void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level) { + log_[type].level = level; } - void SetAllLogLevels(LogLevel level) { - for (int i = 0; i < (int)LogType::NUMBER_OF_LOGS; ++i) { + void SetAllLogLevels(LogTypes::LOG_LEVELS level) { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { log_[i].level = level; } } - void SetEnabled(LogType type, bool enable) { - log_[(size_t)type].enabled = enable; + void SetEnabled(LogTypes::LOG_TYPE type, bool enable) { + log_[type].enabled = enable; } - LogLevel GetLogLevel(LogType type) { - return log_[(size_t)type].level; + LogTypes::LOG_LEVELS GetLogLevel(LogTypes::LOG_TYPE type) { + return log_[type].level; } ConsoleListener *GetConsoleListener() const { diff --git a/Common/LoongArchCPUDetect.cpp b/Common/LoongArchCPUDetect.cpp deleted file mode 100644 index 64f4acd9a..000000000 --- a/Common/LoongArchCPUDetect.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// 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 "ppsspp_config.h" -#if PPSSPP_ARCH(LOONGARCH64) - -#include "ext/cpu_features/include/cpuinfo_loongarch.h" - -#if defined(CPU_FEATURES_OS_LINUX) -#define USE_CPU_FEATURES 1 -#endif - -#include -#include -#include -#include -#include -#include "Common/Common.h" -#include "Common/CPUDetect.h" -#include "Common/StringUtils.h" -#include "Common/File/FileUtil.h" -#include "Common/Data/Encoding/Utf8.h" - -// Only Linux platforms have /proc/cpuinfo -#if defined(__linux__) -const char procfile[] = "/proc/cpuinfo"; -// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu -const char syscpupresentfile[] = "/sys/devices/system/cpu/present"; - -class LoongArchCPUInfoParser { -public: - LoongArchCPUInfoParser(); - - int ProcessorCount(); - int TotalLogicalCount(); - -private: - std::vector> cores_; -}; - -LoongArchCPUInfoParser::LoongArchCPUInfoParser() { - std::string procdata, line; - if (!File::ReadFileToString(true, Path(procfile), procdata)) - return; - - std::istringstream file(procdata); - int index = -1; - while (std::getline(file, line)) { - if (line.length() == 0) { - index = -1; - } else { - if (index == -1) { - index = (int)cores_.size(); - cores_.push_back(std::vector()); - } - cores_[index].push_back(line); - } - } -} - -int LoongArchCPUInfoParser::ProcessorCount() { - static const char *marker = "core"; - std::set coreIndex; - for (auto core : cores_) { - for (auto line : core) { - if (line.find(marker) != line.npos) - coreIndex.insert(line); - } - } - - return (int)coreIndex.size(); -} - -int LoongArchCPUInfoParser::TotalLogicalCount() { - std::string presentData, line; - bool presentSuccess = File::ReadFileToString(true, Path(syscpupresentfile), presentData); - if (presentSuccess) { - std::istringstream presentFile(presentData); - - int low, high, found; - std::getline(presentFile, line); - found = sscanf(line.c_str(), "%d-%d", &low, &high); - if (found == 1){ - return 1; - } - if (found == 2){ - return high - low + 1; - } - }else{ - return 1; - } -} - -#endif - -static bool ExtensionSupported(unsigned long v, unsigned int i) { - // https://github.com/torvalds/linux/blob/master/arch/loongarch/include/uapi/asm/hwcap.h - unsigned long mask = 1 << i; - return v & mask; -} - -CPUInfo cpu_info; - -CPUInfo::CPUInfo() { - Detect(); -} - -// Detects the various cpu features -void CPUInfo::Detect() -{ - // Set some defaults here - HTT = false; -#if PPSSPP_ARCH(LOONGARCH64) - OS64bit = true; - CPU64bit = true; - Mode64bit = true; -#else - OS64bit = false; - CPU64bit = false; - Mode64bit = false; -#endif - vendor = VENDOR_OTHER; - truncate_cpy(brand_string, "Loongson"); - truncate_cpy(cpu_string, "Loongson"); -#if !defined(__linux__) - num_cores = 1; - logical_cpu_count = 1; - truncate_cpy(brand_string, "Unknown"); - truncate_cpy(cpu_string, "Unknown"); -#else // __linux__ - LoongArchCPUInfoParser parser; - num_cores = parser.ProcessorCount(); - logical_cpu_count = parser.TotalLogicalCount() / num_cores; - if (logical_cpu_count <= 0) - logical_cpu_count = 1; -#endif - - unsigned long hwcap = getauxval(AT_HWCAP); - LOONGARCH_CPUCFG = true; - LOONGARCH_LAM = ExtensionSupported(hwcap, 1); - LOONGARCH_UAL = ExtensionSupported(hwcap, 2); - LOONGARCH_FPU = ExtensionSupported(hwcap, 3); - LOONGARCH_LSX = ExtensionSupported(hwcap, 4); - LOONGARCH_LASX = ExtensionSupported(hwcap, 5); - LOONGARCH_CRC32 = ExtensionSupported(hwcap, 6); - LOONGARCH_COMPLEX = ExtensionSupported(hwcap, 7); - LOONGARCH_CRYPTO = ExtensionSupported(hwcap, 8); - LOONGARCH_LVZ = ExtensionSupported(hwcap, 9); - LOONGARCH_LBT_X86 = ExtensionSupported(hwcap, 10); - LOONGARCH_LBT_ARM = ExtensionSupported(hwcap, 11); - LOONGARCH_LBT_MIPS = ExtensionSupported(hwcap, 12); - LOONGARCH_PTW = ExtensionSupported(hwcap, 13); - -#ifdef USE_CPU_FEATURES - cpu_features::LoongArchInfo info = cpu_features::GetLoongArchInfo(); - LOONGARCH_CPUCFG = true; - LOONGARCH_LAM = info.features.LAM; - LOONGARCH_UAL = info.features.UAL; - LOONGARCH_FPU = info.features.FPU; - LOONGARCH_LSX = info.features.LSX; - LOONGARCH_LASX = info.features.LASX; - LOONGARCH_CRC32 = info.features.CRC32; - LOONGARCH_COMPLEX = info.features.COMPLEX; - LOONGARCH_CRYPTO = info.features.CRYPTO; - LOONGARCH_LVZ = info.features.LVZ; - LOONGARCH_LBT_X86 = info.features.LBT_X86; - LOONGARCH_LBT_ARM = info.features.LBT_ARM; - LOONGARCH_LBT_MIPS = info.features.LBT_MIPS; - LOONGARCH_PTW = info.features.PTW; -#endif -} - -std::vector CPUInfo::Features() { -std::vector features; - - struct Flag { - bool &flag; - const char *str; - }; - const Flag list[] = { - { LOONGARCH_CPUCFG, "Identify CPU Features" }, - { LOONGARCH_LAM, "Atomic Memory Access Instructions" }, - { LOONGARCH_UAL, "Non-Aligned Memory Access" }, - { LOONGARCH_FPU, "Basic Floating-Point Instructions" }, - { LOONGARCH_LSX, "Loongson SIMD eXtension" }, - { LOONGARCH_LASX, "Loongson Advanced SIMD eXtension" }, - { LOONGARCH_CRC32, "Cyclic Redundancy Check Instructions" }, - { LOONGARCH_COMPLEX, "Complex Vector Operation Instructions" }, - { LOONGARCH_CRYPTO, "Encryption And Decryption Vector Instructions" }, - { LOONGARCH_LVZ, "Virtualization" }, - { LOONGARCH_LBT_X86, "X86 Binary Translation Extension" }, - { LOONGARCH_LBT_ARM, "ARM Binary Translation Extension" }, - { LOONGARCH_LBT_MIPS, "MIPS Binary Translation Extension" }, - { LOONGARCH_PTW, "Page Table Walker" }, - }; - - for (auto &item : list) { - if (item.flag) { - features.push_back(item.str); - } - } - - return features; -} - -// 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); - - auto features = Features(); - for (std::string &feature : features) { - sum += ", " + feature; - } - return sum; -} - -#endif // PPSSPP_ARCH(LOONGARCH64) diff --git a/Common/Math/Statistics.h b/Common/Math/Statistics.h index bcf33c0a5..0b03d1d42 100644 --- a/Common/Math/Statistics.h +++ b/Common/Math/Statistics.h @@ -32,7 +32,6 @@ struct SimpleStat { void Format(char *buffer, size_t sz); private: - SimpleStat() {} const char *name_; // These are initialized in Reset(). diff --git a/Common/Math/expression_parser.cpp b/Common/Math/expression_parser.cpp index aa9ba4c0a..a5f48e64c 100644 --- a/Common/Math/expression_parser.cpp +++ b/Common/Math/expression_parser.cpp @@ -1,4 +1,3 @@ -#include "Common/StringUtils.h" #include "expression_parser.h" #include #include @@ -15,7 +14,7 @@ typedef enum { typedef enum { EXCOMM_CONST, EXCOMM_CONST_FLOAT, EXCOMM_REF, EXCOMM_OP } ExpressionCommand; -static std::string expressionError; +static char expressionError[512]; typedef struct { char Name[4]; @@ -220,7 +219,7 @@ bool isAlphaNum(char c) bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest) { - expressionError.clear(); + expressionError[0] = 0; int infixPos = 0; int infixLen = (int)strlen(infix); @@ -254,7 +253,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf isFloat = true; else if (parseNumber(subStr,16,subPos,value) == false) { - expressionError = StringFromFormat("Invalid number \"%s\"", subStr); + snprintf(expressionError, sizeof(expressionError), "Invalid number \"%s\"",subStr); return false; } @@ -283,14 +282,14 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf continue; } - expressionError = StringFromFormat("Invalid symbol \"%s\"", subStr); + snprintf(expressionError, sizeof(expressionError), "Invalid symbol \"%s\"",subStr); return false; } else { int len; ExpressionOpcodeType type = getExpressionOpcode(&infix[infixPos],len,lastOpcode); if (type == EXOP_NONE) { - expressionError = StringFromFormat("Invalid operator at \"%s\"", &infix[infixPos]); + snprintf(expressionError, sizeof(expressionError), "Invalid operator at \"%s\"",&infix[infixPos]); return false; } @@ -305,7 +304,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf { if (opcodeStack.empty()) { - expressionError = "Closing parenthesis without opening one"; + snprintf(expressionError, sizeof(expressionError), "Closing parenthesis without opening one"); return false; } ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; @@ -319,7 +318,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf { if (opcodeStack.empty()) { - expressionError = "Closing bracket without opening one"; + snprintf(expressionError, sizeof(expressionError), "Closing bracket without opening one"); return false; } ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; @@ -372,7 +371,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf if (t == EXOP_BRACKETL) // opening bracket without closing one { - expressionError = "Parenthesis not closed"; + snprintf(expressionError, sizeof(expressionError), "Parenthesis not closed"); return false; } dest.push_back(ExpressionPair(EXCOMM_OP,t)); @@ -431,7 +430,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, opcode = exp[num++].second; if (valueStack.size() < ExpressionOpcodes[opcode].args) { - expressionError = "Not enough arguments"; + snprintf(expressionError, sizeof(expressionError), "Not enough arguments"); return false; } for (int l = 0; l < ExpressionOpcodes[opcode].args; l++) @@ -447,12 +446,12 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_MEMSIZE: // must be followed by EXOP_MEM if (exp[num++].second != EXOP_MEM) { - expressionError = "Invalid memsize operator"; + snprintf(expressionError, sizeof(expressionError), "Invalid memsize operator"); return false; } uint32_t val; - if (funcs->getMemoryValue(arg[1], arg[0], val, &expressionError) == false) + if(funcs->getMemoryValue(arg[1],arg[0],val,expressionError, sizeof(expressionError)) == false) { return false; } @@ -461,7 +460,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_MEM: { uint32_t val; - if (funcs->getMemoryValue(arg[0], 4, val, &expressionError) == false) + if (funcs->getMemoryValue(arg[0],4,val,expressionError, sizeof(expressionError)) == false) { return false; } @@ -491,7 +490,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_DIV: // a/b if (arg[0] == 0) { - expressionError = "Division by zero"; + snprintf(expressionError, sizeof(expressionError), "Division by zero"); return false; } if (useFloat) @@ -502,7 +501,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_MOD: // a%b if (arg[0] == 0) { - expressionError = "Modulo by zero"; + snprintf(expressionError, sizeof(expressionError), "Modulo by zero"); return false; } valueStack.push_back(arg[1]%arg[0]); @@ -575,7 +574,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_TERTELSE: // exp ? exp : exp, else muss zuerst kommen! if (exp[num++].second != EXOP_TERTIF) { - expressionError = "Invalid tertiary operator"; + snprintf(expressionError, sizeof(expressionError), "Invalid tertiary operator"); return false; } valueStack.push_back(arg[2]?arg[1]:arg[0]); @@ -596,9 +595,8 @@ bool parseExpression(const char *exp, IExpressionFunctions *funcs, uint32_t &des return parsePostfixExpression(postfix,funcs,dest); } -const char *getExpressionError() +const char* getExpressionError() { - if (expressionError.empty()) - expressionError = "Invalid expression"; - return expressionError.c_str(); + if (expressionError[0] == 0) snprintf(expressionError, sizeof(expressionError), "Invalid expression"); + return expressionError; } diff --git a/Common/Math/expression_parser.h b/Common/Math/expression_parser.h index ee6330a92..fb82fc944 100644 --- a/Common/Math/expression_parser.h +++ b/Common/Math/expression_parser.h @@ -2,7 +2,6 @@ #include #include -#include #include typedef std::pair ExpressionPair; @@ -22,7 +21,7 @@ public: virtual bool parseSymbol(char* str, uint32_t& symbolValue) = 0; virtual uint32_t getReferenceValue(uint32_t referenceIndex) = 0; virtual ExpressionType getReferenceType(uint32_t referenceIndex) = 0; - virtual bool getMemoryValue(uint32_t address, int size, uint32_t& dest, std::string *error) = 0; + virtual bool getMemoryValue(uint32_t address, int size, uint32_t& dest, char *error, size_t errorBufSize) = 0; }; bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest); diff --git a/Common/Math/geom2d.h b/Common/Math/geom2d.h index f319d7c79..c063ca0d6 100644 --- a/Common/Math/geom2d.h +++ b/Common/Math/geom2d.h @@ -69,22 +69,9 @@ struct Bounds { Bounds Expand(float xAmount, float yAmount) const { return Bounds(x - xAmount, y - yAmount, w + xAmount * 2, h + yAmount * 2); } - Bounds Expand(float left, float top, float right, float bottom) const { - return Bounds(x - left, y - top, w + left + right, h + top + bottom); - } Bounds Offset(float xAmount, float yAmount) const { return Bounds(x + xAmount, y + yAmount, w, h); } - Bounds Inset(float left, float top, float right, float bottom) { - return Bounds(x + left, y + top, w - left - right, h - bottom - top); - } - - Bounds Inset(float xAmount, float yAmount) const { - return Bounds(x + xAmount, y + yAmount, w - xAmount * 2, h - yAmount * 2); - } - Bounds Inset(float left, float top, float right, float bottom) const { - return Bounds(x + left, y + top, w - left - right, h - top - bottom); - } float x; float y; diff --git a/Common/Math/math_util.h b/Common/Math/math_util.h index a821be5fe..b76e1f393 100644 --- a/Common/Math/math_util.h +++ b/Common/Math/math_util.h @@ -67,13 +67,6 @@ inline T clamp_value(T val, T floor, T cap) { return val; } -// Very common operation, familiar from shaders. -inline float saturatef(float x) { - if (x > 1.0f) return 1.0f; - else if (x < 0.0f) return 0.0f; - else return x; -} - #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUND_DOWN(x, a) ((x) & ~((a) - 1)) diff --git a/Common/MemArena.h b/Common/MemArena.h index 9a905b134..85112e912 100644 --- a/Common/MemArena.h +++ b/Common/MemArena.h @@ -39,7 +39,7 @@ public: bool GrabMemSpace(size_t size); void ReleaseSpace(); void *CreateView(s64 offset, size_t size, void *base = 0); - void ReleaseView(s64 offset, void *view, size_t size); + void ReleaseView(void *view, size_t size); // This only finds 1 GB in 32-bit u8 *Find4GBBase(); diff --git a/Common/MemArenaAndroid.cpp b/Common/MemArenaAndroid.cpp index 73dd4e7cc..f7ea90cfe 100644 --- a/Common/MemArenaAndroid.cpp +++ b/Common/MemArenaAndroid.cpp @@ -129,7 +129,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) { return retval; } -void MemArena::ReleaseView(s64 offset, void* view, size_t size) { +void MemArena::ReleaseView(void* view, size_t size) { munmap(view, size); } diff --git a/Common/MemArenaDarwin.cpp b/Common/MemArenaDarwin.cpp index 0b1abd16b..d13e37a8a 100644 --- a/Common/MemArenaDarwin.cpp +++ b/Common/MemArenaDarwin.cpp @@ -79,7 +79,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) { return (void *)target; } -void MemArena::ReleaseView(s64 offset, void* view, size_t size) { +void MemArena::ReleaseView(void* view, size_t size) { vm_address_t addr = (vm_address_t)view; vm_deallocate(mach_task_self(), addr, size); } diff --git a/Common/MemArenaHorizon.cpp b/Common/MemArenaHorizon.cpp deleted file mode 100644 index a57028ffa..000000000 --- a/Common/MemArenaHorizon.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2023 M4xw - -// 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 or later versions. - -// 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/ - -#include "ppsspp_config.h" -#if PPSSPP_PLATFORM(SWITCH) - -#include -#include // memalign -#include - -#include "Common/MemArena.h" - -static uintptr_t memoryBase = 0; -static uintptr_t memoryCodeBase = 0; -static uintptr_t memorySrcBase = 0; - -size_t MemArena::roundup(size_t x) { - return x; -} - -bool MemArena::NeedsProbing() { - return false; -} - -bool MemArena::GrabMemSpace(size_t size) { - return true; -} - -void MemArena::ReleaseSpace() { - if (R_FAILED(svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)memoryCodeBase, (u64)memorySrcBase, 0x10000000))) - printf("Failed to release view space...\n"); - - free((void *)memorySrcBase); - memorySrcBase = 0; -} - -void *MemArena::CreateView(s64 offset, size_t size, void *base) { - Result rc = svcMapProcessMemory(base, envGetOwnProcessHandle(), (u64)(memoryCodeBase + offset), size); - if (R_FAILED(rc)) { - printf("Fatal error creating the view... base: %p offset: %p size: %p src: %p err: %d\n", - (void *)base, (void *)offset, (void *)size, (void *)(memoryCodeBase + offset), rc); - } else { - printf("Created the view... base: %p offset: %p size: %p src: %p err: %d\n", - (void *)base, (void *)offset, (void *)size, (void *)(memoryCodeBase + offset), rc); - } - - return base; -} - -void MemArena::ReleaseView(s64 offset, void *view, size_t size) { - if (R_FAILED(svcUnmapProcessMemory(view, envGetOwnProcessHandle(), (u64)(memoryCodeBase + offset), size))) - printf("Failed to unmap view...\n"); -} - -u8 *MemArena::Find4GBBase() { - memorySrcBase = (uintptr_t)memalign(0x1000, 0x10000000); - - if (!memoryBase) - memoryBase = (uintptr_t)virtmemReserve(0x10000000); - - if (!memoryCodeBase) - memoryCodeBase = (uintptr_t)virtmemReserve(0x10000000); - - if (R_FAILED(svcMapProcessCodeMemory(envGetOwnProcessHandle(), (u64)memoryCodeBase, (u64)memorySrcBase, 0x10000000))) - printf("Failed to map memory...\n"); - if (R_FAILED(svcSetProcessMemoryPermission(envGetOwnProcessHandle(), memoryCodeBase, 0x10000000, Perm_Rx))) - printf("Failed to set perms...\n"); - - return (u8 *)memoryBase; -} - -#endif // PPSSPP_PLATFORM(SWITCH) diff --git a/Common/MemArenaPosix.cpp b/Common/MemArenaPosix.cpp index 7923b99b8..5016cd429 100644 --- a/Common/MemArenaPosix.cpp +++ b/Common/MemArenaPosix.cpp @@ -17,7 +17,7 @@ #include "ppsspp_config.h" -#if !defined(_WIN32) && !defined(ANDROID) && !defined(__APPLE__) && !PPSSPP_PLATFORM(SWITCH) +#if !defined(_WIN32) && !defined(ANDROID) && !defined(__APPLE__) #include #include @@ -52,7 +52,6 @@ bool MemArena::NeedsProbing() { } bool MemArena::GrabMemSpace(size_t size) { -#ifndef NO_MMAP constexpr mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // Try a few times in case multiple instances are started near each other. @@ -99,21 +98,15 @@ bool MemArena::GrabMemSpace(size_t size) { ERROR_LOG(MEMMAP, "Failed to ftruncate %d (%s) to size %08x", (int)fd, ram_temp_file.c_str(), (int)size); // Should this be a failure? } -#endif return true; } void MemArena::ReleaseSpace() { -#ifndef NO_MMAP close(fd); -#endif } void *MemArena::CreateView(s64 offset, size_t size, void *base) { -#ifdef NO_MMAP - return (void*) base; -#else void *retval = mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | // Do not sync memory to underlying file. Linux has this by default. #if defined(__DragonFly__) || defined(__FreeBSD__) @@ -126,13 +119,10 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) return 0; } return retval; -#endif } -void MemArena::ReleaseView(s64 offset, void* view, size_t size) { -#ifndef NO_MMAP +void MemArena::ReleaseView(void* view, size_t size) { munmap(view, size); -#endif } u8* MemArena::Find4GBBase() { @@ -157,9 +147,6 @@ u8* MemArena::Find4GBBase() { // This has been known to fail lately though, see issue #12249. return hardcoded_ptr; } -#elif defined(NO_MMAP) - void* base = std::malloc(0x0A000000); - return static_cast(base); #else size_t size = 0x10000000; void* base = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED | MAP_NORESERVE, -1, 0); diff --git a/Common/MemArenaWin32.cpp b/Common/MemArenaWin32.cpp index 85ee094ca..39d0d6de7 100644 --- a/Common/MemArenaWin32.cpp +++ b/Common/MemArenaWin32.cpp @@ -54,7 +54,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *viewbase) { return ptr; } -void MemArena::ReleaseView(s64 offset, void* view, size_t size) { +void MemArena::ReleaseView(void* view, size_t size) { #if PPSSPP_PLATFORM(UWP) #else UnmapViewOfFile(view); diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index 4cebd6eb4..cee1e33ec 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -17,7 +17,6 @@ #include "ppsspp_config.h" -#if !PPSSPP_PLATFORM(SWITCH) #include #include @@ -26,7 +25,6 @@ #include "Common/MemoryUtil.h" #include "Common/StringUtils.h" #include "Common/SysError.h" -#include "Common/Data/Text/Parsers.h" #ifdef _WIN32 #include "Common/CommonWindows.h" @@ -258,9 +256,8 @@ void *AllocateAlignedMemory(size_t size, size_t alignment) { } #endif #endif - char temp[32]; - NiceSizeFormat(size, temp, sizeof(temp)); - _assert_msg_(ptr != nullptr, "Failed to allocate aligned memory of size %s (%llu)", temp, (unsigned long long)size); + + _assert_msg_(ptr != nullptr, "Failed to allocate aligned memory of size %llu", size); return ptr; } @@ -358,4 +355,3 @@ int GetMemoryProtectPageSize() { #endif return MEM_PAGE_SIZE; } -#endif // !PPSSPP_PLATFORM(SWITCH) diff --git a/Common/MemoryUtil.h b/Common/MemoryUtil.h index aa7cfd5df..9d72de9ab 100644 --- a/Common/MemoryUtil.h +++ b/Common/MemoryUtil.h @@ -18,11 +18,7 @@ #pragma once #ifndef _WIN32 -#ifndef __SWITCH__ #include -#else -#include -#endif // !__SWITCH__ #endif #include diff --git a/Common/MemoryUtilHorizon.cpp b/Common/MemoryUtilHorizon.cpp deleted file mode 100644 index e0ae8090a..000000000 --- a/Common/MemoryUtilHorizon.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// 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 or later versions. - -// 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 "ppsspp_config.h" - -#if PPSSPP_PLATFORM(SWITCH) -#include -#include - -#include "Common/CommonTypes.h" -#include "Common/Log.h" -#include "Common/MemoryUtil.h" -#include "Common/StringUtils.h" -#include "Common/SysError.h" - -#include -#include - -#include // memalign - -#define MEM_PAGE_SIZE (0x1000) -#define MEM_PAGE_MASK ((MEM_PAGE_SIZE)-1) -#define ppsspp_round_page(x) ((((uintptr_t)(x)) + MEM_PAGE_MASK) & ~(MEM_PAGE_MASK)) - -// On Switch we dont support allocating executable memory here -// See CodeBlock.h -void *AllocateExecutableMemory(size_t size) { - return nullptr; -} - -void *AllocateMemoryPages(size_t size, uint32_t memProtFlags) { - void* ptr = nullptr; - size = ppsspp_round_page(size); - ptr = memalign(MEM_PAGE_SIZE, size); - return ptr; -} - -void *AllocateAlignedMemory(size_t size, size_t alignment) { - void* ptr = memalign(alignment, size); - - _assert_msg_(ptr != nullptr, "Failed to allocate aligned memory of size %lu", size); - return ptr; -} - -void FreeMemoryPages(void *ptr, size_t size) { - if (!ptr) - return; - - free(ptr); - return; -} - -void FreeExecutableMemory(void *ptr, size_t size) { - return; // Not supported on Switch -} - -void FreeAlignedMemory(void* ptr) { - if (!ptr) - return; - - free(ptr); -} - -bool PlatformIsWXExclusive() { - return false; // Switch technically is W^X but we use dual mappings instead of reprotecting the pages to allow a W and X mapping -} - -bool ProtectMemoryPages(const void* ptr, size_t size, uint32_t memProtFlags) { - return true; -} - -int GetMemoryProtectPageSize() { - return MEM_PAGE_SIZE; -} -#endif // PPSSPP_PLATFORM(SWITCH) diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp index c6366af82..7ef0c15df 100644 --- a/Common/Net/HTTPClient.cpp +++ b/Common/Net/HTTPClient.cpp @@ -2,7 +2,6 @@ #include "Common/TimeUtil.h" #include "Common/StringUtils.h" -#include "Common/System/OSD.h" #ifndef _WIN32 #include @@ -30,7 +29,6 @@ #include "Common/Net/URL.h" #include "Common/File/FileDescriptor.h" -#include "Common/SysError.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Compression.h" #include "Common/Net/NetBuffer.h" @@ -94,18 +92,6 @@ bool Connection::Resolve(const char *host, int port, DNSType type) { return true; } -static void FormatAddr(char *addrbuf, size_t bufsize, const addrinfo *info) { - switch (info->ai_family) { - case AF_INET: - case AF_INET6: - inet_ntop(info->ai_family, &((sockaddr_in *)info->ai_addr)->sin_addr, addrbuf, bufsize); - break; - default: - snprintf(addrbuf, bufsize, "(Unknown AF %d)", info->ai_family); - break; - } -} - bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { if (port_ <= 0) { ERROR_LOG(IO, "Bad port"); @@ -130,31 +116,7 @@ bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { fd_util::SetNonBlocking(sock, true); // Start trying to connect (async with timeout.) - errno = 0; - if (connect(sock, possible->ai_addr, (int)possible->ai_addrlen) < 0) { -#if PPSSPP_PLATFORM(WINDOWS) - int errorCode = WSAGetLastError(); - std::string errorString = GetStringErrorMsg(errorCode); - bool unreachable = errorCode == WSAENETUNREACH; - bool inProgress = errorCode == WSAEINPROGRESS || errorCode == WSAEWOULDBLOCK; -#else - int errorCode = errno; - std::string errorString = strerror(errno); - bool unreachable = errorCode == ENETUNREACH; - bool inProgress = errorCode == EINPROGRESS || errorCode == EWOULDBLOCK; -#endif - if (!inProgress) { - char addrStr[128]{}; - FormatAddr(addrStr, sizeof(addrStr), possible); - if (!unreachable) { - ERROR_LOG(HTTP, "connect(%d) call to %s failed (%d: %s)", sock, addrStr, errorCode, errorString.c_str()); - } else { - INFO_LOG(HTTP, "connect(%d): Ignoring unreachable resolved address %s", sock, addrStr); - } - closesocket(sock); - continue; - } - } + connect(sock, possible->ai_addr, (int)possible->ai_addrlen); sockets.push_back(sock); FD_SET(sock, &fds); if (maxfd < sock + 1) { @@ -218,10 +180,10 @@ void Connection::Disconnect() { namespace http { // TODO: do something sane here -constexpr const char *DEFAULT_USERAGENT = "PPSSPP"; -constexpr const char *HTTP_VERSION = "1.1"; +constexpr const char *DEFAULT_USERAGENT = "NATIVEAPP 1.0"; Client::Client() { + httpVersion_ = "1.1"; userAgent_ = DEFAULT_USERAGENT; } @@ -255,7 +217,7 @@ bool GetHeaderValue(const std::vector &responseHeaders, const std:: return found; } -void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength) { +void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength, float *progress) { int dechunkedBytes = 0; while (true) { std::string line; @@ -274,11 +236,14 @@ void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength) { return; } dechunkedBytes += chunkSize; + if (progress && contentLength) { + *progress = (float)dechunkedBytes / contentLength; + } inbuffer->Skip(2); } } -int Client::GET(const RequestParams &req, Buffer *output, std::vector &responseHeaders, net::RequestProgress *progress) { +int Client::GET(const RequestParams &req, Buffer *output, std::vector &responseHeaders, RequestProgress *progress) { const char *otherHeaders = "Accept-Encoding: gzip\r\n"; int err = SendRequest("GET", req, otherHeaders, progress); @@ -299,13 +264,13 @@ int Client::GET(const RequestParams &req, Buffer *output, std::vector responseHeaders; int code = GET(req, output, responseHeaders, progress); return code; } -int Client::POST(const RequestParams &req, const std::string &data, const std::string &mime, Buffer *output, net::RequestProgress *progress) { +int Client::POST(const RequestParams &req, const std::string &data, const std::string &mime, Buffer *output, RequestProgress *progress) { char otherHeaders[2048]; if (mime.empty()) { snprintf(otherHeaders, sizeof(otherHeaders), "Content-Length: %lld\r\n", (long long)data.size()); @@ -331,16 +296,16 @@ int Client::POST(const RequestParams &req, const std::string &data, const std::s return code; } -int Client::POST(const RequestParams &req, const std::string &data, Buffer *output, net::RequestProgress *progress) { +int Client::POST(const RequestParams &req, const std::string &data, Buffer *output, RequestProgress *progress) { return POST(req, data, "", output, progress); } -int Client::SendRequest(const char *method, const RequestParams &req, const char *otherHeaders, net::RequestProgress *progress) { +int Client::SendRequest(const char *method, const RequestParams &req, const char *otherHeaders, RequestProgress *progress) { return SendRequestWithData(method, req, "", otherHeaders, progress); } -int Client::SendRequestWithData(const char *method, const RequestParams &req, const std::string &data, const char *otherHeaders, net::RequestProgress *progress) { - progress->Update(0, 0, false); +int Client::SendRequestWithData(const char *method, const RequestParams &req, const std::string &data, const char *otherHeaders, RequestProgress *progress) { + progress->progress = 0.01f; net::Buffer buffer; const char *tpl = @@ -353,7 +318,7 @@ int Client::SendRequestWithData(const char *method, const RequestParams &req, co "\r\n"; buffer.Printf(tpl, - method, req.resource.c_str(), HTTP_VERSION, + method, req.resource.c_str(), httpVersion_, host_.c_str(), userAgent_.c_str(), req.acceptMime, @@ -366,7 +331,7 @@ int Client::SendRequestWithData(const char *method, const RequestParams &req, co return 0; } -int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector &responseHeaders, net::RequestProgress *progress) { +int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector &responseHeaders, RequestProgress *progress) { // Snarf all the data we can into RAM. A little unsafe but hey. static constexpr float CANCEL_INTERVAL = 0.25f; bool ready = false; @@ -376,13 +341,13 @@ int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector & return -1; ready = fd_util::WaitUntilReady(sock(), CANCEL_INTERVAL, false); if (!ready && time_now_d() > endTimeout) { - ERROR_LOG(HTTP, "HTTP headers timed out"); + ERROR_LOG(IO, "HTTP headers timed out"); return -1; } }; // Let's hope all the headers are available in a single packet... if (readbuf->Read(sock(), 4096) < 0) { - ERROR_LOG(HTTP, "Failed to read HTTP headers :("); + ERROR_LOG(IO, "Failed to read HTTP headers :("); return -1; } @@ -400,28 +365,26 @@ int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector & if (code_pos != line.npos) { code = atoi(&line[code_pos]); } else { - ERROR_LOG(HTTP, "Could not parse HTTP status code: %s", line.c_str()); + ERROR_LOG(IO, "Could not parse HTTP status code: %s", line.c_str()); return -1; } while (true) { int sz = readbuf->TakeLineCRLF(&line); - if (!sz || sz < 0) + if (!sz) break; responseHeaders.push_back(line); } if (responseHeaders.size() == 0) { - ERROR_LOG(HTTP, "No HTTP response headers"); + ERROR_LOG(IO, "No HTTP response headers"); return -1; } return code; } -int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, net::RequestProgress *progress) { - _dbg_assert_(progress->cancelled); - +int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, RequestProgress *progress) { bool gzip = false; bool chunked = false; int contentLength = 0; @@ -449,18 +412,30 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vectorReadAllWithProgress(sock(), contentLength, progress)) - return -1; + if (!contentLength) { + // Content length is unknown. + // Set progress to 1% so it looks like something is happening... + progress->progress = 0.1f; + } + + if (!contentLength) { + // No way to know how far along we are. Let's just not update the progress counter. + if (!readbuf->ReadAllWithProgress(sock(), contentLength, nullptr, &progress->kBps, progress->cancelled)) + return -1; + } else { + // Let's read in chunks, updating progress between each. + if (!readbuf->ReadAllWithProgress(sock(), contentLength, &progress->progress, &progress->kBps, progress->cancelled)) + return -1; + } // output now contains the rest of the reply. Dechunk it. if (!output->IsVoid()) { if (chunked) { - DeChunk(readbuf, output, contentLength); + DeChunk(readbuf, output, contentLength, &progress->progress); } else { output->Append(*readbuf); } @@ -471,59 +446,53 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vectorTakeAll(&compressed); bool result = decompress_string(compressed, &decompressed); if (!result) { - ERROR_LOG(HTTP, "Error decompressing using zlib"); - progress->Update(0, 0, true); + ERROR_LOG(IO, "Error decompressing using zlib"); + progress->progress = 0.0f; return -1; } output->Append(decompressed); } } - progress->Update(contentLength, contentLength, true); + progress->progress = 1.0f; return 0; } -HTTPRequest::HTTPRequest(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode, const std::string &name) - : Request(method, url, name, &cancelled_, progressBarMode), postData_(postData), postMime_(postMime), outfile_(outfile) { +Download::Download(const std::string &url, const Path &outfile) + : progress_(&cancelled_), url_(url), outfile_(outfile) { } -HTTPRequest::~HTTPRequest() { - g_OSD.RemoveProgressBar(url_, Failed() ? false : true, 0.5f); - +Download::~Download() { _assert_msg_(joined_, "Download destructed without join"); } -void HTTPRequest::Start() { - thread_ = std::thread(std::bind(&HTTPRequest::Do, this)); +void Download::Start() { + thread_ = std::thread(std::bind(&Download::Do, this)); } -void HTTPRequest::Join() { +void Download::Join() { if (joined_) { - ERROR_LOG(HTTP, "Already joined thread!"); + ERROR_LOG(IO, "Already joined thread!"); } thread_.join(); joined_ = true; } -void HTTPRequest::SetFailed(int code) { +void Download::SetFailed(int code) { failed_ = true; - progress_.Update(0, 0, true); + progress_.progress = 1.0f; completed_ = true; } -int HTTPRequest::Perform(const std::string &url) { +int Download::PerformGET(const std::string &url) { Url fileUrl(url); if (!fileUrl.Valid()) { return -1; } http::Client client; - if (!userAgent_.empty()) { - client.SetUserAgent(userAgent_); - } - if (!client.Resolve(fileUrl.Host().c_str(), fileUrl.Port())) { - ERROR_LOG(HTTP, "Failed resolving %s", url.c_str()); + ERROR_LOG(IO, "Failed resolving %s", url.c_str()); return -1; } @@ -532,7 +501,7 @@ int HTTPRequest::Perform(const std::string &url) { } if (!client.Connect(2, 20.0, &cancelled_)) { - ERROR_LOG(HTTP, "Failed connecting to server or cancelled."); + ERROR_LOG(IO, "Failed connecting to server or cancelled."); return -1; } @@ -541,14 +510,10 @@ int HTTPRequest::Perform(const std::string &url) { } RequestParams req(fileUrl.Resource(), acceptMime_); - if (method_ == RequestMethod::GET) { - return client.GET(req, &buffer_, responseHeaders_, &progress_); - } else { - return client.POST(req, postData_, postMime_, &buffer_, &progress_); - } + return client.GET(req, &buffer_, responseHeaders_, &progress_); } -std::string HTTPRequest::RedirectLocation(const std::string &baseUrl) { +std::string Download::RedirectLocation(const std::string &baseUrl) { std::string redirectUrl; if (GetHeaderValue(responseHeaders_, "Location", &redirectUrl)) { Url url(baseUrl); @@ -559,15 +524,16 @@ std::string HTTPRequest::RedirectLocation(const std::string &baseUrl) { return redirectUrl; } -void HTTPRequest::Do() { - SetCurrentThreadName("HTTPDownload::Do"); +void Download::Do() { + SetCurrentThreadName("Downloader::Do"); AndroidJNIThreadContext jniContext; + resultCode_ = 0; std::string downloadURL = url_; while (resultCode_ == 0) { - int resultCode = Perform(downloadURL); + int resultCode = PerformGET(downloadURL); if (resultCode == -1) { SetFailed(resultCode); return; @@ -576,7 +542,7 @@ void HTTPRequest::Do() { if (resultCode == 301 || resultCode == 302 || resultCode == 303 || resultCode == 307 || resultCode == 308) { std::string redirectURL = RedirectLocation(downloadURL); if (redirectURL.empty()) { - ERROR_LOG(HTTP, "Could not find Location header for redirect"); + ERROR_LOG(IO, "Could not find Location header for redirect"); resultCode_ = resultCode; } else if (redirectURL == downloadURL || redirectURL == url_) { // Simple loop detected, bail out. @@ -585,25 +551,82 @@ void HTTPRequest::Do() { // Perform the next GET. if (resultCode_ == 0) - INFO_LOG(HTTP, "Download of %s redirected to %s", downloadURL.c_str(), redirectURL.c_str()); + INFO_LOG(IO, "Download of %s redirected to %s", downloadURL.c_str(), redirectURL.c_str()); downloadURL = redirectURL; continue; } if (resultCode == 200) { - INFO_LOG(HTTP, "Completed requesting %s (storing result to %s)", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str()); + INFO_LOG(IO, "Completed downloading %s to %s", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str()); if (!outfile_.empty() && !buffer_.FlushToFile(outfile_)) { - ERROR_LOG(HTTP, "Failed writing download to '%s'", outfile_.c_str()); + ERROR_LOG(IO, "Failed writing download to '%s'", outfile_.c_str()); } } else { - ERROR_LOG(HTTP, "Error requesting '%s' (storing result to '%s'): %i", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str(), resultCode); + ERROR_LOG(IO, "Error downloading '%s' to '%s': %i", url_.c_str(), outfile_.c_str(), resultCode); } resultCode_ = resultCode; } + progress_.progress = 1.0f; + // Set this last to ensure no race conditions when checking Done. Users must always check // Done before looking at the result code. completed_ = true; } +std::shared_ptr Downloader::StartDownload(const std::string &url, const Path &outfile, const char *acceptMime) { + std::shared_ptr dl(new Download(url, outfile)); + if (acceptMime) + dl->SetAccept(acceptMime); + downloads_.push_back(dl); + dl->Start(); + return dl; +} + +std::shared_ptr Downloader::StartDownloadWithCallback( + const std::string &url, + const Path &outfile, + std::function callback, + const char *acceptMime) { + std::shared_ptr dl(new Download(url, outfile)); + if (acceptMime) + dl->SetAccept(acceptMime); + dl->SetCallback(callback); + downloads_.push_back(dl); + dl->Start(); + return dl; +} + +void Downloader::Update() { + restart: + for (size_t i = 0; i < downloads_.size(); i++) { + auto &dl = downloads_[i]; + if (dl->Done()) { + dl->RunCallback(); + dl->Join(); + downloads_.erase(downloads_.begin() + i); + goto restart; + } + } +} + +std::vector Downloader::GetCurrentProgress() { + std::vector progress; + for (size_t i = 0; i < downloads_.size(); i++) { + if (!downloads_[i]->IsHidden()) + progress.push_back(downloads_[i]->Progress()); + } + return progress; +} + +void Downloader::CancelAll() { + for (size_t i = 0; i < downloads_.size(); i++) { + downloads_[i]->Cancel(); + } + for (size_t i = 0; i < downloads_.size(); i++) { + downloads_[i]->Join(); + } + downloads_.clear(); +} + } // http diff --git a/Common/Net/HTTPClient.h b/Common/Net/HTTPClient.h index 619ab8042..cafe4b08c 100644 --- a/Common/Net/HTTPClient.h +++ b/Common/Net/HTTPClient.h @@ -8,7 +8,6 @@ #include "Common/File/Path.h" #include "Common/Net/NetBuffer.h" #include "Common/Net/Resolve.h" -#include "Common/Net/HTTPRequest.h" namespace net { @@ -45,8 +44,16 @@ namespace http { bool GetHeaderValue(const std::vector &responseHeaders, const std::string &header, std::string *value); -class RequestParams { -public: +struct RequestProgress { + RequestProgress() {} + explicit RequestProgress(bool *c) : cancelled(c) {} + + float progress = 0.0f; + float kBps = 0.0f; + bool *cancelled = nullptr; +}; + +struct RequestParams { RequestParams() {} explicit RequestParams(const char *r) : resource(r) {} RequestParams(const std::string &r, const char *a) : resource(r), acceptMime(a) {} @@ -61,20 +68,20 @@ public: ~Client(); // Return value is the HTTP return code. 200 means OK. < 0 means some local error. - int GET(const RequestParams &req, Buffer *output, net::RequestProgress *progress); - int GET(const RequestParams &req, Buffer *output, std::vector &responseHeaders, net::RequestProgress *progress); + int GET(const RequestParams &req, Buffer *output, RequestProgress *progress); + int GET(const RequestParams &req, Buffer *output, std::vector &responseHeaders, RequestProgress *progress); // Return value is the HTTP return code. - int POST(const RequestParams &req, const std::string &data, const std::string &mime, Buffer *output, net::RequestProgress *progress); - int POST(const RequestParams &req, const std::string &data, Buffer *output, net::RequestProgress *progress); + int POST(const RequestParams &req, const std::string &data, const std::string &mime, Buffer *output, RequestProgress *progress); + int POST(const RequestParams &req, const std::string &data, Buffer *output, RequestProgress *progress); // HEAD, PUT, DELETE aren't implemented yet, but can be done with SendRequest. - int SendRequest(const char *method, const RequestParams &req, const char *otherHeaders, net::RequestProgress *progress); - int SendRequestWithData(const char *method, const RequestParams &req, const std::string &data, const char *otherHeaders, net::RequestProgress *progress); - int ReadResponseHeaders(net::Buffer *readbuf, std::vector &responseHeaders, net::RequestProgress *progress); + int SendRequest(const char *method, const RequestParams &req, const char *otherHeaders, RequestProgress *progress); + int SendRequestWithData(const char *method, const RequestParams &req, const std::string &data, const char *otherHeaders, RequestProgress *progress); + int ReadResponseHeaders(net::Buffer *readbuf, std::vector &responseHeaders, RequestProgress *progress); // If your response contains a response, you must read it. - int ReadResponseEntity(net::Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, net::RequestProgress *progress); + int ReadResponseEntity(net::Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, RequestProgress *progress); void SetDataTimeout(double t) { dataTimeout_ = t; @@ -86,55 +93,111 @@ public: protected: std::string userAgent_; + const char *httpVersion_; double dataTimeout_ = 900.0; }; -// Really an asynchronous request. -class HTTPRequest : public Request { +// Not particularly efficient, but hey - it's a background download, that's pretty cool :P +class Download { public: - HTTPRequest(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode = ProgressBarMode::DELAYED, const std::string &name = ""); - ~HTTPRequest(); + Download(const std::string &url, const Path &outfile); + ~Download(); - void Start() override; - void Join() override; + void Start(); - bool Done() override { return completed_; } - bool Failed() const override { return failed_; } + void Join(); + + // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). + float Progress() const { return progress_.progress; } + float SpeedKBps() const { return progress_.kBps; } + + bool Done() const { return completed_; } + bool Failed() const { return failed_; } // NOTE! The value of ResultCode is INVALID until Done() returns true. - int ResultCode() const override { return resultCode_; } + int ResultCode() const { return resultCode_; } - const Path &outfile() const override { return outfile_; } + std::string url() const { return url_; } + const Path &outfile() const { return outfile_; } + + void SetAccept(const char *mime) { + acceptMime_ = mime; + } // If not downloading to a file, access this to get the result. - Buffer &buffer() override { return buffer_; } - const Buffer &buffer() const override { return buffer_; } + Buffer &buffer() { return buffer_; } + const Buffer &buffer() const { return buffer_; } - void Cancel() override { + void Cancel() { cancelled_ = true; } - bool IsCancelled() const override { + bool IsCancelled() const { return cancelled_; } + // NOTE: Callbacks are NOT executed until RunCallback is called. This is so that + // the call will end up on the thread that calls g_DownloadManager.Update(). + void SetCallback(std::function callback) { + callback_ = callback; + } + void RunCallback() { + if (callback_) { + callback_(*this); + } + } + + // Just metadata. Convenient for download managers, for example, if set, + // Downloader::GetCurrentProgress won't return it in the results. + bool IsHidden() const { return hidden_; } + void SetHidden(bool hidden) { hidden_ = hidden; } + private: void Do(); // Actually does the download. Runs on thread. - int Perform(const std::string &url); + int PerformGET(const std::string &url); std::string RedirectLocation(const std::string &baseUrl); void SetFailed(int code); - std::string postData_; + RequestProgress progress_; Buffer buffer_; std::vector responseHeaders_; + std::string url_; Path outfile_; std::thread thread_; - std::string postMime_; + const char *acceptMime_ = "*/*"; int resultCode_ = 0; bool completed_ = false; bool failed_ = false; bool cancelled_ = false; + bool hidden_ = false; bool joined_ = false; + std::function callback_; +}; + +using std::shared_ptr; + +class Downloader { +public: + ~Downloader() { + CancelAll(); + } + + std::shared_ptr StartDownload(const std::string &url, const Path &outfile, const char *acceptMime = nullptr); + + std::shared_ptr StartDownloadWithCallback( + const std::string &url, + const Path &outfile, + std::function callback, + const char *acceptMime = nullptr); + + // Drops finished downloads from the list. + void Update(); + void CancelAll(); + + std::vector GetCurrentProgress(); + +private: + std::vector> downloads_; }; } // http diff --git a/Common/Net/HTTPHeaders.cpp b/Common/Net/HTTPHeaders.cpp index ddb706285..18450030e 100644 --- a/Common/Net/HTTPHeaders.cpp +++ b/Common/Net/HTTPHeaders.cpp @@ -26,12 +26,12 @@ bool RequestHeader::GetParamValue(const char *param_name, std::string *value) co if (!params) return false; std::string p(params); - std::vector v; + std::vector v; SplitString(p, '&', v); for (size_t i = 0; i < v.size(); i++) { - std::vector parts; + std::vector parts; SplitString(v[i], '=', parts); - DEBUG_LOG(IO, "Param: %.*s Value: %.*s", (int)parts[0].size(), parts[0].data(), (int)parts[1].size(), parts[1].data()); + DEBUG_LOG(IO, "Param: %s Value: %s", parts[0].c_str(), parts[1].c_str()); if (parts[0] == param_name) { *value = parts[1]; return true; diff --git a/Common/Net/HTTPNaettRequest.cpp b/Common/Net/HTTPNaettRequest.cpp deleted file mode 100644 index 9660ba6a3..000000000 --- a/Common/Net/HTTPNaettRequest.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef HTTPS_NOT_AVAILABLE - -#include - -#include "Common/Net/HTTPRequest.h" -#include "Common/Net/HTTPNaettRequest.h" -#include "Common/Thread/ThreadUtil.h" -#include "Common/StringUtils.h" -#include "Common/Log.h" - -#include "ext/naett/naett.h" - -namespace http { - -HTTPSRequest::HTTPSRequest(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode, const std::string &name) - : Request(method, url, name, &cancelled_, progressBarMode), method_(method), postData_(postData), postMime_(postMime), outfile_(outfile) { -} - -HTTPSRequest::~HTTPSRequest() { - Join(); -} - -void HTTPSRequest::Start() { - _dbg_assert_(!req_); - _dbg_assert_(!res_); - - std::vector options; - options.push_back(naettMethod(method_ == RequestMethod::GET ? "GET" : "POST")); - options.push_back(naettHeader("Accept", acceptMime_)); - options.push_back(naettUserAgent(userAgent_.c_str())); - if (!postMime_.empty()) { - options.push_back(naettHeader("Content-Type", postMime_.c_str())); - } - if (method_ == RequestMethod::POST) { - if (!postData_.empty()) { - // Note: Naett does not take ownership over the body. - options.push_back(naettBody(postData_.data(), (int)postData_.size())); - } - } else { - _dbg_assert_(postData_.empty()); - } - // 30 s timeout - not sure what's reasonable? - options.push_back(naettTimeout(30 * 1000)); // milliseconds - - const naettOption **opts = (const naettOption **)options.data(); - req_ = naettRequestWithOptions(url_.c_str(), (int)options.size(), opts); - res_ = naettMake(req_); - - progress_.Update(0, 0, false); -} - -void HTTPSRequest::Join() { - if (!res_ || !req_) - return; // No pending operation. - // Tear down. - if (completed_ && res_) { - _dbg_assert_(req_); - naettClose(res_); - naettFree(req_); - res_ = nullptr; - req_ = nullptr; - } else { - ERROR_LOG(IO, "HTTPSDownload::Join not implemented"); - } -} - -bool HTTPSRequest::Done() { - if (completed_) - return true; - - if (!naettComplete(res_)) { - int total = 0; - int size = naettGetTotalBytesRead(res_, &total); - progress_.Update(size, total, false); - return false; - } - - // -1000 is a code specified by us to represent cancellation, that is unlikely to ever collide with naett error codes. - resultCode_ = IsCancelled() ? -1000 : naettGetStatus(res_); - if (resultCode_ < 0) { - // It's a naett error. Translate and handle. - switch (resultCode_) { - case naettConnectionError: // -1 - ERROR_LOG(IO, "Connection error"); - break; - case naettProtocolError: // -2 - ERROR_LOG(IO, "Protocol error"); - break; - case naettReadError: // -3 - ERROR_LOG(IO, "Read error"); - break; - case naettWriteError: // -4 - ERROR_LOG(IO, "Write error"); - break; - case naettGenericError: // -5 - ERROR_LOG(IO, "Generic error"); - break; - default: - ERROR_LOG(IO, "Unhandled naett error %d", resultCode_); - break; - } - failed_ = true; - progress_.Update(0, 0, true); - } else if (resultCode_ == 200) { - int bodyLength; - const void *body = naettGetBody(res_, &bodyLength); - char *dest = buffer_.Append(bodyLength); - memcpy(dest, body, bodyLength); - if (!outfile_.empty() && !buffer_.FlushToFile(outfile_)) { - ERROR_LOG(IO, "Failed writing download to '%s'", outfile_.c_str()); - } - progress_.Update(bodyLength, bodyLength, true); - } else { - WARN_LOG(IO, "Naett request failed: %d", resultCode_); - failed_ = true; - progress_.Update(0, 0, true); - } - - completed_ = true; - - // The callback will be called later. - return true; -} - -} // namespace http - -#endif // HTTPS_NOT_AVAILABLE diff --git a/Common/Net/HTTPNaettRequest.h b/Common/Net/HTTPNaettRequest.h deleted file mode 100644 index e5ec14746..000000000 --- a/Common/Net/HTTPNaettRequest.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include - -#include "Common/Net/HTTPRequest.h" - -#ifndef HTTPS_NOT_AVAILABLE - -#include "ext/naett/naett.h" - -namespace http { - -// Really an asynchronous request. -class HTTPSRequest : public Request { -public: - HTTPSRequest(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile, ProgressBarMode progressBarMode = ProgressBarMode::DELAYED, const std::string &name = ""); - ~HTTPSRequest(); - - void Start() override; - void Join() override; - - // Also acts as a Poll. - bool Done() override; - bool Failed() const override { return failed_; } - - // NOTE! The value of ResultCode is INVALID until Done() returns true. - int ResultCode() const override { return resultCode_; } - - const Path &outfile() const override { return outfile_; } - - // If not downloading to a file, access this to get the result. - Buffer &buffer() override { return buffer_; } - const Buffer &buffer() const override { return buffer_; } - - void Cancel() override { - cancelled_ = true; - } - - bool IsCancelled() const override { - return cancelled_; - } - -private: - RequestMethod method_; - std::string postData_; - Buffer buffer_; - std::vector responseHeaders_; - Path outfile_; - std::string postMime_; - int resultCode_ = 0; - bool completed_ = false; - bool failed_ = false; - bool cancelled_ = false; - bool joined_ = false; - - // Naett state - naettReq *req_ = nullptr; - naettRes *res_ = nullptr; -}; - -} // namespace http - -#endif // HTTPS_NOT_AVAILABLE diff --git a/Common/Net/HTTPRequest.cpp b/Common/Net/HTTPRequest.cpp deleted file mode 100644 index e0009b0e3..000000000 --- a/Common/Net/HTTPRequest.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "Common/Net/HTTPRequest.h" -#include "Common/Net/HTTPClient.h" -#include "Common/Net/HTTPNaettRequest.h" -#include "Common/TimeUtil.h" -#include "Common/StringUtils.h" -#include "Common/Log.h" -#include "Common/System/OSD.h" -#include "Common/System/System.h" - -namespace http { - -Request::Request(RequestMethod method, const std::string &url, const std::string &name, bool *cancelled, ProgressBarMode mode) : method_(method), url_(url), name_(name), progress_(cancelled), progressBarMode_(mode) { - INFO_LOG(HTTP, "HTTP %s request: %s (%s)", RequestMethodToString(method), url.c_str(), name.c_str()); - - progress_.callback = [=](int64_t bytes, int64_t contentLength, bool done) { - std::string message; - if (!name_.empty()) { - message = name_; - } else { - std::size_t pos = url_.rfind('/'); - if (pos != std::string::npos) { - message = url_.substr(pos + 1); - } else { - message = url_; - } - } - if (progressBarMode_ != ProgressBarMode::NONE) { - if (!done) { - g_OSD.SetProgressBar(url_, std::move(message), 0.0f, (float)contentLength, (float)bytes, progressBarMode_ == ProgressBarMode::DELAYED ? 3.0f : 0.0f); // delay 3 seconds before showing. - } else { - g_OSD.RemoveProgressBar(url_, Failed() ? false : true, 0.5f); - } - } - }; -} - -bool RequestManager::IsHttpsUrl(const std::string &url) { - return startsWith(url, "https:"); -} - -std::shared_ptr RequestManager::StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime) { - std::shared_ptr dl; - if (IsHttpsUrl(url) && System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) { -#ifndef HTTPS_NOT_AVAILABLE - dl.reset(new HTTPSRequest(RequestMethod::GET, url, "", "", outfile, mode)); -#else - return std::shared_ptr(); -#endif - } else { - dl.reset(new HTTPRequest(RequestMethod::GET, url, "", "", outfile, mode)); - } - - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - if (acceptMime) - dl->SetAccept(acceptMime); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -std::shared_ptr RequestManager::StartDownloadWithCallback( - const std::string &url, - const Path &outfile, - ProgressBarMode mode, - std::function callback, - const std::string &name, - const char *acceptMime) { - std::shared_ptr dl; - if (IsHttpsUrl(url) && System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) { -#ifndef HTTPS_NOT_AVAILABLE - dl.reset(new HTTPSRequest(RequestMethod::GET, url, "", "", outfile, mode, name)); -#else - return std::shared_ptr(); -#endif - } else { - dl.reset(new HTTPRequest(RequestMethod::GET, url, "", "", outfile, mode, name)); - } - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - if (acceptMime) - dl->SetAccept(acceptMime); - dl->SetCallback(callback); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -std::shared_ptr RequestManager::AsyncPostWithCallback( - const std::string &url, - const std::string &postData, - const std::string &postMime, - ProgressBarMode mode, - std::function callback, - const std::string &name) { - std::shared_ptr dl; - if (IsHttpsUrl(url) && System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) { -#ifndef HTTPS_NOT_AVAILABLE - dl.reset(new HTTPSRequest(RequestMethod::POST, url, postData, postMime, Path(), mode, name)); -#else - return std::shared_ptr(); -#endif - } else { - dl.reset(new HTTPRequest(RequestMethod::POST, url, postData, postMime, Path(), mode, name)); - } - if (!userAgent_.empty()) - dl->SetUserAgent(userAgent_); - dl->SetCallback(callback); - newDownloads_.push_back(dl); - dl->Start(); - return dl; -} - -void RequestManager::Update() { - for (auto iter : newDownloads_) { - downloads_.push_back(iter); - } - newDownloads_.clear(); - -restart: - for (size_t i = 0; i < downloads_.size(); i++) { - auto dl = downloads_[i]; - if (dl->Done()) { - dl->RunCallback(); - dl->Join(); - downloads_.erase(downloads_.begin() + i); - goto restart; - } - } -} - -void RequestManager::WaitForAll() { - // TODO: Should lock? Though, OK if called from main thread, where Update() is called from. - while (!downloads_.empty()) { - Update(); - sleep_ms(10); - } -} - -void RequestManager::CancelAll() { - for (size_t i = 0; i < downloads_.size(); i++) { - downloads_[i]->Cancel(); - } - for (size_t i = 0; i < downloads_.size(); i++) { - downloads_[i]->Join(); - } - downloads_.clear(); -} - -} // namespace diff --git a/Common/Net/HTTPRequest.h b/Common/Net/HTTPRequest.h deleted file mode 100644 index 4201fc907..000000000 --- a/Common/Net/HTTPRequest.h +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "Common/File/Path.h" -#include "Common/Net/NetBuffer.h" - -namespace http { - -enum class RequestMethod { - GET, - POST, -}; - -enum class ProgressBarMode { - NONE, - VISIBLE, - DELAYED, -}; - -// Abstract request. -class Request { -public: - Request(RequestMethod method, const std::string &url, const std::string &name, bool *cancelled, ProgressBarMode mode); - virtual ~Request() {} - - void SetAccept(const char *mime) { - acceptMime_ = mime; - } - - void SetUserAgent(const std::string &userAgent) { - userAgent_ = userAgent; - } - - // NOTE: Completion callbacks (which these are) are deferred until RunCallback is called. This is so that - // the call will end up on the thread that calls g_DownloadManager.Update(). - void SetCallback(std::function callback) { - callback_ = callback; - } - void RunCallback() { - if (callback_) { - callback_(*this); - } - } - - virtual void Start() = 0; - virtual void Join() = 0; - - virtual bool Done() = 0; - virtual bool Failed() const = 0; - - virtual int ResultCode() const = 0; - - // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). - float Progress() const { return progress_.progress; } - float SpeedKBps() const { return progress_.kBps; } - std::string url() const { return url_; } - virtual const Path &outfile() const = 0; - - virtual void Cancel() = 0; - virtual bool IsCancelled() const = 0; - - // Response - virtual Buffer &buffer() = 0; - virtual const Buffer &buffer() const = 0; - -protected: - std::function callback_; - RequestMethod method_; - std::string url_; - std::string name_; - const char *acceptMime_ = "*/*"; - std::string userAgent_; - - net::RequestProgress progress_; - ProgressBarMode progressBarMode_; -}; - -using std::shared_ptr; - -class RequestManager { -public: - ~RequestManager() { - CancelAll(); - } - - std::shared_ptr StartDownload(const std::string &url, const Path &outfile, ProgressBarMode mode, const char *acceptMime = nullptr); - - std::shared_ptr StartDownloadWithCallback( - const std::string &url, - const Path &outfile, - ProgressBarMode mode, - std::function callback, - const std::string &name = "", - const char *acceptMime = nullptr); - - std::shared_ptr AsyncPostWithCallback( - const std::string &url, - const std::string &postData, - const std::string &postMime, // Use postMime = "application/x-www-form-urlencoded" for standard form-style posts, such as used by retroachievements. For encoding form data manually we have MultipartFormDataEncoder. - ProgressBarMode mode, - std::function callback, - const std::string &name = ""); - - // Drops finished downloads from the list. - void Update(); - void CancelAll(); - - void WaitForAll(); - void SetUserAgent(const std::string &userAgent) { - userAgent_ = userAgent; - } - -private: - bool IsHttpsUrl(const std::string &url); - - std::vector> downloads_; - // These get copied to downloads_ in Update(). It's so that callbacks can add new downloads - // while running. - std::vector> newDownloads_; - - std::string userAgent_; -}; - -inline const char *RequestMethodToString(RequestMethod method) { - switch (method) { - case RequestMethod::GET: return "GET"; - case RequestMethod::POST: return "POST"; - default: return "N/A"; - } -} - -} // namespace net diff --git a/Common/Net/HTTPServer.cpp b/Common/Net/HTTPServer.cpp index 3822083b7..e1fa53bc6 100644 --- a/Common/Net/HTTPServer.cpp +++ b/Common/Net/HTTPServer.cpp @@ -60,7 +60,7 @@ namespace http { // Note: charset here helps prevent XSS. const char *const DEFAULT_MIME_TYPE = "text/html; charset=utf-8"; -ServerRequest::ServerRequest(int fd) +Request::Request(int fd) : fd_(fd) { in_ = new net::InputSink(fd); out_ = new net::OutputSink(fd); @@ -73,7 +73,7 @@ ServerRequest::ServerRequest(int fd) } } -ServerRequest::~ServerRequest() { +Request::~Request() { Close(); if (!in_->Empty()) { @@ -86,7 +86,7 @@ ServerRequest::~ServerRequest() { delete out_; } -void ServerRequest::WriteHttpResponseHeader(const char *ver, int status, int64_t size, const char *mimeType, const char *otherHeaders) const { +void Request::WriteHttpResponseHeader(const char *ver, int status, int64_t size, const char *mimeType, const char *otherHeaders) const { const char *statusStr; switch (status) { case 200: statusStr = "OK"; break; @@ -123,18 +123,18 @@ void ServerRequest::WriteHttpResponseHeader(const char *ver, int status, int64_t buffer->Push("\r\n"); } -void ServerRequest::WritePartial() const { +void Request::WritePartial() const { _assert_(fd_); out_->Flush(); } -void ServerRequest::Write() { +void Request::Write() { _assert_(fd_); WritePartial(); Close(); } -void ServerRequest::Close() { +void Request::Close() { if (fd_) { closesocket(fd_); fd_ = 0; @@ -317,7 +317,7 @@ void Server::Stop() { } void Server::HandleConnection(int conn_fd) { - ServerRequest request(conn_fd); + Request request(conn_fd); if (!request.IsOK()) { WARN_LOG(IO, "Bad request, ignoring."); return; @@ -331,11 +331,11 @@ void Server::HandleConnection(int conn_fd) { request.Write(); } -void Server::HandleRequest(const ServerRequest &request) { +void Server::HandleRequest(const Request &request) { HandleRequestDefault(request); } -void Server::HandleRequestDefault(const ServerRequest &request) { +void Server::HandleRequestDefault(const Request &request) { if (request.resource() == nullptr) { fallback_(request); return; @@ -350,14 +350,14 @@ void Server::HandleRequestDefault(const ServerRequest &request) { } } -void Server::Handle404(const ServerRequest &request) { +void Server::Handle404(const Request &request) { INFO_LOG(IO, "No handler for '%s', falling back to 404.", request.resource()); const char *payload = "404 not found\r\n"; request.WriteHttpResponseHeader("1.0", 404, (int)strlen(payload)); request.Out()->Push(payload); } -void Server::HandleListing(const ServerRequest &request) { +void Server::HandleListing(const Request &request) { request.WriteHttpResponseHeader("1.0", 200, -1, "text/plain"); for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { request.Out()->Printf("%s\n", iter->first.c_str()); diff --git a/Common/Net/HTTPServer.h b/Common/Net/HTTPServer.h index c9051226a..40e336bb5 100644 --- a/Common/Net/HTTPServer.h +++ b/Common/Net/HTTPServer.h @@ -25,10 +25,10 @@ class OutputSink; namespace http { -class ServerRequest { +class Request { public: - ServerRequest(int fd); - ~ServerRequest(); + Request(int fd); + ~Request(); const char *resource() const { return header_.resource; @@ -75,7 +75,7 @@ public: Server(NewThreadExecutor *executor); virtual ~Server(); - typedef std::function UrlHandlerFunc; + typedef std::function UrlHandlerFunc; typedef std::map UrlHandlerMap; // Runs forever, serving request. If you want to do something else than serve pages, @@ -94,7 +94,7 @@ public: // If you want to customize things at a lower level than just a simple path handler, // then inherit and override this. Implementations should forward to HandleRequestDefault // if they don't recognize the url. - virtual void HandleRequest(const ServerRequest &request); + virtual void HandleRequest(const Request &request); int Port() { return port_; @@ -107,11 +107,11 @@ private: void HandleConnection(int conn_fd); // Things like default 404, etc. - void HandleRequestDefault(const ServerRequest &request); + void HandleRequestDefault(const Request &request); // Neat built-in handlers that are tied to the server. - void HandleListing(const ServerRequest &request); - void Handle404(const ServerRequest &request); + void HandleListing(const Request &request); + void Handle404(const Request &request); int listener_; int port_ = 0; diff --git a/Common/Net/NetBuffer.cpp b/Common/Net/NetBuffer.cpp index 09a485396..17a5aae91 100644 --- a/Common/Net/NetBuffer.cpp +++ b/Common/Net/NetBuffer.cpp @@ -22,18 +22,6 @@ namespace net { -void RequestProgress::Update(int64_t downloaded, int64_t totalBytes, bool done) { - if (totalBytes) { - progress = (double)downloaded / (double)totalBytes; - } else { - progress = 0.01f; - } - - if (callback) { - callback(downloaded, totalBytes, done); - } -} - bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) { static constexpr float CANCEL_INTERVAL = 0.25f; for (size_t pos = 0, end = data_.size(); pos < end; ) { @@ -60,7 +48,7 @@ bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) { return true; } -bool Buffer::ReadAllWithProgress(int fd, int knownSize, RequestProgress *progress) { +bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, float *kBps, bool *cancelled) { static constexpr float CANCEL_INTERVAL = 0.25f; std::vector buf; // We're non-blocking and reading from an OS buffer, so try to read as much as we can at a time. @@ -76,15 +64,11 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, RequestProgress *progres int total = 0; while (true) { bool ready = false; - - // If we might need to cancel, check on a timer for it to be ready. - // After this, we'll block on reading so we do this while first if we have a cancel pointer. - while (!ready && progress && progress->cancelled) { - if (*progress->cancelled) + while (!ready && cancelled) { + if (*cancelled) return false; ready = fd_util::WaitUntilReady(fd, CANCEL_INTERVAL, false); } - int retval = recv(fd, &buf[0], (int)buf.size(), MSG_NOSIGNAL); if (retval == 0) { return true; @@ -104,10 +88,10 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, RequestProgress *progres char *p = Append((size_t)retval); memcpy(p, &buf[0], retval); total += retval; - if (progress) { - progress->Update(total, knownSize, false); - progress->kBps = (float)(total / (time_now_d() - st)) / 1024.0f; - } + if (progress) + *progress = (float)total / (float)knownSize; + if (kBps) + *kBps = (float)(total / (time_now_d() - st)) / 1024.0f; } return true; } @@ -130,4 +114,4 @@ int Buffer::Read(int fd, size_t sz) { return (int)received; } -} // namespace +} diff --git a/Common/Net/NetBuffer.h b/Common/Net/NetBuffer.h index b30851d12..12a4ba37c 100644 --- a/Common/Net/NetBuffer.h +++ b/Common/Net/NetBuffer.h @@ -1,29 +1,16 @@ -#pragma once +#pragma once #include -#include #include "Common/Buffer.h" namespace net { -class RequestProgress { -public: - explicit RequestProgress(bool *c) : cancelled(c) {} - - void Update(int64_t downloaded, int64_t totalBytes, bool done); - - float progress = 0.0f; - float kBps = 0.0f; - bool *cancelled = nullptr; - std::function callback; -}; - class Buffer : public ::Buffer { public: bool FlushSocket(uintptr_t sock, double timeout, bool *cancelled = nullptr); - bool ReadAllWithProgress(int fd, int knownSize, RequestProgress *progress); + bool ReadAllWithProgress(int fd, int knownSize, float *progress, float *kBps, bool *cancelled); // < 0: error // >= 0: number of bytes read diff --git a/Common/Net/Resolve.cpp b/Common/Net/Resolve.cpp index c8fe42518..76f0055f5 100644 --- a/Common/Net/Resolve.cpp +++ b/Common/Net/Resolve.cpp @@ -29,20 +29,9 @@ #include "Common/Log.h" #include "Common/TimeUtil.h" -#include "Common/Data/Encoding/Utf8.h" - -#ifndef HTTPS_NOT_AVAILABLE -#include "ext/naett/naett.h" -#endif - -#if PPSSPP_PLATFORM(ANDROID) -#include -extern JavaVM *gJvm; -#endif namespace net { -static bool g_naettInitialized; void Init() { @@ -51,17 +40,6 @@ void Init() WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif - if (!g_naettInitialized) { -#ifndef HTTPS_NOT_AVAILABLE -#if PPSSPP_PLATFORM(ANDROID) - _assert_(gJvm != nullptr); - naettInit(gJvm); -#else - naettInit(NULL); -#endif -#endif - g_naettInitialized = true; - } } void Shutdown() @@ -110,7 +88,7 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** if (result != 0) { #ifdef _WIN32 - error = ConvertWStringToUTF8(gai_strerror(result)); + error = gai_strerrorA(result); #else error = gai_strerror(result); #endif diff --git a/Common/Net/URL.cpp b/Common/Net/URL.cpp index 0fdeab107..cc9d5fcac 100644 --- a/Common/Net/URL.cpp +++ b/Common/Net/URL.cpp @@ -115,13 +115,13 @@ const char HEX2DEC[256] = /* F */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1 }; -std::string UriDecode(std::string_view sSrc) +std::string UriDecode(const std::string & sSrc) { // Note from RFC1630: "Sequences which start with a percent sign // but are not followed by two hexadecimal characters (0-9, A-F) are reserved // for future extension" - const unsigned char * pSrc = (const unsigned char *)sSrc.data(); + const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); const size_t SRC_LEN = sSrc.length(); const unsigned char * const SRC_END = pSrc + SRC_LEN; const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%' @@ -129,10 +129,14 @@ std::string UriDecode(std::string_view sSrc) char * const pStart = new char[SRC_LEN]; // Output will be shorter. char * pEnd = pStart; - while (pSrc < SRC_LAST_DEC) { - if (*pSrc == '%') { + while (pSrc < SRC_LAST_DEC) + { + if (*pSrc == '%') + { char dec1, dec2; - if (N1 != (dec1 = HEX2DEC[*(pSrc + 1)]) && N1 != (dec2 = HEX2DEC[*(pSrc + 2)])) { + if (N1 != (dec1 = HEX2DEC[*(pSrc + 1)]) + && N1 != (dec2 = HEX2DEC[*(pSrc + 2)])) + { *pEnd++ = (dec1 << 4) + dec2; pSrc += 3; continue; @@ -152,7 +156,8 @@ std::string UriDecode(std::string_view sSrc) } // Only alphanum and underscore is safe. -static const char SAFE[256] = { +const char SAFE[256] = +{ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, @@ -175,18 +180,21 @@ static const char SAFE[256] = { /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; -std::string UriEncode(std::string_view sSrc) { +std::string UriEncode(const std::string & sSrc) +{ const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; - const unsigned char * pSrc = (const unsigned char *)sSrc.data(); + const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); const size_t SRC_LEN = sSrc.length(); unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; unsigned char * pEnd = pStart; const unsigned char * const SRC_END = pSrc + SRC_LEN; - for (; pSrc < SRC_END; ++pSrc) { - if (SAFE[*pSrc]) { + for (; pSrc < SRC_END; ++pSrc) + { + if (SAFE[*pSrc]) *pEnd++ = *pSrc; - } else { + else + { // escape this char *pEnd++ = '%'; *pEnd++ = DEC2HEX[*pSrc >> 4]; diff --git a/Common/Net/URL.h b/Common/Net/URL.h index b6288eaa6..e7f33e6d8 100644 --- a/Common/Net/URL.h +++ b/Common/Net/URL.h @@ -203,5 +203,5 @@ private: }; -std::string UriDecode(std::string_view sSrc); -std::string UriEncode(std::string_view sSrc); +std::string UriDecode(const std::string & sSrc); +std::string UriEncode(const std::string & sSrc); diff --git a/Common/Net/WebsocketServer.cpp b/Common/Net/WebsocketServer.cpp index e55c0644f..3b6f98ed2 100644 --- a/Common/Net/WebsocketServer.cpp +++ b/Common/Net/WebsocketServer.cpp @@ -69,7 +69,7 @@ static bool ListContainsNoCase(const std::string &list, const std::string value) return false; } -WebSocketServer *WebSocketServer::CreateAsUpgrade(const http::ServerRequest &request, const std::string &protocol) { +WebSocketServer *WebSocketServer::CreateAsUpgrade(const http::Request &request, const std::string &protocol) { auto requireHeader = [&](const char *name, const char *expected) { std::string val; if (!request.GetHeader(name, &val)) { diff --git a/Common/Net/WebsocketServer.h b/Common/Net/WebsocketServer.h index 591e800e9..7a05b0f03 100644 --- a/Common/Net/WebsocketServer.h +++ b/Common/Net/WebsocketServer.h @@ -29,7 +29,7 @@ enum class WebSocketClose : uint16_t { // RFC 6455 class WebSocketServer { public: - static WebSocketServer *CreateAsUpgrade(const http::ServerRequest &request, const std::string &protocol = ""); + static WebSocketServer *CreateAsUpgrade(const http::Request &request, const std::string &protocol = ""); void Send(const std::string &str); void Send(const std::vector &payload); diff --git a/Common/OSVersion.cpp b/Common/OSVersion.cpp index f50c17109..adc2f1d31 100644 --- a/Common/OSVersion.cpp +++ b/Common/OSVersion.cpp @@ -11,16 +11,6 @@ #include "OSVersion.h" #include "Common/CommonWindows.h" -struct WindowsReleaseInfo -{ - uint32_t major; - uint32_t minor; - uint32_t spMajor; - uint32_t spMinor; - uint32_t build; - bool greater = false; -}; - bool GetVersionFromKernel32(uint32_t &major, uint32_t &minor, uint32_t &build) { #if PPSSPP_PLATFORM(UWP) return false; @@ -47,7 +37,12 @@ bool GetVersionFromKernel32(uint32_t &major, uint32_t &minor, uint32_t &build) { } bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool greater) { -#if !PPSSPP_PLATFORM(UWP) +#if PPSSPP_PLATFORM(UWP) + if (greater) + return true; + else + return major >= 7; +#else if (spMajor == 0 && spMinor == 0) { // "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)." // Try to use kernel32.dll instead, for Windows 10+. Doesn't do SP versions. @@ -72,102 +67,76 @@ bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, u VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, op); VER_SET_CONDITION(conditionMask, VER_MINORVERSION, op); - uint32_t typeMask = VER_MAJORVERSION | VER_MINORVERSION; + VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, op); + VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, op); - if (spMajor > 0) { - VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, op); - typeMask |= VER_SERVICEPACKMAJOR; - } - if (spMinor > 0) { - VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, op); - typeMask |= VER_SERVICEPACKMINOR; - } + const uint32_t typeMask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR; return VerifyVersionInfo(&osvi, typeMask, conditionMask) != FALSE; - -#else - if (greater) { - return true; - } - return false; #endif } -bool DoesVersionMatchWindows(WindowsReleaseInfo release) { - if (release.spMajor == 0 && release.spMinor == 0) { - // Compare Info - uint32_t major = release.major; - uint32_t minor = release.minor; - uint32_t build = release.build; - bool greater = release.greater; - - OSVERSIONINFOEX osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - GetVersionEx((LPOSVERSIONINFO)&osvi); - - // OS Info - uint32_t osMajor = osvi.dwMajorVersion; - uint32_t osMinor = osvi.dwMinorVersion; - uint32_t osBuild = osvi.dwBuildNumber; - -#if !PPSSPP_PLATFORM(UWP) - // "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)." - // Try to use kernel32.dll instead, for Windows 10+. - GetVersionFromKernel32(osMajor, osMinor, osBuild); -#endif - - if (major == osMajor) { - // To detect Windows 11 we must check build number - if (osMinor >= minor && osBuild >= build) { - return true; - } - } - } - else { - return DoesVersionMatchWindows(release.major, release.minor, release.spMajor, release.spMinor, release.greater); - } - - return false; -} - bool IsVistaOrHigher() { - // Vista is 6.0 - return DoesVersionMatchWindows(6, 0, 0, 0, true); +#if PPSSPP_PLATFORM(UWP) + return true; +#else + OSVERSIONINFOEX osvi; + DWORDLONG dwlConditionMask = 0; + int op = VER_GREATER_EQUAL; + ZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = 6; // Vista is 6.0 + osvi.dwMinorVersion = 0; + + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op); + + return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask) != FALSE; +#endif } bool IsWin7OrHigher() { - // Win7 is 6.1 - return DoesVersionMatchWindows(6, 1, 0, 0, true); +#if PPSSPP_PLATFORM(UWP) + return true; +#else + OSVERSIONINFOEX osvi; + DWORDLONG dwlConditionMask = 0; + int op = VER_GREATER_EQUAL; + ZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = 6; // Win7 is 6.1 + osvi.dwMinorVersion = 1; + + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op); + + return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask) != FALSE; +#endif } std::string GetWindowsVersion() { - std::vector> windowsReleases = { - /* { "Preview text", { major, minor, spMajor, spMinor, build, greater } }, */ - { "Microsoft Windows XP, Service Pack 2", { 5, 1, 2, 0 } }, - { "Microsoft Windows XP, Service Pack 3", { 5, 1, 3, 0 } }, - { "Microsoft Windows Vista", { 6, 0, 0, 0 } }, - { "Microsoft Windows Vista, Service Pack 1", { 6, 0, 1, 0 } }, - { "Microsoft Windows Vista, Service Pack 2", { 6, 0, 2, 0 } }, - { "Microsoft Windows 7", { 6, 1, 0, 0 } }, - { "Microsoft Windows 7, Service Pack 1", { 6, 1, 1, 0 } }, - { "Microsoft Windows 8", { 6, 2, 0, 0 } }, - { "Microsoft Windows 8.1", { 6, 3, 0, 0 } }, - { "Microsoft Windows 10", { 10, 0, 0, 0 } }, - { "Microsoft Windows 11", { 10, 0, 0, 0, 22000 } }, - }; + const bool IsWindowsXPSP2 = DoesVersionMatchWindows(5, 1, 2, 0, false); + const bool IsWindowsXPSP3 = DoesVersionMatchWindows(5, 1, 3, 0, false); + const bool IsWindowsVista = DoesVersionMatchWindows(6, 0, 0, 0, false); + const bool IsWindowsVistaSP1 = DoesVersionMatchWindows(6, 0, 1, 0, false); + const bool IsWindowsVistaSP2 = DoesVersionMatchWindows(6, 0, 2, 0, false); + const bool IsWindows7 = DoesVersionMatchWindows(6, 1, 0, 0, false); + const bool IsWindows7SP1 = DoesVersionMatchWindows(6, 1, 1, 0, false); + const bool IsWindows8 = DoesVersionMatchWindows(6, 2, 0, 0, false); + const bool IsWindows8_1 = DoesVersionMatchWindows(6, 3, 0, 0, false); + const bool IsWindows10 = DoesVersionMatchWindows(10, 0, 0, 0, false); - // Start from higher to lower - for (auto release = rbegin(windowsReleases); release != rend(windowsReleases); ++release) { - std::string previewText = release->first; - WindowsReleaseInfo releaseInfo = release->second; - bool buildMatch = DoesVersionMatchWindows(releaseInfo); - if (buildMatch) { - return previewText; - } - } - - return "Unknown version of Microsoft Windows."; + if (IsWindowsXPSP2) return "Microsoft Windows XP, Service Pack 2"; + if (IsWindowsXPSP3) return "Microsoft Windows XP, Service Pack 3"; + if (IsWindowsVista) return "Microsoft Windows Vista"; + if (IsWindowsVistaSP1) return "Microsoft Windows Vista, Service Pack 1"; + if (IsWindowsVistaSP2) return "Microsoft Windows Vista, Service Pack 2"; + if (IsWindows7) return "Microsoft Windows 7"; + if (IsWindows7SP1) return "Microsoft Windows 7, Service Pack 1"; + if (IsWindows8) return "Microsoft Windows 8"; + if (IsWindows8_1) return "Microsoft Windows 8.1"; + if (IsWindows10) return "Microsoft Windows 10"; + return "Unsupported version of Microsoft Windows."; } std::string GetWindowsSystemArchitecture() { diff --git a/Common/Render/DrawBuffer.cpp b/Common/Render/DrawBuffer.cpp index 8e2973239..73c0f30a6 100644 --- a/Common/Render/DrawBuffer.cpp +++ b/Common/Render/DrawBuffer.cpp @@ -39,11 +39,13 @@ void DrawBuffer::Init(Draw::DrawContext *t3d, Draw::Pipeline *pipeline) { Draw::InputLayout *DrawBuffer::CreateInputLayout(Draw::DrawContext *t3d) { using namespace Draw; InputLayoutDesc desc = { - sizeof(Vertex), { - { SEM_POSITION, DataFormat::R32G32B32_FLOAT, 0 }, - { SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 12 }, - { SEM_COLOR0, DataFormat::R8G8B8A8_UNORM, 20 }, + { sizeof(Vertex), false }, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32B32_FLOAT, 0 }, + { 0, SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 12 }, + { 0, SEM_COLOR0, DataFormat::R8G8B8A8_UNORM, 20 }, }, }; @@ -104,7 +106,7 @@ void DrawBuffer::V(float x, float y, float z, uint32_t color, float u, float v) void DrawBuffer::Rect(float x, float y, float w, float h, uint32_t color, int align) { DoAlign(align, &x, &y, &w, &h); - RectVGradient(x, y, x + w, y + h, color, color); + RectVGradient(x, y, w, h, color, color); } void DrawBuffer::hLine(float x1, float y, float x2, uint32_t color) { @@ -119,13 +121,13 @@ void DrawBuffer::vLine(float x, float y1, float y2, uint32_t color) { Rect(x, y1, g_display.pixel_in_dps_x, y2 - y1, color); } -void DrawBuffer::RectVGradient(float x1, float y1, float x2, float y2, uint32_t colorTop, uint32_t colorBottom) { - V(x1, y1, 0, colorTop, 0, 0); - V(x2, y1, 0, colorTop, 1, 0); - V(x2, y2, 0, colorBottom, 1, 1); - V(x1, y1, 0, colorTop, 0, 0); - V(x2, y2, 0, colorBottom, 1, 1); - V(x1, y2, 0, colorBottom, 0, 1); +void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32_t colorTop, uint32_t colorBottom) { + V(x, y, 0, colorTop, 0, 0); + V(x + w, y, 0, colorTop, 1, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y, 0, colorTop, 0, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y + h, 0, colorBottom, 0, 1); } void DrawBuffer::RectOutline(float x, float y, float w, float h, uint32_t color, int align) { @@ -140,7 +142,7 @@ void DrawBuffer::MultiVGradient(float x, float y, float w, float h, const Gradie for (int i = 0; i < numStops - 1; i++) { float t0 = stops[i].t, t1 = stops[i+1].t; uint32_t c0 = stops[i].color, c1 = stops[i+1].color; - RectVGradient(x, y + h * t0, x + w, y + h * (t1 - t0), c0, c1); + RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1); } } diff --git a/Common/Render/DrawBuffer.h b/Common/Render/DrawBuffer.h index f16ab1e62..8c6262c7c 100644 --- a/Common/Render/DrawBuffer.h +++ b/Common/Render/DrawBuffer.h @@ -83,10 +83,9 @@ public: void RectOutline(float x, float y, float w, float h, uint32_t color, int align = ALIGN_TOPLEFT); - // NOTE: This one takes x2/y2 instead of w/h, better for gap-free graphics. - void RectVGradient(float x1, float y1, float x2, float y2, uint32_t colorTop, uint32_t colorBottom); + void RectVGradient(float x, float y, float w, float h, uint32_t colorTop, uint32_t colorBottom); void RectVDarkFaded(float x, float y, float w, float h, uint32_t colorTop) { - RectVGradient(x, y, x + w, y + h, colorTop, darkenColor(colorTop)); + RectVGradient(x, y, w, h, colorTop, darkenColor(colorTop)); } void MultiVGradient(float x, float y, float w, float h, const GradientStop *stops, int numStops); diff --git a/Common/Render/ManagedTexture.cpp b/Common/Render/ManagedTexture.cpp index c926ea9dd..dce43253c 100644 --- a/Common/Render/ManagedTexture.cpp +++ b/Common/Render/ManagedTexture.cpp @@ -186,15 +186,8 @@ void ManagedTexture::DeviceLost() { void ManagedTexture::DeviceRestored(Draw::DrawContext *draw) { INFO_LOG(G3D, "ManagedTexture::DeviceRestored(%s)", filename_.c_str()); - + _assert_(!texture_); draw_ = draw; - - _dbg_assert_(!texture_); - if (texture_) { - ERROR_LOG(G3D, "ManagedTexture: Unexpected - texture already present: %s", filename_.c_str()); - return; - } - // Vulkan: Can't load textures before the first frame has started. // Should probably try to lift that restriction again someday.. loadPending_ = true; diff --git a/Common/Render/Text/draw_text.cpp b/Common/Render/Text/draw_text.cpp index cb09dbda9..4d4b58e7f 100644 --- a/Common/Render/Text/draw_text.cpp +++ b/Common/Render/Text/draw_text.cpp @@ -11,7 +11,6 @@ #include "Common/Render/Text/draw_text_uwp.h" #include "Common/Render/Text/draw_text_qt.h" #include "Common/Render/Text/draw_text_android.h" -#include "Common/Render/Text/draw_text_sdl.h" TextDrawer::TextDrawer(Draw::DrawContext *draw) : draw_(draw) { // These probably shouldn't be state. @@ -93,8 +92,6 @@ TextDrawer *TextDrawer::Create(Draw::DrawContext *draw) { drawer = new TextDrawerQt(draw); #elif PPSSPP_PLATFORM(ANDROID) drawer = new TextDrawerAndroid(draw); -#elif USE_SDL2_TTF - drawer = new TextDrawerSDL(draw); #endif if (drawer && !drawer->IsReady()) { delete drawer; diff --git a/Common/Render/Text/draw_text_android.cpp b/Common/Render/Text/draw_text_android.cpp index d98987cce..cab0bdca7 100644 --- a/Common/Render/Text/draw_text_android.cpp +++ b/Common/Render/Text/draw_text_android.cpp @@ -1,5 +1,4 @@ #include "ppsspp_config.h" - #include "Common/Log.h" #include "Common/StringUtils.h" #include "Common/System/Display.h" @@ -29,10 +28,8 @@ TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) } dpiScale_ = CalculateDPIScale(); - // Pick between the two supported formats, of which at least one is supported on each platform. Prefer R8 (but only if swizzle is supported) use4444Format_ = (draw->GetDataFormatSupport(Draw::DataFormat::R4G4B4A4_UNORM_PACK16) & Draw::FMT_TEXTURE) != 0; - if ((draw->GetDataFormatSupport(Draw::DataFormat::R8_UNORM) & Draw::FMT_TEXTURE) != 0 && draw->GetDeviceCaps().textureSwizzleSupported) - use4444Format_ = false; + INFO_LOG(G3D, "Initializing TextDrawerAndroid with DPI scale %f, use4444=%d", dpiScale_, (int)use4444Format_); } @@ -208,30 +205,20 @@ void TextDrawerAndroid::DrawStringBitmap(std::vector &bitmapData, TextS if (texFormat == Draw::DataFormat::B4G4R4A4_UNORM_PACK16 || texFormat == Draw::DataFormat::R4G4B4A4_UNORM_PACK16) { bitmapData.resize(entry.bmWidth * entry.bmHeight * sizeof(uint16_t)); uint16_t *bitmapData16 = (uint16_t *)&bitmapData[0]; - for (int y = 0; y < entry.bmHeight; y++) { - for (int x = 0; x < entry.bmWidth; x++) { + for (int x = 0; x < entry.bmWidth; x++) { + for (int y = 0; y < entry.bmHeight; y++) { uint32_t v = jimage[imageWidth * y + x]; - v = 0xFFF0 | ((v >> 28) & 0xF); // Grab the upper bits from the alpha channel, and put directly in the 16-bit alpha channel. + v = 0xFFF0 | ((v >> 12) & 0xF); // Just grab some bits from the green channel. bitmapData16[entry.bmWidth * y + x] = (uint16_t)v; } } } else if (texFormat == Draw::DataFormat::R8_UNORM) { bitmapData.resize(entry.bmWidth * entry.bmHeight); - for (int y = 0; y < entry.bmHeight; y++) { - for (int x = 0; x < entry.bmWidth; x++) { + for (int x = 0; x < entry.bmWidth; x++) { + for (int y = 0; y < entry.bmHeight; y++) { uint32_t v = jimage[imageWidth * y + x]; - bitmapData[entry.bmWidth * y + x] = (uint8_t)(v >> 24); - } - } - } else if (texFormat == Draw::DataFormat::R8G8B8A8_UNORM) { - bitmapData.resize(entry.bmWidth * entry.bmHeight * sizeof(uint32_t)); - uint32_t *bitmapData32 = (uint32_t *)&bitmapData[0]; - for (int y = 0; y < entry.bmHeight; y++) { - for (int x = 0; x < entry.bmWidth; x++) { - uint32_t v = jimage[imageWidth * y + x]; - // Swap R and B, for some reason. - v = (v & 0xFF00FF00) | ((v >> 16) & 0xFF) | ((v << 16) & 0xFF0000); - bitmapData32[entry.bmWidth * y + x] = v; + v = (v >> 12) & 0xF; // Just grab some bits from the green channel. + bitmapData[entry.bmWidth * y + x] = (uint8_t)(v | (v << 4)); } } } else { @@ -260,11 +247,8 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, entry = iter->second.get(); entry->lastUsedFrame = frameCount_; } else { + // Actually, I don't know why we don't always use R8_UNORM.. DataFormat texFormat = use4444Format_ ? Draw::DataFormat::R4G4B4A4_UNORM_PACK16 : Draw::DataFormat::R8_UNORM; - bool emoji = AnyEmojiInString(text.c_str(), text.size()); - if (emoji) { - texFormat = Draw::DataFormat::R8G8B8A8_UNORM; - } entry = new TextStringEntry(); @@ -280,7 +264,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, desc.depth = 1; desc.mipLevels = 1; desc.generateMips = false; - desc.swizzle = texFormat == Draw::DataFormat::R8_UNORM ? Draw::TextureSwizzle::R8_AS_ALPHA : Draw::TextureSwizzle::DEFAULT, + desc.swizzle = use4444Format_ ? Draw::TextureSwizzle::DEFAULT : Draw::TextureSwizzle::R8_AS_ALPHA, desc.tag = "TextDrawer"; entry->texture = draw_->CreateTexture(desc); cache_[key] = std::unique_ptr(entry); diff --git a/Common/Render/Text/draw_text_sdl.cpp b/Common/Render/Text/draw_text_sdl.cpp deleted file mode 100644 index 494858355..000000000 --- a/Common/Render/Text/draw_text_sdl.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include "ppsspp_config.h" - -#include "Common/Log.h" -#include "Common/StringUtils.h" -#include "Common/System/Display.h" -#include "Common/GPU/thin3d.h" -#include "Common/Data/Hash/Hash.h" -#include "Common/Data/Text/WrapText.h" -#include "Common/Data/Encoding/Utf8.h" -#include "Common/File/VFS/VFS.h" -#include "Common/File/FileUtil.h" -#include "Common/File/Path.h" -#include "Common/Render/Text/draw_text.h" -#include "Common/Render/Text/draw_text_sdl.h" - -#if defined(USE_SDL2_TTF) - -#include "SDL2/SDL.h" -#include "SDL2/SDL_ttf.h" - -TextDrawerSDL::TextDrawerSDL(Draw::DrawContext *draw): TextDrawer(draw) { - if (TTF_Init() < 0) { - ERROR_LOG(G3D, "Unable to initialize SDL2_ttf"); - } - - dpiScale_ = CalculateDPIScale(); - -#if defined(USE_SDL2_TTF_FONTCONFIG) - config = FcInitLoadConfigAndFonts(); -#endif - - PrepareFallbackFonts(); -} - -TextDrawerSDL::~TextDrawerSDL() { - ClearCache(); - TTF_Quit(); - -#if defined(USE_SDL2_TTF_FONTCONFIG) - FcConfigDestroy(config); - // Don't call this - it crashes, see https://github.com/openframeworks/openFrameworks/issues/5061. - //FcFini(); -#endif -} - -// If a user complains about missing characters on SDL, re-visit this! -void TextDrawerSDL::PrepareFallbackFonts() { -#if defined(USE_SDL2_TTF_FONTCONFIG) - FcObjectSet *os = FcObjectSetBuild (FC_FILE, FC_INDEX, (char *) 0); - - FcPattern *names[] = { - FcNameParse((const FcChar8 *) "Source Han Sans Medium"), - FcNameParse((const FcChar8 *) "Droid Sans Bold"), - FcNameParse((const FcChar8 *) "DejaVu Sans Condensed"), - FcNameParse((const FcChar8 *) "Noto Sans CJK Medium"), - FcNameParse((const FcChar8 *) "Noto Sans Hebrew Medium"), - FcNameParse((const FcChar8 *) "Noto Sans Lao Medium"), - FcNameParse((const FcChar8 *) "Noto Sans Thai Medium") - }; - - for (int i = 0; i < ARRAY_SIZE(names); i++) { - FcFontSet *foundFonts = FcFontList(config, names[i], os); - - for (int j = 0; foundFonts && j < foundFonts->nfont; ++j) { - FcPattern* font = foundFonts->fonts[j]; - FcChar8 *path; - int fontIndex; - - if (FcPatternGetInteger(font, FC_INDEX, 0, &fontIndex) != FcResultMatch) { - fontIndex = 0; // The 0th face is guaranteed to exist - } - - if (FcPatternGetString(font, FC_FILE, 0, &path) == FcResultMatch) { - std::string path_str((const char*)path); - fallbackFontPaths_.push_back(std::make_pair(path_str, fontIndex)); - } - } - - if (foundFonts) { - FcFontSetDestroy(foundFonts); - } - - FcPatternDestroy(names[i]); - } - - if (os) { - FcObjectSetDestroy(os); - } -#elif PPSSPP_PLATFORM(MAC) - const char *fontDirs[] = { - "/System/Library/Fonts/", - "/System/Library/Fonts/Supplemental/", - "/Library/Fonts/" - }; - - const char *fallbackFonts[] = { - "Hiragino Sans GB.ttc", - "PingFang.ttc", - "PingFang SC.ttc", - "PingFang TC.ttc", - "ヒラギノ角ゴシック W4.ttc", - "AppleGothic.ttf", - "Arial Unicode.ttf", - }; - - for (int i = 0; i < ARRAY_SIZE(fontDirs); i++) { - for (int j = 0; j < ARRAY_SIZE(fallbackFonts); j++) { - Path fontPath = Path(fontDirs[i]) / fallbackFonts[j]; - - if (File::Exists(fontPath)) { - TTF_Font *openedFont = TTF_OpenFont(fontPath.ToString().c_str(), 24); - int64_t numFaces = TTF_FontFaces(openedFont); - - for (int k = 0; k < numFaces; k++) { - TTF_Font *fontFace = TTF_OpenFontIndex(fontPath.ToString().c_str(), 24, k); - std::string fontFaceName(TTF_FontFaceStyleName(fontFace)); - TTF_CloseFont(fontFace); - - if (strstr(fontFaceName.c_str(), "Medium") || - strstr(fontFaceName.c_str(), "Regular")) - { - fallbackFontPaths_.push_back(std::make_pair(fontPath.ToString(), k)); - break; - } - } - - TTF_CloseFont(openedFont); - } - } - } -#else - // We don't have a fallback font for this platform. - // Unsupported characters will be rendered as squares. -#endif -} - -uint32_t TextDrawerSDL::CheckMissingGlyph(const std::string& text) { - TTF_Font *font = fontMap_.find(fontHash_)->second; - UTF8 utf8Decoded(text.c_str()); - - uint32_t missingGlyph = 0; - for (int i = 0; i < text.length(); ) { - uint32_t glyph = utf8Decoded.next(); - i = utf8Decoded.byteIndex(); - - if (!TTF_GlyphIsProvided32(font, glyph)) { - missingGlyph = glyph; - break; - } - } - - return missingGlyph; -} - -// If this returns true, the first font in fallbackFonts_ can be used as a fallback. -bool TextDrawerSDL::FindFallbackFonts(uint32_t missingGlyph, int ptSize) { - // If we encounter a missing glyph, try to use one of the fallback fonts. - for (int i = 0; i < fallbackFonts_.size(); i++) { - TTF_Font *fallbackFont = fallbackFonts_[i]; - if (TTF_GlyphIsProvided32(fallbackFont, missingGlyph)) { - fallbackFonts_.erase(fallbackFonts_.begin() + i); - fallbackFonts_.insert(fallbackFonts_.begin(), fallbackFont); - return true; - } - } - - // If none of the loaded fonts can handle it, load more fonts. - for (int i = 0; i < fallbackFontPaths_.size(); i++) { - std::string& fontPath = fallbackFontPaths_[i].first; - int faceIndex = fallbackFontPaths_[i].second; - - TTF_Font *font = TTF_OpenFontIndex(fontPath.c_str(), ptSize, faceIndex); - - if (TTF_GlyphIsProvided32(font, missingGlyph)) { - fallbackFonts_.insert(fallbackFonts_.begin(), font); - return true; - } else { - TTF_CloseFont(font); - } - } - - return false; -} - -uint32_t TextDrawerSDL::SetFont(const char *fontName, int size, int flags) { - uint32_t fontHash = fontName && strlen(fontName) ? hash::Adler32((const uint8_t *)fontName, strlen(fontName)) : 0; - fontHash ^= size; - fontHash ^= flags << 10; - - auto iter = fontMap_.find(fontHash); - if (iter != fontMap_.end()) { - fontHash_ = fontHash; - return fontHash; - } - - const char *useFont = fontName ? fontName : "Roboto-Condensed.ttf"; - const int ptSize = (int)((size + 6) / dpiScale_); - - TTF_Font *font = TTF_OpenFont(useFont, ptSize); - - if (!font) { - File::FileInfo fileInfo; - g_VFS.GetFileInfo("Roboto-Condensed.ttf", &fileInfo); - font = TTF_OpenFont(fileInfo.fullName.c_str(), ptSize); - } - - fontMap_[fontHash] = font; - fontHash_ = fontHash; - return fontHash; -} - -void TextDrawerSDL::SetFont(uint32_t fontHandle) { - uint32_t fontHash = fontHandle; - auto iter = fontMap_.find(fontHash); - if (iter != fontMap_.end()) { - fontHash_ = fontHandle; - } else { - ERROR_LOG(G3D, "Invalid font handle %08x", fontHandle); - } -} - -void TextDrawerSDL::MeasureString(const char *str, size_t len, float *w, float *h) { - CacheKey key{ std::string(str, len), fontHash_ }; - - TextMeasureEntry *entry; - auto iter = sizeCache_.find(key); - if (iter != sizeCache_.end()) { - entry = iter->second.get(); - } else { - TTF_Font *font = fontMap_.find(fontHash_)->second; - int ptSize = TTF_FontHeight(font) / 1.35; - - uint32_t missingGlyph = CheckMissingGlyph(key.text); - - if (missingGlyph && FindFallbackFonts(missingGlyph, ptSize)) { - font = fallbackFonts_[0]; - } - - int width = 0; - int height = 0; - TTF_SizeUTF8(font, key.text.c_str(), &width, &height); - - entry = new TextMeasureEntry(); - entry->width = width; - entry->height = height; - sizeCache_[key] = std::unique_ptr(entry); - } - - entry->lastUsedFrame = frameCount_; - *w = entry->width * fontScaleX_ * dpiScale_; - *h = entry->height * fontScaleY_ * dpiScale_; -} - -void TextDrawerSDL::MeasureStringRect(const char *str, size_t len, const Bounds &bounds, float *w, float *h, int align) { - std::string toMeasure = std::string(str, len); - int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT); - if (wrap) { - bool rotated = (align & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) != 0; - WrapString(toMeasure, toMeasure.c_str(), rotated ? bounds.h : bounds.w, wrap); - } - - TTF_Font *font = fontMap_.find(fontHash_)->second; - int ptSize = TTF_FontHeight(font) / 1.35; - uint32_t missingGlyph = CheckMissingGlyph(toMeasure); - - if (missingGlyph && FindFallbackFonts(missingGlyph, ptSize)) { - font = fallbackFonts_[0]; - } - - std::vector lines; - SplitString(toMeasure, '\n', lines); - - int total_w = 0; - int total_h = 0; - for (size_t i = 0; i < lines.size(); i++) { - CacheKey key{ lines[i], fontHash_ }; - - TextMeasureEntry *entry; - auto iter = sizeCache_.find(key); - if (iter != sizeCache_.end()) { - entry = iter->second.get(); - } else { - int width = 0; - int height = 0; - TTF_SizeUTF8(font, lines[i].c_str(), &width, &height); - entry = new TextMeasureEntry(); - entry->width = width; - entry->height = height; - sizeCache_[key] = std::unique_ptr(entry); - } - - entry->lastUsedFrame = frameCount_; - if (total_w < entry->width) { - total_w = entry->width; - } - total_h += TTF_FontLineSkip(font); - } - - *w = total_w * fontScaleX_ * dpiScale_; - *h = total_h * fontScaleY_ * dpiScale_; -} - -void TextDrawerSDL::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { - using namespace Draw; - if (!strlen(str)) - return; - - CacheKey key{ std::string(str), fontHash_ }; - target.Flush(true); - - TextStringEntry *entry; - - auto iter = cache_.find(key); - if (iter != cache_.end()) { - entry = iter->second.get(); - entry->lastUsedFrame = frameCount_; - } else { - DataFormat texFormat = Draw::DataFormat::R4G4B4A4_UNORM_PACK16; - if ((draw_->GetDataFormatSupport(texFormat) & Draw::FMT_TEXTURE) == 0) { - // This is always supported in Vulkan. The other format is the common OpenGL one. - texFormat = Draw::DataFormat::B4G4R4A4_UNORM_PACK16; - } - - entry = new TextStringEntry(); - - TextureDesc desc{}; - std::vector bitmapData; - DrawStringBitmap(bitmapData, *entry, texFormat, str, align); - desc.initData.push_back(&bitmapData[0]); - - desc.type = TextureType::LINEAR2D; - desc.format = texFormat; - desc.width = entry->bmWidth; - desc.height = entry->bmHeight; - desc.depth = 1; - desc.mipLevels = 1; - desc.tag = "TextDrawer"; - entry->texture = draw_->CreateTexture(desc); - cache_[key] = std::unique_ptr(entry); - } - - if (entry->texture) { - draw_->BindTexture(0, entry->texture); - } - - float w = entry->bmWidth * fontScaleX_ * dpiScale_; - float h = entry->bmHeight * fontScaleY_ * dpiScale_; - DrawBuffer::DoAlign(align, &x, &y, &w, &h); - if (entry->texture) { - target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color); - target.Flush(true); - } -} - -void TextDrawerSDL::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, const char *str, int align) { - if (!strlen(str)) { - bitmapData.clear(); - return; - } - - // Replace "&&" with "&" - std::string processedStr = ReplaceAll(str, "&&", "&"); - - // If a string includes only newlines, SDL2_ttf will refuse to render it - // thinking it is empty. Add a space to avoid that. - bool isAllNewline = processedStr.find_first_not_of('\n') == std::string::npos; - - if (isAllNewline) { - processedStr.push_back(' '); - } - - TTF_Font *font = fontMap_.find(fontHash_)->second; - int ptSize = TTF_FontHeight(font) / 1.35; - - uint32_t missingGlyph = CheckMissingGlyph(processedStr); - - if (missingGlyph && FindFallbackFonts(missingGlyph, ptSize)) { - font = fallbackFonts_[0]; - } - -#if SDL_TTF_VERSION_ATLEAST(2, 20, 0) - if (align & ALIGN_HCENTER) - TTF_SetFontWrappedAlign(font, TTF_WRAPPED_ALIGN_CENTER); - else if (align & ALIGN_RIGHT) - TTF_SetFontWrappedAlign(font, TTF_WRAPPED_ALIGN_RIGHT); - else - TTF_SetFontWrappedAlign(font, TTF_WRAPPED_ALIGN_LEFT); -#endif - - SDL_Color fgColor = { 0xFF, 0xFF, 0xFF, 0xFF }; - SDL_Surface *text = TTF_RenderUTF8_Blended_Wrapped(font, processedStr.c_str(), fgColor, 0); - SDL_LockSurface(text); - - entry.texture = nullptr; - // Each row of pixel needs to be aligned to 8 bytes (= 2 pixels), or else - // graphics corruption occurs. Made it 16-byte aligned just to be sure. - entry.bmWidth = entry.width = (text->w + 3) & ~3; - entry.bmHeight = entry.height = text->h; - entry.lastUsedFrame = frameCount_; - - uint32_t *imageData = (uint32_t *)text->pixels; - uint32_t pitch = text->pitch / sizeof(uint32_t); - - if (texFormat == Draw::DataFormat::B4G4R4A4_UNORM_PACK16 || texFormat == Draw::DataFormat::R4G4B4A4_UNORM_PACK16) { - bitmapData.resize(entry.bmWidth * entry.bmHeight * sizeof(uint16_t)); - uint16_t *bitmapData16 = (uint16_t *)&bitmapData[0]; - - for (int x = 0; x < entry.bmWidth; x++) { - for (int y = 0; y < entry.bmHeight; y++) { - uint64_t index = entry.bmWidth * y + x; - bitmapData16[index] = 0xfff0 | (imageData[pitch * y + x] >> 28); - } - } - } else if (texFormat == Draw::DataFormat::R8_UNORM) { - bitmapData.resize(entry.bmWidth * entry.bmHeight); - for (int x = 0; x < entry.bmWidth; x++) { - for (int y = 0; y < entry.bmHeight; y++) { - uint64_t index = entry.bmWidth * y + x; - bitmapData[index] = imageData[pitch * y + x] >> 24; - } - } - } else { - _assert_msg_(false, "Bad TextDrawer format"); - } - - SDL_UnlockSurface(text); - SDL_FreeSurface(text); -} - -void TextDrawerSDL::OncePerFrame() { - // Reset everything if DPI changes - float newDpiScale = CalculateDPIScale(); - if (newDpiScale != dpiScale_) { - dpiScale_ = newDpiScale; - ClearCache(); - } - - // Drop old strings. Use a prime number to reduce clashing with other rhythms - if (frameCount_ % 23 == 0) { - for (auto iter = cache_.begin(); iter != cache_.end();) { - if (frameCount_ - iter->second->lastUsedFrame > 100) { - if (iter->second->texture) - iter->second->texture->Release(); - cache_.erase(iter++); - } else { - iter++; - } - } - - for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) { - if (frameCount_ - iter->second->lastUsedFrame > 100) { - sizeCache_.erase(iter++); - } else { - iter++; - } - } - } -} - -void TextDrawerSDL::ClearCache() { - for (auto &iter : cache_) { - if (iter.second->texture) - iter.second->texture->Release(); - } - cache_.clear(); - sizeCache_.clear(); - - for (auto iter : fontMap_) { - TTF_CloseFont(iter.second); - } - for (auto iter : fallbackFonts_) { - TTF_CloseFont(iter); - } - fontMap_.clear(); - fallbackFonts_.clear(); - fontHash_ = 0; -} - -#endif diff --git a/Common/Render/Text/draw_text_sdl.h b/Common/Render/Text/draw_text_sdl.h deleted file mode 100644 index 87c543a66..000000000 --- a/Common/Render/Text/draw_text_sdl.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "ppsspp_config.h" - -#include -#include "Common/Render/Text/draw_text.h" - -#if defined(USE_SDL2_TTF_FONTCONFIG) -#include -#endif - -// SDL2_ttf's TTF_Font is a typedef of _TTF_Font. -struct _TTF_Font; - -class TextDrawerSDL : public TextDrawer { -public: - TextDrawerSDL(Draw::DrawContext *draw); - ~TextDrawerSDL(); - - uint32_t SetFont(const char *fontName, int size, int flags) override; - void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once. - void MeasureString(const char *str, size_t len, float *w, float *h) override; - void MeasureStringRect(const char *str, size_t len, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override; - void DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override; - void DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, const char *str, int align = ALIGN_TOPLEFT) override; - // Use for housekeeping like throwing out old strings. - void OncePerFrame() override; - -protected: - void ClearCache() override; - void PrepareFallbackFonts(); - uint32_t CheckMissingGlyph(const std::string& text); - bool FindFallbackFonts(uint32_t missingGlyph, int ptSize); - - uint32_t fontHash_; - std::map fontMap_; - - std::map> cache_; - std::map> sizeCache_; - - std::vector<_TTF_Font *> fallbackFonts_; - std::vector> fallbackFontPaths_; // path and font face index - -#if defined(USE_SDL2_TTF_FONTCONFIG) - FcConfig *config; -#endif -}; diff --git a/Common/Render/Text/draw_text_uwp.cpp b/Common/Render/Text/draw_text_uwp.cpp index 832a0caa0..fbbe454ef 100644 --- a/Common/Render/Text/draw_text_uwp.cpp +++ b/Common/Render/Text/draw_text_uwp.cpp @@ -137,6 +137,7 @@ TextDrawerUWP::TextDrawerUWP(Draw::DrawContext *draw) : TextDrawer(draw), ctx_(n ); m_d2dContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White, 1.0f), &m_d2dWhiteBrush); + } TextDrawerUWP::~TextDrawerUWP() { @@ -380,7 +381,7 @@ void TextDrawerUWP::DrawStringBitmap(std::vector &bitmapData, TextStrin m_d2dContext->BeginDraw(); m_d2dContext->Clear(); - m_d2dContext->DrawTextLayout(D2D1::Point2F(0.0f, 0.0f), layout, m_d2dWhiteBrush, texFormat == Draw::DataFormat::R8G8B8A8_UNORM ? D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT : D2D1_DRAW_TEXT_OPTIONS_NONE); + m_d2dContext->DrawTextLayout(D2D1::Point2F(0.0f, 0.0f), layout, m_d2dWhiteBrush); m_d2dContext->EndDraw(); layout->Release(); @@ -395,15 +396,11 @@ void TextDrawerUWP::DrawStringBitmap(std::vector &bitmapData, TextStrin // because we need white. Well, we could using swizzle, but not all our backends support that. if (texFormat == Draw::DataFormat::R8G8B8A8_UNORM || texFormat == Draw::DataFormat::B8G8R8A8_UNORM) { bitmapData.resize(entry.bmWidth * entry.bmHeight * sizeof(uint32_t)); - bool swap = texFormat == Draw::DataFormat::R8G8B8A8_UNORM; uint32_t *bitmapData32 = (uint32_t *)&bitmapData[0]; for (int y = 0; y < entry.bmHeight; y++) { - uint32_t *bmpLine = (uint32_t *)&map.bits[map.pitch * y]; for (int x = 0; x < entry.bmWidth; x++) { - uint32_t v = bmpLine[x]; - if (swap) - v = (v & 0xFF00FF00) | ((v >> 16) & 0xFF) | ((v << 16) & 0xFF0000); - bitmapData32[entry.bmWidth * y + x] = v; + uint8_t bAlpha = (uint8_t)(map.bits[map.pitch * y + x * 4] & 0xff); + bitmapData32[entry.bmWidth * y + x] = (bAlpha << 24) | 0x00ffffff; } } } else if (texFormat == Draw::DataFormat::B4G4R4A4_UNORM_PACK16 || texFormat == Draw::DataFormat::R4G4B4A4_UNORM_PACK16) { @@ -455,7 +452,6 @@ void TextDrawerUWP::DrawString(DrawBuffer &target, const char *str, float x, flo entry->lastUsedFrame = frameCount_; } else { DataFormat texFormat; - // For our purposes these are equivalent, so just choose the supported one. D3D can emulate them. if (draw_->GetDataFormatSupport(Draw::DataFormat::A4R4G4B4_UNORM_PACK16) & FMT_TEXTURE) texFormat = Draw::DataFormat::A4R4G4B4_UNORM_PACK16; @@ -464,10 +460,6 @@ void TextDrawerUWP::DrawString(DrawBuffer &target, const char *str, float x, flo else texFormat = Draw::DataFormat::R8G8B8A8_UNORM; - bool emoji = AnyEmojiInString(key.text.c_str(), key.text.size()); - if (emoji) - texFormat = Draw::DataFormat::R8G8B8A8_UNORM; - entry = new TextStringEntry(); // Convert the bitmap to a Thin3D compatible array of 16-bit pixels. Can't use a single channel format diff --git a/Common/Render/Text/draw_text_win.cpp b/Common/Render/Text/draw_text_win.cpp index d0eb2b944..6cd9885fe 100644 --- a/Common/Render/Text/draw_text_win.cpp +++ b/Common/Render/Text/draw_text_win.cpp @@ -134,25 +134,13 @@ void TextDrawerWin32::MeasureString(const char *str, size_t len, float *w, float SelectObject(ctx_->hDC, iter->second->hFont); } - std::string toMeasure = ReplaceAll(std::string(str, len), "&&", "&"); - - std::vector lines; - SplitString(toMeasure, '\n', lines); - - int extW = 0, extH = 0; - for (auto &line : lines) { - SIZE size; - std::wstring wstr = ConvertUTF8ToWString(line); - GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size); - - if (size.cx > extW) - extW = size.cx; - extH += size.cy; - } + SIZE size; + std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(ReplaceAll(std::string(str, len), "\n", "\r\n"), "&&", "&")); + GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size); entry = new TextMeasureEntry(); - entry->width = extW; - entry->height = extH; + entry->width = size.cx; + entry->height = size.cy; sizeCache_[key] = std::unique_ptr(entry); } diff --git a/Common/RiscVCPUDetect.cpp b/Common/RiscVCPUDetect.cpp index 5f18db8cd..b4f8b608d 100644 --- a/Common/RiscVCPUDetect.cpp +++ b/Common/RiscVCPUDetect.cpp @@ -194,7 +194,7 @@ void CPUInfo::Detect() truncate_cpy(cpu_string, parser.ISAString().c_str()); - // A number of CPUs support a limited set of bitmanip. It's not all U74, so we use SOC for now... + // A number of CPUs support a limited set of B. It's not all U74, so we use SOC for now... if (parser.FirmwareMatchesCompatible("starfive,jh7110")) { RiscV_Zba = true; RiscV_Zbb = true; @@ -208,8 +208,9 @@ void CPUInfo::Detect() RiscV_D = ExtensionSupported(hwcap, 'D'); RiscV_C = ExtensionSupported(hwcap, 'C'); RiscV_V = ExtensionSupported(hwcap, 'V'); - // We assume as in RVA20U64 that F means Zicsr is available. - RiscV_Zicsr = RiscV_F; + RiscV_B = ExtensionSupported(hwcap, 'B'); + // Let's assume for now... + RiscV_Zicsr = RiscV_M && RiscV_A && RiscV_F && RiscV_D; #ifdef USE_CPU_FEATURES cpu_features::RiscvInfo info = cpu_features::GetRiscvInfo(); @@ -219,9 +220,7 @@ void CPUInfo::Detect() RiscV_F = info.features.F; RiscV_D = info.features.D; RiscV_C = info.features.C; - RiscV_V = info.features.V; - // Seems to be wrong sometimes, assume we have it if we have F. - RiscV_Zicsr = info.features.Zicsr || info.features.F; + RiscV_Zicsr = info.features.Zicsr; truncate_cpy(brand_string, info.uarch); #endif @@ -241,10 +240,11 @@ std::vector CPUInfo::Features() { { RiscV_D, "Double" }, { RiscV_C, "Compressed" }, { RiscV_V, "Vector" }, - { RiscV_Zba, "Bitmanip Zba" }, - { RiscV_Zbb, "Bitmanip Zbb" }, - { RiscV_Zbc, "Bitmanip Zbc" }, - { RiscV_Zbs, "Bitmanip Zbs" }, + { RiscV_B, "Bitmanip" }, + { RiscV_Zba, "Zba" }, + { RiscV_Zbb, "Zbb" }, + { RiscV_Zbc, "Zbc" }, + { RiscV_Zbs, "Zbs" }, { RiscV_Zicsr, "Zicsr" }, { CPU64bit, "64-bit" }, }; diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index 6f11dbe2c..1fa966e1f 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -62,10 +62,10 @@ static inline bool SupportsVector() { static inline bool SupportsBitmanip(char zbx) { switch (zbx) { - case 'a': return cpu_info.RiscV_Zba; - case 'b': return cpu_info.RiscV_Zbb; - case 'c': return cpu_info.RiscV_Zbc; - case 's': return cpu_info.RiscV_Zbs; + case 'a': return cpu_info.RiscV_B || cpu_info.RiscV_Zba; + case 'b': return cpu_info.RiscV_B || cpu_info.RiscV_Zbb; + case 'c': return cpu_info.RiscV_B || cpu_info.RiscV_Zbc; + case 's': return cpu_info.RiscV_B || cpu_info.RiscV_Zbs; default: return false; } } @@ -1180,27 +1180,6 @@ bool RiscVEmitter::CJInRange(const void *src, const void *dst) const { return BJInRange(src, dst, 12); } -void RiscVEmitter::QuickJAL(RiscVReg scratchreg, RiscVReg rd, const u8 *dst) { - if (!JInRange(GetCodePointer(), dst)) { - int32_t lower = 0; - static_assert(sizeof(intptr_t) <= sizeof(int64_t)); - // If it's near PC, we're better off shooting for AUIPC. Should take 8 bytes. - int64_t pcdelta = (int64_t)dst - (int64_t)GetCodePointer(); - if (pcdelta < 0x100000000LL && pcdelta >= -0x100000000LL) { - lower = (int32_t)SignReduce64(pcdelta, 12); - uintptr_t upper = ((pcdelta - lower) >> 12) << 12; - LI(scratchreg, (uintptr_t)GetCodePointer() + upper); - } else { - lower = (int32_t)SignReduce64((int64_t)dst, 12); - // Abuse rd as a temporary if we need to. - LI(scratchreg, dst - lower, rd == scratchreg ? R_ZERO : rd); - } - JALR(rd, scratchreg, lower); - } else { - JAL(rd, dst); - } -} - void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) { int64_t svalue = (int64_t)value; _assert_msg_(IsGPR(rd) && IsGPR(temp), "SetRegToImmediate only supports GPRs"); @@ -1215,24 +1194,13 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) auto useUpper = [&](int64_t v, void (RiscVEmitter::*upperOp)(RiscVReg, s32), bool force = false) { if (SignReduce64(v, 32) == v || force) { - int32_t lower = (int32_t)SignReduce64(v, 12); + int32_t lower = (int32_t)SignReduce64(svalue, 12); int32_t upper = ((v - lower) >> 12) << 12; - bool clearUpper = v >= 0 && upper < 0; - if (clearUpper) { - _assert_msg_(BitsSupported() >= 64, "Shouldn't be possible on 32-bit"); - _assert_msg_(force || (((int64_t)upper + lower) & 0xFFFFFFFF) == v, "Upper + ADDI immediate math mistake?"); - // This isn't safe to do using AUIPC. We can't have the high bit set this way. - if (upperOp == &RiscVEmitter::AUIPC) - return false; - } else { - _assert_msg_(force || (int64_t)upper + lower == v, "Upper + ADDI immediate math mistake?"); - } + _assert_msg_(force || (int64_t)upper + lower == v, "Upper + ADDI immediate math mistake?"); // Should be fused on some processors. (this->*upperOp)(rd, upper); - if (clearUpper) - ADDIW(rd, rd, lower); - else if (lower != 0) + if (lower != 0) ADDI(rd, rd, lower); return true; } @@ -1263,12 +1231,8 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) // If this is just a 32-bit unsigned value, use a wall to mask. if ((svalue >> 32) == 0) { LI(rd, (int32_t)(svalue & 0xFFFFFFFF)); - if (SupportsBitmanip('a')) { - ZEXT_W(rd, rd); - } else { - SLLI(rd, rd, BitsSupported() - 32); - SRLI(rd, rd, BitsSupported() - 32); - } + SLLI(rd, rd, BitsSupported() - 32); + SRLI(rd, rd, BitsSupported() - 32); return; } @@ -1286,7 +1250,7 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) return; } - // Okay, let's just start with the upper 32 bits and add the rest via ADDI. + // Okay, let's just start with the upper 32 bits and add the rest via ORI. int64_t upper = svalue >> 32; LI(rd, upper); @@ -1302,7 +1266,7 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) int32_t chunk = (remaining >> sourceShift) & 0x07FF; SLLI(rd, rd, targetShift - shifted); - ADDI(rd, rd, chunk); + ORI(rd, rd, chunk); // Okay, increase shift and clear the bits we've deposited. shifted = targetShift; @@ -2160,7 +2124,6 @@ void RiscVEmitter::FCVT(FConv to, FConv from, RiscVReg rd, RiscVReg rs1, Round r _assert_msg_(rm == Round::DYNAMIC || rm == Round::NEAREST_EVEN, "Invalid rounding mode for widening FCVT"); rm = Round::NEAREST_EVEN; } - _assert_msg_(fromFmt != toFmt, "FCVT cannot convert to same float type"); Write32(EncodeR(Opcode32::OP_FP, rd, (Funct3)rm, rs1, (RiscVReg)fromFmt, toFmt, Funct5::FCVT_SZ)); } else { Funct5 funct5 = FConvToIntegerBits(to) == 0 ? Funct5::FCVT_FROMX : Funct5::FCVT_TOX; diff --git a/Common/RiscVEmitter.h b/Common/RiscVEmitter.h index 9fe5d8716..720db3faa 100644 --- a/Common/RiscVEmitter.h +++ b/Common/RiscVEmitter.h @@ -213,19 +213,6 @@ public: bool BInRange(const void *func) const; bool JInRange(const void *func) const; - void QuickJAL(RiscVReg scratchreg, RiscVReg rd, const u8 *dst); - void QuickJ(RiscVReg scratchreg, const u8 *dst) { - QuickJAL(scratchreg, R_ZERO, dst); - } - void QuickCallFunction(const u8 *func, RiscVReg scratchreg = R_RA) { - QuickJAL(scratchreg, R_RA, func); - } - template - void QuickCallFunction(T *func, RiscVReg scratchreg = R_RA) { - static_assert(std::is_function::value, "QuickCallFunction without function"); - QuickCallFunction((const u8 *)func, scratchreg); - } - void LUI(RiscVReg rd, s32 simm32); void AUIPC(RiscVReg rd, s32 simm32); @@ -315,12 +302,6 @@ public: void NEG(RiscVReg rd, RiscVReg rs) { SUB(rd, R_ZERO, rs); } - void SNEZ(RiscVReg rd, RiscVReg rs) { - SLTU(rd, R_ZERO, rs); - } - void SEQZ(RiscVReg rd, RiscVReg rs) { - SLTIU(rd, rs, 1); - } void FENCE(Fence predecessor, Fence successor); void FENCE_TSO(); @@ -915,9 +896,6 @@ public: void MINU(RiscVReg rd, RiscVReg rs1, RiscVReg rs2); void SEXT_B(RiscVReg rd, RiscVReg rs); void SEXT_H(RiscVReg rd, RiscVReg rs); - void SEXT_W(RiscVReg rd, RiscVReg rs) { - ADDIW(rd, rs, 0); - } void ZEXT_H(RiscVReg rd, RiscVReg rs); void ZEXT_W(RiscVReg rd, RiscVReg rs) { ADD_UW(rd, rs, R_ZERO); diff --git a/Common/Serialize/Serializer.h b/Common/Serialize/Serializer.h index 808967b51..a7fa964a0 100644 --- a/Common/Serialize/Serializer.h +++ b/Common/Serialize/Serializer.h @@ -147,11 +147,6 @@ public: void DoMarker(const char *prevName, u32 arbitraryNumber = 0x42); - void SkipBytes(size_t bytes) { - // Should work in all modes. - *ptr += bytes; - } - size_t Offset() const { return *ptr - ptrStart_; } private: diff --git a/Common/StringUtils.cpp b/Common/StringUtils.cpp index 2cf21ebc2..c691d4223 100644 --- a/Common/StringUtils.cpp +++ b/Common/StringUtils.cpp @@ -239,15 +239,18 @@ std::string StringFromFormat(const char* format, ...) return temp; } -std::string StringFromInt(int value) { +std::string StringFromInt(int value) +{ char temp[16]; snprintf(temp, sizeof(temp), "%d", value); return temp; } // Turns " hej " into "hej". Also handles tabs. -std::string StripSpaces(const std::string &str) { +std::string StripSpaces(const std::string &str) +{ const size_t s = str.find_first_not_of(" \t\r\n"); + if (str.npos != s) return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); else @@ -265,26 +268,8 @@ std::string StripQuotes(const std::string& s) return s; } -// Turns " hej " into "hej". Also handles tabs. -std::string_view StripSpaces(std::string_view str) { - const size_t s = str.find_first_not_of(" \t\r\n"); - if (str.npos != s) - return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); - else - return ""; -} - -// "\"hello\"" is turned to "hello" -// This one assumes that the string has already been space stripped in both -// ends, as done by StripSpaces above, for example. -std::string_view StripQuotes(std::string_view s) { - if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) - return s.substr(1, s.size() - 2); - else - return s; -} - -void SplitString(std::string_view str, const char delim, std::vector &output) { +void SplitString(const std::string& str, const char delim, std::vector& output) +{ size_t next = 0; for (size_t pos = 0, len = str.length(); pos < len; ++pos) { if (str[pos] == delim) { @@ -301,23 +286,6 @@ void SplitString(std::string_view str, const char delim, std::vector &output) { - size_t next = 0; - for (size_t pos = 0, len = str.length(); pos < len; ++pos) { - if (str[pos] == delim) { - output.emplace_back(str.substr(next, pos - next)); - // Skip the delimiter itself. - next = pos + 1; - } - } - - if (next == 0) { - output.emplace_back(str); - } else if (next < str.length()) { - output.emplace_back(str.substr(next)); - } -} - static std::string ApplyHtmlEscapes(std::string str) { struct Repl { const char *a; @@ -337,7 +305,8 @@ static std::string ApplyHtmlEscapes(std::string str) { } // Meant for HTML listings and similar, so supports some HTML escapes. -void GetQuotedStrings(const std::string& str, std::vector &output) { +void GetQuotedStrings(const std::string& str, std::vector& output) +{ size_t next = 0; bool even = 0; for (size_t pos = 0, len = str.length(); pos < len; ++pos) { @@ -356,13 +325,15 @@ void GetQuotedStrings(const std::string& str, std::vector &output) } } -std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) { +std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) +{ size_t pos = 0; if (src == dest) return result; - while (true) { + while (1) + { pos = result.find(src, pos); if (pos == result.npos) break; @@ -397,65 +368,3 @@ std::string UnescapeMenuString(const char *input, char *shortcutChar) { } return output; } - -std::string ApplySafeSubstitutions(const char *format, std::string_view string1, std::string_view string2, std::string_view string3, std::string_view string4) { - size_t formatLen = strlen(format); - std::string output; - output.reserve(formatLen + 20); - for (size_t i = 0; i < formatLen; i++) { - char c = format[i]; - if (c != '%') { - output.push_back(c); - continue; - } - if (i >= formatLen - 1) { - break; - } - switch (format[i + 1]) { - case '1': - output += string1; i++; - break; - case '2': - output += string2; i++; - break; - case '3': - output += string3; i++; - break; - case '4': - output += string4; i++; - break; - } - } - return output; -} - -std::string ApplySafeSubstitutions(const char *format, int i1, int i2, int i3, int i4) { - size_t formatLen = strlen(format); - std::string output; - output.reserve(formatLen + 20); - for (size_t i = 0; i < formatLen; i++) { - char c = format[i]; - if (c != '%') { - output.push_back(c); - continue; - } - if (i >= formatLen - 1) { - break; - } - switch (format[i + 1]) { - case '1': - output += StringFromInt(i1); i++; - break; - case '2': - output += StringFromInt(i2); i++; - break; - case '3': - output += StringFromInt(i3); i++; - break; - case '4': - output += StringFromInt(i4); i++; - break; - } - } - return output; -} diff --git a/Common/StringUtils.h b/Common/StringUtils.h index 43079da69..5e68baec6 100644 --- a/Common/StringUtils.h +++ b/Common/StringUtils.h @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include #ifdef _MSC_VER @@ -37,36 +35,34 @@ std::string IndentString(const std::string &str, const std::string &sep, bool sk // Other simple string utilities. -inline bool startsWith(std::string_view str, std::string_view key) { - if (str.size() < key.size()) +inline bool startsWith(const std::string &str, const std::string &what) { + if (str.size() < what.size()) return false; - return !memcmp(str.data(), key.data(), key.size()); + return str.substr(0, what.size()) == what; } -inline bool endsWith(std::string_view str, std::string_view what) { +inline bool endsWith(const std::string &str, const std::string &what) { if (str.size() < what.size()) return false; return str.substr(str.size() - what.size()) == what; } // Only use on strings where you're only concerned about ASCII. -inline bool startsWithNoCase(std::string_view str, std::string_view key) { - if (str.size() < key.size()) +inline bool startsWithNoCase(const std::string &str, const std::string &what) { + if (str.size() < what.size()) return false; - return strncasecmp(str.data(), key.data(), key.size()) == 0; + return strncasecmp(str.c_str(), what.c_str(), what.size()) == 0; } -inline bool endsWithNoCase(std::string_view str, std::string_view key) { - if (str.size() < key.size()) +inline bool endsWithNoCase(const std::string &str, const std::string &what) { + if (str.size() < what.size()) return false; - const size_t offset = str.size() - key.size(); - return strncasecmp(str.data() + offset, key.data(), key.size()) == 0; + const size_t offset = str.size() - what.size(); + return strncasecmp(str.c_str() + offset, what.c_str(), what.size()) == 0; } -inline bool equalsNoCase(std::string_view str, std::string_view key) { - if (str.size() != key.size()) - return false; - return strncasecmp(str.data(), key.data(), key.size()) == 0; +inline bool equalsNoCase(const std::string &str, const char *what) { + return strcasecmp(str.c_str(), what) == 0; } void DataToHexString(const uint8_t *data, size_t size, std::string *output); @@ -78,12 +74,7 @@ std::string StringFromInt(int value); std::string StripSpaces(const std::string &s); std::string StripQuotes(const std::string &s); -std::string_view StripSpaces(std::string_view s); -std::string_view StripQuotes(std::string_view s); - -// TODO: Make this a lot more efficient by outputting string_views. -void SplitString(std::string_view str, const char delim, std::vector &output); -void SplitString(std::string_view str, const char delim, std::vector &output); +void SplitString(const std::string& str, const char delim, std::vector& output); void GetQuotedStrings(const std::string& str, std::vector& output); @@ -120,9 +111,3 @@ inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...) // "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe" bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension); - -// Replaces %1, %2, %3 in format with arg1, arg2, arg3. -// Much safer than snprintf and friends. -// For mixes of strings and ints, manually convert the ints to strings. -std::string ApplySafeSubstitutions(const char *format, std::string_view string1, std::string_view string2 = "", std::string_view string3 = "", std::string_view string4 = ""); -std::string ApplySafeSubstitutions(const char *format, int i1, int i2 = 0, int i3 = 0, int i4 = 0); diff --git a/Common/System/NativeApp.h b/Common/System/NativeApp.h index 4799fa6f1..d1286a8d7 100644 --- a/Common/System/NativeApp.h +++ b/Common/System/NativeApp.h @@ -20,6 +20,9 @@ class GraphicsContext; // This might get called multiple times in some implementations, you must be able to handle that. void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape, std::string *version); +// Generic host->C++ messaging, used for functionality like system-native popup input boxes. +void NativeMessageReceived(const char *message, const char *value); + // Easy way for the Java side to ask the C++ side for configuration options, such as // the rotation lock which must be controlled from Java on Android. // It is currently not called on non-Android platforms. @@ -49,17 +52,21 @@ void NativeSetRestarting(); // Retrieve current restarting flag. bool NativeIsRestarting(); -// Delivers touch/key/axis events "instantly", without waiting for the next frame so that NativeFrame can deliver. -// Some systems like UI will buffer these events internally but at least in gameplay we can get the minimum possible -// input latency - assuming your main loop is architected properly (NativeFrame called from a different thread than input event handling). +// Called ~sixty times a second, delivers the current input state. +// Main thread. +void NativeUpdate(); + +// Delivers touch events "instantly", without waiting for the next frame so that NativeUpdate can deliver. +// Useful for triggering audio events, saving a few ms. +// If you don't care about touch latency, just do a no-op implementation of this. +// time is not yet implemented. finger can be from 0 to 7, inclusive. void NativeTouch(const TouchInput &touch); bool NativeKey(const KeyInput &key); -void NativeAxis(const AxisInput *axis, size_t count); -void NativeAccelerometer(float tiltX, float tiltY, float tiltZ); +void NativeAxis(const AxisInput &axis); -// Called when it's process a frame, including rendering. If the device can keep up, this -// will be called sixty times per second. Main thread. -void NativeFrame(GraphicsContext *graphicsContext); +// Called when it's time to render. If the device can keep up, this +// will also be called sixty times per second. Main thread. +void NativeRender(GraphicsContext *graphicsContext); // This should render num_samples 44khz stereo samples. // Try not to make too many assumptions on the granularity @@ -80,8 +87,3 @@ void NativeShutdownGraphics(); void NativeShutdown(); void PostLoadConfig(); - -// Returns false on failure. Shouldn't really happen, though. -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data); -// On failure, returns an empty string. Good enough since any real secret is non-empty. -std::string NativeLoadSecret(const char *nameOfSecret); diff --git a/Common/System/OSD.cpp b/Common/System/OSD.cpp deleted file mode 100644 index 7d0eb9a48..000000000 --- a/Common/System/OSD.cpp +++ /dev/null @@ -1,297 +0,0 @@ -#include -#include -// for std::min - -#include "Common/System/OSD.h" -#include "Common/TimeUtil.h" -#include "Common/Log.h" -#include "Common/Math/math_util.h" - -OnScreenDisplay g_OSD; - -// Effectively forever. -constexpr double forever_s = 10000000000.0; - -void OnScreenDisplay::Update() { - std::lock_guard guard(mutex_); - - double now = time_now_d(); - for (auto iter = entries_.begin(); iter != entries_.end(); ) { - if (now >= iter->endTime) { - iter = entries_.erase(iter); - } else { - iter++; - } - } -} - -std::vector OnScreenDisplay::Entries() { - std::lock_guard guard(mutex_); - return entries_; // makes a copy. -} - -void OnScreenDisplay::NudgeSidebar() { - sideBarShowTime_ = time_now_d(); -} - -float OnScreenDisplay::SidebarAlpha() const { - double timeSinceNudge = time_now_d() - sideBarShowTime_; - - // Fade out in 1/4 second, 0.1s after the last nudge. - return saturatef(1.0f - ((float)timeSinceNudge - 0.1f) * 4.0f); -} - -void OnScreenDisplay::DismissEntry(size_t index, double now) { - std::lock_guard guard(mutex_); - if (index < entries_.size() && entries_[index].type != OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR) { - entries_[index].endTime = std::min(now + FadeoutTime(), entries_[index].endTime); - } -} - -void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::string &text2, const std::string &icon, float duration_s, const char *id) { - // Automatic duration based on type. - if (duration_s <= 0.0f) { - switch (type) { - case OSDType::MESSAGE_ERROR: - case OSDType::MESSAGE_WARNING: - duration_s = 4.0f; - break; - case OSDType::MESSAGE_FILE_LINK: - duration_s = 5.0f; - break; - case OSDType::MESSAGE_INFO: - duration_s = 3.0f; - break; - case OSDType::MESSAGE_SUCCESS: - duration_s = 2.0f; - break; - default: - duration_s = 1.5f; - break; - } - } - - double now = time_now_d(); - std::lock_guard guard(mutex_); - if (id) { - for (auto iter = entries_.begin(); iter != entries_.end(); ++iter) { - if (iter->id == id) { - Entry msg = *iter; - msg.endTime = now + duration_s; - msg.text = text; - msg.text2 = text2; - msg.type = type; - msg.iconName = icon; - // Move to top (should we? maybe not?) - entries_.erase(iter); - entries_.insert(entries_.begin(), msg); - return; - } - } - } - - Entry msg; - msg.text = text; - msg.text2 = text2; - msg.iconName = icon; - msg.startTime = now; - msg.endTime = now + duration_s; - msg.type = type; - if (id) { - msg.id = id; - } - entries_.insert(entries_.begin(), msg); -} - -void OnScreenDisplay::ShowOnOff(const std::string &message, bool on, float duration_s) { - // TODO: translate "on" and "off"? Or just get rid of this whole thing? - Show(OSDType::MESSAGE_INFO, message + ": " + (on ? "on" : "off"), duration_s); -} - -void OnScreenDisplay::ShowAchievementUnlocked(int achievementID) { - double now = time_now_d(); - - double duration_s = 5.0; - - Entry msg; - msg.numericID = achievementID; - msg.type = OSDType::ACHIEVEMENT_UNLOCKED; - msg.startTime = now; - msg.endTime = now + duration_s; - entries_.insert(entries_.begin(), msg); -} - -void OnScreenDisplay::ShowAchievementProgress(int achievementID, bool show) { - double now = time_now_d(); - - // There can only be one of these at a time. - for (auto &entry : entries_) { - if (entry.type == OSDType::ACHIEVEMENT_PROGRESS) { - if (!show) { - // Hide and eventually delete it. - entry.endTime = now + (double)FadeoutTime(); - // Found it, we're done. - return; - } - // Else update it. - entry.numericID = achievementID; - entry.endTime = now + forever_s; - return; - } - } - - if (!show) { - // Sanity check - return; - } - - // OK, let's make a new side-entry. - Entry entry; - entry.numericID = achievementID; - entry.type = OSDType::ACHIEVEMENT_PROGRESS; - entry.startTime = now; - entry.endTime = now + forever_s; - entries_.insert(entries_.begin(), entry); -} - -void OnScreenDisplay::ShowChallengeIndicator(int achievementID, bool show) { - double now = time_now_d(); - - for (auto &entry : entries_) { - if (entry.numericID == achievementID && entry.type == OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR && !show) { - // Hide and eventually delete it. - entry.endTime = now + (double)FadeoutTime(); - // Found it, we're done. - return; - } - } - - if (!show) { - // Sanity check - return; - } - - // OK, let's make a new side-entry. - Entry entry; - entry.numericID = achievementID; - entry.type = OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR; - entry.startTime = now; - entry.endTime = now + forever_s; - entries_.insert(entries_.begin(), entry); -} - -void OnScreenDisplay::ShowLeaderboardTracker(int leaderboardTrackerID, const char *trackerText, bool show) { // show=true is used both for create and update. - double now = time_now_d(); - - for (auto &entry : entries_) { - if (entry.numericID == leaderboardTrackerID && entry.type == OSDType::LEADERBOARD_TRACKER) { - if (show) { - // Just an update. - entry.text = trackerText ? trackerText : ""; - // Bump the end-time, in case it was fading out. - entry.endTime = now + forever_s; - } else { - // Keep the current text, hide and eventually delete it. - entry.endTime = now + (double)FadeoutTime(); - } - // Found it, we're done. - return; - } - } - - if (!show) { - // Sanity check - return; - } - - // OK, let's make a new side-entry. - Entry entry; - entry.numericID = leaderboardTrackerID; - entry.type = OSDType::LEADERBOARD_TRACKER; - entry.startTime = now; - entry.endTime = now + forever_s; - if (trackerText) { - entry.text = trackerText; - } - entries_.insert(entries_.begin(), entry); -} - -void OnScreenDisplay::ShowLeaderboardStartEnd(const std::string &title, const std::string &description, bool started) { - g_OSD.Show(OSDType::LEADERBOARD_STARTED_FAILED, title, description, 3.0f); -} - -void OnScreenDisplay::ShowLeaderboardSubmitted(const std::string &title, const std::string &value) { - g_OSD.Show(OSDType::LEADERBOARD_SUBMITTED, title, value, 3.0f); -} - -void OnScreenDisplay::SetProgressBar(std::string id, std::string &&message, float minValue, float maxValue, float progress, float delay) { - _dbg_assert_(!my_isnanorinf(progress)); - _dbg_assert_(!my_isnanorinf(minValue)); - _dbg_assert_(!my_isnanorinf(maxValue)); - - double now = time_now_d(); - bool found = false; - - std::lock_guard guard(mutex_); - for (auto &bar : entries_) { - if (bar.type == OSDType::PROGRESS_BAR && bar.id == id) { - bar.minValue = minValue; - bar.maxValue = maxValue; - bar.progress = progress; - bar.text = message; - bar.endTime = now + 60.0; // Nudge the progress bar to keep it shown. - return; - } - } - - Entry bar; - bar.id = id; - bar.type = OSDType::PROGRESS_BAR; - bar.text = std::move(message); - bar.minValue = minValue; - bar.maxValue = maxValue; - bar.progress = progress; - bar.startTime = now + delay; - bar.endTime = now + 60.0; // Show the progress bar for 60 seconds, then fade it out. - entries_.push_back(bar); -} - -void OnScreenDisplay::RemoveProgressBar(std::string id, bool success, float delay_s) { - std::lock_guard guard(mutex_); - for (auto iter = entries_.begin(); iter != entries_.end(); iter++) { - if (iter->type == OSDType::PROGRESS_BAR && iter->id == id) { - if (success) { - // Quickly shoot up to max, if we weren't there. - if (iter->maxValue != 0.0f) { - iter->progress = iter->maxValue; - } else { - // Fake a full progress - iter->minValue = 0; - iter->maxValue = 1; - iter->progress = 1; - } - } - iter->endTime = time_now_d() + delay_s + FadeoutTime(); - break; - } - } -} - -// Fades out everything related to achievements. Should be used on game shutdown. -void OnScreenDisplay::ClearAchievementStuff() { - double now = time_now_d(); - for (auto &iter : entries_) { - switch (iter.type) { - case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: - case OSDType::ACHIEVEMENT_UNLOCKED: - case OSDType::ACHIEVEMENT_PROGRESS: - case OSDType::LEADERBOARD_TRACKER: - case OSDType::LEADERBOARD_STARTED_FAILED: - case OSDType::LEADERBOARD_SUBMITTED: - iter.endTime = now; - break; - default: - break; - } - } -} diff --git a/Common/System/OSD.h b/Common/System/OSD.h deleted file mode 100644 index 4f81e4ad3..000000000 --- a/Common/System/OSD.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include -#include -#include - -// Shows a visible message to the user. -// The default implementation in NativeApp.cpp uses our "osm" system (on screen messaging). -enum class OSDType { - MESSAGE_INFO, - MESSAGE_SUCCESS, - MESSAGE_WARNING, - MESSAGE_ERROR, - MESSAGE_ERROR_DUMP, // displays lots of text (after the first line), small size - MESSAGE_FILE_LINK, - - ACHIEVEMENT_UNLOCKED, - - // Side entries - ACHIEVEMENT_PROGRESS, // Achievement icon + "measured_progress" text, auto-hide after 2s - ACHIEVEMENT_CHALLENGE_INDICATOR, // Achievement icon ONLY, no auto-hide - - LEADERBOARD_TRACKER, - LEADERBOARD_STARTED_FAILED, - LEADERBOARD_SUBMITTED, - - PROGRESS_BAR, - - VALUE_COUNT, -}; - -// Data holder for on-screen messages. -class OnScreenDisplay { -public: - // If you specify 0.0f as duration, a duration will be chosen automatically depending on type. - void Show(OSDType type, const std::string &text, float duration_s = 0.0f, const char *id = nullptr) { - Show(type, text, "", duration_s, id); - } - void Show(OSDType type, const std::string &text, const std::string &text2, float duration_s = 0.0f, const char *id = nullptr) { - Show(type, text, text2, "", duration_s, id); - } - void Show(OSDType type, const std::string &text, const std::string &text2, const std::string &icon, float duration_s = 0.0f, const char *id = nullptr); - - void ShowOnOff(const std::string &message, bool on, float duration_s = 0.0f); - - bool IsEmpty() const { return entries_.empty(); } // Shortcut to skip rendering. - - // Call this every frame, cleans up old entries. - void Update(); - - // Specialized achievement-related types. These go to the side notifications, not the top-middle. - void ShowAchievementUnlocked(int achievementID); - void ShowAchievementProgress(int achievementID, bool show); // call with show=false to hide. There can only be one of these. When hiding it's ok to not pass a valid achievementID. - void ShowChallengeIndicator(int achievementID, bool show); // call with show=false to hide. - void ShowLeaderboardTracker(int leaderboardTrackerID, const char *trackerText, bool show); // show=true is used both for create and update. - void ShowLeaderboardStartEnd(const std::string &title, const std::string &description, bool started); // started = true for started, false for ended. - void ShowLeaderboardSubmitted(const std::string &title, const std::string &value); - - // Progress bar controls - // Set is both create and update. If you set maxValue <= minValue, you'll create an "indeterminate" progress - // bar that doesn't show a specific amount of progress. - void SetProgressBar(std::string id, std::string &&message, float minValue, float maxValue, float progress, float delay_s); - void RemoveProgressBar(std::string id, bool success, float delay_s); - - // Call every frame to keep the sidebar visible. Otherwise it'll fade out. - void NudgeSidebar(); - float SidebarAlpha() const; - - // Fades out everything related to achievements. Should be used on game shutdown. - void ClearAchievementStuff(); - - struct Entry { - OSDType type; - std::string text; - std::string text2; - std::string iconName; - int numericID; - std::string id; - double startTime; - double endTime; - - // Progress-bar-only data: - float minValue; - float maxValue; - float progress; - }; - - std::vector Entries(); - - // TODO: Use something more stable than the index. - void DismissEntry(size_t index, double now); - - static float FadeinTime() { return 0.1f; } - static float FadeoutTime() { return 0.25f; } - -private: - std::vector entries_; - std::mutex mutex_; - - double sideBarShowTime_ = 0.0; -}; - -extern OnScreenDisplay g_OSD; diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index 1635152a2..2173eecd5 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -1,23 +1,7 @@ -#include "ppsspp_config.h" - -#include - #include "Common/System/Request.h" #include "Common/System/System.h" #include "Common/Log.h" #include "Common/File/Path.h" -#include "Common/TimeUtil.h" - -#if PPSSPP_PLATFORM(ANDROID) - -// Maybe not the most natural place for this, but not sure what would be. It needs to be in the Common project -// unless we want to make another System_ function to retrieve it. - -#include - -JavaVM *gJvm = nullptr; - -#endif RequestManager g_requestManager; @@ -40,7 +24,7 @@ bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback c callbackMap_[requestId] = { callback, failedCallback }; } - VERBOSE_LOG(SYSTEM, "Making system request %s: id %d", RequestTypeAsString(type), requestId); + DEBUG_LOG(SYSTEM, "Making system request %s: id %d", RequestTypeAsString(type), requestId); if (!System_MakeRequest(type, requestId, param1, param2, param3)) { if (callback || failedCallback) { std::lock_guard guard(callbackMutex_); @@ -115,7 +99,3 @@ void RequestManager::Clear() { void System_CreateGameShortcut(const Path &path, const std::string &title) { g_requestManager.MakeSystemRequest(SystemRequestType::CREATE_GAME_SHORTCUT, nullptr, nullptr, path.ToString(), title, 0); } - -void System_ShowFileInFolder(const Path &path) { - g_requestManager.MakeSystemRequest(SystemRequestType::SHOW_FILE_IN_FOLDER, nullptr, nullptr, path.ToString(), "", 0); -} diff --git a/Common/System/Request.h b/Common/System/Request.h index 8f734cdd0..547b07387 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -29,7 +29,7 @@ public: void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0); void PostSystemFailure(int requestId); - // This must be called every frame from the beginning of NativeFrame(). + // This must be called every frame from the beginning of NativeUpdate(). // This will call the callback of any finished requests. void ProcessRequests(); @@ -61,8 +61,7 @@ private: RequestFailedCallback callback; }; - // Let's start at 10 to get a recognizably valid ID in logs. - int idCounter_ = 10; + int idCounter_ = 0; std::vector pendingSuccesses_; std::vector pendingFailures_; std::mutex responseMutex_; @@ -73,13 +72,12 @@ const char *RequestTypeAsString(SystemRequestType type); extern RequestManager g_requestManager; // Wrappers for easy requests. -// NOTE: Semantics have changed - this no longer calls the callback on cancellation, instead you -// can specify a different callback for that. +// NOTE: Semantics have changed - this no longer calls the callback on cancellation. inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, failedCallback, title, defaultValue, 0); } -// This one will pop up a special image browser if available. You can also pick +// This one will pop up a special image brwoser if available. You can also pick // images with the file browser below. inline void System_BrowseForImage(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, failedCallback, title, "", 0); @@ -90,7 +88,6 @@ enum class BrowseFileType { IMAGE, INI, DB, - SOUND_EFFECT, ANY, }; @@ -102,11 +99,6 @@ inline void System_BrowseForFolder(const std::string &title, RequestCallback cal g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, failedCallback, title, "", 0); } -// The returned string is username + '\n' + password. -inline void System_AskUsernamePassword(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { - g_requestManager.MakeSystemRequest(SystemRequestType::ASK_USERNAME_PASSWORD, callback, failedCallback, title, "", 0); -} - inline void System_CopyStringToClipboard(const std::string &string) { g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, nullptr, string, "", 0); } @@ -166,4 +158,4 @@ inline void System_SendDebugScreenshot(const std::string &data, int height) { // Non-inline to avoid including Path.h void System_CreateGameShortcut(const Path &path, const std::string &title); -void System_ShowFileInFolder(const Path &path); + diff --git a/Common/System/System.h b/Common/System/System.h index 48cfaa280..d00324d9b 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -4,7 +4,6 @@ #include #include #include -#include // Platform integration @@ -49,6 +48,7 @@ enum class LaunchUrlType { }; void System_Vibrate(int length_ms); +void System_ShowFileInFolder(const char *path); void System_LaunchUrl(LaunchUrlType urlType, const char *url); // It's sometimes a little unclear what should be a request, and what should be a separate function. @@ -57,7 +57,6 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url); enum class SystemRequestType { INPUT_TEXT_MODAL, - ASK_USERNAME_PASSWORD, BROWSE_FOR_IMAGE, BROWSE_FOR_FILE, BROWSE_FOR_FOLDER, @@ -71,7 +70,6 @@ enum class SystemRequestType { TOGGLE_FULLSCREEN_STATE, GRAPHICS_BACKEND_FAILED_ALERT, CREATE_GAME_SHORTCUT, - SHOW_FILE_IN_FOLDER, // Commonly ignored, used when automated tests generate output. SEND_DEBUG_OUTPUT, @@ -117,7 +115,6 @@ enum SystemProperty { SYSPROP_BOARDNAME, SYSPROP_CLIPBOARD_TEXT, SYSPROP_GPUDRIVER_VERSION, - SYSPROP_BUILD_VERSION, // Separate SD cards or similar. // Need hacky solutions to get at this. @@ -130,17 +127,9 @@ enum SystemProperty { SYSPROP_HAS_IMAGE_BROWSER, SYSPROP_HAS_BACK_BUTTON, SYSPROP_HAS_KEYBOARD, - SYSPROP_HAS_ACCELEROMETER, // Used to enable/disable tilt input settings SYSPROP_HAS_OPEN_DIRECTORY, - SYSPROP_HAS_LOGIN_DIALOG, - SYSPROP_HAS_TEXT_INPUT_DIALOG, // Indicates that System_InputBoxGetString is available. SYSPROP_CAN_CREATE_SHORTCUT, - SYSPROP_CAN_SHOW_FILE, - - SYSPROP_SUPPORTS_HTTPS, - - SYSPROP_DEBUGGER_PRESENT, // Available as Int: SYSPROP_SYSTEMVERSION, @@ -186,8 +175,6 @@ enum SystemProperty { SYSPROP_KEYBOARD_LAYOUT, SYSPROP_SKIP_UI, - - SYSPROP_USER_DOCUMENTS_DIR, }; enum class SystemNotification { @@ -205,43 +192,6 @@ enum class SystemNotification { SUSTAINED_PERF_CHANGE, POLL_CONTROLLERS, TOGGLE_DEBUG_CONSOLE, // TODO: Kinda weird, just ported forward. - TEST_JAVA_EXCEPTION, - KEEP_SCREEN_AWAKE, - ACTIVITY, -}; - -// I guess it's not super great architecturally to centralize this, since it's not general - but same with a lot of -// the other stuff, and this is only used by PPSSPP, so... better this than ugly strings. -enum class UIMessage { - PERMISSION_GRANTED, - POWER_SAVING, - RECREATE_VIEWS, - CONFIG_LOADED, - REQUEST_GAME_BOOT, - REQUEST_GAME_RUN, // or continue? - REQUEST_GAME_PAUSE, - REQUEST_GAME_RESET, - REQUEST_GAME_STOP, - SHOW_CONTROL_MAPPING, - SHOW_CHAT_SCREEN, - SHOW_DISPLAY_LAYOUT_EDITOR, - SHOW_SETTINGS, - SHOW_LANGUAGE_SCREEN, - REQUEST_GPU_DUMP_NEXT_FRAME, - REQUEST_CLEAR_JIT, - APP_RESUMED, - REQUEST_PLAY_SOUND, - WINDOW_MINIMIZED, - LOST_FOCUS, - GOT_FOCUS, - GPU_CONFIG_CHANGED, - GPU_RENDER_RESIZED, - GPU_DISPLAY_RESIZED, - POSTSHADER_UPDATED, - ACHIEVEMENT_LOGIN_STATE_CHANGE, - SAVESTATE_DISPLAY_SLOT, - GAMESETTINGS_SEARCH, - SAVEDATA_SEARCH, }; std::string System_GetProperty(SystemProperty prop); @@ -257,17 +207,18 @@ std::vector System_GetCameraDeviceList(); bool System_AudioRecordingIsAvailable(); bool System_AudioRecordingState(); -// This will be changed to take an enum. Replacement for the old NativeMessageReceived. -void System_PostUIMessage(UIMessage message, const std::string ¶m = ""); +// This will be changed to take an enum. Currently simply implemented by forwarding to NativeMessageReceived. +void System_PostUIMessage(const std::string &message, const std::string ¶m); + +// Shows a visible message to the user. +// The default implementation in NativeApp.cpp uses our "osm" system (on screen messaging). +void System_NotifyUserMessage(const std::string &message, float duration = 1.0f, uint32_t color = 0x00FFFFFF, const char *id = nullptr); // For these functions, most platforms will use the implementation provided in UI/AudioCommon.cpp, // no need to implement separately. void System_AudioGetDebugStats(char *buf, size_t bufSize); void System_AudioClear(); - // These samples really have 16 bits of value, but can be a little out of range. -// This is for pushing rate-controlled 44khz audio from emulation. -// If you push a little too fast, we'll pitch up to a limit, for example. void System_AudioPushSamples(const int32_t *audio, int numSamples); inline void System_AudioResetStatCounters() { diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index 93e4dfd98..f8dbaf9e6 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -45,7 +45,6 @@ public: template class Promise { public: - // Never fails. static Promise *Spawn(ThreadManager *threadman, std::function fun, TaskType taskType, TaskPriority taskPriority = TaskPriority::NORMAL) { Mailbox *mailbox = new Mailbox(); diff --git a/Common/TimeUtil.cpp b/Common/TimeUtil.cpp index b24a1da4e..ad07fbd18 100644 --- a/Common/TimeUtil.cpp +++ b/Common/TimeUtil.cpp @@ -1,18 +1,14 @@ -#include "ppsspp_config.h" - #include #include +#include "ppsspp_config.h" + #include "Common/TimeUtil.h" #ifdef HAVE_LIBNX #include #endif // HAVE_LIBNX -#ifdef __EMSCRIPTEN__ -#include -#endif // __EMSCRIPTEN__ - #ifdef _WIN32 #include "CommonWindows.h" #include @@ -21,20 +17,11 @@ #include #include #endif - -// for _mm_pause -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) -#include -#endif - #include // TODO: https://github.com/floooh/sokol/blob/9a6237fcdf213e6da48e4f9201f144bcb2dcb46f/sokol_time.h#L229-L248 -static const double micros = 1000000.0; -static const double nanos = 1000000000.0; - -#if PPSSPP_PLATFORM(WINDOWS) +#ifdef _WIN32 static LARGE_INTEGER frequency; static double frequencyMult; @@ -52,82 +39,6 @@ double time_now_d() { return elapsed * frequencyMult; } -// Fake, but usable in a pinch. Don't, though. -uint64_t time_now_raw() { - return (uint64_t)(time_now_d() * nanos); -} - -double from_time_raw(uint64_t raw_time) { - if (raw_time == 0) { - return 0.0; // invalid time - } - return (double)raw_time * (1.0 / nanos); -} - -double from_time_raw_relative(uint64_t raw_time) { - return from_time_raw(raw_time); -} - -double time_now_unix_utc() { - const int64_t UNIX_TIME_START = 0x019DB1DED53E8000; //January 1, 1970 (start of Unix epoch) in "ticks" - const double TICKS_PER_SECOND = 10000000; //a tick is 100ns - - FILETIME ft; - GetSystemTimeAsFileTime(&ft); //returns ticks in UTC - // Copy the low and high parts of FILETIME into a LARGE_INTEGER - LARGE_INTEGER li; - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - //Convert ticks since 1/1/1970 into seconds - return (double)(li.QuadPart - UNIX_TIME_START) / TICKS_PER_SECOND; -} - -void yield() { - YieldProcessor(); -} - -#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - -// The only intended use is to match the timings in VK_GOOGLE_display_timing -uint64_t time_now_raw() { - struct timespec tp; - clock_gettime(CLOCK_MONOTONIC, &tp); - return tp.tv_sec * 1000000000ULL + tp.tv_nsec; -} - -static uint64_t g_startTime; - -double from_time_raw(uint64_t raw_time) { - return (double)(raw_time - g_startTime) * (1.0 / nanos); -} - -double time_now_d() { - uint64_t raw_time = time_now_raw(); - if (g_startTime == 0) { - g_startTime = raw_time; - } - return from_time_raw(raw_time); -} - -double from_time_raw_relative(uint64_t raw_time) { - return (double)raw_time * (1.0 / nanos); -} - -double time_now_unix_utc() { - struct timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - return tp.tv_sec * 1000000000ULL + tp.tv_nsec; -} - -void yield() { -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - _mm_pause(); -#elif PPSSPP_ARCH(ARM64) - // Took this out for now. See issue #17877 - // __builtin_arm_isb(15); -#endif -} - #else double time_now_d() { @@ -137,31 +48,7 @@ double time_now_d() { if (start == 0) { start = tv.tv_sec; } - return (double)(tv.tv_sec - start) + (double)tv.tv_usec * (1.0 / micros); -} - -uint64_t time_now_raw() { - static time_t start; - struct timeval tv; - gettimeofday(&tv, nullptr); - if (start == 0) { - start = tv.tv_sec; - } - return (double)tv.tv_sec + (double)tv.tv_usec * (1.0 / micros); -} - -double from_time_raw(uint64_t raw_time) { - return (double)raw_time * (1.0 / nanos); -} - -double from_time_raw_relative(uint64_t raw_time) { - return from_time_raw(raw_time); -} - -void yield() {} - -double time_now_unix_utc() { - return time_now_raw(); + return (double)(tv.tv_sec - start) + (double)tv.tv_usec * (1.0 / 1000000.0); } #endif @@ -171,8 +58,6 @@ void sleep_ms(int ms) { Sleep(ms); #elif defined(HAVE_LIBNX) svcSleepThread(ms * 1000000); -#elif defined(__EMSCRIPTEN__) - emscripten_sleep(ms); #else usleep(ms * 1000); #endif diff --git a/Common/TimeUtil.h b/Common/TimeUtil.h index 779ba07d2..0faf6dac2 100644 --- a/Common/TimeUtil.h +++ b/Common/TimeUtil.h @@ -1,27 +1,11 @@ #pragma once -#include - // Seconds. double time_now_d(); -// Raw time in nanoseconds. -// The only intended use is to match the timings from VK_GOOGLE_display_timing. -uint64_t time_now_raw(); - -// This is only interesting for Linux, in relation to VK_GOOGLE_display_timing. -double from_time_raw(uint64_t raw_time); -double from_time_raw_relative(uint64_t raw_time); - -// Seconds, Unix UTC time -double time_now_unix_utc(); - // Sleep. Does not necessarily have millisecond granularity, especially on Windows. void sleep_ms(int ms); -// Yield. Signals that this thread is busy-waiting but wants to allow other hyperthreads to run. -void yield(); - void GetTimeFormatted(char formattedTime[13]); // Rust-style Instant for clear and easy timing. diff --git a/Common/UI/Context.cpp b/Common/UI/Context.cpp index 31b59419e..cb62571bf 100644 --- a/Common/UI/Context.cpp +++ b/Common/UI/Context.cpp @@ -208,12 +208,10 @@ void UIContext::SetFontStyle(const UI::FontStyle &fontStyle) { } void UIContext::MeasureText(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, float *x, float *y, int align) const { - _dbg_assert_(str != nullptr); MeasureTextCount(style, scaleX, scaleY, str, (int)strlen(str), x, y, align); } void UIContext::MeasureTextCount(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, int count, float *x, float *y, int align) const { - _dbg_assert_(str != nullptr); if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { float sizeFactor = (float)style.sizePts / 24.0f; Draw()->SetFontScale(scaleX * sizeFactor, scaleY * sizeFactor); @@ -227,7 +225,6 @@ void UIContext::MeasureTextCount(const UI::FontStyle &style, float scaleX, float } void UIContext::MeasureTextRect(const UI::FontStyle &style, float scaleX, float scaleY, const char *str, int count, const Bounds &bounds, float *x, float *y, int align) const { - _dbg_assert_(str != nullptr); if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { float sizeFactor = (float)style.sizePts / 24.0f; Draw()->SetFontScale(scaleX * sizeFactor, scaleY * sizeFactor); @@ -241,7 +238,6 @@ void UIContext::MeasureTextRect(const UI::FontStyle &style, float scaleX, float } void UIContext::DrawText(const char *str, float x, float y, uint32_t color, int align) { - _dbg_assert_(str != nullptr); if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { // Use the font texture if this font is in that texture instead. bool useFontTexture = Draw()->GetFontAtlas()->getFont(fontStyle_->atlasFont) != nullptr; @@ -290,28 +286,6 @@ void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t col RebindTexture(); } -static constexpr float MIN_TEXT_SCALE = 0.7f; - -float UIContext::CalculateTextScale(const char *text, float availWidth, float availHeight) const { - float actualWidth, actualHeight; - Bounds availBounds(0, 0, availWidth, availHeight); - MeasureTextRect(theme->uiFont, 1.0f, 1.0f, text, (int)strlen(text), availBounds, &actualWidth, &actualHeight, ALIGN_VCENTER); - if (actualWidth > availWidth) { - return std::max(MIN_TEXT_SCALE, availWidth / actualWidth); - } - return 1.0f; -} - -void UIContext::DrawTextRectSqueeze(const char *str, const Bounds &bounds, uint32_t color, int align) { - float origScaleX = fontScaleX_; - float origScaleY = fontScaleY_; - float scale = CalculateTextScale(str, bounds.w / origScaleX, bounds.h / origScaleY); - SetFontScale(scale * origScaleX, scale * origScaleY); - Bounds textBounds(bounds.x, bounds.y, bounds.w, bounds.h); - DrawTextRect(str, textBounds, color, align); - SetFontScale(origScaleX, origScaleY); -} - void UIContext::DrawTextShadowRect(const char *str, const Bounds &bounds, uint32_t color, int align) { uint32_t alpha = (color >> 1) & 0xFF000000; Bounds shadowBounds(bounds.x+2, bounds.y+2, bounds.w, bounds.h); @@ -339,17 +313,6 @@ void UIContext::FillRect(const UI::Drawable &drawable, const Bounds &bounds) { } } -void UIContext::DrawRectDropShadow(const Bounds &bounds, float radius, float alpha, uint32_t color) { - if (alpha <= 0.0f) - return; - - color = colorAlpha(color, alpha); - - // Bias the shadow downwards a bit. - Bounds shadowBounds = bounds.Expand(radius, 0.5 * radius, radius, 1.5 * radius); - Draw()->DrawImage4Grid(theme->dropShadow4Grid, shadowBounds.x, shadowBounds.y, shadowBounds.x2(), shadowBounds.y2(), color, radius * (1.0f / 24.0f) * 2.0f); -} - void UIContext::DrawImageVGradient(ImageID image, uint32_t color1, uint32_t color2, const Bounds &bounds) { uidrawbuffer_->DrawImageStretchVGradient(image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), color1, color2); } diff --git a/Common/UI/Context.h b/Common/UI/Context.h index f555fffa9..1e2767d18 100644 --- a/Common/UI/Context.h +++ b/Common/UI/Context.h @@ -77,8 +77,6 @@ public: void SetTintSaturation(float tint, float sat); - // High level drawing functions. They generally assume the default texture to be bounds. - void SetFontStyle(const UI::FontStyle &style); const UI::FontStyle &GetFontStyle() { return *fontStyle_; } void SetFontScale(float scaleX, float scaleY); @@ -89,13 +87,7 @@ public: void DrawTextShadow(const char *str, float x, float y, uint32_t color, int align = 0); void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0); void DrawTextShadowRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0); - // Will squeeze the text into the bounds if needed. - void DrawTextRectSqueeze(const char *str, const Bounds &bounds, uint32_t color, int align = 0); - - float CalculateTextScale(const char *text, float availWidth, float availHeight) const; - void FillRect(const UI::Drawable &drawable, const Bounds &bounds); - void DrawRectDropShadow(const Bounds &bounds, float radius, float alpha, uint32_t color = 0); void DrawImageVGradient(ImageID image, uint32_t color1, uint32_t color2, const Bounds &bounds); // in dps, like dp_xres and dp_yres diff --git a/Common/UI/IconCache.cpp b/Common/UI/IconCache.cpp deleted file mode 100644 index 5a43b2674..000000000 --- a/Common/UI/IconCache.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include - -#include "Common/UI/IconCache.h" -#include "Common/UI/Context.h" -#include "Common/TimeUtil.h" -#include "Common/Data/Format/PNGLoad.h" -#include "Common/Log.h" - -#define ICON_CACHE_VERSION 1 -#define MK_FOURCC(str) (str[0] | ((uint8_t)str[1] << 8) | ((uint8_t)str[2] << 16) | ((uint8_t)str[3] << 24)) - -#define MAX_RUNTIME_CACHE_SIZE (1024 * 1024 * 4) -#define MAX_SAVED_CACHE_SIZE (1024 * 1024 * 1) - -const uint32_t ICON_CACHE_MAGIC = MK_FOURCC("pICN"); - -IconCache g_iconCache; - -struct DiskCacheHeader { - uint32_t magic; - uint32_t version; - uint32_t entryCount; -}; - -struct DiskCacheEntry { - uint32_t keyLen; - uint32_t dataLen; - IconFormat format; - double insertedTimestamp; -}; - -void IconCache::SaveToFile(FILE *file) { - std::unique_lock lock(lock_); - - // First, compute the total size. If above a threshold, remove until under. - Decimate(MAX_SAVED_CACHE_SIZE); - - DiskCacheHeader header; - header.magic = ICON_CACHE_MAGIC; - header.version = ICON_CACHE_VERSION; - header.entryCount = (uint32_t)cache_.size(); - - fwrite(&header, 1, sizeof(header), file); - - for (auto &iter : cache_) { - DiskCacheEntry entryHeader; - memset(&entryHeader, 0, sizeof(entryHeader)); // valgrind complains about padding bytes - entryHeader.keyLen = (uint32_t)iter.first.size(); - entryHeader.dataLen = (uint32_t)iter.second.data.size(); - entryHeader.format = iter.second.format; - entryHeader.insertedTimestamp = iter.second.insertedTimeStamp; - fwrite(&entryHeader, 1, sizeof(entryHeader), file); - fwrite(iter.first.c_str(), 1, iter.first.size(), file); - fwrite(iter.second.data.data(), 1, iter.second.data.size(), file); - } -} - -bool IconCache::LoadFromFile(FILE *file) { - std::unique_lock lock(lock_); - - DiskCacheHeader header; - if (fread(&header, 1, sizeof(header), file) != sizeof(DiskCacheHeader)) { - return false; - } - if (header.magic != ICON_CACHE_MAGIC || header.version != ICON_CACHE_VERSION) { - return false; - } - - double now = time_now_d(); - - for (uint32_t i = 0; i < header.entryCount; i++) { - DiskCacheEntry entryHeader; - if (fread(&entryHeader, 1, sizeof(entryHeader), file) != sizeof(entryHeader)) { - break; - } - - std::string key; - key.resize(entryHeader.keyLen, 0); - if (entryHeader.keyLen > 0x1000) { - // Let's say this is invalid, probably a corrupted file. - break; - } - - if (fread(&key[0], 1, entryHeader.keyLen, file) != entryHeader.keyLen) { - break; - } - - // Check if we already have the entry somehow. - if (cache_.find(key) != cache_.end()) { - // Seek past the data and go to the next entry. - fseek(file, entryHeader.dataLen, SEEK_CUR); - continue; - } - - std::string data; - data.resize(entryHeader.dataLen); - size_t len = fread(&data[0], 1, entryHeader.dataLen, file); - if (len != (size_t)entryHeader.dataLen) { - // Stop reading and don't use this entry. Seems the file is truncated, but we'll recover. - break; - } - - Entry entry{}; - entry.data = data; - entry.format = entryHeader.format; - entry.insertedTimeStamp = entryHeader.insertedTimestamp; - entry.usedTimeStamp = now; - cache_.insert(std::pair(key, entry)); - } - - return true; -} - -void IconCache::ClearTextures() { - std::unique_lock lock(lock_); - for (auto &iter : cache_) { - if (iter.second.texture) { - iter.second.texture->Release(); - iter.second.texture = nullptr; - } - } -} - -void IconCache::ClearData() { - ClearTextures(); - std::unique_lock lock(lock_); - cache_.clear(); -} - -void IconCache::FrameUpdate() { - std::unique_lock lock(lock_); - // Remove old textures after a while. - double now = time_now_d(); - if (now > lastUpdate_ + 2.0) { - for (auto &iter : cache_) { - double useAge = now - iter.second.usedTimeStamp; - if (useAge > 5.0) { - // Release the texture after a few seconds of no use. - // Still, keep the png data loaded, it's small. - if (iter.second.texture) { - iter.second.texture->Release(); - iter.second.texture = nullptr; - } - } - } - lastUpdate_ = now; - } - - if (now > lastDecimate_ + 60.0) { - Decimate(MAX_RUNTIME_CACHE_SIZE); - lastDecimate_ = now; - } -} - -void IconCache::Decimate(int64_t maxSize) { - // Call this under the lock. - - int64_t totalSize = 0; - for (auto &iter : cache_) { - totalSize += iter.second.data.size(); - } - - if (totalSize <= maxSize) { - return; - } - - // Create a list of all the entries, sort by date. Then delete until we reach the desired size. - struct SortEntry { - std::string key; - double usedTimestamp; - size_t size; - }; - - std::vector sortEntries; - for (auto iter : cache_) { - sortEntries.push_back({ iter.first, iter.second.usedTimeStamp, iter.second.data.size() }); - } - - std::sort(sortEntries.begin(), sortEntries.end(), [](const SortEntry &a, const SortEntry &b) { - // Oldest should be last in the lsit. - return a.usedTimestamp > b.usedTimestamp; - }); - - while (totalSize > maxSize && !sortEntries.empty()) { - totalSize -= sortEntries.back().size; - auto iter = cache_.find(sortEntries.back().key); - if (iter != cache_.end()) { - if (iter->second.texture) { - iter->second.texture->Release(); - } - cache_.erase(iter); - } - sortEntries.pop_back(); - } -} - -bool IconCache::GetDimensions(const std::string &key, int *width, int *height) { - std::unique_lock lock(lock_); - auto iter = cache_.find(key); - if (iter == cache_.end()) { - // Don't have this entry. - return false; - } - - if (iter->second.texture) { - // TODO: Store the width/height in the cache. - *width = iter->second.texture->Width(); - *height = iter->second.texture->Height(); - return true; - } else { - return false; - } -} - -bool IconCache::Contains(const std::string &key) { - std::unique_lock lock(lock_); - return cache_.find(key) != cache_.end(); -} - -bool IconCache::MarkPending(const std::string &key) { - std::unique_lock lock(lock_); - if (cache_.find(key) != cache_.end()) { - return false; - } - if (pending_.find(key) != pending_.end()) { - return false; - } - pending_.insert(key); - return true; -} - -void IconCache::CancelPending(const std::string &key) { - std::unique_lock lock(lock_); - pending_.erase(key); -} - -bool IconCache::InsertIcon(const std::string &key, IconFormat format, std::string &&data) { - if (key.empty()) { - return false; - } - - if (data.empty()) { - _dbg_assert_(false); - ERROR_LOG(G3D, "Can't insert empty data into icon cache"); - return false; - } - - std::unique_lock lock(lock_); - if (cache_.find(key) != cache_.end()) { - // Already have this entry. - return false; - } - - if (data.size() > 1024 * 512) { - WARN_LOG(G3D, "Unusually large icon inserted in icon cache: %s (%d bytes)", key.c_str(), (int)data.size()); - } - - pending_.erase(key); - - double now = time_now_d(); - cache_.emplace(key, Entry{ std::move(data), format, nullptr, now, now, false }); - return true; -} - -Draw::Texture *IconCache::BindIconTexture(UIContext *context, const std::string &key) { - if (key.empty()) { - return nullptr; - } - - // TODO: Cut down on how long we're holding this lock here. - std::unique_lock lock(lock_); - auto iter = cache_.find(key); - if (iter == cache_.end()) { - // Don't have this entry. - return nullptr; - } - - if (iter->second.texture) { - context->GetDrawContext()->BindTexture(0, iter->second.texture); - iter->second.usedTimeStamp = time_now_d(); - return iter->second.texture; - } - - if (iter->second.badData) { - return nullptr; - } - - // OK, don't have a texture. Upload it! - int width = 0; - int height = 0; - Draw::DataFormat dataFormat; - unsigned char *buffer = nullptr; - - switch (iter->second.format) { - case IconFormat::PNG: - { - int result = pngLoadPtr((const unsigned char *)iter->second.data.data(), iter->second.data.size(), &width, - &height, &buffer); - - if (result != 1) { - ERROR_LOG(G3D, "IconCache: Failed to load png (%d bytes) for key %s", (int)iter->second.data.size(), key.c_str()); - iter->second.badData = true; - return nullptr; - } - dataFormat = Draw::DataFormat::R8G8B8A8_UNORM; - break; - } - default: - return nullptr; - } - - Draw::TextureDesc iconDesc{}; - iconDesc.width = width; - iconDesc.height = height; - iconDesc.depth = 1; - iconDesc.initData.push_back((const uint8_t *)buffer); - iconDesc.mipLevels = 1; - iconDesc.swizzle = Draw::TextureSwizzle::DEFAULT; - iconDesc.generateMips = false; - iconDesc.tag = key.c_str(); - iconDesc.format = dataFormat; - iconDesc.type = Draw::TextureType::LINEAR2D; - - Draw::Texture *texture = context->GetDrawContext()->CreateTexture(iconDesc); - iter->second.texture = texture; - iter->second.usedTimeStamp = time_now_d(); - - free(buffer); - - return texture; -} - -IconCacheStats IconCache::GetStats() { - IconCacheStats stats{}; - - std::unique_lock lock(lock_); - - for (auto &iter : cache_) { - stats.cachedCount++; - if (iter.second.texture) - stats.textureCount++; - stats.dataSize += iter.second.data.size(); - } - - stats.pending = pending_.size(); - - return stats; -} diff --git a/Common/UI/IconCache.h b/Common/UI/IconCache.h deleted file mode 100644 index a3646c525..000000000 --- a/Common/UI/IconCache.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "Common/GPU/thin3d.h" - -class UIContext; - -enum class IconFormat : uint32_t { - PNG, -}; - -namespace Draw { -class Texture; -} - -// TODO: Possibly make this smarter and use instead of ManagedTexture? - -struct IconCacheStats { - size_t cachedCount; - size_t textureCount; // number of cached images that are "live" textures - size_t pending; - size_t dataSize; -}; - -class IconCache { -public: - // NOTE: Don't store the returned texture. Only use it to look up dimensions or other properties, - // instead call BindIconTexture every time you want to use it. - Draw::Texture *BindIconTexture(UIContext *context, const std::string &key); - - // It's okay to call these from any thread. - bool MarkPending(const std::string &key); // returns false if already pending or loaded - void CancelPending(const std::string &key); - bool InsertIcon(const std::string &key, IconFormat format, std::string &&pngData); - bool GetDimensions(const std::string &key, int *width, int *height); - bool Contains(const std::string &key); - - void SaveToFile(FILE *file); - bool LoadFromFile(FILE *file); - - void FrameUpdate(); - - void ClearTextures(); - void ClearData(); - - IconCacheStats GetStats(); - -private: - void Decimate(int64_t maxSize); - - struct Entry { - std::string data; - IconFormat format; - Draw::Texture *texture; - double insertedTimeStamp; - double usedTimeStamp; - bool badData; - }; - - std::map cache_; - std::set pending_; - - std::mutex lock_; - - double lastUpdate_ = 0.0; - double lastDecimate_ = 0.0; -}; - -extern IconCache g_iconCache; diff --git a/Common/UI/PopupScreens.cpp b/Common/UI/PopupScreens.cpp index f3dacb997..3ed8f21d8 100644 --- a/Common/UI/PopupScreens.cpp +++ b/Common/UI/PopupScreens.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "Common/UI/PopupScreens.h" #include "Common/UI/ViewGroup.h" @@ -8,8 +7,6 @@ #include "Common/UI/Root.h" #include "Common/StringUtils.h" #include "Common/Data/Text/I18n.h" -#include "Common/System/System.h" -#include "Common/System/Request.h" namespace UI { @@ -17,9 +14,9 @@ void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; UIContext &dc = *screenManager()->getUIContext(); - std::vector messageLines; + std::vector messageLines; SplitString(message_, '\n', messageLines); - for (auto lineOfText : messageLines) + for (const auto &lineOfText : messageLines) parent->Add(new UI::TextView(lineOfText, ALIGN_LEFT | ALIGN_VCENTER, false))->SetTextColor(dc.theme->popupStyle.fgColor); } @@ -122,18 +119,12 @@ void PopupMultiChoice::UpdateText() { if (index < 0 || index >= numChoices_) { valueText_ = "(invalid choice)"; // Shouldn't happen. Should be no need to translate this. } else { - if (choices_[index]) { - valueText_ = T(category_, choices_[index]); - } else { - valueText_ = ""; - } + valueText_ = T(category_, choices_[index]); } } void PopupMultiChoice::ChoiceCallback(int num) { if (num != -1) { - _assert_(value_ != nullptr); - *value_ = num + minVal_; UpdateText(); @@ -167,15 +158,12 @@ PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, int PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, float defaultValue, const std::string &text, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams) : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), defaultValue_(defaultValue), step_(1.0f), units_(units), screenManager_(screenManager) { - _dbg_assert_(maxValue > minValue); fmt_ = "%2.2f"; OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, float defaultValue, const std::string &text, float step, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams) : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), defaultValue_(defaultValue), step_(step), units_(units), screenManager_(screenManager) { - _dbg_assert_(step > 0.0f); - _dbg_assert_(maxValue > minValue); fmt_ = "%2.2f"; OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } @@ -272,7 +260,7 @@ std::string PopupSliderChoiceFloat::ValueText() const { temp[0] = '\0'; if (zeroLabel_.size() && *value_ == 0.0f) { truncate_cpy(temp, zeroLabel_.c_str()); - } else if (IsValidNumberFormatString(fmt_)) { + } else if (IsValidNumberFormatString(fmt_.c_str())) { snprintf(temp, sizeof(temp), fmt_.c_str(), *value_); } else { snprintf(temp, sizeof(temp), "%0.2f", *value_); @@ -507,16 +495,6 @@ PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string EventReturn PopupTextInputChoice::HandleClick(EventParams &e) { restoreFocus_ = HasFocus(); - // Choose method depending on platform capabilities. - if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { - System_InputBoxGetString(text_, *value_ , [=](const std::string &enteredValue, int) { - *value_ = StripSpaces(enteredValue); - EventParams params{}; - OnChange.Trigger(params); - }); - return EVENT_DONE; - } - TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_); popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange); if (e.v) @@ -604,12 +582,7 @@ void AbstractChoiceWithValueDisplay::Draw(UIContext &dc) { int paddingX = 12; dc.SetFontStyle(dc.theme->uiFont); - std::string valueText = ValueText(); - - if (passwordDisplay_) { - // Replace all characters with stars. - memset(&valueText[0], '*', valueText.size()); - } + const std::string valueText = ValueText(); // If there is a label, assume we want at least 20% of the size for it, at a minimum. @@ -663,28 +636,4 @@ std::string ChoiceWithValueDisplay::ValueText() const { return valueText.str(); } -FileChooserChoice::FileChooserChoice(std::string *value, const std::string &text, BrowseFileType fileType, LayoutParams *layoutParams) - : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), fileType_(fileType) { - OnClick.Add([=](UI::EventParams &) { - System_BrowseForFile(text_, fileType, [=](const std::string &returnValue, int) { - if (*value_ != returnValue) { - *value = returnValue; - UI::EventParams e{}; - e.s = *value; - OnChange.Trigger(e); - } - }); - return UI::EVENT_DONE; - }); -} - -std::string FileChooserChoice::ValueText() const { - if (value_->empty()) { - auto di = GetI18NCategory(I18NCat::DIALOG); - return di->T("Default"); - } - Path path(*value_); - return path.GetFilename(); -} - } // namespace diff --git a/Common/UI/PopupScreens.h b/Common/UI/PopupScreens.h index 8fdfb68e1..0e0c13bcb 100644 --- a/Common/UI/PopupScreens.h +++ b/Common/UI/PopupScreens.h @@ -1,7 +1,5 @@ #pragma once -#include "Common/System/Request.h" - #include "Common/Data/Text/I18n.h" #include "Common/UI/UIScreen.h" #include "Common/UI/UI.h" @@ -55,9 +53,6 @@ class MessagePopupScreen : public PopupScreen { public: MessagePopupScreen(std::string title, std::string message, std::string button1, std::string button2, std::function callback) : PopupScreen(title, button1, button2), message_(message), callback_(callback) {} - - const char *tag() const override { return "MessagePopupScreen"; } - UI::Event OnChoice; protected: @@ -196,16 +191,10 @@ public: void Draw(UIContext &dc) override; void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override; - void SetPasswordDisplay() { - passwordDisplay_ = true; - } - protected: virtual std::string ValueText() const = 0; float CalculateValueScale(const UIContext &dc, const std::string &valueText, float availWidth) const; - - bool passwordDisplay_ = false; }; // Reads and writes value to determine the current selection. @@ -370,7 +359,6 @@ private: bool hasDropShadow_ = true; }; -// NOTE: This one will defer to a system-native dialog if possible. class PopupTextInputChoice : public AbstractChoiceWithValueDisplay { public: PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams = 0); @@ -412,20 +400,4 @@ private: std::string(*translateCallback_)(const char *value) = nullptr; }; -enum class FileChooserFileType { - WAVE_FILE, -}; - -class FileChooserChoice : public AbstractChoiceWithValueDisplay { -public: - FileChooserChoice(std::string *value, const std::string &title, BrowseFileType fileType, LayoutParams *layoutParams = nullptr); - std::string ValueText() const override; - - Event OnChange; - -private: - std::string *value_; - BrowseFileType fileType_; -}; - } // namespace UI diff --git a/Common/UI/Root.cpp b/Common/UI/Root.cpp index 9bb84218b..ccd1f6735 100644 --- a/Common/UI/Root.cpp +++ b/Common/UI/Root.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include "ppsspp_config.h" @@ -10,14 +12,16 @@ namespace UI { +static std::mutex focusLock; static std::vector focusMoves; extern bool focusForced; static View *focusedView; static bool focusMovementEnabled; bool focusForced; +static std::mutex eventMutex_; -static std::function soundCallback; +static std::function soundCallback; static bool soundEnabled = true; struct DispatchQueueItem { @@ -25,20 +29,29 @@ struct DispatchQueueItem { EventParams params; }; +std::atomic hasDispatchQueue; std::deque g_dispatchQueue; void EventTriggered(Event *e, EventParams params) { DispatchQueueItem item{ e, params }; + + std::unique_lock guard(eventMutex_); + // Set before adding so we lock and check the added value. + hasDispatchQueue = true; g_dispatchQueue.push_front(item); } void DispatchEvents() { - while (!g_dispatchQueue.empty()) { + while (hasDispatchQueue) { DispatchQueueItem item; - if (g_dispatchQueue.empty()) - break; - item = g_dispatchQueue.back(); - g_dispatchQueue.pop_back(); + { + std::unique_lock guard(eventMutex_); + if (g_dispatchQueue.empty()) + break; + item = g_dispatchQueue.back(); + g_dispatchQueue.pop_back(); + hasDispatchQueue = !g_dispatchQueue.empty(); + } if (item.e) { item.e->Dispatch(item.params); } @@ -46,6 +59,9 @@ void DispatchEvents() { } void RemoveQueuedEventsByView(View *view) { + if (!hasDispatchQueue) + return; + std::unique_lock guard(eventMutex_); for (auto it = g_dispatchQueue.begin(); it != g_dispatchQueue.end(); ) { if (it->params.v == view) { it = g_dispatchQueue.erase(it); @@ -56,6 +72,9 @@ void RemoveQueuedEventsByView(View *view) { } void RemoveQueuedEventsByEvent(Event *event) { + if (!hasDispatchQueue) + return; + std::unique_lock guard(eventMutex_); for (auto it = g_dispatchQueue.begin(); it != g_dispatchQueue.end(); ) { if (it->e == event) { it = g_dispatchQueue.erase(it); @@ -114,15 +133,16 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root, bool ignoreInsets root->Layout(); } -static void MoveFocus(ViewGroup *root, FocusDirection direction) { - View *focusedView = GetFocusedView(); - if (!focusedView) { +void MoveFocus(ViewGroup *root, FocusDirection direction) { + if (!GetFocusedView()) { // Nothing was focused when we got in here. Focus the first non-group in the hierarchy. root->SetFocus(); return; } - NeighborResult neigh = root->FindNeighbor(focusedView, direction, NeighborResult()); + NeighborResult neigh(0, 0); + neigh = root->FindNeighbor(GetFocusedView(), direction, neigh); + if (neigh.view) { neigh.view->SetFocus(); root->SubviewFocused(neigh.view); @@ -135,13 +155,13 @@ void SetSoundEnabled(bool enabled) { soundEnabled = enabled; } -void SetSoundCallback(std::function func) { +void SetSoundCallback(std::function func) { soundCallback = func; } -void PlayUISound(UISound sound, float volume) { +void PlayUISound(UISound sound) { if (soundEnabled && soundCallback) { - soundCallback(sound, volume); + soundCallback(sound); } } @@ -155,8 +175,8 @@ static int frameCount; // completely broken input where the original keypresses have deviceId = 10 and the repeats // have deviceId = 0. struct HeldKey { - InputKeyCode key; - InputDeviceID deviceId; + int key; + int deviceId; double triggerTime; // Ignores startTime @@ -184,8 +204,8 @@ bool IsScrollKey(const KeyInput &input) { } } -static KeyEventResult KeyEventToFocusMoves(const KeyInput &key) { - KeyEventResult retval = KeyEventResult::PASS_THROUGH; +bool KeyEvent(const KeyInput &key, ViewGroup *root) { + bool retval = false; // Ignore repeats for focus moves. if ((key.flags & (KEY_DOWN | KEY_IS_REPEAT)) == KEY_DOWN) { if (IsDPadKey(key) || IsScrollKey(key)) { @@ -198,12 +218,13 @@ static KeyEventResult KeyEventToFocusMoves(const KeyInput &key) { // Check if the key is already held. If it is, ignore it. This is to avoid // multiple key repeat mechanisms colliding. if (heldKeys.find(hk) != heldKeys.end()) { - return KeyEventResult::IGNORE_KEY; + return false; } heldKeys.insert(hk); + std::lock_guard lock(focusLock); focusMoves.push_back(key.keyCode); - retval = KeyEventResult::ACCEPT; + retval = true; } } if (key.flags & KEY_UP) { @@ -215,59 +236,70 @@ static KeyEventResult KeyEventToFocusMoves(const KeyInput &key) { hk.triggerTime = 0.0; // irrelevant if (heldKeys.find(hk) != heldKeys.end()) { heldKeys.erase(hk); - retval = KeyEventResult::ACCEPT; + retval = true; } } } - return retval; -} -KeyEventResult UnsyncKeyEvent(const KeyInput &key, ViewGroup *root) { - KeyEventResult retval = KeyEventToFocusMoves(key); + retval = root->Key(key); // Ignore volume keys and stuff here. Not elegant but need to propagate bools through the view hierarchy as well... switch (key.keyCode) { case NKCODE_VOLUME_DOWN: case NKCODE_VOLUME_UP: case NKCODE_VOLUME_MUTE: - retval = KeyEventResult::PASS_THROUGH; - break; - default: - if (!(key.flags & KEY_IS_REPEAT)) { - // If a repeat, we follow what KeyEventToFocusMoves set it to. - // Otherwise we signal that we used the key, always. - retval = KeyEventResult::ACCEPT; - } + retval = false; break; } + return retval; } -bool KeyEvent(const KeyInput &key, ViewGroup *root) { - return root->Key(key); +static void ProcessHeldKeys(ViewGroup *root) { + double now = time_now_d(); + +restart: + + for (std::set::iterator iter = heldKeys.begin(); iter != heldKeys.end(); ++iter) { + if (iter->triggerTime < now) { + KeyInput key; + key.keyCode = iter->key; + key.deviceId = iter->deviceId; + key.flags = KEY_DOWN; + KeyEvent(key, root); + + std::lock_guard lock(focusLock); + focusMoves.push_back(key.keyCode); + + // Cannot modify the current item when looping over a set, so let's do this instead. + HeldKey hk = *iter; + heldKeys.erase(hk); + hk.triggerTime = now + repeatInterval; + heldKeys.insert(hk); + goto restart; + } + } } -void TouchEvent(const TouchInput &touch, ViewGroup *root) { +bool TouchEvent(const TouchInput &touch, ViewGroup *root) { focusForced = false; root->Touch(touch); if ((touch.flags & TOUCH_DOWN) && !focusForced) { EnableFocusMovement(false); } + return true; } -static void FakeKeyEvent(const KeyInput &key, ViewGroup *root) { - KeyEventToFocusMoves(key); - KeyEvent(key, root); -} - -void AxisEvent(const AxisInput &axis, ViewGroup *root) { +bool AxisEvent(const AxisInput &axis, ViewGroup *root) { enum class DirState { NONE = 0, POS = 1, NEG = 2, }; struct PrevState { - PrevState() : x(DirState::NONE), y(DirState::NONE) {} + PrevState() : x(DirState::NONE), y(DirState::NONE) { + } + DirState x; DirState y; }; @@ -286,18 +318,18 @@ void AxisEvent(const AxisInput &axis, ViewGroup *root) { // Cannot use the remapper since this is for the menu, so we provide our own // axis->button emulation here. - auto GenerateKeyFromAxis = [=](DirState old, DirState cur, InputKeyCode neg_key, InputKeyCode pos_key) { + auto GenerateKeyFromAxis = [&](DirState old, DirState cur, keycode_t neg_key, keycode_t pos_key) { if (old == cur) return; if (old == DirState::POS) { - FakeKeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, pos_key, KEY_UP }, root); + KeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, pos_key, KEY_UP }, root); } else if (old == DirState::NEG) { - FakeKeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, neg_key, KEY_UP }, root); + KeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, neg_key, KEY_UP }, root); } if (cur == DirState::POS) { - FakeKeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, pos_key, KEY_DOWN }, root); + KeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, pos_key, KEY_DOWN }, root); } else if (cur == DirState::NEG) { - FakeKeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, neg_key, KEY_DOWN }, root); + KeyEvent(KeyInput{ DEVICE_ID_KEYBOARD, neg_key, KEY_DOWN }, root); } }; @@ -328,7 +360,7 @@ void AxisEvent(const AxisInput &axis, ViewGroup *root) { // We stupidly interpret the joystick Y axis backwards on Android and Linux instead of reversing // it early (see keymaps...). Too late to fix without invalidating a lot of config files, so we // reverse it here too. -#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_UP, NKCODE_DPAD_DOWN); #else GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_DOWN, NKCODE_DPAD_UP); @@ -342,35 +374,10 @@ void AxisEvent(const AxisInput &axis, ViewGroup *root) { } break; } - default: - break; } root->Axis(axis); -} - -static void ProcessHeldKeys(ViewGroup *root) { - double now = time_now_d(); - -restart: - for (std::set::iterator iter = heldKeys.begin(); iter != heldKeys.end(); ++iter) { - if (iter->triggerTime < now) { - KeyInput key; - key.keyCode = iter->key; - key.deviceId = iter->deviceId; - key.flags = KEY_DOWN; - KeyEvent(key, root); - - focusMoves.push_back(key.keyCode); - - // Cannot modify the current item when looping over a set, so let's do this instead. - HeldKey hk = *iter; - heldKeys.erase(hk); - hk.triggerTime = now + repeatInterval; - heldKeys.insert(hk); - goto restart; - } - } + return true; } void UpdateViewHierarchy(ViewGroup *root) { @@ -383,9 +390,9 @@ void UpdateViewHierarchy(ViewGroup *root) { } if (focusMoves.size()) { + std::lock_guard lock(focusLock); EnableFocusMovement(true); if (!GetFocusedView()) { - // Find a view to focus. View *defaultView = root->GetDefaultFocusView(); // Can't focus what you can't see. if (defaultView && defaultView->GetVisibility() == V_VISIBLE) { @@ -415,4 +422,4 @@ void UpdateViewHierarchy(ViewGroup *root) { DispatchEvents(); } -} // namespace UI +} diff --git a/Common/UI/Root.h b/Common/UI/Root.h index 2c79777af..c19dc44ac 100644 --- a/Common/UI/Root.h +++ b/Common/UI/Root.h @@ -23,19 +23,10 @@ class ViewGroup; void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root, bool ignoreInsets); void UpdateViewHierarchy(ViewGroup *root); - -enum class KeyEventResult { - IGNORE_KEY, // Don't let it be processed. - PASS_THROUGH, // Let it be processed, but return false. - ACCEPT, // Let it be processed, but return true. -}; - // Hooks arrow keys for navigation -KeyEventResult UnsyncKeyEvent(const KeyInput &key, ViewGroup *root); - bool KeyEvent(const KeyInput &key, ViewGroup *root); -void TouchEvent(const TouchInput &touch, ViewGroup *root); -void AxisEvent(const AxisInput &axis, ViewGroup *root); +bool TouchEvent(const TouchInput &touch, ViewGroup *root); +bool AxisEvent(const AxisInput &axis, ViewGroup *root); enum class UISound { SELECT = 0, @@ -43,16 +34,12 @@ enum class UISound { CONFIRM, TOGGLE_ON, TOGGLE_OFF, - ACHIEVEMENT_UNLOCKED, - LEADERBOARD_SUBMITTED, COUNT, }; void SetSoundEnabled(bool enabled); -void SetSoundCallback(std::function func); +void SetSoundCallback(std::function func); -// This is only meant for actual UI navigation sound, not achievements. -// Call directly into the player for other UI effects. -void PlayUISound(UISound sound, float volume = 0.25f); +void PlayUISound(UISound sound); } // namespace UI diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index cf5e754de..047ec0448 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -6,20 +6,13 @@ #include "Common/UI/UI.h" #include "Common/UI/View.h" #include "Common/UI/ViewGroup.h" -#include "Common/UI/IconCache.h" #include "Common/Log.h" #include "Common/TimeUtil.h" -#include "Core/KeyMap.h" - -void Screen::focusChanged(ScreenFocusChange focusChange) { - char *eventName = ""; - switch (focusChange) { - case ScreenFocusChange::FOCUS_LOST_TOP: eventName = "FOCUS_LOST_TOP"; break; - case ScreenFocusChange::FOCUS_BECAME_TOP: eventName = "FOCUS_BECAME_TOP"; break; - } - DEBUG_LOG(SYSTEM, "Screen %s got %s", this->tag(), eventName); +ScreenManager::ScreenManager() { + uiContext_ = 0; + dialogFinished_ = 0; } ScreenManager::~ScreenManager() { @@ -27,8 +20,6 @@ ScreenManager::~ScreenManager() { } void ScreenManager::switchScreen(Screen *screen) { - // TODO: inputLock_ ? - if (!nextStack_.empty() && screen == nextStack_.front().screen) { ERROR_LOG(SYSTEM, "Already switching to this screen"); return; @@ -57,15 +48,9 @@ void ScreenManager::update() { switchToNext(); } - if (overlayScreen_) { - // NOTE: This is not a full UIScreen update, to avoid double global event processing. - overlayScreen_->update(); - } if (stack_.size()) { stack_.back().screen->update(); } - - g_iconCache.FrameUpdate(); } void ScreenManager::switchToNext() { @@ -77,17 +62,14 @@ void ScreenManager::switchToNext() { Layer temp = {nullptr, 0}; if (!stack_.empty()) { temp = stack_.back(); - temp.screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); stack_.pop_back(); } stack_.push_back(nextStack_.front()); - nextStack_.front().screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); if (temp.screen) { delete temp.screen; } UI::SetFocusedView(nullptr); - // When will this ever happen? Should handle focus here too? for (size_t i = 1; i < nextStack_.size(); ++i) { stack_.push_back(nextStack_[i]); } @@ -100,18 +82,11 @@ void ScreenManager::touch(const TouchInput &touch) { if (touch.flags & TOUCH_RELEASE_ALL) { for (auto &layer : stack_) { Screen *screen = layer.screen; - layer.screen->UnsyncTouch(screen->transformTouch(touch)); + layer.screen->touch(screen->transformTouch(touch)); } } else if (!stack_.empty()) { - // Let the overlay know about touch-downs, to be able to dismiss popups. - bool skip = false; - if (overlayScreen_ && (touch.flags & TOUCH_DOWN)) { - skip = overlayScreen_->UnsyncTouch(overlayScreen_->transformTouch(touch)); - } - if (!skip) { - Screen *screen = stack_.back().screen; - stack_.back().screen->UnsyncTouch(screen->transformTouch(touch)); - } + Screen *screen = stack_.back().screen; + stack_.back().screen->touch(screen->transformTouch(touch)); } } @@ -121,25 +96,40 @@ bool ScreenManager::key(const KeyInput &key) { // Send key up to every screen layer, to avoid stuck keys. if (key.flags & KEY_UP) { for (auto &layer : stack_) { - result = layer.screen->UnsyncKey(key); + result = layer.screen->key(key); } } else if (!stack_.empty()) { - result = stack_.back().screen->UnsyncKey(key); + result = stack_.back().screen->key(key); } return result; } -void ScreenManager::axis(const AxisInput *axes, size_t count) { +void ScreenManager::axis(const AxisInput &axis) { std::lock_guard guard(inputLock_); - if (!stack_.empty()) { - stack_.back().screen->UnsyncAxis(axes, count); + + // Ignore duplicate values to prevent axis values overwriting each other. + uint64_t key = ((uint64_t)axis.axisId << 32) | axis.deviceId; + // Center value far from zero just to ensure we send the first zero. + // PSP games can't see higher resolution than this. + int value = 128 + ceilf(axis.value * 127.5f + 127.5f); + if (lastAxis_[key] == value) { + return; + } + lastAxis_[key] = value; + + // Send center axis to every screen layer. + if (axis.value == 0) { + for (auto &layer : stack_) { + layer.screen->axis(axis); + } + } else if (!stack_.empty()) { + stack_.back().screen->axis(axis); } } void ScreenManager::deviceLost() { for (auto &iter : stack_) iter.screen->deviceLost(); - g_iconCache.ClearTextures(); } void ScreenManager::deviceRestored() { @@ -160,49 +150,35 @@ void ScreenManager::resized() { void ScreenManager::render() { if (!stack_.empty()) { switch (stack_.back().flags) { + case LAYER_SIDEMENU: case LAYER_TRANSPARENT: if (stack_.size() == 1) { ERROR_LOG(SYSTEM, "Can't have sidemenu over nothing"); break; } else { - auto last = stack_.end(); - auto iter = last; + auto iter = stack_.end(); iter--; - while (iter->flags == LAYER_TRANSPARENT) { - iter--; - } - auto first = iter; - _assert_(iter->screen); + iter--; + Layer backback = *iter; + + _assert_(backback.screen); // TODO: Make really sure that this "mismatched" pre/post only happens // when screens are "compatible" (both are UIScreens, for example). - first->screen->preRender(); - while (iter < last) { - iter->screen->render(); - iter++; - } + backback.screen->preRender(); + backback.screen->render(); stack_.back().screen->render(); - if (overlayScreen_) { - overlayScreen_->render(); - } - if (postRenderCb_) { - // Really can't render anything after this! Will crash the screenshot mechanism if we do. + if (postRenderCb_) postRenderCb_(getUIContext(), postRenderUserdata_); - } - first->screen->postRender(); + backback.screen->postRender(); break; } default: _assert_(stack_.back().screen); stack_.back().screen->preRender(); stack_.back().screen->render(); - if (overlayScreen_) { - overlayScreen_->render(); - } - if (postRenderCb_) { - // Really can't render anything after this! Will crash the screenshot mechanism if we do. + if (postRenderCb_) postRenderCb_(getUIContext(), postRenderUserdata_); - } stack_.back().screen->postRender(); break; } @@ -222,10 +198,10 @@ void ScreenManager::getFocusPosition(float &x, float &y, float &z) { z = stack_.size(); } -void ScreenManager::sendMessage(UIMessage message, const char *value) { - if (message == UIMessage::RECREATE_VIEWS) { +void ScreenManager::sendMessage(const char *msg, const char *value) { + if (!strcmp(msg, "recreateviews")) RecreateAllViews(); - } else if (message == UIMessage::LOST_FOCUS) { + if (!strcmp(msg, "lost_focus")) { TouchInput input{}; input.x = -50000.0f; input.y = -50000.0f; @@ -234,9 +210,8 @@ void ScreenManager::sendMessage(UIMessage message, const char *value) { input.id = 0; touch(input); } - if (!stack_.empty()) - stack_.back().screen->sendMessage(message, value); + stack_.back().screen->sendMessage(msg, value); } Screen *ScreenManager::topScreen() const { @@ -254,8 +229,6 @@ void ScreenManager::shutdown() { for (auto layer : nextStack_) delete layer.screen; nextStack_.clear(); - delete overlayScreen_; - overlayScreen_ = nullptr; } void ScreenManager::push(Screen *screen, int layerFlags) { @@ -276,37 +249,23 @@ void ScreenManager::push(Screen *screen, int layerFlags) { touch(input); Layer layer = {screen, layerFlags}; - - if (!stack_.empty()) { - stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); - } - - if (nextStack_.empty()) { - layer.screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); + if (nextStack_.empty()) stack_.push_back(layer); - } else { + else nextStack_.push_back(layer); - } } void ScreenManager::pop() { std::lock_guard guard(inputLock_); - if (!stack_.empty()) { - stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); - + if (stack_.size()) { delete stack_.back().screen; stack_.pop_back(); - - if (!stack_.empty()) { - stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); - } } else { ERROR_LOG(SYSTEM, "Can't pop when stack empty"); } } void ScreenManager::RecreateAllViews() { - std::lock_guard guard(inputLock_); for (auto it = stack_.begin(); it != stack_.end(); ++it) { it->screen->RecreateViews(); } @@ -343,19 +302,12 @@ void ScreenManager::processFinishDialog() { std::lock_guard guard(inputLock_); // Another dialog may have been pushed before the render, so search for it. Screen *caller = dialogParent(dialogFinished_); - bool erased = false; for (size_t i = 0; i < stack_.size(); ++i) { if (stack_[i].screen == dialogFinished_) { - stack_[i].screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); stack_.erase(stack_.begin() + i); - erased = true; } } - if (erased && !stack_.empty()) { - stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); - } - if (!caller) { ERROR_LOG(SYSTEM, "ERROR: no top screen when finishing dialog"); } else if (caller != topScreen()) { @@ -369,11 +321,3 @@ void ScreenManager::processFinishDialog() { dialogFinished_ = nullptr; } } - -void ScreenManager::SetOverlayScreen(Screen *screen) { - if (overlayScreen_) { - delete overlayScreen_; - } - overlayScreen_ = screen; - overlayScreen_->setScreenManager(this); -} diff --git a/Common/UI/Screen.h b/Common/UI/Screen.h index ae911b120..2db57f115 100644 --- a/Common/UI/Screen.h +++ b/Common/UI/Screen.h @@ -21,7 +21,6 @@ #include "Common/Common.h" #include "Common/Input/InputState.h" -#include "Common/System/System.h" namespace UI { class View; @@ -42,11 +41,6 @@ namespace Draw { class DrawContext; } -enum class ScreenFocusChange { - FOCUS_LOST_TOP, // Another screen was pushed on top - FOCUS_BECAME_TOP, // Became the top screen again -}; - class Screen { public: Screen() : screenManager_(nullptr) { } @@ -61,18 +55,13 @@ public: virtual void postRender() {} virtual void resized() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} - virtual void sendMessage(UIMessage message, const char *value) {} + virtual void touch(const TouchInput &touch) {} + virtual bool key(const KeyInput &key) { return false; } + virtual void axis(const AxisInput &touch) {} + virtual void sendMessage(const char *msg, const char *value) {} virtual void deviceLost() {} virtual void deviceRestored() {} - virtual void focusChanged(ScreenFocusChange focusChange); - - // Return value of UnsyncTouch is only used to let the overlay screen block touches. - virtual bool UnsyncTouch(const TouchInput &touch) = 0; - // Return value of UnsyncKey is used to not block certain system keys like volume when unhandled, on Android. - virtual bool UnsyncKey(const KeyInput &touch) = 0; - virtual void UnsyncAxis(const AxisInput *axes, size_t count) = 0; - virtual void RecreateViews() {} ScreenManager *screenManager() { return screenManager_; } @@ -100,6 +89,7 @@ public: }; enum { + LAYER_SIDEMENU = 1, LAYER_TRANSPARENT = 2, }; @@ -107,6 +97,7 @@ typedef void(*PostRenderCallback)(UIContext *ui, void *userdata); class ScreenManager { public: + ScreenManager(); virtual ~ScreenManager(); void switchScreen(Screen *screen); @@ -143,18 +134,15 @@ public: // Instant touch, separate from the update() mechanism. void touch(const TouchInput &touch); bool key(const KeyInput &key); - void axis(const AxisInput *axes, size_t count); + void axis(const AxisInput &touch); // Generic facility for gross hacks :P - void sendMessage(UIMessage message, const char *value); + void sendMessage(const char *msg, const char *value); Screen *topScreen() const; void getFocusPosition(float &x, float &y, float &z); - // Will delete any existing overlay screen. - void SetOverlayScreen(Screen *screen); - std::recursive_mutex inputLock_; private: @@ -162,16 +150,14 @@ private: void switchToNext(); void processFinishDialog(); - UIContext *uiContext_ = nullptr; - Draw::DrawContext *thin3DContext_ = nullptr; + UIContext *uiContext_; + Draw::DrawContext *thin3DContext_; PostRenderCallback postRenderCb_ = nullptr; void *postRenderUserdata_ = nullptr; - const Screen *dialogFinished_ = nullptr; - DialogResult dialogResult_{}; - - Screen *overlayScreen_ = nullptr; + const Screen *dialogFinished_; + DialogResult dialogResult_; struct Layer { Screen *screen; diff --git a/Common/UI/ScrollView.cpp b/Common/UI/ScrollView.cpp index 25bad50c1..991f1c25d 100644 --- a/Common/UI/ScrollView.cpp +++ b/Common/UI/ScrollView.cpp @@ -112,8 +112,6 @@ bool ScrollView::Key(const KeyInput &input) { case DEVICE_ID_XR_CONTROLLER_RIGHT: scrollSpeed = 50; break; - default: - break; } if (input.flags & KEY_DOWN) { @@ -129,8 +127,6 @@ bool ScrollView::Key(const KeyInput &input) { case NKCODE_EXT_MOUSEWHEEL_DOWN: ScrollRelative(scrollSpeed); break; - default: - break; } } return ViewGroup::Key(input); diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index 94c3c420f..6b7a7b3c8 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -1,6 +1,5 @@ #include #include "Common/System/Display.h" -#include "Common/System/System.h" #include "Common/Input/InputState.h" #include "Common/Input/KeyCodes.h" #include "Common/Math/curves.h" @@ -10,8 +9,8 @@ #include "Common/UI/Root.h" #include "Common/Data/Text/I18n.h" #include "Common/Render/DrawBuffer.h" + #include "Common/Log.h" -#include static const bool ClickDebug = false; @@ -61,78 +60,6 @@ void UIScreen::DoRecreateViews() { } } -void UIScreen::touch(const TouchInput &touch) { - if (!ignoreInput_ && root_) { - UI::TouchEvent(touch, root_); - } -} - -void UIScreen::axis(const AxisInput &axis) { - if (!ignoreInput_ && root_) { - UI::AxisEvent(axis, root_); - } -} - -bool UIScreen::key(const KeyInput &key) { - if (!ignoreInput_ && root_) { - return UI::KeyEvent(key, root_); - } else { - return false; - } -} - -bool UIScreen::UnsyncTouch(const TouchInput &touch) { - if (ClickDebug && root_ && (touch.flags & TOUCH_DOWN)) { - INFO_LOG(SYSTEM, "Touch down!"); - std::vector views; - root_->Query(touch.x, touch.y, views); - for (auto view : views) { - INFO_LOG(SYSTEM, "%s", view->DescribeLog().c_str()); - } - } - - QueuedEvent ev{}; - ev.type = QueuedEventType::TOUCH; - ev.touch = touch; - std::lock_guard guard(eventQueueLock_); - eventQueue_.push_back(ev); - return false; -} - -void UIScreen::UnsyncAxis(const AxisInput *axes, size_t count) { - QueuedEvent ev{}; - ev.type = QueuedEventType::AXIS; - std::lock_guard guard(eventQueueLock_); - for (size_t i = 0; i < count; i++) { - ev.axis = axes[i]; - eventQueue_.push_back(ev); - } -} - -bool UIScreen::UnsyncKey(const KeyInput &key) { - bool retval = false; - if (root_) { - // TODO: Make key events async too. The return value is troublesome, though. - switch (UI::UnsyncKeyEvent(key, root_)) { - case UI::KeyEventResult::ACCEPT: - retval = true; - break; - case UI::KeyEventResult::PASS_THROUGH: - retval = false; - break; - case UI::KeyEventResult::IGNORE_KEY: - return false; - } - } - - QueuedEvent ev{}; - ev.type = QueuedEventType::KEY; - ev.key = key; - std::lock_guard guard(eventQueueLock_); - eventQueue_.push_back(ev); - return retval; -} - void UIScreen::update() { bool vertical = UseVerticalLayout(); if (vertical != lastVertical_) { @@ -145,41 +72,6 @@ void UIScreen::update() { if (root_) { UpdateViewHierarchy(root_); } - - while (true) { - QueuedEvent ev{}; - { - std::lock_guard guard(eventQueueLock_); - if (!eventQueue_.empty()) { - ev = eventQueue_.front(); - eventQueue_.pop_front(); - } else { - break; - } - } - if (ignoreInput_) { - continue; - } - switch (ev.type) { - case QueuedEventType::KEY: - key(ev.key); - break; - case QueuedEventType::TOUCH: - if (ClickDebug && (ev.touch.flags & TOUCH_DOWN)) { - INFO_LOG(SYSTEM, "Touch down!"); - std::vector views; - root_->Query(ev.touch.x, ev.touch.y, views); - for (auto view : views) { - INFO_LOG(SYSTEM, "%s", view->DescribeLog().c_str()); - } - } - touch(ev.touch); - break; - case QueuedEventType::AXIS: - axis(ev.axis); - break; - } - } } void UIScreen::deviceLost() { @@ -195,7 +87,10 @@ void UIScreen::deviceRestored() { void UIScreen::preRender() { using namespace Draw; Draw::DrawContext *draw = screenManager()->getDrawContext(); - _dbg_assert_(draw != nullptr); + if (!draw) { + return; + } + draw->BeginFrame(); // Bind and clear the back buffer draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }, "UI"); screenManager()->getUIContext()->BeginFrame(); @@ -212,7 +107,12 @@ void UIScreen::preRender() { } void UIScreen::postRender() { + Draw::DrawContext *draw = screenManager()->getDrawContext(); + if (!draw) { + return; + } screenManager()->getUIContext()->Flush(); + draw->EndFrame(); } void UIScreen::render() { @@ -248,6 +148,34 @@ TouchInput UIScreen::transformTouch(const TouchInput &touch) { return updated; } +void UIScreen::touch(const TouchInput &touch) { + if (root_ && !ignoreInput_) { + if (ClickDebug && (touch.flags & TOUCH_DOWN)) { + INFO_LOG(SYSTEM, "Touch down!"); + std::vector views; + root_->Query(touch.x, touch.y, views); + for (auto view : views) { + INFO_LOG(SYSTEM, "%s", view->DescribeLog().c_str()); + } + } + + UI::TouchEvent(touch, root_); + } +} + +bool UIScreen::key(const KeyInput &key) { + if (root_ && !ignoreInput_) { + return UI::KeyEvent(key, root_); + } + return false; +} + +void UIScreen::axis(const AxisInput &axis) { + if (root_ && !ignoreInput_) { + UI::AxisEvent(axis, root_); + } +} + void UIScreen::TriggerFinish(DialogResult result) { // From here on, this dialog cannot receive input. ignoreInput_ = true; @@ -269,10 +197,10 @@ bool UIDialogScreen::key(const KeyInput &key) { return retval; } -void UIDialogScreen::sendMessage(UIMessage message, const char *value) { +void UIDialogScreen::sendMessage(const char *msg, const char *value) { Screen *screen = screenManager()->dialogParent(this); if (screen) { - screen->sendMessage(message, value); + screen->sendMessage(msg, value); } } @@ -393,10 +321,6 @@ void PopupScreen::TriggerFinish(DialogResult result) { OnCompleted(result); } -#if PPSSPP_PLATFORM(UWP) - // Inform UI that popup close to hide OSK (if visible) - System_NotifyUIState("popup_closed"); -#endif } void PopupScreen::CreateViews() { @@ -426,6 +350,7 @@ void PopupScreen::CreateViews() { CreatePopupContents(box_); root_->SetDefaultFocusView(box_); + if (ShowButtons() && !button1_.empty()) { // And the two buttons at the bottom. LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); diff --git a/Common/UI/UIScreen.h b/Common/UI/UIScreen.h index 767cd462c..1d5443a5f 100644 --- a/Common/UI/UIScreen.h +++ b/Common/UI/UIScreen.h @@ -1,8 +1,6 @@ #pragma once -#include -#include -#include +#include #include "Common/Math/lin/vec3.h" #include "Common/UI/Screen.h" @@ -15,21 +13,6 @@ namespace Draw { class DrawContext; } -enum class QueuedEventType : u8 { - KEY, - AXIS, - TOUCH, -}; - -struct QueuedEvent { - QueuedEventType type; - union { - TouchInput touch; - KeyInput key; - AxisInput axis; - }; -}; - class UIScreen : public Screen { public: UIScreen(); @@ -42,13 +25,9 @@ public: void deviceLost() override; void deviceRestored() override; - virtual void touch(const TouchInput &touch); - virtual bool key(const KeyInput &key); - virtual void axis(const AxisInput &axis); - - bool UnsyncTouch(const TouchInput &touch) override; - bool UnsyncKey(const KeyInput &key) override; - void UnsyncAxis(const AxisInput *axes, size_t count) override; + void touch(const TouchInput &touch) override; + bool key(const KeyInput &touch) override; + void axis(const AxisInput &touch) override; TouchInput transformTouch(const TouchInput &touch) override; @@ -73,22 +52,18 @@ protected: bool ignoreInsets_ = false; bool ignoreInput_ = false; -protected: +private: void DoRecreateViews(); bool recreateViews_ = true; bool lastVertical_; - -private: - std::mutex eventQueueLock_; - std::deque eventQueue_; }; class UIDialogScreen : public UIScreen { public: UIDialogScreen() : UIScreen(), finished_(false) {} bool key(const KeyInput &key) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *msg, const char *value) override; private: bool finished_; diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index 6ebac93d3..d8fa40444 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -25,18 +25,18 @@ static constexpr Size ITEM_HEIGHT = 64.f; static constexpr float MIN_TEXT_SCALE = 0.8f; static constexpr float MAX_ITEM_SIZE = 65535.0f; -void MeasureBySpec(Size sz, float contentDim, MeasureSpec spec, float *measured) { +void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured) { if (sz == WRAP_CONTENT) { if (spec.type == UNSPECIFIED) - *measured = contentDim; + *measured = contentWidth; else if (spec.type == AT_MOST) - *measured = contentDim < spec.size ? contentDim : spec.size; + *measured = contentWidth < spec.size ? contentWidth : spec.size; else if (spec.type == EXACTLY) *measured = spec.size; } else if (sz == FILL_PARENT) { // UNSPECIFIED may have a minimum size of the parent. Let's use it to fill. if (spec.type == UNSPECIFIED) - *measured = std::max(spec.size, contentDim); + *measured = std::max(spec.size, contentWidth); else *measured = spec.size; } else if (spec.type == EXACTLY || (spec.type == AT_MOST && *measured > spec.size)) { @@ -46,7 +46,7 @@ void MeasureBySpec(Size sz, float contentDim, MeasureSpec spec, float *measured) } } -static void ApplyBoundBySpec(float &bound, MeasureSpec spec) { +void ApplyBoundBySpec(float &bound, MeasureSpec spec) { switch (spec.type) { case AT_MOST: bound = bound < spec.size ? bound : spec.size; @@ -122,8 +122,9 @@ void View::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureBySpec(layoutParams_->height, contentH, vert, &measuredHeight_); } +// Default values + void View::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - // Default values w = 10.0f; h = 10.0f; } @@ -307,21 +308,6 @@ bool IsEscapeKey(const KeyInput &key) { } } -// Corresponds to Triangle -bool IsInfoKey(const KeyInput &key) { - if (infoKeys.empty()) { - // This path is pretty much not used, infoKeys should be set. - // TODO: Get rid of this stuff? - if (key.deviceId == DEVICE_ID_KEYBOARD) { - return key.keyCode == NKCODE_S || key.keyCode == NKCODE_NUMPAD_ADD; - } else { - return key.keyCode == NKCODE_BUTTON_Y || key.keyCode == NKCODE_BUTTON_3; - } - } else { - return MatchesKeyDef(infoKeys, key); - } -} - bool IsTabLeftKey(const KeyInput &key) { if (tabLeftKeys.empty()) { // This path is pretty much not used, tabLeftKeys should be set. @@ -363,7 +349,7 @@ bool Clickable::Key(const KeyInput &key) { down_ = false; ret = true; } - } else if (down_ && IsEscapeKey(key)) { + } else if (IsEscapeKey(key)) { down_ = false; } } @@ -474,7 +460,7 @@ void Choice::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, } if (horiz.type != EXACTLY && layoutParams_->width > 0.0f && availWidth > layoutParams_->width) availWidth = layoutParams_->width; - float scale = dc.CalculateTextScale(text_.c_str(), availWidth, bounds_.h); + float scale = CalculateTextScale(dc, availWidth); Bounds availBounds(0, 0, availWidth, vert.size); float textW = 0.0f, textH = 0.0f; dc.MeasureTextRect(dc.theme->uiFont, scale, scale, text_.c_str(), (int)text_.size(), availBounds, &textW, &textH, FLAG_WRAP_TEXT); @@ -487,6 +473,16 @@ void Choice::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, h = std::max(h, ITEM_HEIGHT); } +float Choice::CalculateTextScale(const UIContext &dc, float availWidth) const { + float actualWidth, actualHeight; + Bounds availBounds(0, 0, availWidth, bounds_.h); + dc.MeasureTextRect(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), (int)text_.size(), availBounds, &actualWidth, &actualHeight, drawTextFlags_); + if (actualWidth > availWidth) { + return std::max(MIN_TEXT_SCALE, availWidth / actualWidth); + } + return 1.0f; +} + void Choice::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; if (HasFocus()) style = dc.theme->itemFocusedStyle; @@ -512,15 +508,18 @@ void Choice::Draw(UIContext &dc) { dc.Draw()->DrawImage(image_, bounds_.x + 6, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_LEFT | ALIGN_VCENTER); } + float scale = CalculateTextScale(dc, availWidth); + + dc.SetFontScale(scale, scale); if (centered_) { - dc.DrawTextRectSqueeze(text_.c_str(), bounds_, style.fgColor, ALIGN_CENTER | FLAG_WRAP_TEXT | drawTextFlags_); + dc.DrawTextRect(text_.c_str(), bounds_, style.fgColor, ALIGN_CENTER | FLAG_WRAP_TEXT | drawTextFlags_); } else { if (rightIconImage_.isValid()) { uint32_t col = rightIconKeepColor_ ? 0xffffffff : style.fgColor; // Don't apply theme to gold icon dc.Draw()->DrawImageRotated(rightIconImage_, bounds_.x2() - 32 - paddingX, bounds_.centerY(), rightIconScale_, rightIconRot_, col, rightIconFlipH_); } Bounds textBounds(bounds_.x + paddingX + textPadding_.left, bounds_.y, availWidth, bounds_.h); - dc.DrawTextRectSqueeze(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT | drawTextFlags_); + dc.DrawTextRect(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT | drawTextFlags_); } dc.SetFontScale(1.0f, 1.0f); } @@ -532,7 +531,7 @@ void Choice::Draw(UIContext &dc) { std::string Choice::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 choice"), text_); + return ReplaceAll(u->T("%1 choice"), "%1", text_); } InfoItem::InfoItem(const std::string &text, const std::string &rightText, LayoutParams *layoutParams) @@ -580,7 +579,7 @@ void InfoItem::Draw(UIContext &dc) { std::string InfoItem::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1: %2"), text_, rightText_); + return ReplaceAll(ReplaceAll(u->T("%1: %2"), "%1", text_), "%2", rightText_); } ItemHeader::ItemHeader(const std::string &text, LayoutParams *layoutParams) @@ -610,49 +609,7 @@ void ItemHeader::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec hor std::string ItemHeader::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 heading"), text_); -} - -CollapsibleHeader::CollapsibleHeader(bool *toggle, const std::string &text, LayoutParams *layoutParams) - : CheckBox(toggle, text, "", layoutParams) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = 40; -} - -void CollapsibleHeader::Draw(UIContext &dc) { - Style style = dc.theme->itemStyle; - style.background.color = 0; - if (HasFocus()) style = dc.theme->itemFocusedStyle; - if (down_) style = dc.theme->itemDownStyle; - if (!IsEnabled()) style = dc.theme->itemDisabledStyle; - - DrawBG(dc, style); - - float xoff = 37.0f; - - dc.SetFontStyle(dc.theme->uiFontSmall); - dc.DrawText(text_.c_str(), bounds_.x + 4 + xoff, bounds_.centerY(), dc.theme->headerStyle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); - dc.Draw()->DrawImageCenterTexel(dc.theme->whiteImage, bounds_.x, bounds_.y2() - 2, bounds_.x2(), bounds_.y2(), dc.theme->headerStyle.fgColor); - if (hasSubItems_) { - dc.Draw()->DrawImageRotated(ImageID("I_ARROW"), bounds_.x + 20.0f, bounds_.y + 20.0f, 1.0f, *toggle_ ? -M_PI / 2 : M_PI); - } -} - -void CollapsibleHeader::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const { - Bounds bounds(0, 0, layoutParams_->width, layoutParams_->height); - if (bounds.w < 0) { - // If there's no size, let's grow as big as we want. - bounds.w = horiz.size == 0 ? MAX_ITEM_SIZE : horiz.size; - } - if (bounds.h < 0) { - bounds.h = vert.size == 0 ? MAX_ITEM_SIZE : vert.size; - } - ApplyBoundsBySpec(bounds, horiz, vert); - dc.MeasureTextRect(dc.theme->uiFontSmall, 1.0f, 1.0f, text_.c_str(), (int)text_.length(), bounds, &w, &h, ALIGN_LEFT | ALIGN_VCENTER); -} - -void CollapsibleHeader::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - View::GetContentDimensions(dc, w, h); + return ReplaceAll(u->T("%1 heading"), "%1", text_); } void BorderView::Draw(UIContext &dc) { @@ -717,7 +674,7 @@ void PopupHeader::Draw(UIContext &dc) { std::string PopupHeader::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 heading"), text_); + return ReplaceAll(u->T("%1 heading"), "%1", text_); } void CheckBox::Toggle() { @@ -787,8 +744,10 @@ void CheckBox::Draw(UIContext &dc) { const float availWidth = bounds_.w - paddingX * 2 - imageW - paddingX; if (!text_.empty()) { + float scale = CalculateTextScale(dc, availWidth); + dc.SetFontScale(scale, scale); Bounds textBounds(bounds_.x + paddingX, bounds_.y, availWidth, bounds_.h); - dc.DrawTextRectSqueeze(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT); + dc.DrawTextRect(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT); } dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); dc.SetFontScale(1.0f, 1.0f); @@ -796,13 +755,23 @@ void CheckBox::Draw(UIContext &dc) { std::string CheckBox::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - std::string text = ApplySafeSubstitutions(u->T("%1 checkbox"), text_); + std::string text = ReplaceAll(u->T("%1 checkbox"), "%1", text_); if (!smallText_.empty()) { text += "\n" + smallText_; } return text; } +float CheckBox::CalculateTextScale(const UIContext &dc, float availWidth) const { + float actualWidth, actualHeight; + Bounds availBounds(0, 0, availWidth, bounds_.h); + dc.MeasureTextRect(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), (int)text_.size(), availBounds, &actualWidth, &actualHeight, ALIGN_VCENTER); + if (actualWidth > availWidth) { + return std::max(MIN_TEXT_SCALE, availWidth / actualWidth); + } + return 1.0f; +} + void CheckBox::GetContentDimensions(const UIContext &dc, float &w, float &h) const { ImageID image = Toggled() ? dc.theme->checkOn : dc.theme->checkOff; if (imageID_.isValid()) { @@ -830,7 +799,7 @@ void CheckBox::GetContentDimensions(const UIContext &dc, float &w, float &h) con } if (!text_.empty()) { - float scale = dc.CalculateTextScale(text_.c_str(), availWidth, bounds_.h); + float scale = CalculateTextScale(dc, availWidth); float actualWidth, actualHeight; Bounds availBounds(0, 0, availWidth, bounds_.h); @@ -889,7 +858,7 @@ void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const std::string Button::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 button"), GetText()); + return ReplaceAll(u->T("%1 button"), "%1", GetText()); } void Button::Click() { @@ -951,7 +920,7 @@ void RadioButton::GetContentDimensions(const UIContext &dc, float &w, float &h) std::string RadioButton::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 radio button"), text_); + return ReplaceAll(u->T("%1 radio button"), "%1", text_); } void RadioButton::Click() { @@ -1094,17 +1063,6 @@ TextEdit::TextEdit(const std::string &text, const std::string &title, const std: caret_ = (int)text_.size(); } -void TextEdit::FocusChanged(int focusFlags) { -#if PPSSPP_PLATFORM(UWP) - if (focusFlags == FF_GOTFOCUS) { - System_NotifyUIState("text_gotfocus"); - } - else { - System_NotifyUIState("text_lostfocus"); - } -#endif -} - void TextEdit::Draw(UIContext &dc) { dc.PushScissor(bounds_); dc.SetFontStyle(dc.theme->uiFont); @@ -1150,7 +1108,7 @@ void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) con std::string TextEdit::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 text field"), GetText()); + return ReplaceAll(u->T("%1 text field"), "%1", GetText()); } // Handles both windows and unix line endings. @@ -1232,15 +1190,13 @@ bool TextEdit::Key(const KeyInput &input) { case NKCODE_BACK: case NKCODE_ESCAPE: return false; - default: - break; } if (ctrlDown_) { switch (input.keyCode) { case NKCODE_C: // Just copy the entire text contents, until we get selection support. - System_CopyStringToClipboard(text_); + System_CopyStringToClipboard(text_.c_str()); break; case NKCODE_V: { @@ -1271,8 +1227,6 @@ bool TextEdit::Key(const KeyInput &input) { case NKCODE_Z: text_ = undo_; break; - default: - break; } } @@ -1290,8 +1244,6 @@ bool TextEdit::Key(const KeyInput &input) { case NKCODE_CTRL_RIGHT: ctrlDown_ = false; break; - default: - break; } } @@ -1341,7 +1293,7 @@ void ProgressBar::Draw(UIContext &dc) { std::string ProgressBar::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); float percent = progress_ * 100.0f; - return ApplySafeSubstitutions(u->T("Progress: %1%"), StringFromInt((int)percent)); + return ReplaceAll(u->T("Progress: %1%"), "%1", StringFromInt((int)percent)); } void Spinner::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -1417,7 +1369,7 @@ bool Slider::Key(const KeyInput &input) { } } -bool Slider::ApplyKey(InputKeyCode keyCode) { +bool Slider::ApplyKey(int keyCode) { switch (keyCode) { case NKCODE_DPAD_LEFT: case NKCODE_MINUS: @@ -1545,7 +1497,7 @@ bool SliderFloat::Key(const KeyInput &input) { } } -bool SliderFloat::ApplyKey(InputKeyCode keyCode) { +bool SliderFloat::ApplyKey(int keyCode) { switch (keyCode) { case NKCODE_DPAD_LEFT: case NKCODE_MINUS: @@ -1572,9 +1524,6 @@ bool SliderFloat::ApplyKey(InputKeyCode keyCode) { default: return false; } - - _dbg_assert_(!my_isnanorinf(*value_)); - EventParams params{}; params.v = this; params.a = (uint32_t)(*value_); @@ -1602,7 +1551,6 @@ bool SliderFloat::Touch(const TouchInput &input) { } void SliderFloat::Clamp() { - _dbg_assert_(!my_isnanorinf(*value_)); if (*value_ < minValue_) *value_ = minValue_; else if (*value_ > maxValue_) diff --git a/Common/UI/View.h b/Common/UI/View.h index 190da0b11..f857d837a 100644 --- a/Common/UI/View.h +++ b/Common/UI/View.h @@ -19,7 +19,6 @@ #include "Common/Math/lin/matrix4x4.h" #include "Common/Math/math_util.h" #include "Common/Math/geom2d.h" -#include "Common/Input/KeyCodes.h" #include "Common/Common.h" @@ -620,7 +619,7 @@ public: Event OnChange; private: - bool ApplyKey(InputKeyCode keyCode); + bool ApplyKey(int keyCode); int *value_; bool showPercent_; @@ -630,7 +629,7 @@ private: float paddingRight_; int step_; int repeat_ = 0; - InputKeyCode repeatCode_ = NKCODE_UNKNOWN; + int repeatCode_ = 0; }; class SliderFloat : public Clickable { @@ -650,7 +649,7 @@ public: Event OnChange; private: - bool ApplyKey(InputKeyCode keyCode); + bool ApplyKey(int keyCode); float *value_; float minValue_; @@ -658,7 +657,7 @@ private: float paddingLeft_; float paddingRight_; int repeat_; - InputKeyCode repeatCode_ = NKCODE_UNKNOWN; + int repeatCode_ = 0; }; // Basic button that modifies a bitfield based on the pressed status. Supports multitouch. @@ -736,6 +735,7 @@ public: protected: // hackery virtual bool IsSticky() const { return false; } + virtual float CalculateTextScale(const UIContext &dc, float availWidth) const; std::string text_; std::string smallText_; @@ -856,26 +856,15 @@ public: //allow external agents to toggle the checkbox virtual void Toggle(); virtual bool Toggled() const; +private: + float CalculateTextScale(const UIContext &dc, float availWidth) const; -protected: bool *toggle_; std::string text_; std::string smallText_; ImageID imageID_; }; -class CollapsibleHeader : public CheckBox { -public: - CollapsibleHeader(bool *toggle, const std::string &text, LayoutParams *layoutParams = nullptr); - void Draw(UIContext &dc) override; - void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override; - void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; - - void SetHasSubitems(bool hasSubItems) { hasSubItems_ = hasSubItems; } -private: - bool hasSubItems_ = true; -}; - class BitCheckBox : public CheckBox { public: BitCheckBox(uint32_t *bitfield, uint32_t bit, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = nullptr) @@ -927,10 +916,10 @@ private: class TextView : public InertView { public: - TextView(std::string_view text, LayoutParams *layoutParams = 0) + TextView(const std::string &text, LayoutParams *layoutParams = 0) : InertView(layoutParams), text_(text), textAlign_(0), textColor_(0xFFFFFFFF), small_(false), shadow_(false), focusable_(false), clip_(true) {} - TextView(std::string_view text, int textAlign, bool small, LayoutParams *layoutParams = 0) + TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small), shadow_(false), focusable_(false), clip_(true) {} void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override; @@ -971,7 +960,6 @@ public: void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; } void SetTextAlign(int align) { align_ = align; } // Only really useful for setting FLAG_DYNAMIC_ASCII - void FocusChanged(int focusFlags) override; void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; void Draw(UIContext &dc) override; std::string DescribeText() const override; @@ -1061,12 +1049,10 @@ private: }; void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); -void ApplyBoundsBySpec(Bounds &bounds, MeasureSpec horiz, MeasureSpec vert); bool IsDPadKey(const KeyInput &key); bool IsAcceptKey(const KeyInput &key); bool IsEscapeKey(const KeyInput &key); -bool IsInfoKey(const KeyInput &key); bool IsTabLeftKey(const KeyInput &key); bool IsTabRightKey(const KeyInput &key); diff --git a/Common/UI/ViewGroup.cpp b/Common/UI/ViewGroup.cpp index 229ef8206..41722bf70 100644 --- a/Common/UI/ViewGroup.cpp +++ b/Common/UI/ViewGroup.cpp @@ -47,12 +47,12 @@ ViewGroup::~ViewGroup() { Clear(); } -void ViewGroup::RemoveSubview(View *subView) { - // loop counter needed, so can't convert loop. +void ViewGroup::RemoveSubview(View *view) { + std::lock_guard guard(modifyLock_); for (size_t i = 0; i < views_.size(); i++) { - if (views_[i] == subView) { + if (views_[i] == view) { views_.erase(views_.begin() + i); - delete subView; + delete view; return; } } @@ -67,13 +67,17 @@ bool ViewGroup::ContainsSubview(const View *view) const { } void ViewGroup::Clear() { - for (View *view : views_) { - delete view; + std::lock_guard guard(modifyLock_); + for (size_t i = 0; i < views_.size(); i++) { + delete views_[i]; + views_[i] = nullptr; } views_.clear(); } void ViewGroup::PersistData(PersistStatus status, std::string anonId, PersistMap &storage) { + std::lock_guard guard(modifyLock_); + std::string tag = Tag(); if (tag.empty()) { tag = anonId; @@ -85,11 +89,12 @@ void ViewGroup::PersistData(PersistStatus status, std::string anonId, PersistMap } bool ViewGroup::Touch(const TouchInput &input) { + std::lock_guard guard(modifyLock_); bool any = false; - for (View *view : views_) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - if (view->GetVisibility() == V_VISIBLE) { - bool touch = view->Touch(input); + if ((*iter)->GetVisibility() == V_VISIBLE) { + bool touch = (*iter)->Touch(input); any = any || touch; if (exclusiveTouch_ && touch && (input.flags & TOUCH_DOWN)) { break; @@ -106,39 +111,43 @@ bool ViewGroup::Touch(const TouchInput &input) { void ViewGroup::Query(float x, float y, std::vector &list) { if (bounds_.Contains(x, y)) { list.push_back(this); - for (View *view : views_) { - view->Query(x, y, list); + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + (*iter)->Query(x, y, list); } } } bool ViewGroup::Key(const KeyInput &input) { + std::lock_guard guard(modifyLock_); bool ret = false; - for (View *view : views_) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - if (view->GetVisibility() == V_VISIBLE) - ret = ret || view->Key(input); + if ((*iter)->GetVisibility() == V_VISIBLE) + ret = ret || (*iter)->Key(input); } return ret; } void ViewGroup::Axis(const AxisInput &input) { - for (View *view : views_) { + std::lock_guard guard(modifyLock_); + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - if (view->GetVisibility() == V_VISIBLE) - view->Axis(input); + if ((*iter)->GetVisibility() == V_VISIBLE) + (*iter)->Axis(input); } } void ViewGroup::DeviceLost() { - for (View *view : views_) { - view->DeviceLost(); + std::lock_guard guard(modifyLock_); + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + (*iter)->DeviceLost(); } } void ViewGroup::DeviceRestored(Draw::DrawContext *draw) { - for (View *view : views_) { - view->DeviceRestored(draw); + std::lock_guard guard(modifyLock_); + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + (*iter)->DeviceRestored(draw); } } @@ -236,18 +245,21 @@ void ViewGroup::Update() { } bool ViewGroup::SetFocus() { + std::lock_guard guard(modifyLock_); if (!CanBeFocused() && !views_.empty()) { - for (View *view : views_) { - if (view->SetFocus()) + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->SetFocus()) return true; } } return false; } -bool ViewGroup::SubviewFocused(View *queryView) { - for (View *view : views_) { - if (view == queryView || view->SubviewFocused(queryView)) +bool ViewGroup::SubviewFocused(View *view) { + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i] == view) + return true; + if (views_[i]->SubviewFocused(view)) return true; } return false; @@ -389,13 +401,10 @@ static float GetDirectionScore(int originIndex, const View *origin, View *destin } NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { - if (!IsEnabled()) { - INFO_LOG(SCECTRL, "Not enabled"); + if (!IsEnabled()) return result; - } - if (GetVisibility() != V_VISIBLE) { + if (GetVisibility() != V_VISIBLE) return result; - } // First, find the position of the view in the list. int num = -1; @@ -406,6 +415,24 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei } } + if (direction == FOCUS_PREV || direction == FOCUS_NEXT) { + switch (direction) { + case FOCUS_PREV: + // If view not found, no neighbor to find. + if (num == -1) + return NeighborResult(0, 0.0f); + return NeighborResult(views_[(num + views_.size() - 1) % views_.size()], 0.0f); + + case FOCUS_NEXT: + // If view not found, no neighbor to find. + if (num == -1) + return NeighborResult(0, 0.0f); + return NeighborResult(views_[(num + 1) % views_.size()], 0.0f); + default: + return NeighborResult(nullptr, 0.0f); + } + } + switch (direction) { case FOCUS_UP: case FOCUS_LEFT: @@ -441,22 +468,12 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei } return result; } + case FOCUS_PREV_PAGE: case FOCUS_NEXT_PAGE: return FindScrollNeighbor(view, Point(INFINITY, INFINITY), direction, result); - case FOCUS_PREV: - // If view not found, no neighbor to find. - if (num == -1) - return NeighborResult(nullptr, 0.0f); - return NeighborResult(views_[(num + views_.size() - 1) % views_.size()], 0.0f); - case FOCUS_NEXT: - // If view not found, no neighbor to find. - if (num == -1) - return NeighborResult(0, 0.0f); - return NeighborResult(views_[(num + 1) % views_.size()], 0.0f); default: - ERROR_LOG(SYSTEM, "Bad focus direction %d", (int)direction); return result; } } @@ -812,57 +829,55 @@ void AnchorLayout::MeasureViews(const UIContext &dc, MeasureSpec horiz, MeasureS } } -static void ApplyAnchorLayoutParams(float measuredWidth, float measuredHeight, const Bounds &container, const AnchorLayoutParams *params, Bounds *vBounds) { - vBounds->w = measuredWidth; - vBounds->h = measuredHeight; - - // Clamp width/height to our own - if (vBounds->w > container.w) vBounds->w = container.w; - if (vBounds->h > container.h) vBounds->h = container.h; - - float left = 0, top = 0, right = 0, bottom = 0; - bool center = false; - if (params) { - left = params->left; - top = params->top; - right = params->right; - bottom = params->bottom; - center = params->center; - } - - if (left > NONE) { - vBounds->x = container.x + left; - if (center) - vBounds->x -= vBounds->w * 0.5f; - } else if (right > NONE) { - vBounds->x = container.x2() - right - vBounds->w; - if (center) { - vBounds->x += vBounds->w * 0.5f; - } - } else { - // Both left and right are NONE. Center. - vBounds->x = (container.w - vBounds->w) / 2.0f + container.x; - } - - if (top > NONE) { - vBounds->y = container.y + top; - if (center) - vBounds->y -= vBounds->h * 0.5f; - } else if (bottom > NONE) { - vBounds->y = container.y2() - bottom - vBounds->h; - if (center) - vBounds->y += vBounds->h * 0.5f; - } else { - // Both top and bottom are NONE. Center. - vBounds->y = (container.h - vBounds->h) / 2.0f + container.y; - } -} - void AnchorLayout::Layout() { for (size_t i = 0; i < views_.size(); i++) { const AnchorLayoutParams *params = views_[i]->GetLayoutParams()->As(); + Bounds vBounds; - ApplyAnchorLayoutParams(views_[i]->GetMeasuredWidth(), views_[i]->GetMeasuredHeight(), bounds_, params, &vBounds); + vBounds.w = views_[i]->GetMeasuredWidth(); + vBounds.h = views_[i]->GetMeasuredHeight(); + + // Clamp width/height to our own + if (vBounds.w > bounds_.w) vBounds.w = bounds_.w; + if (vBounds.h > bounds_.h) vBounds.h = bounds_.h; + + float left = 0, top = 0, right = 0, bottom = 0; + bool center = false; + if (params) { + left = params->left; + top = params->top; + right = params->right; + bottom = params->bottom; + center = params->center; + } + + if (left > NONE) { + vBounds.x = bounds_.x + left; + if (center) + vBounds.x -= vBounds.w * 0.5f; + } else if (right > NONE) { + vBounds.x = bounds_.x2() - right - vBounds.w; + if (center) { + vBounds.x += vBounds.w * 0.5f; + } + } else { + // Both left and right are NONE. Center. + vBounds.x = (bounds_.w - vBounds.w) / 2.0f + bounds_.x; + } + + if (top > NONE) { + vBounds.y = bounds_.y + top; + if (center) + vBounds.y -= vBounds.h * 0.5f; + } else if (bottom > NONE) { + vBounds.y = bounds_.y2() - bottom - vBounds.h; + if (center) + vBounds.y += vBounds.h * 0.5f; + } else { + // Both top and bottom are NONE. Center. + vBounds.y = (bounds_.h - vBounds.h) / 2.0f + bounds_.y; + } + views_[i]->SetBounds(vBounds); views_[i]->Layout(); } @@ -877,22 +892,18 @@ GridLayout::GridLayout(GridLayoutSettings settings, LayoutParams *layoutParams) void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureSpecType measureType = settings_.fillCells ? EXACTLY : AT_MOST; - int numItems = 0; for (size_t i = 0; i < views_.size(); i++) { - if (views_[i]->GetVisibility() != V_GONE) { - views_[i]->Measure(dc, MeasureSpec(measureType, settings_.columnWidth), MeasureSpec(measureType, settings_.rowHeight)); - numItems++; - } + views_[i]->Measure(dc, MeasureSpec(measureType, settings_.columnWidth), MeasureSpec(measureType, settings_.rowHeight)); } // Use the max possible width so AT_MOST gives us the full size. - float maxWidth = (settings_.columnWidth + settings_.spacing) * numItems + settings_.spacing; + float maxWidth = (settings_.columnWidth + settings_.spacing) * views_.size() + settings_.spacing; MeasureBySpec(layoutParams_->width, maxWidth, horiz, &measuredWidth_); // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. numColumns_ = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); if (!numColumns_) numColumns_ = 1; - int numRows = (numItems + (numColumns_ - 1)) / numColumns_; + int numRows = (int)(views_.size() + (numColumns_ - 1)) / numColumns_; float estimatedHeight = (settings_.rowHeight + settings_.spacing) * numRows; @@ -904,9 +915,6 @@ void GridLayout::Layout() { int x = 0; int count = 0; for (size_t i = 0; i < views_.size(); i++) { - if (views_[i]->GetVisibility() == V_GONE) - continue; - const GridLayoutParams *lp = views_[i]->GetLayoutParams()->As(); Bounds itemBounds, innerBounds; Gravity grav = lp ? lp->gravity : G_CENTER; @@ -1170,24 +1178,4 @@ StickyChoice *ChoiceStrip::Choice(int index) { return nullptr; } -CollapsibleSection::CollapsibleSection(const std::string &title, LayoutParams *layoutParams) : LinearLayout(ORIENT_VERTICAL, layoutParams) { - SetSpacing(0.0f); - - heading_ = new CollapsibleHeader(&open_, title); - views_.push_back(heading_); - heading_->OnClick.Add([=](UI::EventParams &) { - // Change the visibility of all children except the first one. - // Later maybe try something more ambitious. - for (size_t i = 1; i < views_.size(); i++) { - views_[i]->SetVisibility(open_ ? V_VISIBLE : V_GONE); - } - return UI::EVENT_DONE; - }); -} - -void CollapsibleSection::Update() { - ViewGroup::Update(); - heading_->SetHasSubitems(views_.size() > 1); -} - } // namespace UI diff --git a/Common/UI/ViewGroup.h b/Common/UI/ViewGroup.h index b0bceb3f6..b3a4ba074 100644 --- a/Common/UI/ViewGroup.h +++ b/Common/UI/ViewGroup.h @@ -15,8 +15,9 @@ class AnchorTranslateTween; class ScrollView; struct NeighborResult { - NeighborResult() : view(nullptr), score(0) {} + NeighborResult() : view(0), score(0) {} NeighborResult(View *v, float s) : view(v), score(s) {} + View *view; float score; }; @@ -45,6 +46,7 @@ public: // Takes ownership! DO NOT add a view to multiple parents! template T *Add(T *view) { + std::lock_guard guard(modifyLock_); views_.push_back(view); return view; } @@ -75,6 +77,9 @@ public: void SetExclusiveTouch(bool exclusive) { exclusiveTouch_ = exclusive; } void SetClickableBackground(bool clickableBackground) { clickableBackground_ = clickableBackground; } + void Lock() { modifyLock_.lock(); } + void Unlock() { modifyLock_.unlock(); } + void SetClip(bool clip) { clip_ = clip; } std::string DescribeLog() const override { return "ViewGroup: " + View::DescribeLog(); } std::string DescribeText() const override; @@ -83,6 +88,7 @@ protected: std::string DescribeListUnordered(const char *heading) const; std::string DescribeListOrdered(const char *heading) const; + std::mutex modifyLock_; // Hold this when changing the subviews. std::vector views_; View *defaultFocusView_ = nullptr; Drawable bg_; @@ -285,6 +291,7 @@ private: bool topTabs_ = false; }; + class TabHolder : public LinearLayout { public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0); @@ -319,17 +326,4 @@ private: std::vector tabTweens_; }; -class CollapsibleHeader; - -class CollapsibleSection : public LinearLayout { -public: - CollapsibleSection(const std::string &title, LayoutParams *layoutParams = nullptr); - - void Update() override; - -private: - bool open_ = true; - CollapsibleHeader *heading_; -}; - } // namespace UI diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 84c76e970..e580a6af8 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -26,7 +26,15 @@ #include "Core/KeyMap.h" #include "Core/System.h" +enum VRMatrix { + VR_PROJECTION_MATRIX, + VR_VIEW_MATRIX_LEFT_EYE, + VR_VIEW_MATRIX_RIGHT_EYE, + VR_MATRIX_COUNT +}; + enum VRMirroring { + VR_MIRRORING_UPDATED, VR_MIRRORING_AXIS_X, VR_MIRRORING_AXIS_Y, VR_MIRRORING_AXIS_Z, @@ -38,21 +46,18 @@ enum VRMirroring { static VRAppMode appMode = VR_MENU_MODE; static std::map > pspAxis; -static std::map pspKeys; // key can be virtual, so not using the enum. +static std::map pspKeys; static int vr3DGeometryCount = 0; static long vrCompat[VR_COMPAT_MAX]; static bool vrFlatForced = false; static bool vrFlatGame = false; -static double vrFov[2] = {}; +static float vrMatrix[VR_MATRIX_COUNT][16]; static bool vrMirroring[VR_MIRRORING_COUNT]; -static int vrMirroringVariant = 0; -static float vrViewMatrix[2][16]; -static XrView vrView[2]; -static void (*cbNativeAxis)(const AxisInput *axis, size_t count); -static bool (*cbNativeKey)(const KeyInput &key); -static void (*cbNativeTouch)(const TouchInput &touch); +static void (*NativeAxis)(const AxisInput &axis); +static bool (*NativeKey)(const KeyInput &key); +static void (*NativeTouch)(const TouchInput &touch); /* ================================================================================ @@ -64,11 +69,11 @@ VR button mapping struct ButtonMapping { ovrButton ovr; - InputKeyCode keycode; + int keycode; bool pressed; int repeat; - ButtonMapping(InputKeyCode keycode, ovrButton ovr) { + ButtonMapping(int keycode, ovrButton ovr) { this->keycode = keycode; this->ovr = ovr; pressed = false; @@ -101,7 +106,7 @@ static std::vector rightControllerMapping = { ButtonMapping(NKCODE_ENTER, ovrButton_Trigger), }; -static const InputDeviceID controllerIds[] = {DEVICE_ID_XR_CONTROLLER_LEFT, DEVICE_ID_XR_CONTROLLER_RIGHT}; +static const int controllerIds[] = {DEVICE_ID_XR_CONTROLLER_LEFT, DEVICE_ID_XR_CONTROLLER_RIGHT}; static std::vector controllerMapping[2] = { leftControllerMapping, rightControllerMapping @@ -157,7 +162,6 @@ void InitVROnAndroid(void* vm, void* activity, const char* system, int version, } else if ((strcmp(vendor, "META") == 0) || (strcmp(vendor, "OCULUS") == 0)) { VR_SetPlatformFLag(VR_PLATFORM_CONTROLLER_QUEST, true); VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_FOVEATION, true); - VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_PASSTHROUGH, true); VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_PERFORMANCE, true); } VR_SetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN, (GPUBackend)g_Config.iGPUBackend == GPUBackend::VULKAN); @@ -199,10 +203,10 @@ void GetVRResolutionPerEye(int* width, int* height) { } } -void SetVRCallbacks(void (*axis)(const AxisInput *axis, size_t count), bool(*key)(const KeyInput &key), void (*touch)(const TouchInput &touch)) { - cbNativeAxis = axis; - cbNativeKey = key; - cbNativeTouch = touch; +void SetVRCallbacks(void (*axis)(const AxisInput &axis), bool(*key)(const KeyInput &key), void (*touch)(const TouchInput &touch)) { + NativeAxis = axis; + NativeKey = key; + NativeTouch = touch; } /* @@ -219,21 +223,21 @@ void SetVRAppMode(VRAppMode mode) { void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { //axis - if (pspKeys[(int)VIRTKEY_VR_CAMERA_ADJUST]) { - AxisInput axis[2] = {}; - axis[0].deviceId = DEVICE_ID_DEFAULT; - axis[1].deviceId = DEVICE_ID_DEFAULT; + if (pspKeys[VIRTKEY_VR_CAMERA_ADJUST]) { + AxisInput axis = {}; for (int j = 0; j < 2; j++) { XrVector2f joystick = IN_VRGetJoystickState(j); + axis.deviceId = DEVICE_ID_DEFAULT; //horizontal - axis[0].axisId = j == 0 ? JOYSTICK_AXIS_X : JOYSTICK_AXIS_Z; - axis[0].value = joystick.x; + axis.axisId = j == 0 ? JOYSTICK_AXIS_X : JOYSTICK_AXIS_Z; + axis.value = joystick.x; + NativeAxis(axis); //vertical - axis[1].axisId = j == 0 ? JOYSTICK_AXIS_Y : JOYSTICK_AXIS_RZ; - axis[1].value = -joystick.y; - cbNativeAxis(axis, 2); + axis.axisId = j == 0 ? JOYSTICK_AXIS_Y : JOYSTICK_AXIS_RZ; + axis.value = -joystick.y; + NativeAxis(axis); } } @@ -255,12 +259,12 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { if (pressed && haptics) { INVR_Vibrate(100, j, 1000); } - cbNativeKey(keyInput); + NativeKey(keyInput); m.pressed = pressed; m.repeat = 0; } else if (pressed && (m.repeat > 30)) { keyInput.flags |= KEY_IS_REPEAT; - cbNativeKey(keyInput); + NativeKey(keyInput); m.repeat = 0; } else { m.repeat++; @@ -283,7 +287,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOTION_UP; keyInput.deviceId = controllerIds[j]; - if (controllerMotion[j][0] != activate) cbNativeKey(keyInput); + if (controllerMotion[j][0] != activate) NativeKey(keyInput); controllerMotion[j][0] = activate; //down @@ -291,7 +295,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOTION_DOWN; keyInput.deviceId = controllerIds[j]; - if (controllerMotion[j][1] != activate) cbNativeKey(keyInput); + if (controllerMotion[j][1] != activate) NativeKey(keyInput); controllerMotion[j][1] = activate; //left @@ -299,7 +303,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOTION_LEFT; keyInput.deviceId = controllerIds[j]; - if (controllerMotion[j][2] != activate) cbNativeKey(keyInput); + if (controllerMotion[j][2] != activate) NativeKey(keyInput); controllerMotion[j][2] = activate; //right @@ -307,7 +311,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOTION_RIGHT; keyInput.deviceId = controllerIds[j]; - if (controllerMotion[j][3] != activate) cbNativeKey(keyInput); + if (controllerMotion[j][3] != activate) NativeKey(keyInput); controllerMotion[j][3] = activate; //forward @@ -315,7 +319,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOTION_FORWARD; keyInput.deviceId = controllerIds[j]; - if (controllerMotion[j][4] != activate) cbNativeKey(keyInput); + if (controllerMotion[j][4] != activate) NativeKey(keyInput); controllerMotion[j][4] = activate; } } @@ -352,7 +356,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { activate = !disable && yaw < -limit; keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_ROTATION_LEFT; - if (hmdMotion[2] != activate) cbNativeKey(keyInput); + if (hmdMotion[2] != activate) NativeKey(keyInput); if (isVR && activate) hmdMotionDiff[1] += limit; hmdMotion[2] = activate; @@ -360,7 +364,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { activate = !disable && yaw > limit; keyInput.flags = activate ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_ROTATION_RIGHT; - if (hmdMotion[3] != activate) cbNativeKey(keyInput); + if (hmdMotion[3] != activate) NativeKey(keyInput); if (isVR && activate) hmdMotionDiff[1] -= limit; hmdMotion[3] = activate; } @@ -381,15 +385,9 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { g_Config.fCameraHeight = clampFloat(g_Config.fCameraHeight, -150.0f, 150.0f); break; case JOYSTICK_AXIS_Z: - if (g_Config.bEnableVR) { - if (axis.second < -0.75f) g_Config.fHeadUpDisplayScale -= 0.01f; - if (axis.second > 0.75f) g_Config.fHeadUpDisplayScale += 0.01f; - g_Config.fHeadUpDisplayScale = clampFloat(g_Config.fHeadUpDisplayScale, 0.0f, 1.5f); - } else { - if (axis.second < -0.75f) g_Config.fCanvas3DDistance += 0.1f; - if (axis.second > 0.75f) g_Config.fCanvas3DDistance -= 0.1f; - g_Config.fCanvas3DDistance = clampFloat(g_Config.fCanvas3DDistance, 1.0f, 15.0f); - } + if (axis.second < -0.75f) g_Config.fHeadUpDisplayScale -= 0.01f; + if (axis.second > 0.75f) g_Config.fHeadUpDisplayScale += 0.01f; + g_Config.fHeadUpDisplayScale = clampFloat(g_Config.fHeadUpDisplayScale, 0.0f, 1.5f); break; case JOYSTICK_AXIS_RZ: if (axis.second > 0.75f) g_Config.fCameraDistance -= 0.1f; @@ -432,7 +430,6 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { VR_SetConfig(VR_CONFIG_MOUSE_X, (int)x); VR_SetConfig(VR_CONFIG_MOUSE_Y, (int)y); VR_SetConfig(VR_CONFIG_MOUSE_SIZE, 6 * (int)pow(VR_GetConfigFloat(VR_CONFIG_CANVAS_DISTANCE), 0.25f)); - VR_SetConfig(VR_CONFIG_CANVAS_6DOF, g_Config.bEnable6DoF); //inform engine about the status TouchInput touch; @@ -443,9 +440,9 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { if (mousePressed != pressed) { if (pressed) { touch.flags = TOUCH_DOWN; - cbNativeTouch(touch); + NativeTouch(touch); touch.flags = TOUCH_UP; - cbNativeTouch(touch); + NativeTouch(touch); } mousePressed = pressed; } @@ -457,24 +454,21 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { float scroll = -IN_VRGetJoystickState(j).y; keyInput.flags = scroll < -0.5f ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - cbNativeKey(keyInput); + NativeKey(keyInput); keyInput.flags = scroll > 0.5f ? KEY_DOWN : KEY_UP; keyInput.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - cbNativeKey(keyInput); + NativeKey(keyInput); } } else { VR_SetConfig(VR_CONFIG_MOUSE_SIZE, 0); } } -bool UpdateVRAxis(const AxisInput *axes, size_t count) { - for (size_t i = 0; i < count; i++) { - const AxisInput &axis = axes[i]; - if (pspAxis.find(axis.deviceId) == pspAxis.end()) { - pspAxis[axis.deviceId] = std::map(); - } - pspAxis[axis.deviceId][axis.axisId] = axis.value; +bool UpdateVRAxis(const AxisInput &axis) { + if (pspAxis.find(axis.deviceId) == pspAxis.end()) { + pspAxis[axis.deviceId] = std::map(); } + pspAxis[axis.deviceId][axis.axisId] = axis.value; return !pspKeys[VIRTKEY_VR_CAMERA_ADJUST]; } @@ -521,8 +515,8 @@ bool UpdateVRKeys(const KeyInput &key) { pspKeys[VIRTKEY_VR_CAMERA_ADJUST] = false; for (auto& pspKey : pspKeys) { if (pspKey.second) { - keyUp.keyCode = (InputKeyCode)pspKey.first; - cbNativeKey(keyUp); + keyUp.keyCode = pspKey.first; + NativeKey(keyUp); } } pspKeys[VIRTKEY_VR_CAMERA_ADJUST] = true; @@ -530,7 +524,6 @@ bool UpdateVRKeys(const KeyInput &key) { // Reset camera adjust if (pspKeys[VIRTKEY_VR_CAMERA_ADJUST] && pspKeys[VIRTKEY_VR_CAMERA_RESET]) { - g_Config.fCanvas3DDistance = 3.0f; g_Config.fCameraHeight = 0; g_Config.fCameraSide = 0; g_Config.fCameraDistance = 0; @@ -567,15 +560,12 @@ void PreprocessSkyplane(GLRStep* step) { // Clear sky with the fog color. if (!vrCompat[VR_COMPAT_FBO_CLEAR]) { - GLRRenderData &skyClear = step->commands.insert(step->commands.begin()); + GLRRenderData skyClear {}; skyClear.cmd = GLRRenderCommand::CLEAR; skyClear.clear.colorMask = 0xF; - skyClear.clear.clearMask = GL_COLOR_BUFFER_BIT; // don't need to initialize clearZ, clearStencil + skyClear.clear.clearMask = GL_COLOR_BUFFER_BIT; skyClear.clear.clearColor = vrCompat[VR_COMPAT_FOG_COLOR]; - skyClear.clear.scissorX = 0; - skyClear.clear.scissorY = 0; - skyClear.clear.scissorW = 0; // signal no scissor - skyClear.clear.scissorH = 0; + step->commands.insert(step->commands.begin(), skyClear); vrCompat[VR_COMPAT_FBO_CLEAR] = true; } @@ -584,7 +574,7 @@ void PreprocessSkyplane(GLRStep* step) { for (auto& command : step->commands) { if (command.cmd == GLRRenderCommand::DEPTH) { depthEnabled = command.depth.enabled; - } else if ((command.cmd == GLRRenderCommand::DRAW && command.draw.indexBuffer != nullptr) && !depthEnabled) { + } else if ((command.cmd == GLRRenderCommand::DRAW && command.draw.indices != nullptr) && !depthEnabled) { command.draw.count = 0; } } @@ -630,22 +620,155 @@ bool StartVRRender() { bool vrScene = !vrFlatForced && (g_Config.bManualForceVR || (vr3DGeometryCount > 15)); bool vrStereo = !PSP_CoreParameter().compat.vrCompat().ForceMono && g_Config.bEnableStereo; - // Get VR status - for (int eye = 0; eye < ovrMaxNumEyes; eye++) { - vrView[eye] = VR_GetView(eye); - } - UpdateVRViewMatrices(); - - // Calculate field of view + // Get OpenXR view and fov XrFovf fov = {}; - for (auto & eye : vrView) { - fov.angleLeft += eye.fov.angleLeft / 2.0f; - fov.angleRight += eye.fov.angleRight / 2.0f; - fov.angleUp += eye.fov.angleUp / 2.0f; - fov.angleDown += eye.fov.angleDown / 2.0f; + XrPosef invViewTransform[2]; + for (int eye = 0; eye < ovrMaxNumEyes; eye++) { + XrView view = VR_GetView(eye); + fov.angleLeft += view.fov.angleLeft / 2.0f; + fov.angleRight += view.fov.angleRight / 2.0f; + fov.angleUp += view.fov.angleUp / 2.0f; + fov.angleDown += view.fov.angleDown / 2.0f; + invViewTransform[eye] = view.pose; + } + + // Get 6DoF scale + float scale = 1.0f; + if (PSP_CoreParameter().compat.vrCompat().UnitsPerMeter > 0) { + scale = PSP_CoreParameter().compat.vrCompat().UnitsPerMeter; + } + + // Update matrices + for (int matrix = 0; matrix < VR_MATRIX_COUNT; matrix++) { + if (matrix == VR_PROJECTION_MATRIX) { + float nearZ = g_Config.fFieldOfViewPercentage / 200.0f; + float tanAngleLeft = tanf(fov.angleLeft); + float tanAngleRight = tanf(fov.angleRight); + float tanAngleDown = tanf(fov.angleDown); + float tanAngleUp = tanf(fov.angleUp); + + float M[16] = {}; + M[0] = 2 / (tanAngleRight - tanAngleLeft); + M[2] = (tanAngleRight + tanAngleLeft) / (tanAngleRight - tanAngleLeft); + M[5] = 2 / (tanAngleUp - tanAngleDown); + M[6] = (tanAngleUp + tanAngleDown) / (tanAngleUp - tanAngleDown); + M[10] = -1; + M[11] = -(nearZ + nearZ); + M[14] = -1; + + memcpy(vrMatrix[matrix], M, sizeof(float) * 16); + } else if ((matrix == VR_VIEW_MATRIX_LEFT_EYE) || (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) { + bool flatScreen = false; + XrPosef invView = invViewTransform[0]; + int vrMode = VR_GetConfig(VR_CONFIG_MODE); + if ((vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN)) { + invView = XrPosef_Identity(); + flatScreen = true; + } + + // get axis mirroring configuration + float mx = vrMirroring[VR_MIRRORING_PITCH] ? -1.0f : 1.0f; + float my = vrMirroring[VR_MIRRORING_YAW] ? -1.0f : 1.0f; + float mz = vrMirroring[VR_MIRRORING_ROLL] ? -1.0f : 1.0f; + + // ensure there is maximally one axis to mirror rotation + if (mx + my + mz < 0) { + mx *= -1.0f; + my *= -1.0f; + mz *= -1.0f; + } else { + invView = XrPosef_Inverse(invView); + } + + // apply camera pitch offset + XrVector3f positionOffset = {g_Config.fCameraSide, g_Config.fCameraHeight, g_Config.fCameraDistance}; + if (!flatScreen) { + float pitchOffset = 0; + switch (g_Config.iCameraPitch) { + case 1: //Top view -> First person + pitchOffset = 90; + positionOffset = {positionOffset.x, positionOffset.z, -positionOffset.y}; + break; + case 2: //First person -> Top view + pitchOffset = -90; + positionOffset = {positionOffset.x, -positionOffset.z + 20, positionOffset.y}; + break; + } + XrQuaternionf rotationOffset = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, ToRadians(pitchOffset)); + invView.orientation = XrQuaternionf_Multiply(rotationOffset, invView.orientation); + } + + // decompose rotation + XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation); + float mPitch = mx * ToRadians(rotation.x); + float mYaw = my * ToRadians(rotation.y); + float mRoll = mz * ToRadians(rotation.z); + + // use in-game camera interpolated rotation + if (g_Config.bHeadRotationEnabled) mYaw = -my * ToRadians(hmdMotionDiffLast[1]); // horizontal + + // create updated quaternion + XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mPitch); + XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, mYaw); + XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mRoll); + invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw)); + + float M[16]; + XrQuaternionf_ToMatrix4f(&invView.orientation, M); + + // Apply 6Dof head movement + if (!flatScreen && g_Config.bEnable6DoF && !g_Config.bHeadRotationEnabled && (g_Config.iCameraPitch == 0)) { + M[3] -= invViewTransform[0].position.x * (vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f) * scale; + M[7] -= invViewTransform[0].position.y * (vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f) * scale; + M[11] -= invViewTransform[0].position.z * (vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f) * scale; + } + // Camera adjust - distance + if (fabsf(positionOffset.z) > 0.0f) { + XrVector3f forward = {0.0f, 0.0f, positionOffset.z * scale}; + forward = XrQuaternionf_Rotate(invView.orientation, forward); + forward = XrVector3f_ScalarMultiply(forward, vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f); + M[3] += forward.x; + M[7] += forward.y; + M[11] += forward.z; + } + // Camera adjust - height + if (fabsf(positionOffset.y) > 0.0f) { + XrVector3f up = {0.0f, -positionOffset.y * scale, 0.0f}; + up = XrQuaternionf_Rotate(invView.orientation, up); + up = XrVector3f_ScalarMultiply(up, vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f); + M[3] += up.x; + M[7] += up.y; + M[11] += up.z; + } + // Camera adjust - side + if (fabsf(positionOffset.x) > 0.0f) { + XrVector3f side = {-positionOffset.x * scale, 0.0f, 0.0f}; + side = XrQuaternionf_Rotate(invView.orientation, side); + side = XrVector3f_ScalarMultiply(side, vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f); + M[3] += side.x; + M[7] += side.y; + M[11] += side.z; + } + // Stereoscopy + if (vrStereo) { + bool mirrored = vrMirroring[VR_MIRRORING_AXIS_Z] ^ (matrix == VR_VIEW_MATRIX_RIGHT_EYE); + float dx = fabs(invViewTransform[1].position.x - invViewTransform[0].position.x); + float dy = fabs(invViewTransform[1].position.y - invViewTransform[0].position.y); + float dz = fabs(invViewTransform[1].position.z - invViewTransform[0].position.z); + float ipd = sqrt(dx * dx + dy * dy + dz * dz); + XrVector3f separation = {ipd * scale * 0.5f, 0.0f, 0.0f}; + separation = XrQuaternionf_Rotate(invView.orientation, separation); + separation = XrVector3f_ScalarMultiply(separation, mirrored ? -1.0f : 1.0f); + M[3] += separation.x; + M[7] += separation.y; + M[11] += separation.z; + } + + memcpy(vrMatrix[matrix], M, sizeof(float) * 16); + } else { + assert(false); + } } - vrFov[0] = 2.0 / (tan(fov.angleRight) - tan(fov.angleLeft)); - vrFov[1] = 2.0 / (tan(fov.angleUp) - tan(fov.angleDown)); // Decide if the scene is 3D or not VR_SetConfigFloat(VR_CONFIG_CANVAS_ASPECT, 480.0f / 272.0f); @@ -665,8 +788,8 @@ bool StartVRRender() { // Set customizations __DisplaySetFramerate(g_Config.bForce72Hz ? 72 : 60); - VR_SetConfigFloat(VR_CONFIG_CANVAS_DISTANCE, vrScene && (appMode == VR_GAME_MODE) ? g_Config.fCanvas3DDistance : g_Config.fCanvasDistance); - VR_SetConfig(VR_CONFIG_PASSTHROUGH, g_Config.bPassthrough); + VR_SetConfigFloat(VR_CONFIG_CANVAS_DISTANCE, g_Config.fCanvasDistance); + vrMirroring[VR_MIRRORING_UPDATED] = false; return true; } return false; @@ -702,10 +825,6 @@ bool IsMultiviewSupported() { return false; } -bool IsPassthroughSupported() { - return VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PASSTHROUGH); -} - bool IsFlatVRGame() { return vrFlatGame; } @@ -738,68 +857,80 @@ bool Is2DVRObject(float* projMatrix, bool ortho) { return identity || ortho; } -void UpdateVRParams(float* projMatrix) { +void UpdateVRParams(float* projMatrix, float* viewMatrix) { // Set mirroring of axes - vrMirroring[VR_MIRRORING_AXIS_X] = projMatrix[0] < 0; - vrMirroring[VR_MIRRORING_AXIS_Y] = projMatrix[5] < 0; - vrMirroring[VR_MIRRORING_AXIS_Z] = projMatrix[10] > 0; + bool identityView = PSP_CoreParameter().compat.vrCompat().IdentityViewHack && IsMatrixIdentity(viewMatrix); + if (!vrMirroring[VR_MIRRORING_UPDATED] && !IsMatrixIdentity(projMatrix) && !identityView) { + vrMirroring[VR_MIRRORING_UPDATED] = true; + vrMirroring[VR_MIRRORING_AXIS_X] = projMatrix[0] < 0; + vrMirroring[VR_MIRRORING_AXIS_Y] = projMatrix[5] < 0; + vrMirroring[VR_MIRRORING_AXIS_Z] = projMatrix[10] > 0; - int variant = 1; - variant += projMatrix[0] < 0; - variant += (projMatrix[5] < 0) << 1; - variant += (projMatrix[10] < 0) << 2; - if (PSP_CoreParameter().compat.vrCompat().MirroringVariant > 0) { - variant = PSP_CoreParameter().compat.vrCompat().MirroringVariant; - } + float up = 0; + for (int i = 4; i < 7; i++) { + up += viewMatrix[i]; + } - switch (variant) { - case 1: //e.g. ATV - vrMirroring[VR_MIRRORING_PITCH] = false; - vrMirroring[VR_MIRRORING_YAW] = true; - vrMirroring[VR_MIRRORING_ROLL] = true; - break; - case 2: //e.g. Tales of the World - vrMirroring[VR_MIRRORING_PITCH] = false; - vrMirroring[VR_MIRRORING_YAW] = false; - vrMirroring[VR_MIRRORING_ROLL] = false; - break; - case 3: //e.g.PES 2014 - case 4: //untested - case 6: //e.g Dante's Inferno - case 8: //untested - vrMirroring[VR_MIRRORING_PITCH] = true; - vrMirroring[VR_MIRRORING_YAW] = true; - vrMirroring[VR_MIRRORING_ROLL] = false; - break; - case 5: //e.g. Assassins Creed - case 7: //e.g. Ghost in the shell - vrMirroring[VR_MIRRORING_PITCH] = true; - vrMirroring[VR_MIRRORING_YAW] = false; - vrMirroring[VR_MIRRORING_ROLL] = true; - break; - default: - assert(false); - std::exit(1); - } + int variant = projMatrix[0] < 0; + variant += (projMatrix[5] < 0) << 1; + variant += (projMatrix[10] < 0) << 2; + variant += (up < 0) << 3; - if (vrMirroringVariant != variant) { - vrMirroringVariant = variant; - UpdateVRViewMatrices(); + switch (variant) { + case 0: //e.g. ATV + vrMirroring[VR_MIRRORING_PITCH] = false; + vrMirroring[VR_MIRRORING_YAW] = true; + vrMirroring[VR_MIRRORING_ROLL] = true; + break; + case 1: //e.g. Tales of the World + vrMirroring[VR_MIRRORING_PITCH] = false; + vrMirroring[VR_MIRRORING_YAW] = false; + vrMirroring[VR_MIRRORING_ROLL] = false; + break; + case 2: //e.g.PES 2014 + case 3: //untested + case 5: //e.g Dante's Inferno + case 7: //untested + case 8: //untested + case 9: //untested + case 10: //untested + case 11: //untested + case 13: //untested + case 15: //untested + vrMirroring[VR_MIRRORING_PITCH] = true; + vrMirroring[VR_MIRRORING_YAW] = true; + vrMirroring[VR_MIRRORING_ROLL] = false; + break; + case 4: //e.g. Assassins Creed + case 6: //e.g. Ghost in the shell + case 12: //e.g. GTA Vice City + case 14: //untested + vrMirroring[VR_MIRRORING_PITCH] = true; + vrMirroring[VR_MIRRORING_YAW] = false; + vrMirroring[VR_MIRRORING_ROLL] = true; + break; + default: + assert(false); + std::exit(1); + } } } void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye) { - float hmdProjection[16]; - memcpy(hmdProjection, projMatrix, 16 * sizeof(float)); - hmdProjection[0] = vrFov[0]; - hmdProjection[5] = vrFov[1]; + float* hmdProjection = vrMatrix[VR_PROJECTION_MATRIX]; + for (int i = 0; i < 16; i++) { + if ((hmdProjection[i] > 0) != (projMatrix[i] > 0)) { + hmdProjection[i] *= -1.0f; + } + } memcpy(leftEye, hmdProjection, 16 * sizeof(float)); memcpy(rightEye, hmdProjection, 16 * sizeof(float)); } void UpdateVRView(float* leftEye, float* rightEye) { float* dst[] = {leftEye, rightEye}; + float* matrix[] = {vrMatrix[VR_VIEW_MATRIX_LEFT_EYE], vrMatrix[VR_VIEW_MATRIX_RIGHT_EYE]}; for (int index = 0; index < 2; index++) { // Validate the view matrix @@ -813,133 +944,10 @@ void UpdateVRView(float* leftEye, float* rightEye) { // Get view matrix from the headset Lin::Matrix4x4 hmdView = {}; - memcpy(hmdView.m, vrViewMatrix[index], 16 * sizeof(float)); + memcpy(hmdView.m, matrix[index], 16 * sizeof(float)); // Combine the matrices Lin::Matrix4x4 renderView = hmdView * gameView; memcpy(dst[index], renderView.m, 16 * sizeof(float)); } } - -void UpdateVRViewMatrices() { - - // Get 6DoF scale - float scale = 1.0f; - if (PSP_CoreParameter().compat.vrCompat().UnitsPerMeter > 0) { - scale = PSP_CoreParameter().compat.vrCompat().UnitsPerMeter; - } - - // Get input - bool flatScreen = false; - XrPosef invView = vrView[0].pose; - int vrMode = VR_GetConfig(VR_CONFIG_MODE); - if ((vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN)) { - invView = XrPosef_Identity(); - flatScreen = true; - } - - // get axis mirroring configuration - float mx = vrMirroring[VR_MIRRORING_PITCH] ? -1.0f : 1.0f; - float my = vrMirroring[VR_MIRRORING_YAW] ? -1.0f : 1.0f; - float mz = vrMirroring[VR_MIRRORING_ROLL] ? -1.0f : 1.0f; - - // ensure there is maximally one axis to mirror rotation - if (mx + my + mz < 0) { - mx *= -1.0f; - my *= -1.0f; - mz *= -1.0f; - } else { - invView = XrPosef_Inverse(invView); - } - - // apply camera pitch offset - XrVector3f positionOffset = {g_Config.fCameraSide, g_Config.fCameraHeight, g_Config.fCameraDistance}; - if (!flatScreen) { - float pitchOffset = 0; - switch (g_Config.iCameraPitch) { - case 1: //Top view -> First person - pitchOffset = 90; - positionOffset = {positionOffset.x, positionOffset.z, -positionOffset.y}; - break; - case 2: //First person -> Top view - pitchOffset = -90; - positionOffset = {positionOffset.x, -positionOffset.z + 20, positionOffset.y}; - break; - } - XrQuaternionf rotationOffset = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, ToRadians(pitchOffset)); - invView.orientation = XrQuaternionf_Multiply(rotationOffset, invView.orientation); - } - - // decompose rotation - XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation); - float mPitch = mx * ToRadians(rotation.x); - float mYaw = my * ToRadians(rotation.y); - float mRoll = mz * ToRadians(rotation.z); - - // use in-game camera interpolated rotation - if (g_Config.bHeadRotationEnabled) mYaw = -my * ToRadians(hmdMotionDiffLast[1]); // horizontal - - // create updated quaternion - XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mPitch); - XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, mYaw); - XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mRoll); - invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw)); - - float M[16]; - XrQuaternionf_ToMatrix4f(&invView.orientation, M); - - // Apply 6Dof head movement - if (g_Config.bEnable6DoF && !g_Config.bHeadRotationEnabled && (g_Config.iCameraPitch == 0)) { - M[3] -= vrView[0].pose.position.x * (vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f) * scale; - M[7] -= vrView[0].pose.position.y * (vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f) * scale; - M[11] -= vrView[0].pose.position.z * (vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f) * scale; - } - // Camera adjust - distance - if (fabsf(positionOffset.z) > 0.0f) { - XrVector3f forward = {0.0f, 0.0f, positionOffset.z * scale}; - forward = XrQuaternionf_Rotate(invView.orientation, forward); - forward = XrVector3f_ScalarMultiply(forward, vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f); - M[3] += forward.x; - M[7] += forward.y; - M[11] += forward.z; - } - // Camera adjust - height - if (fabsf(positionOffset.y) > 0.0f) { - XrVector3f up = {0.0f, -positionOffset.y * scale, 0.0f}; - up = XrQuaternionf_Rotate(invView.orientation, up); - up = XrVector3f_ScalarMultiply(up, vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f); - M[3] += up.x; - M[7] += up.y; - M[11] += up.z; - } - // Camera adjust - side - if (fabsf(positionOffset.x) > 0.0f) { - XrVector3f side = {-positionOffset.x * scale, 0.0f, 0.0f}; - side = XrQuaternionf_Rotate(invView.orientation, side); - side = XrVector3f_ScalarMultiply(side, vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f); - M[3] += side.x; - M[7] += side.y; - M[11] += side.z; - } - - for (int eye = 0; eye < ovrMaxNumEyes; eye++) { - - // Stereoscopy - bool vrStereo = !PSP_CoreParameter().compat.vrCompat().ForceMono && g_Config.bEnableStereo; - if (vrStereo) { - bool mirrored = vrMirroring[VR_MIRRORING_AXIS_Z] ^ (eye == 1); - float dx = fabs(vrView[1].pose.position.x - vrView[0].pose.position.x); - float dy = fabs(vrView[1].pose.position.y - vrView[0].pose.position.y); - float dz = fabs(vrView[1].pose.position.z - vrView[0].pose.position.z); - float ipd = sqrt(dx * dx + dy * dy + dz * dz); - XrVector3f separation = {ipd * scale * 0.5f, 0.0f, 0.0f}; - separation = XrQuaternionf_Rotate(invView.orientation, separation); - separation = XrVector3f_ScalarMultiply(separation, mirrored ? -1.0f : 2.0f); - M[3] += separation.x; - M[7] += separation.y; - M[11] += separation.z; - } - - memcpy(vrViewMatrix[eye], M, sizeof(float) * 16); - } -} diff --git a/Common/VR/PPSSPPVR.h b/Common/VR/PPSSPPVR.h index b78000e4e..59264d67f 100644 --- a/Common/VR/PPSSPPVR.h +++ b/Common/VR/PPSSPPVR.h @@ -1,7 +1,5 @@ #pragma once -#include - struct AxisInput; struct TouchInput; struct KeyInput; @@ -32,12 +30,12 @@ bool IsVREnabled(); void InitVROnAndroid(void* vm, void* activity, const char* system, int version, const char* name); void EnterVR(bool firstStart, void* vulkanContext); void GetVRResolutionPerEye(int* width, int* height); -void SetVRCallbacks(void(*axis)(const AxisInput *axis, size_t count), bool(*key)(const KeyInput &key), void(*touch)(const TouchInput &touch)); +void SetVRCallbacks(void(*axis)(const AxisInput &axis), bool(*key)(const KeyInput &key), void(*touch)(const TouchInput &touch)); // VR input integration void SetVRAppMode(VRAppMode mode); void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale); -bool UpdateVRAxis(const AxisInput *axes, size_t count); +bool UpdateVRAxis(const AxisInput &axis); bool UpdateVRKeys(const KeyInput &key); // VR games compatibility @@ -53,12 +51,10 @@ void PostVRFrameRender(); int GetVRFBOIndex(); int GetVRPassesCount(); bool IsMultiviewSupported(); -bool IsPassthroughSupported(); bool IsFlatVRGame(); bool IsFlatVRScene(); bool IsGameVRScene(); bool Is2DVRObject(float* projMatrix, bool ortho); -void UpdateVRParams(float* projMatrix); +void UpdateVRParams(float* projMatrix, float* viewMatrix); void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye); void UpdateVRView(float* leftEye, float* rightEye); -void UpdateVRViewMatrices(); diff --git a/Common/VR/VRBase.cpp b/Common/VR/VRBase.cpp index 6a2220358..715ea6644 100644 --- a/Common/VR/VRBase.cpp +++ b/Common/VR/VRBase.cpp @@ -61,9 +61,6 @@ void VR_Init( void* system, const char* name, int version ) { if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_INSTANCE)) { extensions.push_back(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME); } - if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PASSTHROUGH)) { - extensions.push_back(XR_FB_PASSTHROUGH_EXTENSION_NAME); - } if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PERFORMANCE)) { extensions.push_back(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME); extensions.push_back(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME); diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index 6ebfd4a31..2d3405f8a 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -42,16 +42,12 @@ static void OXR_CheckErrors(XrInstance instance, XrResult result, const char* fu #define OXR(func) func; #endif -#define DECL_PFN(pfn) PFN_##pfn pfn = nullptr -#define INIT_PFN(pfn) OXR(xrGetInstanceProcAddr(engine->appState.Instance, #pfn, (PFN_xrVoidFunction*)(&pfn))) - -enum { ovrMaxLayerCount = 3 }; +enum { ovrMaxLayerCount = 2 }; enum { ovrMaxNumEyes = 2 }; typedef union { XrCompositionLayerProjection Projection; XrCompositionLayerCylinderKHR Cylinder; - XrCompositionLayerPassthroughFB Passthrough; } ovrCompositorLayer_Union; typedef struct { @@ -66,9 +62,8 @@ typedef struct { uint32_t TextureSwapChainLength; uint32_t TextureSwapChainIndex; ovrSwapChain ColorSwapChain; - ovrSwapChain DepthSwapChain; void* ColorSwapChainImage; - void* DepthSwapChainImage; + unsigned int* GLDepthBuffers; unsigned int* GLFrameBuffers; VkFramebuffer* VKFrameBuffers; VkImageView* VKColorImages; @@ -127,7 +122,6 @@ enum VRPlatformFlag { VR_PLATFORM_CONTROLLER_QUEST, VR_PLATFORM_EXTENSION_FOVEATION, VR_PLATFORM_EXTENSION_INSTANCE, - VR_PLATFORM_EXTENSION_PASSTHROUGH, VR_PLATFORM_EXTENSION_PERFORMANCE, VR_PLATFORM_RENDERER_VULKAN, VR_PLATFORM_TRACKING_FLOOR, diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 6fbceac03..4f53b9eb2 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -39,11 +39,8 @@ void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) { frameBuffer->ColorSwapChain.Width = 0; frameBuffer->ColorSwapChain.Height = 0; frameBuffer->ColorSwapChainImage = NULL; - frameBuffer->DepthSwapChain.Handle = XR_NULL_HANDLE; - frameBuffer->DepthSwapChain.Width = 0; - frameBuffer->DepthSwapChain.Height = 0; - frameBuffer->DepthSwapChainImage = NULL; + frameBuffer->GLDepthBuffers = NULL; frameBuffer->GLFrameBuffers = NULL; frameBuffer->Acquired = false; } @@ -109,8 +106,8 @@ static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBu swapChainCreateInfo.arraySize = multiview ? 2 : 1; #ifdef ANDROID - XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo; if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { + XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo; memset(&swapChainFoveationCreateInfo, 0, sizeof(swapChainFoveationCreateInfo)); swapChainFoveationCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB; swapChainCreateInfo.next = &swapChainFoveationCreateInfo; @@ -119,8 +116,6 @@ static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBu frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; - frameBuffer->DepthSwapChain.Width = swapChainCreateInfo.width; - frameBuffer->DepthSwapChain.Height = swapChainCreateInfo.height; // Create the color swapchain. swapChainCreateInfo.format = GL_SRGB8_ALPHA8; @@ -129,45 +124,55 @@ static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBu OXR(xrEnumerateSwapchainImages(frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); frameBuffer->ColorSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); - // Create the depth swapchain. - swapChainCreateInfo.format = GL_DEPTH24_STENCIL8; - swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->DepthSwapChain.Handle)); - frameBuffer->DepthSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); - // Populate the swapchain image array. for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { ((XrSwapchainImageOpenGLESKHR*)frameBuffer->ColorSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; ((XrSwapchainImageOpenGLESKHR*)frameBuffer->ColorSwapChainImage)[i].next = NULL; - ((XrSwapchainImageOpenGLESKHR*)frameBuffer->DepthSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; - ((XrSwapchainImageOpenGLESKHR*)frameBuffer->DepthSwapChainImage)[i].next = NULL; } OXR(xrEnumerateSwapchainImages( frameBuffer->ColorSwapChain.Handle, frameBuffer->TextureSwapChainLength, &frameBuffer->TextureSwapChainLength, (XrSwapchainImageBaseHeader*)frameBuffer->ColorSwapChainImage)); - OXR(xrEnumerateSwapchainImages( - frameBuffer->DepthSwapChain.Handle, - frameBuffer->TextureSwapChainLength, - &frameBuffer->TextureSwapChainLength, - (XrSwapchainImageBaseHeader*)frameBuffer->DepthSwapChainImage)); + frameBuffer->GLDepthBuffers = (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); frameBuffer->GLFrameBuffers = (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { + + // Create color texture. const GLuint colorTexture = ((XrSwapchainImageOpenGLESKHR*)frameBuffer->ColorSwapChainImage)[i].image; - const GLuint depthTexture = ((XrSwapchainImageOpenGLESKHR*)frameBuffer->DepthSwapChainImage)[i].image; + GLenum colorTextureTarget = multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; + GL(glBindTexture(colorTextureTarget, colorTexture)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GL(glBindTexture(colorTextureTarget, 0)); + + // Create depth buffer. + if (multiview) { + GL(glGenTextures(1, &frameBuffer->GLDepthBuffers[i])); + GL(glBindTexture(GL_TEXTURE_2D_ARRAY, frameBuffer->GLDepthBuffers[i])); + GL(glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH24_STENCIL8, width, height, 2)); + GL(glBindTexture(GL_TEXTURE_2D_ARRAY, 0)); + } else { + GL(glGenRenderbuffers(1, &frameBuffer->GLDepthBuffers[i])); + GL(glBindRenderbuffer(GL_RENDERBUFFER, frameBuffer->GLDepthBuffers[i])); + GL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height)); + GL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + } + // Create the frame buffer. GL(glGenFramebuffers(1, &frameBuffer->GLFrameBuffers[i])); GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer->GLFrameBuffers[i])); if (multiview) { - GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexture, 0, 0, 2)); - GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0, 2)); + GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, frameBuffer->GLDepthBuffers[i], 0, 0, 2)); + GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, frameBuffer->GLDepthBuffers[i], 0, 0, 2)); GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, 0, 2)); } else { - GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0)); - GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0)); + GL(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, frameBuffer->GLDepthBuffers[i])); + GL(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, frameBuffer->GLDepthBuffers[i])); GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0)); } GL(GLenum renderFramebufferStatus = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); @@ -203,8 +208,8 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff swapChainCreateInfo.arraySize = multiview ? 2 : 1; #ifdef ANDROID - XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo; if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { + XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo; memset(&swapChainFoveationCreateInfo, 0, sizeof(swapChainFoveationCreateInfo)); swapChainFoveationCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB; swapChainCreateInfo.next = &swapChainFoveationCreateInfo; @@ -213,8 +218,6 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; - frameBuffer->DepthSwapChain.Width = swapChainCreateInfo.width; - frameBuffer->DepthSwapChain.Height = swapChainCreateInfo.height; // Create the color swapchain. swapChainCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; @@ -223,29 +226,16 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff OXR(xrEnumerateSwapchainImages(frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); frameBuffer->ColorSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageVulkanKHR)); - // Create the depth swapchain. - swapChainCreateInfo.format = VK_FORMAT_D24_UNORM_S8_UINT; - swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->DepthSwapChain.Handle)); - frameBuffer->DepthSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageVulkanKHR)); - // Populate the swapchain image array. for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { ((XrSwapchainImageVulkanKHR*)frameBuffer->ColorSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; ((XrSwapchainImageVulkanKHR*)frameBuffer->ColorSwapChainImage)[i].next = NULL; - ((XrSwapchainImageVulkanKHR*)frameBuffer->DepthSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; - ((XrSwapchainImageVulkanKHR*)frameBuffer->DepthSwapChainImage)[i].next = NULL; } OXR(xrEnumerateSwapchainImages( frameBuffer->ColorSwapChain.Handle, frameBuffer->TextureSwapChainLength, &frameBuffer->TextureSwapChainLength, (XrSwapchainImageBaseHeader*)frameBuffer->ColorSwapChainImage)); - OXR(xrEnumerateSwapchainImages( - frameBuffer->DepthSwapChain.Handle, - frameBuffer->TextureSwapChainLength, - &frameBuffer->TextureSwapChainLength, - (XrSwapchainImageBaseHeader*)frameBuffer->DepthSwapChainImage)); frameBuffer->VKColorImages = new VkImageView[frameBuffer->TextureSwapChainLength]; frameBuffer->VKDepthImages = new VkImageView[frameBuffer->TextureSwapChainLength]; @@ -270,14 +260,6 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff return false; } - createInfo.image = ((XrSwapchainImageVulkanKHR*)frameBuffer->DepthSwapChainImage)[i].image; - createInfo.format = VK_FORMAT_D24_UNORM_S8_UINT; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (vkCreateImageView(frameBuffer->VKContext->device, &createInfo, nullptr, &frameBuffer->VKDepthImages[i]) != VK_SUCCESS) { - ALOGE("failed to create depth image view!"); - return false; - } - // Create the frame buffer. VkImageView attachments[] = { frameBuffer->VKColorImages[i], frameBuffer->VKDepthImages[i] }; VkFramebufferCreateInfo framebufferInfo{}; @@ -311,14 +293,14 @@ void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer) { delete[] frameBuffer->VKFrameBuffers; } else { #if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL + GL(glDeleteRenderbuffers(frameBuffer->TextureSwapChainLength, frameBuffer->GLDepthBuffers)); GL(glDeleteFramebuffers(frameBuffer->TextureSwapChainLength, frameBuffer->GLFrameBuffers)); + free(frameBuffer->GLDepthBuffers); free(frameBuffer->GLFrameBuffers); #endif } OXR(xrDestroySwapchain(frameBuffer->ColorSwapChain.Handle)); - OXR(xrDestroySwapchain(frameBuffer->DepthSwapChain.Handle)); free(frameBuffer->ColorSwapChainImage); - free(frameBuffer->DepthSwapChainImage); ovrFramebuffer_Clear(frameBuffer); } @@ -341,8 +323,17 @@ void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) { XrSwapchainImageWaitInfo waitInfo; waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO; waitInfo.next = NULL; - waitInfo.timeout = XR_INFINITE_DURATION; + waitInfo.timeout = 1000000; /* timeout in nanoseconds */ XrResult res = xrWaitSwapchainImage(frameBuffer->ColorSwapChain.Handle, &waitInfo); + int i = 0; + while ((res != XR_SUCCESS) && (i < 10)) { + res = xrWaitSwapchainImage(frameBuffer->ColorSwapChain.Handle, &waitInfo); + i++; + ALOGV( + " Retry xrWaitSwapchainImage %d times due to XR_TIMEOUT_EXPIRED (duration %f micro seconds)", + i, + waitInfo.timeout * (1E-9)); + } frameBuffer->Acquired = res == XR_SUCCESS; ovrFramebuffer_SetCurrent(frameBuffer); @@ -364,10 +355,6 @@ void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) { void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { if (frameBuffer->Acquired) { - XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; - OXR(xrReleaseSwapchainImage(frameBuffer->ColorSwapChain.Handle, &releaseInfo)); - frameBuffer->Acquired = false; - // Clear the alpha channel, other way OpenXR would not transfer the framebuffer fully if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { //TODO:implement @@ -379,6 +366,10 @@ void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { GL(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); #endif } + + XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; + OXR(xrReleaseSwapchainImage(frameBuffer->ColorSwapChain.Handle, &releaseInfo)); + frameBuffer->Acquired = false; } } diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index f7ac27945..5a9a20892 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -20,17 +20,6 @@ float vrConfigFloat[VR_CONFIG_FLOAT_MAX] = {}; XrVector3f hmdorientation; -XrPassthroughFB passthrough = XR_NULL_HANDLE; -XrPassthroughLayerFB passthroughLayer = XR_NULL_HANDLE; -DECL_PFN(xrCreatePassthroughFB); -DECL_PFN(xrDestroyPassthroughFB); -DECL_PFN(xrPassthroughStartFB); -DECL_PFN(xrPassthroughPauseFB); -DECL_PFN(xrCreatePassthroughLayerFB); -DECL_PFN(xrDestroyPassthroughLayerFB); -DECL_PFN(xrPassthroughLayerPauseFB); -DECL_PFN(xrPassthroughLayerResumeFB); - void VR_UpdateStageBounds(ovrApp* pappState) { XrExtent2Df stageBounds = {}; @@ -190,17 +179,6 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { VR_DestroyRenderer(engine); } - if (VR_GetPlatformFlag(VRPlatformFlag::VR_PLATFORM_EXTENSION_PASSTHROUGH)) { - INIT_PFN(xrCreatePassthroughFB); - INIT_PFN(xrDestroyPassthroughFB); - INIT_PFN(xrPassthroughStartFB); - INIT_PFN(xrPassthroughPauseFB); - INIT_PFN(xrCreatePassthroughLayerFB); - INIT_PFN(xrDestroyPassthroughLayerFB); - INIT_PFN(xrPassthroughLayerPauseFB); - INIT_PFN(xrPassthroughLayerResumeFB); - } - int eyeW, eyeH; VR_GetResolution(engine, &eyeW, &eyeH); VR_SetConfig(VR_CONFIG_VIEWPORT_WIDTH, eyeW); @@ -243,32 +221,10 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { ovrRenderer_SetFoveation(&engine->appState.Instance, &engine->appState.Session, &engine->appState.Renderer, XR_FOVEATION_LEVEL_HIGH_TOP_FB, 0, XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB); } #endif - - if (VR_GetPlatformFlag(VRPlatformFlag::VR_PLATFORM_EXTENSION_PASSTHROUGH)) { - XrPassthroughCreateInfoFB ptci = {XR_TYPE_PASSTHROUGH_CREATE_INFO_FB}; - XrResult result; - OXR(result = xrCreatePassthroughFB(engine->appState.Session, &ptci, &passthrough)); - - if (XR_SUCCEEDED(result)) { - XrPassthroughLayerCreateInfoFB plci = {XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB}; - plci.passthrough = passthrough; - plci.purpose = XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB; - OXR(xrCreatePassthroughLayerFB(engine->appState.Session, &plci, &passthroughLayer)); - } - - OXR(xrPassthroughStartFB(passthrough)); - OXR(xrPassthroughLayerResumeFB(passthroughLayer)); - } initialized = true; } void VR_DestroyRenderer( engine_t* engine ) { - if (VR_GetPlatformFlag(VRPlatformFlag::VR_PLATFORM_EXTENSION_PASSTHROUGH)) { - OXR(xrPassthroughLayerPauseFB(passthroughLayer)); - OXR(xrPassthroughPauseFB(passthrough)); - OXR(xrDestroyPassthroughFB(passthrough)); - passthrough = XR_NULL_HANDLE; - } ovrRenderer_Destroy(&engine->appState.Renderer); free(projections); initialized = false; @@ -327,11 +283,7 @@ bool VR_InitFrame( engine_t* engine ) { projectionCapacityInput, &projectionCountOutput, projections)); - if ((viewState.viewStateFlags & XR_VIEW_STATE_POSITION_VALID_BIT) == 0 || - (viewState.viewStateFlags & XR_VIEW_STATE_ORIENTATION_VALID_BIT) == 0) { - return false; // There is no valid tracking poses for the views. - } - + // fov = {}; for (int eye = 0; eye < ovrMaxNumEyes; eye++) { @@ -376,16 +328,6 @@ void VR_EndFrame( engine_t* engine ) { void VR_FinishFrame( engine_t* engine ) { - if (VR_GetPlatformFlag(VRPlatformFlag::VR_PLATFORM_EXTENSION_PASSTHROUGH) && VR_GetConfig(VR_CONFIG_PASSTHROUGH)) { - if (passthroughLayer != XR_NULL_HANDLE) { - XrCompositionLayerPassthroughFB passthrough_layer = {XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB}; - passthrough_layer.layerHandle = passthroughLayer; - passthrough_layer.flags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; - passthrough_layer.space = XR_NULL_HANDLE; - engine->appState.Layers[engine->appState.LayerCount++].Passthrough = passthrough_layer; - } - } - int vrMode = vrConfig[VR_CONFIG_MODE]; XrCompositionLayerProjectionView projection_layer_elements[2] = {}; if ((vrMode == VR_MODE_MONO_6DOF) || (vrMode == VR_MODE_STEREO_6DOF)) { @@ -428,15 +370,14 @@ void VR_FinishFrame( engine_t* engine ) { } else if ((vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN)) { // Flat screen pose - float distance = VR_GetConfigFloat(VR_CONFIG_CANVAS_DISTANCE) / 4.0f - 1.0f; + float distance = VR_GetConfigFloat(VR_CONFIG_CANVAS_DISTANCE); float menuPitch = ToRadians(VR_GetConfigFloat(VR_CONFIG_MENU_PITCH)); float menuYaw = ToRadians(VR_GetConfigFloat(VR_CONFIG_MENU_YAW)); - XrVector3f pos = {-sinf(menuYaw) * distance, 0, -cosf(menuYaw) * distance}; - if (!VR_GetConfig(VR_CONFIG_CANVAS_6DOF)) { - pos.x += invViewTransform[0].position.x; - pos.y += invViewTransform[0].position.y; - pos.z += invViewTransform[0].position.z; - } + XrVector3f pos = { + invViewTransform[0].position.x - sinf(menuYaw) * distance, + invViewTransform[0].position.y, + invViewTransform[0].position.z - cosf(menuYaw) * distance + }; XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, -menuPitch); XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, menuYaw); @@ -454,7 +395,7 @@ void VR_FinishFrame( engine_t* engine ) { cylinder_layer.subImage.imageArrayIndex = 0; cylinder_layer.pose.orientation = XrQuaternionf_Multiply(pitch, yaw); cylinder_layer.pose.position = pos; - cylinder_layer.radius = 2.0f; + cylinder_layer.radius = 12.0f; cylinder_layer.centralAngle = (float)(M_PI * 0.5); cylinder_layer.aspectRatio = VR_GetConfigFloat(VR_CONFIG_CANVAS_ASPECT); @@ -491,7 +432,14 @@ void VR_FinishFrame( engine_t* engine ) { endFrameInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE; endFrameInfo.layerCount = engine->appState.LayerCount; endFrameInfo.layers = layers; + OXR(xrEndFrame(engine->appState.Session, &endFrameInfo)); + int instances = engine->appState.Renderer.Multiview ? 1 : ovrMaxNumEyes; + for (int i = 0; i < instances; i++) { + ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[instances]; + frameBuffer->TextureSwapChainIndex++; + frameBuffer->TextureSwapChainIndex %= frameBuffer->TextureSwapChainLength; + } } int VR_GetConfig( VRConfig config ) { diff --git a/Common/VR/VRRenderer.h b/Common/VR/VRRenderer.h index 7a0b3a87a..8ed786965 100644 --- a/Common/VR/VRRenderer.h +++ b/Common/VR/VRRenderer.h @@ -4,8 +4,8 @@ #include "VRMath.h" enum VRConfig { - //switching between mode - VR_CONFIG_MODE, VR_CONFIG_PASSTHROUGH, VR_CONFIG_CANVAS_6DOF, + //switching between 2D and 3D + VR_CONFIG_MODE, //mouse cursor VR_CONFIG_MOUSE_SIZE, VR_CONFIG_MOUSE_X, VR_CONFIG_MOUSE_Y, //viewport setup diff --git a/Common/x64Emitter.cpp b/Common/x64Emitter.cpp index 814fc7e0d..1d98544e6 100644 --- a/Common/x64Emitter.cpp +++ b/Common/x64Emitter.cpp @@ -140,37 +140,6 @@ const u8 *XEmitter::AlignCodePage() return code; } -const u8 *XEmitter::NopAlignCode16() { - int nops = 16 - ((u64)code & 15); - if (nops == 16) - return code; - - // note: the string lengths are obviously not computable with strlen, but are equal to the index. - // Nop strings from https://stackoverflow.com/questions/25545470/long-multi-byte-nops-commonly-understood-macros-or-other-notation - static const char * const nopStrings[16] = { - "", - "\x90", - "\x66\x90", - "\x0f\x1f\00", - "\x0f\x1f\x40\x00", - "\x0f\x1f\x44\x00\x00", - "\x66\x0f\x1f\x44\x00\x00", - "\x0f\x1f\x80\x00\x00\x00\x00", - "\x0f\x1f\x84\x00\x00\x00\x00\x00", - "\x66\x0f\x1f\x84\x00\x00\x00\x00\x00", - "\x66\x66\x0f\x1f\x84\x00\x00\x00\x00\x00", - "\x66\x66\x66\x0f\x1f\x84\x00\x00\x00\x00\x00", - "\x66\x66\x66\x0f\x1f\x84\x00\x00\x00\x00\x00\x90", - "\x66\x66\x66\x0f\x1f\x84\x00\x00\x00\x00\x00\x66\x90", - "\x66\x66\x66\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\00", - "\x66\x66\x66\x0f\x1f\x84\x00\x00\x00\x00\x00\x0f\x1f\x40\x00", - }; - - memcpy(code, nopStrings[nops], nops); - code += nops; - return code; -} - // This operation modifies flags; check to see the flags are locked. // If the flags are locked, we should immediately and loudly fail before // causing a subtle JIT bug. @@ -1689,14 +1658,12 @@ void XEmitter::CVTTPD2DQ(X64Reg regOp, OpArg arg) {WriteSSEOp(0x66, 0xE6, regOp, void XEmitter::MASKMOVDQU(X64Reg dest, X64Reg src) {WriteSSEOp(0x66, sseMASKMOVDQU, dest, R(src));} -void XEmitter::MOVSHDUP(X64Reg regOp, OpArg arg) { WriteSSEOp(0xF3, sseMOVHPfromRM, regOp, arg); } -void XEmitter::MOVSLDUP(X64Reg regOp, OpArg arg) { WriteSSEOp(0xF3, sseMOVLPfromRM, regOp, arg); } - void XEmitter::MOVMSKPS(X64Reg dest, OpArg arg) {WriteSSEOp(0x00, 0x50, dest, arg);} void XEmitter::MOVMSKPD(X64Reg dest, OpArg arg) {WriteSSEOp(0x66, 0x50, dest, arg);} void XEmitter::LDDQU(X64Reg dest, OpArg arg) {WriteSSEOp(0xF2, sseLDDQU, dest, arg);} // For integer data only +// THESE TWO ARE UNTESTED. void XEmitter::UNPCKLPS(X64Reg dest, OpArg arg) {WriteSSEOp(0x00, 0x14, dest, arg);} void XEmitter::UNPCKHPS(X64Reg dest, OpArg arg) {WriteSSEOp(0x00, 0x15, dest, arg);} @@ -1891,9 +1858,6 @@ void XEmitter::PTEST(X64Reg dest, OpArg arg) {WriteSSE41Op(0x66, 0x3817, dest void XEmitter::PACKUSDW(X64Reg dest, OpArg arg) {WriteSSE41Op(0x66, 0x382b, dest, arg);} void XEmitter::DPPS(X64Reg dest, OpArg arg, u8 mask) {WriteSSE41Op(0x66, 0x3A40, dest, arg, 1); Write8(mask);} -void XEmitter::INSERTPS(X64Reg dest, OpArg arg, u8 dstsubreg, u8 srcsubreg, u8 zmask) { WriteSSE41Op(0x66, 0x3A21, dest, arg, 1); Write8((srcsubreg << 6) | (dstsubreg << 4) | zmask); } -void XEmitter::EXTRACTPS(OpArg dest, X64Reg arg, u8 subreg) { WriteSSE41Op(0x66, 0x3A17, arg, dest, 1); Write8(subreg); } - void XEmitter::PMINSB(X64Reg dest, OpArg arg) {WriteSSE41Op(0x66, 0x3838, dest, arg);} void XEmitter::PMINSD(X64Reg dest, OpArg arg) {WriteSSE41Op(0x66, 0x3839, dest, arg);} void XEmitter::PMINUW(X64Reg dest, OpArg arg) {WriteSSE41Op(0x66, 0x383a, dest, arg);} @@ -2086,7 +2050,7 @@ void XEmitter::VCVTTPD2DQ(int bits, X64Reg regOp1, OpArg arg) { WriteAVXOp(bits, void XEmitter::VCVTTSS2SI(int bits, X64Reg regOp1, OpArg arg) { WriteAVXOp(0, 0xF3, 0x2C, regOp1, arg, 0, bits == 64 ? 1 : 0); } void XEmitter::VCVTTSD2SI(int bits, X64Reg regOp1, OpArg arg) { WriteAVXOp(0, 0xF2, 0x2C, regOp1, arg, 0, bits == 64 ? 1 : 0); } void XEmitter::VEXTRACTPS(OpArg arg, X64Reg regOp1, u8 subreg) { WriteAVXOp(0, 0x66, 0x3A17, regOp1, arg, 1); Write8(subreg); } -void XEmitter::VINSERTPS(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 dstsubreg, u8 srcsubreg, u8 zmask) { WriteAVXOp(0, 0x66, 0x3A21, regOp1, regOp2, arg, 1); Write8((srcsubreg << 6) | (dstsubreg << 4) | zmask); } +void XEmitter::VINSERTPS(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 subreg) { WriteAVXOp(0, 0x66, 0x3A21, regOp1, regOp2, arg, 1); Write8(subreg); } void XEmitter::VLDDQU(int bits, X64Reg regOp1, OpArg arg) { WriteAVXOp(bits, 0xF2, sseLDDQU, regOp1, arg); } void XEmitter::VMOVAPS(int bits, X64Reg regOp1, OpArg arg) { WriteAVXOp(bits, 0x00, sseMOVAPfromRM, regOp1, arg); } void XEmitter::VMOVAPD(int bits, X64Reg regOp1, OpArg arg) { WriteAVXOp(bits, 0x66, sseMOVAPfromRM, regOp1, arg); } diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h index 832ed767c..b52a81f35 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -406,10 +406,6 @@ public: const u8 *AlignCode4(); const u8 *AlignCode16(); const u8 *AlignCodePage(); - - // Nops until the code pointer is 16-byte aligned. Good for loops. - const u8 *NopAlignCode16(); - u8 *GetWritableCodePtr(); void LockFlags() { flags_locked = true; } @@ -684,13 +680,11 @@ public: // SSE4: Further horizontal operations - dot products. These are weirdly flexible, the arg contains both a read mask and a write "mask". void DPPD(X64Reg dest, OpArg src, u8 arg); -#endif - // SSE4: Insert and extract for floats. - // Note: insert from memory or an XMM. - void INSERTPS(X64Reg dest, OpArg arg, u8 dstsubreg, u8 srcsubreg = 0, u8 zmask = 0); - // Extract to memory or GPR. - void EXTRACTPS(OpArg dest, X64Reg arg, u8 subreg); + // These are probably useful for VFPU emulation. + void INSERTPS(X64Reg dest, OpArg src, u8 arg); + void EXTRACTPS(OpArg dest, X64Reg src, u8 arg); +#endif // SSE3: Horizontal operations in SIMD registers. Very slow! shufps-based code beats it handily on Ivy. void HADDPS(X64Reg dest, OpArg src); @@ -748,10 +742,6 @@ public: void MOVD_xmm(const OpArg &arg, X64Reg src); void MOVQ_xmm(OpArg arg, X64Reg src); - // SSE3: Some additional moves. - void MOVSHDUP(X64Reg regOp1, OpArg arg); - void MOVSLDUP(X64Reg regOp1, OpArg arg); - // SSE/SSE2: Generates a mask from the high bits of the components of the packed register in question. void MOVMSKPS(X64Reg dest, OpArg arg); void MOVMSKPD(X64Reg dest, OpArg arg); @@ -1042,7 +1032,7 @@ public: // Can only extract from the low 128 bits. void VEXTRACTPS(OpArg arg, X64Reg regOp1, u8 subreg); // Can only insert into the low 128 bits, zeros upper bits. Inserts from XMM. - void VINSERTPS(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 dstsubreg, u8 srcsubreg = 0, u8 zmask = 0); + void VINSERTPS(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 subreg); void VLDDQU(int bits, X64Reg regOp1, OpArg arg); void VMOVAPS(int bits, X64Reg regOp1, OpArg arg); void VMOVAPD(int bits, X64Reg regOp1, OpArg arg); diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 5e2c1205d..578bcdec3 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -131,17 +131,12 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "DaxterRotatedAnalogStick", &flags_.DaxterRotatedAnalogStick); CheckSetting(iniFile, gameID, "ForceMaxDepthResolution", &flags_.ForceMaxDepthResolution); CheckSetting(iniFile, gameID, "SOCOMClut8Replacement", &flags_.SOCOMClut8Replacement); - CheckSetting(iniFile, gameID, "Fontltn12Hack", &flags_.Fontltn12Hack); - CheckSetting(iniFile, gameID, "LoadCLUTFromCurrentFrameOnly", &flags_.LoadCLUTFromCurrentFrameOnly); - CheckSetting(iniFile, gameID, "ForceUMDReadSpeed", &flags_.ForceUMDReadSpeed); - CheckSetting(iniFile, gameID, "AllowDelayedReadbacks", &flags_.AllowDelayedReadbacks); } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "ForceFlatScreen", &vrCompat_.ForceFlatScreen); CheckSetting(iniFile, gameID, "ForceMono", &vrCompat_.ForceMono); CheckSetting(iniFile, gameID, "IdentityViewHack", &vrCompat_.IdentityViewHack); - CheckSetting(iniFile, gameID, "MirroringVariant", &vrCompat_.MirroringVariant); CheckSetting(iniFile, gameID, "Skyplane", &vrCompat_.Skyplane); CheckSetting(iniFile, gameID, "UnitsPerMeter", &vrCompat_.UnitsPerMeter); @@ -164,9 +159,3 @@ void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, co iniFile.Get(option, gameID.c_str(), &value, "0"); *flag = stof(value); } - -void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, int *flag) { - std::string value; - iniFile.Get(option, gameID.c_str(), &value, "0"); - *flag = stof(value); -} diff --git a/Core/Compatibility.h b/Core/Compatibility.h index 7cff655b0..6bbdc3353 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -101,17 +101,12 @@ struct CompatFlags { bool DaxterRotatedAnalogStick; bool ForceMaxDepthResolution; bool SOCOMClut8Replacement; - bool Fontltn12Hack; - bool LoadCLUTFromCurrentFrameOnly; - bool ForceUMDReadSpeed; - bool AllowDelayedReadbacks; }; struct VRCompat { bool ForceMono; bool ForceFlatScreen; bool IdentityViewHack; - int MirroringVariant; bool Skyplane; float UnitsPerMeter; }; @@ -137,7 +132,6 @@ private: void CheckVRSettings(IniFile &iniFile, const std::string &gameID); void CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag); void CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, float *value); - void CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, int *value); CompatFlags flags_{}; VRCompat vrCompat_{}; diff --git a/Core/Config.cpp b/Core/Config.cpp index 9e662a15f..8a3b0f36f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -47,7 +47,6 @@ #include "Common/Thread/ThreadUtil.h" #include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/VR/PPSSPPVR.h" -#include "Common/System/OSD.h" #include "Core/Config.h" #include "Core/ConfigSettings.h" #include "Core/ConfigValues.h" @@ -58,7 +57,7 @@ #include "GPU/Common/FramebufferManagerCommon.h" // TODO: Find a better place for this. -http::RequestManager g_DownloadManager; +http::Downloader g_DownloadManager; Config g_Config; @@ -81,33 +80,6 @@ static const char *logSectionName = "LogDebug"; static const char *logSectionName = "Log"; #endif -std::string GPUBackendToString(GPUBackend backend) { - switch (backend) { - case GPUBackend::OPENGL: - return "OPENGL"; - case GPUBackend::DIRECT3D9: - return "DIRECT3D9"; - case GPUBackend::DIRECT3D11: - return "DIRECT3D11"; - case GPUBackend::VULKAN: - return "VULKAN"; - } - // Intentionally not a default so we get a warning. - return "INVALID"; -} - -GPUBackend GPUBackendFromString(std::string_view backend) { - if (!equalsNoCase(backend, "OPENGL") || backend == "0") - return GPUBackend::OPENGL; - if (!equalsNoCase(backend, "DIRECT3D9") || backend == "1") - return GPUBackend::DIRECT3D9; - if (!equalsNoCase(backend, "DIRECT3D11") || backend == "2") - return GPUBackend::DIRECT3D11; - if (!equalsNoCase(backend, "VULKAN") || backend == "3") - return GPUBackend::VULKAN; - return GPUBackend::OPENGL; -} - const char *DefaultLangRegion() { // Unfortunate default. There's no need to use bFirstRun, since this is only a default. static std::string defaultLangRegion = "en_US"; @@ -157,26 +129,17 @@ std::string CreateRandMAC() { } static int DefaultCpuCore() { -#if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(RISCV64) +#if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) if (System_GetPropertyBool(SYSPROP_CAN_JIT)) return (int)CPUCore::JIT; - return (int)CPUCore::IR_INTERPRETER; + return (int)CPUCore::IR_JIT; #else - return (int)CPUCore::IR_INTERPRETER; + return (int)CPUCore::IR_JIT; #endif } static bool DefaultCodeGen() { -#if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(RISCV64) - return true; -#else - return false; -#endif -} - -static bool DefaultVSync() { -#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(UWP) - // Previously we didn't allow turning off vsync/FIFO on Android. Let's set the default accordingly. +#if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) return true; #else return false; @@ -210,13 +173,11 @@ static const ConfigSetting generalSettings[] = { ConfigSetting("DiscordPresence", &g_Config.bDiscordPresence, true, CfgFlag::DEFAULT), // Or maybe it makes sense to have it per-game? Race conditions abound... ConfigSetting("UISound", &g_Config.bUISound, false, CfgFlag::DEFAULT), - ConfigSetting("DisableHTTPS", &g_Config.bDisableHTTPS, false, CfgFlag::DONT_SAVE), ConfigSetting("AutoLoadSaveState", &g_Config.iAutoLoadSaveState, 0, CfgFlag::PER_GAME), ConfigSetting("EnableCheats", &g_Config.bEnableCheats, false, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("CwCheatRefreshRate", &g_Config.iCwCheatRefreshRate, 77, CfgFlag::PER_GAME), ConfigSetting("CwCheatScrollPosition", &g_Config.fCwCheatScrollPosition, 0.0f, CfgFlag::PER_GAME), ConfigSetting("GameListScrollPosition", &g_Config.fGameListScrollPosition, 0.0f, CfgFlag::DEFAULT), - ConfigSetting("DebugOverlay", &g_Config.iDebugOverlay, 0, CfgFlag::DONT_SAVE), ConfigSetting("ScreenshotsAsPNG", &g_Config.bScreenshotsAsPNG, false, CfgFlag::PER_GAME), ConfigSetting("UseFFV1", &g_Config.bUseFFV1, false, CfgFlag::DEFAULT), @@ -303,34 +264,6 @@ static bool DefaultSasThread() { return cpu_info.num_cores > 1; } -static const ConfigSetting achievementSettings[] = { - // Core settings - ConfigSetting("AchievementsEnable", &g_Config.bAchievementsEnable, true, CfgFlag::DEFAULT), - ConfigSetting("AchievementsChallengeMode", &g_Config.bAchievementsChallengeMode, true, CfgFlag::DEFAULT), - ConfigSetting("AchievementsEncoreMode", &g_Config.bAchievementsEncoreMode, false, CfgFlag::DEFAULT), - ConfigSetting("AchievementsUnofficial", &g_Config.bAchievementsUnofficial, false, CfgFlag::DEFAULT), - ConfigSetting("AchievementsLogBadMemReads", &g_Config.bAchievementsLogBadMemReads, false, CfgFlag::DEFAULT), - ConfigSetting("bAchievementsSaveStateInChallengeMode", &g_Config.bAchievementsSaveStateInChallengeMode, false, CfgFlag::DEFAULT), - - // Achievements login info. Note that password is NOT stored, only a login token. - // And that login token is stored separately from the ini, see NativeSaveSecret, but it can also be loaded - // from the ini if manually entered (useful when testing various builds on Android). - ConfigSetting("AchievementsToken", &g_Config.sAchievementsToken, "", CfgFlag::DONT_SAVE), - ConfigSetting("AchievementsUserName", &g_Config.sAchievementsUserName, "", CfgFlag::DEFAULT), - - // Customizations - ConfigSetting("AchievementsSoundEffects", &g_Config.bAchievementsSoundEffects, true, CfgFlag::DEFAULT), - ConfigSetting("AchievementsUnlockAudioFile", &g_Config.sAchievementsUnlockAudioFile, "", CfgFlag::DEFAULT), - ConfigSetting("AchievementsLeaderboardSubmitAudioFile", &g_Config.sAchievementsLeaderboardSubmitAudioFile, "", CfgFlag::DEFAULT), - - ConfigSetting("AchievementsLeaderboardTrackerPos", &g_Config.iAchievementsLeaderboardTrackerPos, (int)ScreenEdgePosition::TOP_LEFT, CfgFlag::DEFAULT), - ConfigSetting("AchievementsLeaderboardStartedOrFailedPos", &g_Config.iAchievementsLeaderboardStartedOrFailedPos, (int)ScreenEdgePosition::TOP_LEFT, CfgFlag::DEFAULT), - ConfigSetting("AchievementsLeaderboardSubmittedPos", &g_Config.iAchievementsLeaderboardSubmittedPos, (int)ScreenEdgePosition::TOP_LEFT, CfgFlag::DEFAULT), - ConfigSetting("AchievementsProgressPos", &g_Config.iAchievementsProgressPos, (int)ScreenEdgePosition::TOP_LEFT, CfgFlag::DEFAULT), - ConfigSetting("AchievementsChallengePos", &g_Config.iAchievementsChallengePos, (int)ScreenEdgePosition::TOP_LEFT, CfgFlag::DEFAULT), - ConfigSetting("AchievementsUnlockedPos", &g_Config.iAchievementsUnlockedPos, (int)ScreenEdgePosition::TOP_CENTER, CfgFlag::DEFAULT), -}; - static const ConfigSetting cpuSettings[] = { ConfigSetting("CPUCore", &g_Config.iCpuCore, &DefaultCpuCore, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("SeparateSASThread", &g_Config.bSeparateSASThread, &DefaultSasThread, CfgFlag::PER_GAME | CfgFlag::REPORT), @@ -425,12 +358,6 @@ static int DefaultGPUBackend() { if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 27) { return (int)GPUBackend::VULKAN; } -#else - // There are some newer devices that benefit from Vulkan as default, but are 32-bit. Example: Redmi 9A. - // Let's only allow the very newest generation though. - if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 30) { - return (int)GPUBackend::VULKAN; - } #endif #elif PPSSPP_PLATFORM(MAC) #if PPSSPP_ARCH(ARM64) @@ -541,7 +468,7 @@ bool Config::IsBackendEnabled(GPUBackend backend, bool validate) { return true; } -template +template struct ConfigTranslator { static std::string To(int v) { return StringFromInt(v) + " (" + FTo(T(v)) + ")"; @@ -618,6 +545,7 @@ static const ConfigSetting graphicsSettings[] = { ConfigSetting("AnisotropyLevel", &g_Config.iAnisotropyLevel, 4, CfgFlag::PER_GAME), ConfigSetting("MultiSampleLevel", &g_Config.iMultiSampleLevel, 0, CfgFlag::PER_GAME), // Number of samples is 1 << iMultiSampleLevel + ConfigSetting("VertexDecCache", &g_Config.bVertexCache, false, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("TextureBackoffCache", &g_Config.bTextureBackoffCache, false, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("VertexDecJit", &g_Config.bVertexDecoderJit, &DefaultCodeGen, CfgFlag::DONT_SAVE | CfgFlag::REPORT), @@ -646,7 +574,7 @@ static const ConfigSetting graphicsSettings[] = { ConfigSetting("TexScalingType", &g_Config.iTexScalingType, 0, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("TexDeposterize", &g_Config.bTexDeposterize, false, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("TexHardwareScaling", &g_Config.bTexHardwareScaling, false, CfgFlag::PER_GAME | CfgFlag::REPORT), - ConfigSetting("VSync", &g_Config.bVSync, &DefaultVSync, CfgFlag::PER_GAME), + ConfigSetting("VSyncInterval", &g_Config.bVSync, false, CfgFlag::PER_GAME), ConfigSetting("BloomHack", &g_Config.iBloomHack, 0, CfgFlag::PER_GAME | CfgFlag::REPORT), // Not really a graphics setting... @@ -663,13 +591,8 @@ static const ConfigSetting graphicsSettings[] = { ConfigSetting("InflightFrames", &g_Config.iInflightFrames, 3, CfgFlag::DEFAULT), ConfigSetting("RenderDuplicateFrames", &g_Config.bRenderDuplicateFrames, false, CfgFlag::PER_GAME), - ConfigSetting("MultiThreading", &g_Config.bRenderMultiThreading, true, CfgFlag::DEFAULT), - ConfigSetting("ShaderCache", &g_Config.bShaderCache, true, CfgFlag::DONT_SAVE), // Doesn't save. Ini-only. ConfigSetting("GpuLogProfiler", &g_Config.bGpuLogProfiler, false, CfgFlag::DEFAULT), - - ConfigSetting("UberShaderVertex", &g_Config.bUberShaderVertex, true, CfgFlag::DEFAULT), - ConfigSetting("UberShaderFragment", &g_Config.bUberShaderFragment, true, CfgFlag::DEFAULT), }; static const ConfigSetting soundSettings[] = { @@ -714,47 +637,27 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("ShowTouchSquare", &g_Config.bShowTouchSquare, true, CfgFlag::PER_GAME), ConfigSetting("ShowTouchTriangle", &g_Config.bShowTouchTriangle, true, CfgFlag::PER_GAME), - ConfigSetting("Custom0Mapping", "Custom0Image", "Custom0Shape", "Custom0Toggle", "Custom0Repeat", &g_Config.CustomButton[0], {0, 0, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom1Mapping", "Custom1Image", "Custom1Shape", "Custom1Toggle", "Custom1Repeat", &g_Config.CustomButton[1], {0, 1, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom2Mapping", "Custom2Image", "Custom2Shape", "Custom2Toggle", "Custom2Repeat", &g_Config.CustomButton[2], {0, 2, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom3Mapping", "Custom3Image", "Custom3Shape", "Custom3Toggle", "Custom3Repeat", &g_Config.CustomButton[3], {0, 3, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom4Mapping", "Custom4Image", "Custom4Shape", "Custom4Toggle", "Custom4Repeat", &g_Config.CustomButton[4], {0, 4, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom5Mapping", "Custom5Image", "Custom5Shape", "Custom5Toggle", "Custom5Repeat", &g_Config.CustomButton[5], {0, 0, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom6Mapping", "Custom6Image", "Custom6Shape", "Custom6Toggle", "Custom6Repeat", &g_Config.CustomButton[6], {0, 1, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom7Mapping", "Custom7Image", "Custom7Shape", "Custom7Toggle", "Custom7Repeat", &g_Config.CustomButton[7], {0, 2, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom8Mapping", "Custom8Image", "Custom8Shape", "Custom8Toggle", "Custom8Repeat", &g_Config.CustomButton[8], {0, 3, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom9Mapping", "Custom9Image", "Custom9Shape", "Custom9Toggle", "Custom9Repeat", &g_Config.CustomButton[9], {0, 4, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom10Mapping", "Custom10Image", "Custom10Shape", "Custom10Toggle", "Custom10Repeat", &g_Config.CustomButton[10], {0, 0, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom11Mapping", "Custom11Image", "Custom11Shape", "Custom11Toggle", "Custom11Repeat", &g_Config.CustomButton[11], {0, 1, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom12Mapping", "Custom12Image", "Custom12Shape", "Custom12Toggle", "Custom12Repeat", &g_Config.CustomButton[12], {0, 2, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom13Mapping", "Custom13Image", "Custom13Shape", "Custom13Toggle", "Custom13Repeat", &g_Config.CustomButton[13], {0, 3, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom14Mapping", "Custom14Image", "Custom14Shape", "Custom14Toggle", "Custom14Repeat", &g_Config.CustomButton[14], {0, 4, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom15Mapping", "Custom15Image", "Custom15Shape", "Custom15Toggle", "Custom15Repeat", &g_Config.CustomButton[15], {0, 0, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom16Mapping", "Custom16Image", "Custom16Shape", "Custom16Toggle", "Custom16Repeat", &g_Config.CustomButton[16], {0, 1, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom17Mapping", "Custom17Image", "Custom17Shape", "Custom17Toggle", "Custom17Repeat", &g_Config.CustomButton[17], {0, 2, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom18Mapping", "Custom18Image", "Custom18Shape", "Custom18Toggle", "Custom18Repeat", &g_Config.CustomButton[18], {0, 3, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom19Mapping", "Custom19Image", "Custom19Shape", "Custom19Toggle", "Custom19Repeat", &g_Config.CustomButton[19], {0, 4, 9, false, false}, CfgFlag::PER_GAME), - // Combo keys are something else, but I don't want to break the config backwards compatibility so these will stay wrongly named. - ConfigSetting("fcombo0X", "fcombo0Y", "comboKeyScale0", "ShowComboKey0", &g_Config.touchCustom[0], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo1X", "fcombo1Y", "comboKeyScale1", "ShowComboKey1", &g_Config.touchCustom[1], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo2X", "fcombo2Y", "comboKeyScale2", "ShowComboKey2", &g_Config.touchCustom[2], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo3X", "fcombo3Y", "comboKeyScale3", "ShowComboKey3", &g_Config.touchCustom[3], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo4X", "fcombo4Y", "comboKeyScale4", "ShowComboKey4", &g_Config.touchCustom[4], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo5X", "fcombo5Y", "comboKeyScale5", "ShowComboKey5", &g_Config.touchCustom[5], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo6X", "fcombo6Y", "comboKeyScale6", "ShowComboKey6", &g_Config.touchCustom[6], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo7X", "fcombo7Y", "comboKeyScale7", "ShowComboKey7", &g_Config.touchCustom[7], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo8X", "fcombo8Y", "comboKeyScale8", "ShowComboKey8", &g_Config.touchCustom[8], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo9X", "fcombo9Y", "comboKeyScale9", "ShowComboKey9", &g_Config.touchCustom[9], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo10X", "fcombo10Y", "comboKeyScale10", "ShowComboKey10", &g_Config.touchCustom[10], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo11X", "fcombo11Y", "comboKeyScale11", "ShowComboKey11", &g_Config.touchCustom[11], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo12X", "fcombo12Y", "comboKeyScale12", "ShowComboKey12", &g_Config.touchCustom[12], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo13X", "fcombo13Y", "comboKeyScale13", "ShowComboKey13", &g_Config.touchCustom[13], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo14X", "fcombo14Y", "comboKeyScale14", "ShowComboKey14", &g_Config.touchCustom[14], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo15X", "fcombo15Y", "comboKeyScale15", "ShowComboKey15", &g_Config.touchCustom[15], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo16X", "fcombo16Y", "comboKeyScale16", "ShowComboKey16", &g_Config.touchCustom[16], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo17X", "fcombo17Y", "comboKeyScale17", "ShowComboKey17", &g_Config.touchCustom[17], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo18X", "fcombo18Y", "comboKeyScale18", "ShowComboKey18", &g_Config.touchCustom[18], defaultTouchPosHide, CfgFlag::PER_GAME), - ConfigSetting("fcombo19X", "fcombo19Y", "comboKeyScale19", "ShowComboKey19", &g_Config.touchCustom[19], defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("Custom0Mapping", "Custom0Image", "Custom0Shape", "Custom0Toggle", "Custom0Repeat", &g_Config.CustomButton0, {0, 0, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom1Mapping", "Custom1Image", "Custom1Shape", "Custom1Toggle", "Custom1Repeat", &g_Config.CustomButton1, {0, 1, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom2Mapping", "Custom2Image", "Custom2Shape", "Custom2Toggle", "Custom2Repeat", &g_Config.CustomButton2, {0, 2, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom3Mapping", "Custom3Image", "Custom3Shape", "Custom3Toggle", "Custom3Repeat", &g_Config.CustomButton3, {0, 3, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom4Mapping", "Custom4Image", "Custom4Shape", "Custom4Toggle", "Custom4Repeat", &g_Config.CustomButton4, {0, 4, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom5Mapping", "Custom5Image", "Custom5Shape", "Custom5Toggle", "Custom5Repeat", &g_Config.CustomButton5, {0, 0, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom6Mapping", "Custom6Image", "Custom6Shape", "Custom6Toggle", "Custom6Repeat", &g_Config.CustomButton6, {0, 1, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom7Mapping", "Custom7Image", "Custom7Shape", "Custom7Toggle", "Custom7Repeat", &g_Config.CustomButton7, {0, 2, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom8Mapping", "Custom8Image", "Custom8Shape", "Custom8Toggle", "Custom8Repeat", &g_Config.CustomButton8, {0, 3, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom9Mapping", "Custom9Image", "Custom9Shape", "Custom9Toggle", "Custom9Repeat", &g_Config.CustomButton9, {0, 4, 1, false, false}, CfgFlag::PER_GAME), + // Combo keys are going to be something else, but I don't want to break the config. + ConfigSetting("fcombo0X", "fcombo0Y", "comboKeyScale0", "ShowComboKey0", &g_Config.touchCustom0, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo1X", "fcombo1Y", "comboKeyScale1", "ShowComboKey1", &g_Config.touchCustom1, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo2X", "fcombo2Y", "comboKeyScale2", "ShowComboKey2", &g_Config.touchCustom2, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo3X", "fcombo3Y", "comboKeyScale3", "ShowComboKey3", &g_Config.touchCustom3, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo4X", "fcombo4Y", "comboKeyScale4", "ShowComboKey4", &g_Config.touchCustom4, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo5X", "fcombo5Y", "comboKeyScale5", "ShowComboKey5", &g_Config.touchCustom5, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo6X", "fcombo6Y", "comboKeyScale6", "ShowComboKey6", &g_Config.touchCustom6, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo7X", "fcombo7Y", "comboKeyScale7", "ShowComboKey7", &g_Config.touchCustom7, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo8X", "fcombo8Y", "comboKeyScale8", "ShowComboKey8", &g_Config.touchCustom8, defaultTouchPosHide, CfgFlag::PER_GAME), + ConfigSetting("fcombo9X", "fcombo9Y", "comboKeyScale9", "ShowComboKey9", &g_Config.touchCustom9, defaultTouchPosHide, CfgFlag::PER_GAME), #if defined(_WIN32) // A win32 user seeing touch controls is likely using PPSSPP on a tablet. There it makes @@ -778,8 +681,6 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 60, CfgFlag::PER_GAME), ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 60, CfgFlag::PER_GAME), ConfigSetting("TiltAnalogDeadzoneRadius", &g_Config.fTiltAnalogDeadzoneRadius, 0.0f, CfgFlag::PER_GAME), - ConfigSetting("TiltInverseDeadzone", &g_Config.fTiltInverseDeadzone, 0.0f, CfgFlag::PER_GAME), - ConfigSetting("TiltCircularInverseDeadzone", &g_Config.bTiltCircularInverseDeadzone, true, CfgFlag::PER_GAME), ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, CfgFlag::PER_GAME), #endif @@ -789,7 +690,6 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("TouchButtonOpacity", &g_Config.iTouchButtonOpacity, 65, CfgFlag::PER_GAME), ConfigSetting("TouchButtonHideSeconds", &g_Config.iTouchButtonHideSeconds, 20, CfgFlag::PER_GAME), ConfigSetting("AutoCenterTouchAnalog", &g_Config.bAutoCenterTouchAnalog, false, CfgFlag::PER_GAME), - ConfigSetting("StickyTouchDPad", &g_Config.bStickyTouchDPad, false, CfgFlag::PER_GAME), // Snap touch control position ConfigSetting("TouchSnapToGrid", &g_Config.bTouchSnapToGrid, false, CfgFlag::PER_GAME), @@ -818,8 +718,6 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("AnalogLimiterDeadzone", &g_Config.fAnalogLimiterDeadzone, 0.6f, CfgFlag::DEFAULT), - ConfigSetting("AllowMappingCombos", &g_Config.bAllowMappingCombos, false, CfgFlag::DEFAULT), - ConfigSetting("LeftStickHeadScale", &g_Config.fLeftStickHeadScale, 1.0f, CfgFlag::PER_GAME), ConfigSetting("RightStickHeadScale", &g_Config.fRightStickHeadScale, 1.0f, CfgFlag::PER_GAME), ConfigSetting("HideStickBackground", &g_Config.bHideStickBackground, false, CfgFlag::PER_GAME), @@ -831,10 +729,6 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("MouseSmoothing", &g_Config.fMouseSmoothing, 0.9f, CfgFlag::PER_GAME), ConfigSetting("SystemControls", &g_Config.bSystemControls, true, CfgFlag::DEFAULT), - ConfigSetting("RapidFileInterval", &g_Config.iRapidFireInterval, 5, CfgFlag::DEFAULT), - - ConfigSetting("AnalogGesture", &g_Config.bAnalogGesture, false, CfgFlag::PER_GAME), - ConfigSetting("AnalogGestureSensibility", &g_Config.fAnalogGestureSensibility, 1.0f, CfgFlag::PER_GAME), }; static const ConfigSetting networkSettings[] = { @@ -848,8 +742,8 @@ static const ConfigSetting networkSettings[] = { ConfigSetting("UPnPUseOriginalPort", &g_Config.bUPnPUseOriginalPort, false, CfgFlag::PER_GAME), ConfigSetting("EnableNetworkChat", &g_Config.bEnableNetworkChat, false, CfgFlag::PER_GAME), - ConfigSetting("ChatButtonPosition", &g_Config.iChatButtonPosition, (int)ScreenEdgePosition::BOTTOM_LEFT, CfgFlag::PER_GAME), - ConfigSetting("ChatScreenPosition", &g_Config.iChatScreenPosition, (int)ScreenEdgePosition::BOTTOM_LEFT, CfgFlag::PER_GAME), + ConfigSetting("ChatButtonPosition",&g_Config.iChatButtonPosition,BOTTOM_LEFT, CfgFlag::PER_GAME), + ConfigSetting("ChatScreenPosition",&g_Config.iChatScreenPosition,BOTTOM_LEFT, CfgFlag::PER_GAME), ConfigSetting("EnableQuickChat", &g_Config.bEnableQuickChat, true, CfgFlag::PER_GAME), ConfigSetting("QuickChat1", &g_Config.sQuickChat0, "Quick Chat 1", CfgFlag::PER_GAME), ConfigSetting("QuickChat2", &g_Config.sQuickChat1, "Quick Chat 2", CfgFlag::PER_GAME), @@ -858,12 +752,25 @@ static const ConfigSetting networkSettings[] = { ConfigSetting("QuickChat5", &g_Config.sQuickChat4, "Quick Chat 5", CfgFlag::PER_GAME), }; +static int DefaultSystemParamLanguage() { + int defaultLang = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; + if (g_Config.bFirstRun) { + // TODO: Be smart about same language, different country + auto &langValuesMapping = g_Config.GetLangValuesMapping(); + auto iter = langValuesMapping.find(g_Config.sLanguageIni); + if (iter != langValuesMapping.end()) { + defaultLang = iter->second.second; + } + } + return defaultLang; +} + static const ConfigSetting systemParamSettings[] = { ConfigSetting("PSPModel", &g_Config.iPSPModel, PSP_MODEL_SLIM, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("PSPFirmwareVersion", &g_Config.iFirmwareVersion, PSP_DEFAULT_FIRMWARE, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("NickName", &g_Config.sNickName, "PPSSPP", CfgFlag::PER_GAME), ConfigSetting("MacAddress", &g_Config.sMACAddress, "", CfgFlag::PER_GAME), - ConfigSetting("GameLanguage", &g_Config.iLanguage, -1, CfgFlag::PER_GAME | CfgFlag::REPORT), + ConfigSetting("Language", &g_Config.iLanguage, &DefaultSystemParamLanguage, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("ParamTimeFormat", &g_Config.iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR, CfgFlag::PER_GAME), ConfigSetting("ParamDateFormat", &g_Config.iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD, CfgFlag::PER_GAME), ConfigSetting("TimeZone", &g_Config.iTimeZone, 0, CfgFlag::PER_GAME), @@ -871,7 +778,7 @@ static const ConfigSetting systemParamSettings[] = { ConfigSetting("ButtonPreference", &g_Config.iButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("LockParentalLevel", &g_Config.iLockParentalLevel, 0, CfgFlag::PER_GAME), ConfigSetting("WlanAdhocChannel", &g_Config.iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC, CfgFlag::PER_GAME), -#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) ConfigSetting("BypassOSKWithKeyboard", &g_Config.bBypassOSKWithKeyboard, false, CfgFlag::PER_GAME), #endif ConfigSetting("WlanPowerSave", &g_Config.bWlanPowerSave, (bool) PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF, CfgFlag::PER_GAME), @@ -899,10 +806,12 @@ static const ConfigSetting debuggerSettings[] = { ConfigSetting("DisplayStatusBar", &g_Config.bDisplayStatusBar, true, CfgFlag::DEFAULT), ConfigSetting("ShowBottomTabTitles",&g_Config.bShowBottomTabTitles, true, CfgFlag::DEFAULT), ConfigSetting("ShowDeveloperMenu", &g_Config.bShowDeveloperMenu, false, CfgFlag::DEFAULT), + ConfigSetting("ShowAllocatorDebug", &g_Config.bShowAllocatorDebug, false, CfgFlag::DONT_SAVE), + ConfigSetting("ShowGpuProfile", &g_Config.bShowGpuProfile, false, CfgFlag::DONT_SAVE), ConfigSetting("SkipDeadbeefFilling", &g_Config.bSkipDeadbeefFilling, false, CfgFlag::DEFAULT), ConfigSetting("FuncHashMap", &g_Config.bFuncHashMap, false, CfgFlag::DEFAULT), - ConfigSetting("SkipFuncHashMap", &g_Config.sSkipFuncHashMap, "", CfgFlag::DEFAULT), ConfigSetting("MemInfoDetailed", &g_Config.bDebugMemInfoDetailed, false, CfgFlag::DEFAULT), + ConfigSetting("DrawFrameGraph", &g_Config.bDrawFrameGraph, false, CfgFlag::DEFAULT), }; static const ConfigSetting jitSettings[] = { @@ -921,25 +830,24 @@ static const ConfigSetting themeSettings[] = { static const ConfigSetting vrSettings[] = { - ConfigSetting("VREnable", &g_Config.bEnableVR, true, CfgFlag::PER_GAME), - ConfigSetting("VREnable6DoF", &g_Config.bEnable6DoF, true, CfgFlag::PER_GAME), - ConfigSetting("VREnableStereo", &g_Config.bEnableStereo, false, CfgFlag::PER_GAME), - ConfigSetting("VREnableMotions", &g_Config.bEnableMotions, true, CfgFlag::PER_GAME), - ConfigSetting("VRForce72Hz", &g_Config.bForce72Hz, true, CfgFlag::PER_GAME), - ConfigSetting("VRManualForceVR", &g_Config.bManualForceVR, false, CfgFlag::PER_GAME), - ConfigSetting("VRPassthrough", &g_Config.bPassthrough, false, CfgFlag::PER_GAME), - ConfigSetting("VRRescaleHUD", &g_Config.bRescaleHUD, true, CfgFlag::PER_GAME), - ConfigSetting("VRCameraDistance", &g_Config.fCameraDistance, 0.0f, CfgFlag::PER_GAME), - ConfigSetting("VRCameraHeight", &g_Config.fCameraHeight, 0.0f, CfgFlag::PER_GAME), - ConfigSetting("VRCameraSide", &g_Config.fCameraSide, 0.0f, CfgFlag::PER_GAME), - ConfigSetting("VRCameraPitch", &g_Config.iCameraPitch, 0, CfgFlag::PER_GAME), + ConfigSetting("VREnable", &g_Config.bEnableVR, true, CfgFlag::DEFAULT), + ConfigSetting("VREnable6DoF", &g_Config.bEnable6DoF, true, CfgFlag::DEFAULT), + ConfigSetting("VREnableStereo", &g_Config.bEnableStereo, false, CfgFlag::DEFAULT), + ConfigSetting("VREnableMotions", &g_Config.bEnableMotions, true, CfgFlag::DEFAULT), + ConfigSetting("VRForce72Hz", &g_Config.bForce72Hz, true, CfgFlag::DEFAULT), + ConfigSetting("VRManualForceVR", &g_Config.bManualForceVR, false, CfgFlag::DEFAULT), + ConfigSetting("VRRescaleHUD", &g_Config.bRescaleHUD, true, CfgFlag::DEFAULT), + ConfigSetting("VRCameraDistance", &g_Config.fCameraDistance, 0.0f, CfgFlag::DEFAULT), + ConfigSetting("VRCameraHeight", &g_Config.fCameraHeight, 0.0f, CfgFlag::DEFAULT), + ConfigSetting("VRCameraSide", &g_Config.fCameraSide, 0.0f, CfgFlag::DEFAULT), + ConfigSetting("VRCameraPitch", &g_Config.iCameraPitch, 0, CfgFlag::DEFAULT), ConfigSetting("VRCanvasDistance", &g_Config.fCanvasDistance, 12.0f, CfgFlag::DEFAULT), - ConfigSetting("VRCanvas3DDistance", &g_Config.fCanvas3DDistance, 3.0f, CfgFlag::DEFAULT), - ConfigSetting("VRHeadUpDisplayScale", &g_Config.fHeadUpDisplayScale, 0.3f, CfgFlag::PER_GAME), + ConfigSetting("VRFieldOfView", &g_Config.fFieldOfViewPercentage, 100.0f, CfgFlag::DEFAULT), + ConfigSetting("VRHeadUpDisplayScale", &g_Config.fHeadUpDisplayScale, 0.3f, CfgFlag::DEFAULT), ConfigSetting("VRMotionLength", &g_Config.fMotionLength, 0.5f, CfgFlag::DEFAULT), - ConfigSetting("VRHeadRotationScale", &g_Config.fHeadRotationScale, 5.0f, CfgFlag::PER_GAME), - ConfigSetting("VRHeadRotationEnabled", &g_Config.bHeadRotationEnabled, false, CfgFlag::PER_GAME), - ConfigSetting("VRHeadRotationSmoothing", &g_Config.bHeadRotationSmoothing, false, CfgFlag::PER_GAME), + ConfigSetting("VRHeadRotationScale", &g_Config.fHeadRotationScale, 5.0f, CfgFlag::DEFAULT), + ConfigSetting("VRHeadRotationEnabled", &g_Config.bHeadRotationEnabled, false, CfgFlag::DEFAULT), + ConfigSetting("VRHeadRotationSmoothing", &g_Config.bHeadRotationSmoothing, false, CfgFlag::DEFAULT), }; static const ConfigSectionSettings sections[] = { @@ -955,7 +863,6 @@ static const ConfigSectionSettings sections[] = { {"Upgrade", upgradeSettings, ARRAY_SIZE(upgradeSettings)}, {"Theme", themeSettings, ARRAY_SIZE(themeSettings)}, {"VR", vrSettings, ARRAY_SIZE(vrSettings)}, - {"Achievements", achievementSettings, ARRAY_SIZE(achievementSettings)}, }; const size_t numSections = ARRAY_SIZE(sections); @@ -1095,20 +1002,18 @@ void Config::UpdateAfterSettingAutoFrameSkip() { } void Config::Load(const char *iniFileName, const char *controllerIniFilename) { - double startTime = time_now_d(); - if (!bUpdatedInstanceCounter) { InitInstanceCounter(); bUpdatedInstanceCounter = true; } - g_DownloadManager.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION)); - UpdateIniLocation(iniFileName, controllerIniFilename); INFO_LOG(LOADER, "Loading config: %s", iniFilename_.c_str()); bSaveSettings = true; + bShowFrameProfiler = true; + IniFile iniFile; if (!iniFile.Load(iniFilename_)) { ERROR_LOG(LOADER, "Failed to read '%s'. Setting config to default.", iniFilename_.c_str()); @@ -1157,10 +1062,6 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { } } - // Time tracking - Section *playTime = iniFile.GetOrCreateSection("PlayTime"); - playTimeTracker_.Load(playTime); - auto pinnedPaths = iniFile.GetOrCreateSection("PinnedPaths")->ToMap(); vPinnedPaths.clear(); for (auto it = pinnedPaths.begin(), end = pinnedPaths.end(); it != end; ++it) { @@ -1223,7 +1124,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { if (iRunCount % 10 == 0 && bCheckForNewVersion) { const char *versionUrl = "http://www.ppsspp.org/version.json"; const char *acceptMime = "application/json, text/*; q=0.9, */*; q=0.8"; - g_DownloadManager.StartDownloadWithCallback(versionUrl, Path(), http::ProgressBarMode::NONE, &DownloadCompletedCallback, "version", acceptMime); + auto dl = g_DownloadManager.StartDownloadWithCallback(versionUrl, Path(), &DownloadCompletedCallback, acceptMime); + dl->SetHidden(true); } INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename_.c_str()); @@ -1240,13 +1142,17 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { CleanRecent(); +#if PPSSPP_PLATFORM(ANDROID) + // The on path here is untested, since we don't expose it. + g_Config.bVSync = false; +#endif + PostLoadCleanup(false); - INFO_LOG(LOADER, "Config loaded: '%s' (%0.1f ms)", iniFilename_.c_str(), (time_now_d() - startTime) * 1000.0); + INFO_LOG(LOADER, "Config loaded: '%s'", iniFilename_.c_str()); } bool Config::Save(const char *saveReason) { - double startTime = time_now_d(); if (!IsFirstInstance()) { // TODO: Should we allow saving config if started from a different directory? // How do we tell? @@ -1264,7 +1170,7 @@ bool Config::Save(const char *saveReason) { CleanRecent(); IniFile iniFile; if (!iniFile.Load(iniFilename_)) { - WARN_LOG(LOADER, "Likely saving config for first time - couldn't read ini '%s'", iniFilename_.c_str()); + ERROR_LOG(LOADER, "Error saving config - can't read ini '%s'", iniFilename_.c_str()); } // Need to do this somewhere... @@ -1321,15 +1227,11 @@ bool Config::Save(const char *saveReason) { if (LogManager::GetInstance()) LogManager::GetInstance()->SaveConfig(log); - // Time tracking - Section *playTime = iniFile.GetOrCreateSection("PlayTime"); - playTimeTracker_.Save(playTime); - if (!iniFile.Save(iniFilename_)) { ERROR_LOG(LOADER, "Error saving config (%s)- can't write ini '%s'", saveReason, iniFilename_.c_str()); return false; } - INFO_LOG(LOADER, "Config saved (%s): '%s' (%0.1f ms)", saveReason, iniFilename_.c_str(), (time_now_d() - startTime) * 1000.0); + INFO_LOG(LOADER, "Config saved (%s): '%s'", saveReason, iniFilename_.c_str()); if (!bGameSpecific) //otherwise we already did this in saveGameConfig() { @@ -1355,9 +1257,9 @@ bool Config::Save(const char *saveReason) { void Config::PostLoadCleanup(bool gameSpecific) { // Override ppsspp.ini JIT value to prevent crashing - jitForcedOff = DefaultCpuCore() != (int)CPUCore::JIT && (g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR); + jitForcedOff = DefaultCpuCore() != (int)CPUCore::JIT && g_Config.iCpuCore == (int)CPUCore::JIT; if (jitForcedOff) { - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; + g_Config.iCpuCore = (int)CPUCore::IR_JIT; } // This caps the exponent 4 (so 16x.) @@ -1387,7 +1289,7 @@ void Config::PostLoadCleanup(bool gameSpecific) { void Config::PreSaveCleanup(bool gameSpecific) { if (jitForcedOff) { // If we forced jit off and it's still set to IR, change it back to jit. - if (g_Config.iCpuCore == (int)CPUCore::IR_INTERPRETER) + if (g_Config.iCpuCore == (int)CPUCore::IR_JIT) g_Config.iCpuCore = (int)CPUCore::JIT; } } @@ -1396,12 +1298,12 @@ void Config::PostSaveCleanup(bool gameSpecific) { if (jitForcedOff) { // Force JIT off again just in case Config::Save() is called without exiting PPSSPP. if (g_Config.iCpuCore == (int)CPUCore::JIT) - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; + g_Config.iCpuCore = (int)CPUCore::IR_JIT; } } void Config::NotifyUpdatedCpuCore() { - if (jitForcedOff && g_Config.iCpuCore == (int)CPUCore::IR_INTERPRETER) { + if (jitForcedOff && g_Config.iCpuCore == (int)CPUCore::IR_JIT) { // No longer forced off, the user set it to IR jit. jitForcedOff = false; } @@ -1412,7 +1314,7 @@ void Config::NotifyUpdatedCpuCore() { #define PPSSPP_GIT_VERSION "v0.0.1-gaaaaaaaaa" #endif -void Config::DownloadCompletedCallback(http::Request &download) { +void Config::DownloadCompletedCallback(http::Download &download) { if (download.ResultCode() != 200) { ERROR_LOG(LOADER, "Failed to download %s: %d", download.url().c_str(), download.ResultCode()); return; @@ -1801,9 +1703,16 @@ void Config::ResetControlLayout() { reset(g_Config.touchRKey); reset(g_Config.touchAnalogStick); reset(g_Config.touchRightAnalogStick); - for (int i = 0; i < CUSTOM_BUTTON_COUNT; i++) { - reset(g_Config.touchCustom[i]); - } + reset(g_Config.touchCustom0); + reset(g_Config.touchCustom1); + reset(g_Config.touchCustom2); + reset(g_Config.touchCustom3); + reset(g_Config.touchCustom4); + reset(g_Config.touchCustom5); + reset(g_Config.touchCustom6); + reset(g_Config.touchCustom7); + reset(g_Config.touchCustom8); + reset(g_Config.touchCustom9); g_Config.fLeftStickHeadScale = 1.0f; g_Config.fRightStickHeadScale = 1.0f; } @@ -1820,104 +1729,3 @@ void Config::GetReportingInfo(UrlEncoder &data) { bool Config::IsPortrait() const { return (iInternalScreenRotation == ROTATION_LOCKED_VERTICAL || iInternalScreenRotation == ROTATION_LOCKED_VERTICAL180) && !bSkipBufferEffects; } - -int Config::GetPSPLanguage() { - if (g_Config.iLanguage == -1) { - const auto &langValuesMapping = GetLangValuesMapping(); - auto iter = langValuesMapping.find(g_Config.sLanguageIni); - if (iter != langValuesMapping.end()) { - return iter->second.second; - } else { - // Fallback to English - return PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; - } - } else { - return g_Config.iLanguage; - } -} - -void PlayTimeTracker::Start(std::string gameId) { - INFO_LOG(SYSTEM, "GameTimeTracker::Start(%s)", gameId.c_str()); - if (gameId.empty()) { - return; - } - - auto iter = tracker_.find(std::string(gameId)); - if (iter != tracker_.end()) { - if (iter->second.startTime == 0.0) { - iter->second.lastTimePlayed = time_now_unix_utc(); - iter->second.startTime = time_now_d(); - } - return; - } - - PlayTime playTime; - playTime.lastTimePlayed = time_now_unix_utc(); - playTime.totalTimePlayed = 0.0; - playTime.startTime = time_now_d(); - tracker_[gameId] = playTime; -} - -void PlayTimeTracker::Stop(std::string gameId) { - INFO_LOG(SYSTEM, "GameTimeTracker::Stop(%s)", gameId.c_str()); - _dbg_assert_(!gameId.empty()); - - auto iter = tracker_.find(std::string(gameId)); - if (iter != tracker_.end()) { - if (iter->second.startTime != 0.0) { - iter->second.totalTimePlayed += time_now_d() - iter->second.startTime; - iter->second.startTime = 0.0; - } - iter->second.lastTimePlayed = time_now_unix_utc(); - return; - } - - // Shouldn't happen, ignore this case. - WARN_LOG(SYSTEM, "GameTimeTracker::Stop called without corresponding GameTimeTracker::Start"); -} - -void PlayTimeTracker::Load(const Section *section) { - tracker_.clear(); - - std::vector keys; - section->GetKeys(keys); - - for (auto key : keys) { - std::string value; - if (!section->Get(key.c_str(), &value, nullptr)) { - continue; - } - - // Parse the string. - PlayTime gameTime{}; - if (2 == sscanf(value.c_str(), "%d,%llu", &gameTime.totalTimePlayed, &gameTime.lastTimePlayed)) { - tracker_[key] = gameTime; - } - } -} - -void PlayTimeTracker::Save(Section *section) { - for (auto iter : tracker_) { - std::string formatted = StringFromFormat("%d,%llu", iter.second.totalTimePlayed, iter.second.lastTimePlayed); - section->Set(iter.first.c_str(), formatted); - } -} - -bool PlayTimeTracker::GetPlayedTimeString(const std::string &gameId, std::string *str) const { - auto ga = GetI18NCategory(I18NCat::GAME); - - auto iter = tracker_.find(gameId); - if (iter == tracker_.end()) { - return false; - } - - int totalSeconds = iter->second.totalTimePlayed; - int seconds = totalSeconds % 60; - totalSeconds /= 60; - int minutes = totalSeconds % 60; - totalSeconds /= 60; - int hours = totalSeconds; - - *str = ApplySafeSubstitutions(ga->T("Time Played: %1h %2m %3s"), hours, minutes, seconds); - return true; -} diff --git a/Core/Config.h b/Core/Config.h index 40e8b3d42..1d36130b4 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -29,37 +29,25 @@ extern const char *PPSSPP_GIT_VERSION; +enum ChatPositions { + BOTTOM_LEFT = 0, + BOTTOM_CENTER = 1, + BOTOM_RIGHT = 2, + TOP_LEFT = 3, + TOP_CENTER = 4, + TOP_RIGHT = 5, + CENTER_LEFT = 6, + CENTER_RIGHT = 7, +}; + namespace http { - class Request; - class RequestManager; + class Download; + class Downloader; } struct UrlEncoder; struct ConfigPrivate; -class Section; - -class PlayTimeTracker { -public: - struct PlayTime { - int totalTimePlayed; - double startTime; // time_now_d() time - uint64_t lastTimePlayed; // UTC Unix time for portability. - }; - - // It's OK to call these redundantly. - void Start(std::string gameId); - void Stop(std::string gameId); - - void Load(const Section *section); - void Save(Section *section); - - bool GetPlayedTimeString(const std::string &gameId, std::string *str) const; - -private: - std::map tracker_; -}; - struct Config { public: Config(); @@ -115,8 +103,6 @@ public: bool bPreloadFunctions; uint32_t uJitDisableFlags; - bool bDisableHTTPS; - bool bSeparateSASThread; int iIOTimingMethod; int iLockedCPUSpeed; @@ -199,6 +185,7 @@ public: float fUITint; float fUISaturation; + bool bVertexCache; bool bTextureBackoffCache; bool bVertexDecoderJit; bool bFullScreen; @@ -237,8 +224,6 @@ public: int iSplineBezierQuality; // 0 = low , 1 = Intermediate , 2 = High bool bHardwareTessellation; bool bShaderCache; // Hidden ini-only setting, useful for debugging shader compile times. - bool bUberShaderVertex; - bool bUberShaderFragment; std::vector vPostShaderNames; // Off for chain end (only Off for no shader) std::map mPostShaderSetting; @@ -253,7 +238,6 @@ public: bool bGfxDebugOutput; int iInflightFrames; bool bRenderDuplicateFrames; - bool bRenderMultiThreading; // Sound bool bEnableSound; @@ -279,6 +263,10 @@ public: // These aren't saved, just for instant debugging. bool bLogFrameDrops; + bool bShowDebugStats; + bool bShowAudioDebug; + bool bShowControlDebug; + bool bShowGpuProfile; // Analog stick tilting // This is the held base angle (from the horizon), that we compute the tilt relative from. @@ -291,8 +279,6 @@ public: int iTiltSensitivityY; // The deadzone radius of the tilt. Only used in the analog mapping. float fTiltAnalogDeadzoneRadius; - float fTiltInverseDeadzone; // An inverse deadzone for the output, counteracting excessive deadzones applied by games. See #17483. - bool bTiltCircularInverseDeadzone; // Type of tilt input currently selected: Defined in TiltEventProcessor.h // 0 - no tilt, 1 - analog stick, 2 - D-Pad, 3 - Action Buttons (Tri, Cross, Square, Circle) int iTiltInputType; @@ -320,8 +306,6 @@ public: float fSwipeSensitivity; float fSwipeSmoothing; int iDoubleTapGesture; - bool bAnalogGesture; - float fAnalogGestureSensibility; // Disable diagonals bool bDisableDpadDiagonals; @@ -338,9 +322,6 @@ public: // Floating analog stick (recenters on thumb on press). bool bAutoCenterTouchAnalog; - // Sticky D-pad (can't glide off it) - bool bStickyTouchDPad; - //space between PSP buttons //the PSP button's center (triangle, circle, square, cross) ConfigTouchPos touchActionButtonCenter; @@ -358,9 +339,16 @@ public: ConfigTouchPos touchAnalogStick; ConfigTouchPos touchRightAnalogStick; - enum { CUSTOM_BUTTON_COUNT = 20 }; - - ConfigTouchPos touchCustom[CUSTOM_BUTTON_COUNT]; + ConfigTouchPos touchCustom0; + ConfigTouchPos touchCustom1; + ConfigTouchPos touchCustom2; + ConfigTouchPos touchCustom3; + ConfigTouchPos touchCustom4; + ConfigTouchPos touchCustom5; + ConfigTouchPos touchCustom6; + ConfigTouchPos touchCustom7; + ConfigTouchPos touchCustom8; + ConfigTouchPos touchCustom9; float fLeftStickHeadScale; float fRightStickHeadScale; @@ -374,7 +362,16 @@ public: bool bShowTouchTriangle; bool bShowTouchSquare; - ConfigCustomButton CustomButton[CUSTOM_BUTTON_COUNT]; + ConfigCustomButton CustomButton0; + ConfigCustomButton CustomButton1; + ConfigCustomButton CustomButton2; + ConfigCustomButton CustomButton3; + ConfigCustomButton CustomButton4; + ConfigCustomButton CustomButton5; + ConfigCustomButton CustomButton6; + ConfigCustomButton CustomButton7; + ConfigCustomButton CustomButton8; + ConfigCustomButton CustomButton9; // Ignored on iOS and other platforms that lack pause. bool bShowTouchPause; @@ -393,9 +390,6 @@ public: // Sets up how much the analog limiter button restricts digital->analog input. float fAnalogLimiterDeadzone; - // Sets whether combo mapping is enabled. - bool bAllowMappingCombos; - bool bMouseControl; bool bMapMouse; // Workaround for mapping screen:| bool bMouseConfine; // Trap inside the window. @@ -403,7 +397,6 @@ public: float fMouseSmoothing; bool bSystemControls; - int iRapidFireInterval; // Use the hardware scaler to scale up the image to save fillrate. Similar to Windows' window size, really. int iAndroidHwScale; // 0 = device resolution. 1 = 480x272 (extended to correct aspect), 2 = 960x544 etc. @@ -458,13 +451,12 @@ public: bool bEnableMotions; bool bForce72Hz; bool bManualForceVR; - bool bPassthrough; bool bRescaleHUD; float fCameraDistance; float fCameraHeight; float fCameraSide; float fCanvasDistance; - float fCanvas3DDistance; + float fFieldOfViewPercentage; float fHeadUpDisplayScale; float fMotionLength; float fHeadRotationScale; @@ -491,47 +483,17 @@ public: bool bDisplayStatusBar; bool bShowBottomTabTitles; bool bShowDeveloperMenu; - + bool bShowAllocatorDebug; // Double edged sword: much easier debugging, but not accurate. bool bSkipDeadbeefFilling; - bool bFuncHashMap; - std::string sSkipFuncHashMap; bool bDebugMemInfoDetailed; + bool bDrawFrameGraph; // Volatile development settings - // Overlays - int iDebugOverlay; - + bool bShowFrameProfiler; bool bGpuLogProfiler; // Controls the Vulkan logging profiler (profiles textures uploads etc). - // Retro Achievement settings - // Copied from Duckstation, we might want to remove some. - bool bAchievementsEnable; - bool bAchievementsChallengeMode; - bool bAchievementsEncoreMode; - bool bAchievementsUnofficial; - bool bAchievementsSoundEffects; - bool bAchievementsLogBadMemReads; - bool bAchievementsSaveStateInChallengeMode; - - // Positioning of the various notifications - int iAchievementsLeaderboardTrackerPos; - int iAchievementsLeaderboardStartedOrFailedPos; - int iAchievementsLeaderboardSubmittedPos; - int iAchievementsProgressPos; - int iAchievementsChallengePos; - int iAchievementsUnlockedPos; - - // Customizations - std::string sAchievementsUnlockAudioFile; - std::string sAchievementsLeaderboardSubmitAudioFile; - - // Achivements login info. Note that password is NOT stored, only a login token. - // Still, we may wanna store it more securely than in PPSSPP.ini, especially on Android. - std::string sAchievementsUserName; - std::string sAchievementsToken; // Not saved, to be used if you want to manually make your RA login persistent. See Native_SaveSecret for the normal case. - // Various directories. Autoconfigured, not read from ini. Path currentDirectory; // The directory selected in the game browsing window. Path defaultCurrentDirectory; // Platform dependent, initialized at startup. @@ -571,7 +533,7 @@ public: void RemoveRecent(const std::string &file); void CleanRecent(); - static void DownloadCompletedCallback(http::Request &download); + static void DownloadCompletedCallback(http::Download &download); void DismissUpgrade(); void ResetControlLayout(); @@ -597,12 +559,6 @@ public: void SetAppendedConfigIni(const Path &path); void UpdateAfterSettingAutoFrameSkip(); void NotifyUpdatedCpuCore(); - - // Applies the Auto setting if set. Returns an enum value from PSP_SYSTEMPARAM_LANGUAGE_*. - int GetPSPLanguage(); - - PlayTimeTracker &TimeTracker() { return playTimeTracker_; } - protected: void LoadStandardControllerIni(); void LoadLangValuesMapping(); @@ -617,7 +573,6 @@ private: std::string gameIdTitle_; std::vector recentIsos; std::map> langValuesMapping_; - PlayTimeTracker playTimeTracker_; Path iniFilename_; Path controllerIniFilename_; Path searchPath_; @@ -630,6 +585,6 @@ private: std::string CreateRandMAC(); // TODO: Find a better place for this. -extern http::RequestManager g_DownloadManager; +extern http::Downloader g_DownloadManager; extern Config g_Config; diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index bef7e082d..300b183e5 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -50,8 +50,7 @@ struct ConfigCustomButton { enum class CPUCore { INTERPRETER = 0, JIT = 1, - IR_INTERPRETER = 2, - JIT_IR = 3, + IR_JIT = 2, }; enum { @@ -90,8 +89,32 @@ enum class RestoreSettingsBits : int { }; ENUM_CLASS_BITOPS(RestoreSettingsBits); -std::string GPUBackendToString(GPUBackend backend); -GPUBackend GPUBackendFromString(std::string_view backend); +inline std::string GPUBackendToString(GPUBackend backend) { + switch (backend) { + case GPUBackend::OPENGL: + return "OPENGL"; + case GPUBackend::DIRECT3D9: + return "DIRECT3D9"; + case GPUBackend::DIRECT3D11: + return "DIRECT3D11"; + case GPUBackend::VULKAN: + return "VULKAN"; + } + // Intentionally not a default so we get a warning. + return "INVALID"; +} + +inline GPUBackend GPUBackendFromString(const std::string &backend) { + if (!strcasecmp(backend.c_str(), "OPENGL") || backend == "0") + return GPUBackend::OPENGL; + if (!strcasecmp(backend.c_str(), "DIRECT3D9") || backend == "1") + return GPUBackend::DIRECT3D9; + if (!strcasecmp(backend.c_str(), "DIRECT3D11") || backend == "2") + return GPUBackend::DIRECT3D11; + if (!strcasecmp(backend.c_str(), "VULKAN") || backend == "3") + return GPUBackend::VULKAN; + return GPUBackend::OPENGL; +} enum AudioBackendType { AUDIO_BACKEND_AUTO, @@ -104,7 +127,6 @@ enum IOTimingMethods { IOTIMING_FAST = 0, IOTIMING_HOST = 1, IOTIMING_REALISTIC = 2, - IOTIMING_UMDSLOWREALISTIC = 3, }; enum class AutoLoadSaveState { @@ -141,30 +163,3 @@ enum TiltTypes { TILT_ACTION_BUTTON, TILT_TRIGGER_BUTTONS, }; - -enum class ScreenEdgePosition { - BOTTOM_LEFT = 0, - BOTTOM_CENTER = 1, - BOTTOM_RIGHT = 2, - TOP_LEFT = 3, - TOP_CENTER = 4, - TOP_RIGHT = 5, - CENTER_LEFT = 6, - CENTER_RIGHT = 7, - VALUE_COUNT, -}; - -enum class DebugOverlay : int { - OFF, - DEBUG_STATS, - FRAME_GRAPH, - FRAME_TIMING, -#ifdef USE_PROFILER - FRAME_PROFILE, -#endif - CONTROL, - AUDIO, - GPU_PROFILE, - GPU_ALLOCATOR, - FRAMEBUFFER_LIST, -}; diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index 629b1eaca..07945a02c 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -156,12 +156,11 @@ void ControlMapper::UpdateAnalogOutput(int stick) { void ControlMapper::ForceReleaseVKey(int vkey) { std::vector multiMappings; if (KeyMap::InputMappingsFromPspButton(vkey, &multiMappings, true)) { - double now = time_now_d(); for (const auto &entry : multiMappings) { for (const auto &mapping : entry.mappings) { - curInput_[mapping] = { 0.0f, now }; + curInput_[mapping] = 0.0f; // Different logic for signed axes? - UpdatePSPState(mapping, now); + UpdatePSPState(mapping); } } } @@ -179,15 +178,12 @@ static int RotatePSPKeyCode(int x) { } // Used to decay analog values when clashing with digital ones. -static ControlMapper::InputSample ReduceMagnitude(ControlMapper::InputSample sample, double now) { - float reduction = std::min(std::max(0.0f, (float)(now - sample.timestamp) - 2.0f), 1.0f); - if (reduction > 0.0f) { - sample.value *= (1.0f - reduction); +static float ReduceMagnitude(float value) { + value *= 0.75f; + if ((value > 0.0f && value < 0.05f) || (value < 0.0f && value > -0.05f)) { + value = 0.0f; } - if ((sample.value > 0.0f && sample.value < 0.05f) || (sample.value < 0.0f && sample.value > -0.05f)) { - sample.value = 0.0f; - } - return sample; + return value; } float ControlMapper::MapAxisValue(float value, int vkId, const InputMapping &mapping, const InputMapping &changedMapping, bool *oppositeTouched) { @@ -203,7 +199,7 @@ float ControlMapper::MapAxisValue(float value, int vkId, const InputMapping &map if (other == changedMapping) { *oppositeTouched = true; } - float valueOther = curInput_[other].value; + float valueOther = curInput_[other]; float signedValue = value - valueOther; float ranged = (signedValue + 1.0f) * 0.5f; if (direction == -1) { @@ -251,9 +247,7 @@ void ControlMapper::SwapMappingIfEnabled(uint32_t *vkey) { } // Can only be called from Key or Axis. -// mutex_ should be locked. -// TODO: We should probably make a batched version of this. -bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double now) { +bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) { // Instead of taking an input key and finding what it outputs, we loop through the OUTPUTS and // see if the input that corresponds to it has a value. That way we can easily implement all sorts // of crazy input combos if needed. @@ -296,7 +290,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no bool all = true; for (auto mapping : multiMapping.mappings) { auto iter = curInput_.find(mapping); - bool down = iter != curInput_.end() && iter->second.value > GetDeviceAxisThreshold(iter->first.deviceId); + bool down = iter != curInput_.end() && iter->second > GetDeviceAxisThreshold(iter->first.deviceId); if (!down) all = false; } @@ -313,7 +307,6 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no bool updateAnalogSticks = false; // OK, handle all the virtual keys next. For these we need to do deltas here and send events. - // Note that virtual keys include the analog directions, as they are driven by them. for (int i = 0; i < VIRTKEY_COUNT; i++) { int vkId = i + VIRTKEY_FIRST; std::vector inputMappings; @@ -341,9 +334,9 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no if (iter != curInput_.end()) { if (mapping.IsAxis()) { threshold = GetDeviceAxisThreshold(iter->first.deviceId); - product *= MapAxisValue(iter->second.value, idForMapping, mapping, changedMapping, &touchedByMapping); + product *= MapAxisValue(iter->second, idForMapping, mapping, changedMapping, &touchedByMapping); } else { - product *= iter->second.value; + product *= iter->second; } } else { product = 0.0f; @@ -368,11 +361,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no if (!changedMapping.IsAxis()) { for (auto &multiMapping : inputMappings) { for (auto &mapping : multiMapping.mappings) { - if (mapping != changedMapping && curInput_[mapping].value > 0.0f) { - // Note that this takes the time into account now - values will - // decay after a while, not immediately. - curInput_[mapping] = ReduceMagnitude(curInput_[mapping], now); - } + curInput_[mapping] = ReduceMagnitude(curInput_[mapping]); } } } @@ -423,19 +412,15 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) { // Claim that we handled this. Prevents volume key repeats from popping up the volume control on Android. return true; } - double now = time_now_d(); - if (key.deviceId < DEVICE_ID_COUNT) { - deviceTimestamps_[(int)key.deviceId] = now; - } - - InputMapping mapping(key.deviceId, key.keyCode); std::lock_guard guard(mutex_); + InputMapping mapping(key.deviceId, key.keyCode); + if (key.flags & KEY_DOWN) { - curInput_[mapping] = { 1.0f, now }; + curInput_[mapping] = 1.0f; } else if (key.flags & KEY_UP) { - curInput_[mapping] = { 0.0f, now}; + curInput_[mapping] = 0.0f; } // TODO: See if this can be simplified further somehow. @@ -448,7 +433,7 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) { } } - return UpdatePSPState(mapping, now); + return UpdatePSPState(mapping); } void ControlMapper::ToggleSwapAxes() { @@ -476,42 +461,35 @@ void ControlMapper::ToggleSwapAxes() { UpdateAnalogOutput(1); } -void ControlMapper::Axis(const AxisInput *axes, size_t count) { - double now = time_now_d(); - +void ControlMapper::Axis(const AxisInput &axis) { std::lock_guard guard(mutex_); - for (size_t i = 0; i < count; i++) { - const AxisInput &axis = axes[i]; - size_t deviceIndex = (size_t)axis.deviceId; // this wraps -1 up high, so will get rejected on the next line. - if (deviceIndex < (size_t)DEVICE_ID_COUNT) { - deviceTimestamps_[deviceIndex] = now; - } - if (axis.value >= 0.0f) { - InputMapping mapping(axis.deviceId, axis.axisId, 1); - InputMapping opposite(axis.deviceId, axis.axisId, -1); - curInput_[mapping] = { axis.value, now }; - curInput_[opposite] = { 0.0f, now }; - UpdatePSPState(mapping, now); - UpdatePSPState(opposite, now); - } else if (axis.value < 0.0f) { - InputMapping mapping(axis.deviceId, axis.axisId, -1); - InputMapping opposite(axis.deviceId, axis.axisId, 1); - curInput_[mapping] = { -axis.value, now }; - curInput_[opposite] = { 0.0f, now }; - UpdatePSPState(mapping, now); - UpdatePSPState(opposite, now); - } + if (axis.value >= 0.0f) { + InputMapping mapping(axis.deviceId, axis.axisId, 1); + InputMapping opposite(axis.deviceId, axis.axisId, -1); + curInput_[mapping] = axis.value; + curInput_[opposite] = 0.0f; + UpdatePSPState(mapping); + UpdatePSPState(opposite); + } else if (axis.value < 0.0f) { + InputMapping mapping(axis.deviceId, axis.axisId, -1); + InputMapping opposite(axis.deviceId, axis.axisId, 1); + curInput_[mapping] = -axis.value; + curInput_[opposite] = 0.0f; + UpdatePSPState(mapping); + UpdatePSPState(opposite); } } -void ControlMapper::Update(double now) { +void ControlMapper::Update() { if (autoRotatingAnalogCW_) { + const double now = time_now_d(); // Clamp to a square float x = std::min(1.0f, std::max(-1.0f, 1.42f * (float)cos(now * -g_Config.fAnalogAutoRotSpeed))); float y = std::min(1.0f, std::max(-1.0f, 1.42f * (float)sin(now * -g_Config.fAnalogAutoRotSpeed))); setPSPAnalog_(0, x, y); } else if (autoRotatingAnalogCCW_) { + const double now = time_now_d(); float x = std::min(1.0f, std::max(-1.0f, 1.42f * (float)cos(now * g_Config.fAnalogAutoRotSpeed))); float y = std::min(1.0f, std::max(-1.0f, 1.42f * (float)sin(now * g_Config.fAnalogAutoRotSpeed))); @@ -605,7 +583,7 @@ void ControlMapper::GetDebugString(char *buffer, size_t bufSize) const { for (auto iter : curInput_) { char temp[256]; iter.first.FormatDebug(temp, sizeof(temp)); - str << temp << ": " << iter.second.value << std::endl; + str << temp << ": " << iter.second << std::endl; } for (int i = 0; i < ARRAY_SIZE(virtKeys_); i++) { int vkId = VIRTKEY_FIRST + i; diff --git a/Core/ControlMapper.h b/Core/ControlMapper.h index 24c70a052..bca32ff0e 100644 --- a/Core/ControlMapper.h +++ b/Core/ControlMapper.h @@ -11,12 +11,12 @@ // Main use is of course from EmuScreen.cpp, but also useful from control settings etc. class ControlMapper { public: - void Update(double now); + void Update(); // Inputs to the table-based mapping // These functions are free-threaded. bool Key(const KeyInput &key, bool *pauseTrigger); - void Axis(const AxisInput *axes, size_t count); + void Axis(const AxisInput &axis); // Required callbacks. // TODO: These are so many now that a virtual interface might be more appropriate.. @@ -42,13 +42,8 @@ public: void GetDebugString(char *buffer, size_t bufSize) const; - struct InputSample { - float value; - double timestamp; - }; - private: - bool UpdatePSPState(const InputMapping &changedMapping, double now); + bool UpdatePSPState(const InputMapping &changedMapping); float MapAxisValue(float value, int vkId, const InputMapping &mapping, const InputMapping &changedMapping, bool *oppositeTouched); void SwapMappingIfEnabled(uint32_t *vkey); @@ -62,8 +57,6 @@ private: float virtKeys_[VIRTKEY_COUNT]{}; bool virtKeyOn_[VIRTKEY_COUNT]{}; // Track boolean output separaately since thresholds may differ. - double deviceTimestamps_[(size_t)DEVICE_ID_COUNT]{}; - int lastNonDeadzoneDeviceID_[2]{}; float history_[2][2]{}; @@ -76,11 +69,9 @@ private: bool swapAxes_ = false; // Protects basically all the state. - // TODO: Maybe we should piggyback on the screenmanager mutex - it's always locked - // when events come in here. std::mutex mutex_; - std::map curInput_; + std::map curInput_; // Callbacks std::function onVKey_; diff --git a/Core/Core.cpp b/Core/Core.cpp index 36f9fd0f8..daf858a30 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -48,6 +48,10 @@ #include "Windows/InputDevice.h" #endif +// Time until we stop considering the core active without user input. +// Should this be configurable? 2 hours currently. +static const double ACTIVITY_IDLE_TIMEOUT = 2.0 * 3600.0; + static std::condition_variable m_StepCond; static std::mutex m_hStepMutex; static std::condition_variable m_InactiveCond; @@ -59,12 +63,16 @@ static uint32_t steppingAddress = 0; static std::set lifecycleFuncs; static std::set stopFuncs; static bool windowHidden = false; +static double lastActivity = 0.0; +static double lastKeepAwake = 0.0; +static GraphicsContext *graphicsContext; static bool powerSaving = false; static MIPSExceptionInfo g_exceptionInfo; void Core_SetGraphicsContext(GraphicsContext *ctx) { - PSP_CoreParameter().graphicsContext = ctx; + graphicsContext = ctx; + PSP_CoreParameter().graphicsContext = graphicsContext; } void Core_NotifyWindowHidden(bool hidden) { @@ -72,8 +80,8 @@ void Core_NotifyWindowHidden(bool hidden) { // TODO: Wait until we can react? } -bool Core_IsWindowHidden() { - return windowHidden; +void Core_NotifyActivity() { + lastActivity = time_now_d(); } void Core_ListenLifecycle(CoreLifecycleFunc func) { @@ -154,19 +162,20 @@ static bool IsWindowSmall(int pixelWidth, int pixelHeight) { // TODO: Feels like this belongs elsewhere. bool UpdateScreenScale(int width, int height) { bool smallWindow; - - float g_logical_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_LOGICAL_DPI); +#if defined(USING_QT_UI) g_display.dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); - - if (g_display.dpi < 0.0f) { - g_display.dpi = 96.0f; - } - if (g_logical_dpi < 0.0f) { - g_logical_dpi = 96.0f; - } - + float g_logical_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_LOGICAL_DPI); g_display.dpi_scale_x = g_logical_dpi / g_display.dpi; g_display.dpi_scale_y = g_logical_dpi / g_display.dpi; +#elif PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) + g_display.dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); + g_display.dpi_scale_x = 96.0f / g_display.dpi; + g_display.dpi_scale_y = 96.0f / g_display.dpi; +#else + g_display.dpi = 96.0f; + g_display.dpi_scale_x = 1.0f; + g_display.dpi_scale_y = 1.0f; +#endif g_display.dpi_scale_real_x = g_display.dpi_scale_x; g_display.dpi_scale_real_y = g_display.dpi_scale_y; @@ -196,23 +205,59 @@ bool UpdateScreenScale(int width, int height) { return false; } -// Used by Windows, SDL, Qt. -void UpdateRunLoop(GraphicsContext *ctx) { - NativeFrame(ctx); +// Note: not used on Android. +void UpdateRunLoop() { if (windowHidden && g_Config.bPauseWhenMinimized) { sleep_ms(16); return; } + NativeUpdate(); + NativeRender(graphicsContext); +} + +void KeepScreenAwake() { +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) + SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); +#endif } -// Note: not used on Android. void Core_RunLoop(GraphicsContext *ctx) { - if (windowHidden && g_Config.bPauseWhenMinimized) { - sleep_ms(16); - return; + float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); + + graphicsContext = ctx; + while ((GetUIState() != UISTATE_INGAME || !PSP_IsInited()) && GetUIState() != UISTATE_EXIT) { + // In case it was pending, we're not in game anymore. We won't get to Core_Run(). + Core_StateProcessed(); + double startTime = time_now_d(); + UpdateRunLoop(); + + // Simple throttling to not burn the GPU in the menu. + double diffTime = time_now_d() - startTime; + int sleepTime = (int)(1000.0 / refreshRate) - (int)(diffTime * 1000.0); + if (sleepTime > 0) + sleep_ms(sleepTime); + if (!windowHidden) { + ctx->SwapBuffers(); + } } - NativeFrame(ctx); + while ((coreState == CORE_RUNNING || coreState == CORE_STEPPING) && GetUIState() == UISTATE_INGAME) { + UpdateRunLoop(); + if (!windowHidden && !Core_IsStepping()) { + ctx->SwapBuffers(); + + // Keep the system awake for longer than normal for cutscenes and the like. + const double now = time_now_d(); + if (now < lastActivity + ACTIVITY_IDLE_TIMEOUT) { + // Only resetting it ever prime number seconds in case the call is expensive. + // Using a prime number to ensure there's no interaction with other periodic events. + if (now - lastKeepAwake > 89.0 || now < lastKeepAwake) { + KeepScreenAwake(); + lastKeepAwake = now; + } + } + } + } } void Core_DoSingleStep() { @@ -281,15 +326,14 @@ void Core_ProcessStepping() { } // Many platforms, like Android, do not call this function but handle things on their own. -// Instead they simply call NativeFrame directly. +// Instead they simply call NativeRender and NativeUpdate directly. bool Core_Run(GraphicsContext *ctx) { System_Notify(SystemNotification::DISASSEMBLY); while (true) { if (GetUIState() != UISTATE_INGAME) { Core_StateProcessed(); if (GetUIState() == UISTATE_EXIT) { - // Not sure why we do a final frame here? - NativeFrame(ctx); + UpdateRunLoop(); return false; } Core_RunLoop(ctx); @@ -299,7 +343,6 @@ bool Core_Run(GraphicsContext *ctx) { switch (coreState) { case CORE_RUNNING: case CORE_STEPPING: - Core_StateProcessed(); // enter a fast runloop Core_RunLoop(ctx); if (coreState == CORE_POWERDOWN) { @@ -314,6 +357,7 @@ bool Core_Run(GraphicsContext *ctx) { case CORE_RUNTIME_ERROR: // Exit loop!! Core_StateProcessed(); + return true; case CORE_NEXTFRAME: @@ -393,7 +437,7 @@ const char *ExecExceptionTypeAsString(ExecExceptionType type) { void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type) { const char *desc = MemoryExceptionTypeAsString(type); // In jit, we only flush PC when bIgnoreBadMemAccess is off. - if ((g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR) && g_Config.bIgnoreBadMemAccess) { + if (g_Config.iCpuCore == (int)CPUCore::JIT && g_Config.bIgnoreBadMemAccess) { WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x)", desc, address, accessSize); } else { WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x) PC %08x LR %08x", desc, address, accessSize, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); @@ -421,7 +465,7 @@ void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionTy void Core_MemoryExceptionInfo(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string additionalInfo, bool forceReport) { const char *desc = MemoryExceptionTypeAsString(type); // In jit, we only flush PC when bIgnoreBadMemAccess is off. - if ((g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR) && g_Config.bIgnoreBadMemAccess) { + if (g_Config.iCpuCore == (int)CPUCore::JIT && g_Config.bIgnoreBadMemAccess) { WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x). %s", desc, address, accessSize, additionalInfo.c_str()); } else { WARN_LOG(MEMMAP, "%s: Invalid access at %08x (size %08x) PC %08x LR %08x %s", desc, address, accessSize, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA], additionalInfo.c_str()); diff --git a/Core/Core.h b/Core/Core.h index 9024214c5..f07560929 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -25,7 +25,7 @@ class GraphicsContext; // called from emu thread -void UpdateRunLoop(GraphicsContext *ctx); +void UpdateRunLoop(); // Returns false when an UI exit state is detected. bool Core_Run(GraphicsContext *ctx); @@ -83,7 +83,7 @@ bool UpdateScreenScale(int width, int height); // Don't run the core when minimized etc. void Core_NotifyWindowHidden(bool hidden); -bool Core_IsWindowHidden(); +void Core_NotifyActivity(); void Core_SetPowerSaving(bool mode); bool Core_GetPowerSaving(); diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 4e26d2c07..89454fd9e 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -138,7 +138,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) StreamingSIMDExtensions2 Precise @@ -165,7 +165,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) NotSet Precise @@ -193,7 +193,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) NotSet Precise @@ -221,7 +221,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) NotSet Precise @@ -253,7 +253,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib false StreamingSIMDExtensions2 Precise @@ -286,7 +286,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib NotSet Precise false @@ -321,7 +321,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib NotSet Precise false @@ -356,7 +356,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib NotSet Precise false @@ -547,7 +547,6 @@ - @@ -565,7 +564,6 @@ - @@ -580,17 +578,7 @@ - - - - - - - - - - @@ -601,27 +589,9 @@ - - - - - - - - - - - - - - - - - - @@ -1066,7 +1036,6 @@ - @@ -1076,7 +1045,6 @@ - @@ -1109,7 +1077,6 @@ - @@ -1151,7 +1118,6 @@ - @@ -1170,7 +1136,6 @@ - @@ -1185,21 +1150,14 @@ - - - - - - - @@ -1434,7 +1392,6 @@ - @@ -1445,14 +1402,12 @@ - - @@ -1468,9 +1423,6 @@ {129e5e2b-39c1-4d84-96fe-dfd22dbb4a25} - - {956f1f48-b612-46d8-89ee-96996dcd9383} - {d8a71225-178b-424e-96c1-cc3be2c1b047} diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 596a9421b..cefdfb01c 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -91,9 +91,6 @@ {678fa299-0ff7-4983-982d-2da47b52e238} - - {067e3128-3aaf-4ed1-b19e-bab11606abe7} - @@ -721,9 +718,6 @@ Debugger\WebSocket - - Debugger\WebSocket - Debugger\WebSocket @@ -1204,102 +1198,6 @@ Core - - Core - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\IR - - - MIPS\IR - - - Core - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - Util - @@ -1884,9 +1782,6 @@ Debugger\WebSocket - - Debugger\WebSocket - Debugger\WebSocket @@ -2043,39 +1938,6 @@ Core - - Core - - - MIPS\RiscV - - - MIPS\RiscV - - - MIPS\IR - - - MIPS\IR - - - Core - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - Util - diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 3ca526b46..afa15412a 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -19,7 +19,6 @@ #include -#include "Common/File/Path.h" #include "Core/Compatibility.h" enum GPUCore { diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 857f50cc6..48f2dceb7 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -7,7 +7,7 @@ #include "Common/StringUtils.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/File/FileUtil.h" #include "Core/CoreTiming.h" #include "Core/CoreParameter.h" @@ -19,7 +19,6 @@ #include "Core/System.h" #include "Core/HLE/sceCtrl.h" #include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/RetroAchievements.h" #include "GPU/Common/PostShader.h" #ifdef _WIN32 @@ -320,11 +319,9 @@ void __CheatDoState(PointerWrap &p) { } void hleCheat(u64 userdata, int cyclesLate) { - bool shouldBeEnabled = !Achievements::ChallengeModeActive() && g_Config.bEnableCheats; - - if (cheatsEnabled != shouldBeEnabled) { + if (cheatsEnabled != g_Config.bEnableCheats) { // Okay, let's move to the desired state, then. - if (shouldBeEnabled) { + if (g_Config.bEnableCheats) { __CheatStart(); } else { __CheatStop(); @@ -381,7 +378,7 @@ void CWCheatEngine::CreateCheatFile() { } if (!File::Exists(filename_)) { auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Unable to create cheat file, disk may be full")); + System_NotifyUserMessage(err->T("Unable to create cheat file, disk may be full")); } } } @@ -1196,10 +1193,6 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, } void CWCheatEngine::Run() { - if (Achievements::ChallengeModeActive()) { - return; - } - for (CheatCode cheat : cheats_) { // InterpretNextOp and ExecuteOp move i. for (size_t i = 0; i < cheat.lines.size(); ) { @@ -1214,7 +1207,8 @@ bool CWCheatEngine::HasCheats() { } bool CheatsInEffect() { - if (!cheatEngine || !cheatsEnabled || Achievements::ChallengeModeActive()) + if (!cheatEngine || !cheatsEnabled) return false; return cheatEngine->HasCheats(); } + diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index b02b35c7a..3189acf76 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -311,7 +311,7 @@ BreakAction CBreakPoints::ExecBreakPoint(u32 addr) { std::unique_lock guard(breakPointsMutex_); size_t bp = FindBreakpoint(addr, false); if (bp != INVALID_BREAKPOINT) { - const BreakPoint &info = breakPoints_[bp]; + BreakPoint info = breakPoints_[bp]; guard.unlock(); if (info.hasCond) { diff --git a/Core/Debugger/DebugInterface.h b/Core/Debugger/DebugInterface.h index 7a77b6ac0..1f62aeea1 100644 --- a/Core/Debugger/DebugInterface.h +++ b/Core/Debugger/DebugInterface.h @@ -26,6 +26,7 @@ struct MemMap; class DebugInterface { public: + virtual const char *disasm(unsigned int address, unsigned int align) {return "NODEBUGGER";} virtual int getInstructionSize(int instruction) {return 1;} virtual bool isAlive() {return true;} @@ -54,14 +55,14 @@ public: virtual u32 GetPC() = 0; virtual void SetPC(u32 _pc) = 0; virtual u32 GetLR() {return GetPC();} - virtual void DisAsm(u32 pc, char *out, size_t outSize) { - snprintf(out, outSize, "[%08x] UNKNOWN", pc); + virtual void DisAsm(u32 op, u32 pc, int align, char *out, size_t outSize) { + snprintf(out, outSize, "[%08x] UNKNOWN", op); } // More stuff for debugger virtual int GetNumCategories() {return 0;} virtual int GetNumRegsInCategory(int cat) {return 0;} virtual const char *GetCategoryName(int cat) {return 0;} - virtual std::string GetRegName(int cat, int index) { return ""; } + virtual const char *GetRegName(int cat, int index) {return 0;} virtual void PrintRegValue(int cat, int index, char *out, size_t outSize) { snprintf(out, outSize, "%08X", GetGPR32Value(index)); } diff --git a/Core/Debugger/DisassemblyManager.cpp b/Core/Debugger/DisassemblyManager.cpp index ecea54a86..f9bd9c1f0 100644 --- a/Core/Debugger/DisassemblyManager.cpp +++ b/Core/Debugger/DisassemblyManager.cpp @@ -102,33 +102,36 @@ static HashType computeHash(u32 address, u32 size) } -static void parseDisasm(const char *disasm, char *opcode, size_t opcodeSize, char *arguments, size_t argumentsSize, bool insertSymbols) { +void parseDisasm(const char* disasm, char* opcode, char* arguments, bool insertSymbols) +{ // copy opcode - size_t opcodePos = 0; - while (*disasm != 0 && *disasm != '\t' && opcodePos + 1 < opcodeSize) { - opcode[opcodePos++] = *disasm++; + while (*disasm != 0 && *disasm != '\t') + { + *opcode++ = *disasm++; } - opcode[opcodePos] = 0; + *opcode = 0; - // Otherwise it's a tab, and we skip intentionally. - if (*disasm++ == 0) { + if (*disasm++ == 0) + { *arguments = 0; return; } const char* jumpAddress = strstr(disasm,"->$"); const char* jumpRegister = strstr(disasm,"->"); - size_t argumentsPos = 0; - while (*disasm != 0 && argumentsPos + 1 < argumentsSize) { + while (*disasm != 0) + { // parse symbol - if (disasm == jumpAddress) { + if (disasm == jumpAddress) + { u32 branchTarget = 0; sscanf(disasm+3, "%08x", &branchTarget); const std::string addressSymbol = g_symbolMap->GetLabelString(branchTarget); - if (!addressSymbol.empty() && insertSymbols) { - argumentsPos += snprintf(&arguments[argumentsPos], argumentsSize - argumentsPos, "%s", addressSymbol.c_str()); + if (!addressSymbol.empty() && insertSymbols) + { + arguments += sprintf(arguments, "%s", addressSymbol.c_str()); } else { - argumentsPos += snprintf(&arguments[argumentsPos], argumentsSize - argumentsPos, "0x%08X", branchTarget); + arguments += sprintf(arguments, "0x%08X", branchTarget); } disasm += 3+8; @@ -138,14 +141,15 @@ static void parseDisasm(const char *disasm, char *opcode, size_t opcodeSize, cha if (disasm == jumpRegister) disasm += 2; - if (*disasm == ' ') { + if (*disasm == ' ') + { disasm++; continue; } - arguments[argumentsPos++] = *disasm++; + *arguments++ = *disasm++; } - arguments[argumentsPos] = 0; + *arguments = 0; } std::map::iterator findDisassemblyEntry(std::map& entries, u32 address, bool exact) @@ -762,9 +766,8 @@ bool DisassemblyOpcode::disassemble(u32 address, DisassemblyLineInfo &dest, bool cpuDebug = DisassemblyManager::getCpu(); char opcode[64],arguments[256]; - char dizz[512]; - cpuDebug->DisAsm(address, dizz, sizeof(dizz)); - parseDisasm(dizz, opcode, sizeof(opcode), arguments, sizeof(arguments), insertSymbols); + const char *dizz = cpuDebug->disasm(address, 4); + parseDisasm(dizz,opcode,arguments,insertSymbols); dest.type = DISTYPE_OPCODE; dest.name = opcode; dest.params = arguments; @@ -847,9 +850,9 @@ bool DisassemblyMacro::disassemble(u32 address, DisassemblyLineInfo &dest, bool addressSymbol = g_symbolMap->GetLabelString(immediate); if (!addressSymbol.empty() && insertSymbols) { - snprintf(buffer, sizeof(buffer), "%s,%s", cpuDebug->GetRegName(0, rt).c_str(), addressSymbol.c_str()); + snprintf(buffer, sizeof(buffer), "%s,%s", cpuDebug->GetRegName(0, rt), addressSymbol.c_str()); } else { - snprintf(buffer, sizeof(buffer), "%s,0x%08X", cpuDebug->GetRegName(0, rt).c_str(), immediate); + snprintf(buffer, sizeof(buffer), "%s,0x%08X", cpuDebug->GetRegName(0, rt), immediate); } dest.params = buffer; @@ -862,9 +865,9 @@ bool DisassemblyMacro::disassemble(u32 address, DisassemblyLineInfo &dest, bool addressSymbol = g_symbolMap->GetLabelString(immediate); if (!addressSymbol.empty() && insertSymbols) { - snprintf(buffer, sizeof(buffer), "%s,%s", cpuDebug->GetRegName(0, rt).c_str(), addressSymbol.c_str()); + snprintf(buffer, sizeof(buffer), "%s,%s", cpuDebug->GetRegName(0, rt), addressSymbol.c_str()); } else { - snprintf(buffer, sizeof(buffer), "%s,0x%08X", cpuDebug->GetRegName(0, rt).c_str(), immediate); + snprintf(buffer, sizeof(buffer), "%s,0x%08X", cpuDebug->GetRegName(0, rt), immediate); } dest.params = buffer; diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index f727d3a48..476d62fe3 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -17,10 +17,8 @@ #include #include -#include #include #include -#include #include "Common/Log.h" #include "Common/Serialize/Serializer.h" @@ -51,8 +49,6 @@ private: uint64_t ticks = 0; uint32_t pc = 0; bool allocated = false; - // Intentionally not save stated. - bool bulkStorage = false; char tag[128]{}; Slab *prev = nullptr; Slab *next = nullptr; @@ -61,7 +57,7 @@ private: }; static constexpr uint32_t MAX_SIZE = 0x40000000; - static constexpr uint32_t SLICES = 65536; + static constexpr uint32_t SLICES = 16384; static constexpr uint32_t SLICE_SIZE = MAX_SIZE / SLICES; Slab *FindSlab(uint32_t addr); @@ -76,22 +72,18 @@ private: Slab *first_ = nullptr; Slab *lastFind_ = nullptr; std::vector heads_; - Slab *bulkStorage_ = nullptr; }; struct PendingNotifyMem { MemBlockFlags flags; uint32_t start; uint32_t size; - uint32_t copySrc; uint64_t ticks; uint32_t pc; char tag[128]; }; -// 160 KB. -static constexpr size_t MAX_PENDING_NOTIFIES = 1024; -static constexpr size_t MAX_PENDING_NOTIFIES_THREAD = 1000; +static constexpr size_t MAX_PENDING_NOTIFIES = 512; static MemSlabMap allocMap; static MemSlabMap suballocMap; static MemSlabMap writeMap; @@ -101,17 +93,9 @@ static std::atomic pendingNotifyMinAddr1; static std::atomic pendingNotifyMaxAddr1; static std::atomic pendingNotifyMinAddr2; static std::atomic pendingNotifyMaxAddr2; -// To prevent deadlocks, acquire Read before Write if you're going to acquire both. -static std::mutex pendingWriteMutex; -static std::mutex pendingReadMutex; +static std::mutex pendingMutex; static int detailedOverride; -static std::thread flushThread; -static std::atomic flushThreadRunning; -static std::atomic flushThreadPending; -static std::mutex flushLock; -static std::condition_variable flushCond; - MemSlabMap::MemSlabMap() { Reset(); } @@ -200,7 +184,6 @@ void MemSlabMap::DoState(PointerWrap &p) { // Since heads_ is a static size, let's avoid clearing it. // This helps in case a debugger call happens concurrently. Slab *old = first_; - Slab *oldBulk = bulkStorage_; Do(p, count); first_ = new Slab(); @@ -210,12 +193,9 @@ void MemSlabMap::DoState(PointerWrap &p) { FillHeads(first_); - bulkStorage_ = new Slab[count]; - Slab *slab = first_; for (int i = 0; i < count; ++i) { - slab->next = &bulkStorage_[i]; - slab->next->bulkStorage = true; + slab->next = new Slab(); slab->next->DoState(p); slab->next->prev = slab; @@ -227,11 +207,9 @@ void MemSlabMap::DoState(PointerWrap &p) { // Now that it's entirely disconnected, delete the old slabs. while (old != nullptr) { Slab *next = old->next; - if (!old->bulkStorage) - delete old; + delete old; old = next; } - delete [] oldBulk; } else { for (Slab *slab = first_; slab != nullptr; slab = slab->next) ++count; @@ -275,12 +253,9 @@ void MemSlabMap::Clear() { Slab *s = first_; while (s != nullptr) { Slab *next = s->next; - if (!s->bulkStorage) - delete s; + delete s; s = next; } - delete bulkStorage_; - bulkStorage_ = nullptr; first_ = nullptr; lastFind_ = nullptr; heads_.clear(); @@ -373,8 +348,7 @@ void MemSlabMap::Merge(Slab *a, Slab *b) { } if (lastFind_ == b) lastFind_ = a; - if (!b->bulkStorage) - delete b; + delete b; } void MemSlabMap::FillHeads(Slab *slab) { @@ -395,32 +369,9 @@ void MemSlabMap::FillHeads(Slab *slab) { } } -size_t FormatMemWriteTagAtNoFlush(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size); - void FlushPendingMemInfo() { - // This lock prevents us from another thread reading while we're busy flushing. - std::lock_guard guard(pendingReadMutex); - std::vector thisBatch; - { - std::lock_guard guard(pendingWriteMutex); - thisBatch = std::move(pendingNotifies); - pendingNotifies.clear(); - pendingNotifies.reserve(MAX_PENDING_NOTIFIES); - - pendingNotifyMinAddr1 = 0xFFFFFFFF; - pendingNotifyMaxAddr1 = 0; - pendingNotifyMinAddr2 = 0xFFFFFFFF; - pendingNotifyMaxAddr2 = 0; - } - - for (const auto &info : thisBatch) { - if (info.copySrc != 0) { - char tagData[128]; - size_t tagSize = FormatMemWriteTagAtNoFlush(tagData, sizeof(tagData), info.tag, info.copySrc, info.size); - writeMap.Mark(info.start, info.size, info.ticks, info.pc, true, tagData); - continue; - } - + std::lock_guard guard(pendingMutex); + for (auto info : pendingNotifies) { if (info.flags & MemBlockFlags::ALLOC) { allocMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); } else if (info.flags & MemBlockFlags::FREE) { @@ -441,6 +392,11 @@ void FlushPendingMemInfo() { writeMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); } } + pendingNotifies.clear(); + pendingNotifyMinAddr1 = 0xFFFFFFFF; + pendingNotifyMaxAddr1 = 0; + pendingNotifyMinAddr2 = 0xFFFFFFFF; + pendingNotifyMaxAddr2 = 0; } static inline uint32_t NormalizeAddress(uint32_t addr) { @@ -455,9 +411,6 @@ static inline bool MergeRecentMemInfo(const PendingNotifyMem &info, size_t copyL for (size_t i = 1; i <= 4; ++i) { auto &prev = pendingNotifies[pendingNotifies.size() - i]; - if (prev.copySrc != 0) - return false; - if (prev.flags != info.flags) continue; @@ -487,7 +440,7 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ bool needFlush = false; // When the setting is off, we skip smaller info to keep things fast. - if (MemBlockInfoDetailed(size) && flags != MemBlockFlags::READ) { + if (MemBlockInfoDetailed(size)) { PendingNotifyMem info{ flags, start, size }; info.ticks = CoreTiming::GetTicks(); info.pc = pc; @@ -499,7 +452,7 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ memcpy(info.tag, tagStr, copyLength); info.tag[copyLength] = 0; - std::lock_guard guard(pendingWriteMutex); + std::lock_guard guard(pendingMutex); // Sometimes we get duplicates, quickly check. if (!MergeRecentMemInfo(info, copyLength)) { if (start < 0x08000000) { @@ -511,15 +464,11 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ } pendingNotifies.push_back(info); } - needFlush = pendingNotifies.size() > MAX_PENDING_NOTIFIES_THREAD; + needFlush = pendingNotifies.size() > MAX_PENDING_NOTIFIES; } if (needFlush) { - { - std::lock_guard guard(flushLock); - flushThreadPending = true; - } - flushCond.notify_one(); + FlushPendingMemInfo(); } if (!(flags & MemBlockFlags::SKIP_MEMCHECK)) { @@ -535,50 +484,6 @@ void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const cha NotifyMemInfoPC(flags, start, size, currentMIPS->pc, str, strLength); } -void NotifyMemInfoCopy(uint32_t destPtr, uint32_t srcPtr, uint32_t size, const char *prefix) { - if (size == 0) - return; - - bool needsFlush = false; - if (CBreakPoints::HasMemChecks()) { - // This will cause a flush, but it's needed to trigger memchecks with proper data. - char tagData[128]; - size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), prefix, srcPtr, size); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, size, tagData, tagSize); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, size, tagData, tagSize); - } else if (MemBlockInfoDetailed(size)) { - srcPtr = NormalizeAddress(srcPtr); - destPtr = NormalizeAddress(destPtr); - - PendingNotifyMem info{ MemBlockFlags::WRITE, destPtr, size }; - info.copySrc = srcPtr; - info.ticks = CoreTiming::GetTicks(); - info.pc = currentMIPS->pc; - - // Store the prefix for now. The correct tag will be calculated on flush. - truncate_cpy(info.tag, prefix); - - std::lock_guard guard(pendingWriteMutex); - if (destPtr < 0x08000000) { - pendingNotifyMinAddr1 = std::min(pendingNotifyMinAddr1.load(), destPtr); - pendingNotifyMaxAddr1 = std::max(pendingNotifyMaxAddr1.load(), destPtr + size); - } else { - pendingNotifyMinAddr2 = std::min(pendingNotifyMinAddr2.load(), destPtr); - pendingNotifyMaxAddr2 = std::max(pendingNotifyMaxAddr2.load(), destPtr + size); - } - pendingNotifies.push_back(info); - needsFlush = pendingNotifies.size() > MAX_PENDING_NOTIFIES_THREAD; - } - - if (needsFlush) { - { - std::lock_guard guard(flushLock); - flushThreadPending = true; - } - flushCond.notify_one(); - } -} - std::vector FindMemInfo(uint32_t start, uint32_t size) { start = NormalizeAddress(start); @@ -615,15 +520,13 @@ std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, return results; } -static const char *FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint32_t size, bool flush = true) { +static const char *FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) { start = NormalizeAddress(start); - if (flush) { - if (pendingNotifyMinAddr1 < start + size && pendingNotifyMaxAddr1 >= start) - FlushPendingMemInfo(); - if (pendingNotifyMinAddr2 < start + size && pendingNotifyMaxAddr2 >= start) - FlushPendingMemInfo(); - } + if (pendingNotifyMinAddr1 < start + size && pendingNotifyMaxAddr1 >= start) + FlushPendingMemInfo(); + if (pendingNotifyMinAddr2 < start + size && pendingNotifyMaxAddr2 >= start) + FlushPendingMemInfo(); if (flags & MemBlockFlags::ALLOC) { const char *tag = allocMap.FastFindWriteTag(MemBlockFlags::ALLOC, start, size); @@ -661,63 +564,22 @@ size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t st return snprintf(buf, sz, "%s%08x_size_%08x", prefix, start, size); } -size_t FormatMemWriteTagAtNoFlush(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size) { - const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size, false); - if (tag && strcmp(tag, "MemInit") != 0) { - return snprintf(buf, sz, "%s%s", prefix, tag); - } - // Fall back to alloc and texture, especially for VRAM. We prefer write above. - tag = FindWriteTagByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size, false); - if (tag) { - return snprintf(buf, sz, "%s%s", prefix, tag); - } - return snprintf(buf, sz, "%s%08x_size_%08x", prefix, start, size); -} - -static void FlushMemInfoThread() { - while (flushThreadRunning.load()) { - flushThreadPending = false; - FlushPendingMemInfo(); - - std::unique_lock guard(flushLock); - flushCond.wait(guard, [] { - return flushThreadPending.load(); - }); - } -} - void MemBlockInfoInit() { - std::lock_guard guard(pendingReadMutex); - std::lock_guard guardW(pendingWriteMutex); + std::lock_guard guard(pendingMutex); pendingNotifies.reserve(MAX_PENDING_NOTIFIES); pendingNotifyMinAddr1 = 0xFFFFFFFF; pendingNotifyMaxAddr1 = 0; pendingNotifyMinAddr2 = 0xFFFFFFFF; pendingNotifyMaxAddr2 = 0; - - flushThreadRunning = true; - flushThreadPending = false; - flushThread = std::thread(&FlushMemInfoThread); } void MemBlockInfoShutdown() { - { - std::lock_guard guard(pendingReadMutex); - std::lock_guard guardW(pendingWriteMutex); - allocMap.Reset(); - suballocMap.Reset(); - writeMap.Reset(); - textureMap.Reset(); - pendingNotifies.clear(); - } - - if (flushThreadRunning.load()) { - std::lock_guard guard(flushLock); - flushThreadRunning = false; - flushThreadPending = true; - } - flushCond.notify_one(); - flushThread.join(); + std::lock_guard guard(pendingMutex); + allocMap.Reset(); + suballocMap.Reset(); + writeMap.Reset(); + textureMap.Reset(); + pendingNotifies.clear(); } void MemBlockInfoDoState(PointerWrap &p) { diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index b07c326f8..108423d53 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -53,7 +53,6 @@ struct MemBlockInfo { void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *tag, size_t tagLength); void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const char *tag, size_t tagLength); -void NotifyMemInfoCopy(uint32_t destPtr, uint32_t srcPtr, uint32_t size, const char *prefix); // This lets us avoid calling strlen on string constants, instead the string length (including null, // so we have to subtract 1) is computed at compile time. diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index 199ce1648..6cac80071 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -181,14 +181,6 @@ bool SymbolMap::LoadSymbolMap(const Path &filename) { if (type == ST_DATA && size == 0) size = 4; - // Ignore syscalls, will be recognized from stubs. - // Note: it's still useful to save these for grepping and importing into other tools. - if (strncmp(name, "zz_sce", 6) == 0) - continue; - // Also ignore unresolved imports, which will similarly be replaced. - if (strncmp(name, "zz_[UNK", 7) == 0) - continue; - if (!strcmp(name, ".text") || !strcmp(name, ".init") || strlen(name) <= 1) { } else { diff --git a/Core/Debugger/WebSocket.cpp b/Core/Debugger/WebSocket.cpp index c17aa57c7..23333d5a1 100644 --- a/Core/Debugger/WebSocket.cpp +++ b/Core/Debugger/WebSocket.cpp @@ -62,7 +62,6 @@ #include "Core/Debugger/WebSocket/MemorySubscriber.h" #include "Core/Debugger/WebSocket/ReplaySubscriber.h" #include "Core/Debugger/WebSocket/SteppingSubscriber.h" -#include "Core/Debugger/WebSocket/ClientConfigSubscriber.h" typedef DebuggerSubscriber *(*SubscriberInit)(DebuggerEventHandlerMap &map); static const std::vector subscribers({ @@ -79,7 +78,6 @@ static const std::vector subscribers({ &WebSocketMemoryInit, &WebSocketReplayInit, &WebSocketSteppingInit, - &WebSocketClientConfigInit, }); // To handle webserver restart, keep track of how many running. @@ -131,7 +129,7 @@ static void SetupDebuggerLock() { } } -void HandleDebuggerRequest(const http::ServerRequest &request) { +void HandleDebuggerRequest(const http::Request &request) { net::WebSocketServer *ws = net::WebSocketServer::CreateAsUpgrade(request, "debugger.ppsspp.org"); if (!ws) return; @@ -140,9 +138,6 @@ void HandleDebuggerRequest(const http::ServerRequest &request) { UpdateConnected(1); SetupDebuggerLock(); - WebSocketClientInfo client_info; - auto& disallowed_config = client_info.disallowed; - GameBroadcaster game; LogBroadcaster logger; InputBroadcaster input; @@ -160,18 +155,18 @@ void HandleDebuggerRequest(const http::ServerRequest &request) { ws->SetTextHandler([&](const std::string &t) { JsonReader reader(t.c_str(), t.size()); if (!reader.ok()) { - ws->Send(DebuggerErrorEvent("Bad message: invalid JSON", LogLevel::LERROR)); + ws->Send(DebuggerErrorEvent("Bad message: invalid JSON", LogTypes::LERROR)); return; } const JsonGet root = reader.root(); const char *event = root ? root.getString("event", nullptr) : nullptr; if (!event) { - ws->Send(DebuggerErrorEvent("Bad message: no event property", LogLevel::LERROR, root)); + ws->Send(DebuggerErrorEvent("Bad message: no event property", LogTypes::LERROR, root)); return; } - DebuggerRequest req(event, ws, root, &client_info); + DebuggerRequest req(event, ws, root); auto eventFunc = eventHandlers.find(event); if (eventFunc != eventHandlers.end()) { std::lock_guard guard(lifecycleLock); @@ -185,23 +180,16 @@ void HandleDebuggerRequest(const http::ServerRequest &request) { } }); ws->SetBinaryHandler([&](const std::vector &d) { - ws->Send(DebuggerErrorEvent("Bad message", LogLevel::LERROR)); + ws->Send(DebuggerErrorEvent("Bad message", LogTypes::LERROR)); }); while (ws->Process(highActivity ? 1.0f / 1000.0f : 1.0f / 60.0f)) { std::lock_guard guard(lifecycleLock); - // These send events that aren't just responses to requests - - // The client can explicitly ask not to be notified about some events - // so we check the client settings first - if (!disallowed_config["logger"]) - logger.Broadcast(ws); - if (!disallowed_config["game"]) - game.Broadcast(ws); - if (!disallowed_config["stepping"]) - stepping.Broadcast(ws); - if (!disallowed_config["input"]) - input.Broadcast(ws); + // These send events that aren't just responses to requests. + logger.Broadcast(ws); + game.Broadcast(ws); + stepping.Broadcast(ws); + input.Broadcast(ws); for (size_t i = 0; i < subscribers.size(); ++i) { if (subscriberData[i]) { diff --git a/Core/Debugger/WebSocket.h b/Core/Debugger/WebSocket.h index f05856db2..0151ca686 100644 --- a/Core/Debugger/WebSocket.h +++ b/Core/Debugger/WebSocket.h @@ -18,9 +18,9 @@ #pragma once namespace http { -class ServerRequest; +class Request; } -void HandleDebuggerRequest(const http::ServerRequest &request); +void HandleDebuggerRequest(const http::Request &request); // Note: blocks. void StopAllDebuggers(); diff --git a/Core/Debugger/WebSocket/ClientConfigSubscriber.cpp b/Core/Debugger/WebSocket/ClientConfigSubscriber.cpp deleted file mode 100644 index 9f8ca6727..000000000 --- a/Core/Debugger/WebSocket/ClientConfigSubscriber.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Core/Debugger/WebSocket/ClientConfigSubscriber.h" -#include "Core/Debugger/WebSocket/WebSocketUtils.h" -#include "Common/StringUtils.h" - -DebuggerSubscriber *WebSocketClientConfigInit(DebuggerEventHandlerMap & map) { - map["broadcast.config.get"] = &WebSocketBroadcastConfigGet; - map["broadcast.config.set"] = &WebSocketBroadcastConfigSet; - - return nullptr; -} - - -// Request the current client broadcast configuration (broadcast.config.get) -// -// No parameters. -// -// Response (same event name): -// - disallowed: object with optional boolean fields: -// - logger: whether logger events are disallowed -// - game: whether game events are disallowed -// - stepping: whether stepping events are disallowed -// - input: whether input events are disallowed -void WebSocketBroadcastConfigGet(DebuggerRequest & req) { - JsonWriter &json = req.Respond(); - const auto& disallowed_config = req.client->disallowed; - - json.pushDict("disallowed"); - - for (const auto[name, status] : disallowed_config) { - if (status) - json.writeBool(name, true); - } - - json.end(); -} - -// Update the current client broadcast configuration (broadcast.config.set) -// -// Parameters: -// - disallowed: object with boolean fields (all of them are optional): -// - logger: new logger config state -// - game: new game config state -// - stepping: new stepping config state -// - input: new input config state -// -// Response (same event name): -// - disallowed: object with optional boolean fields: -// - logger: whether logger events are now disallowed -// - game: whether game events are now disallowed -// - stepping: whether stepping events are now disallowed -// - input: whether input events are now disallowed -void WebSocketBroadcastConfigSet(DebuggerRequest & req) { - JsonWriter &json = req.Respond(); - auto& disallowed_config = req.client->disallowed; - - const JsonNode *jsonDisallowed = req.data.get("disallowed"); - if (!jsonDisallowed) { - return req.Fail("Missing 'disallowed' parameter"); - } - if (jsonDisallowed->value.getTag() != JSON_OBJECT) { - return req.Fail("Invalid 'disallowed' parameter type"); - } - - for (const JsonNode *broadcaster : jsonDisallowed->value) { - auto it = disallowed_config.find(broadcaster->key); - if (it == disallowed_config.end()) { - return req.Fail(StringFromFormat("Unsupported 'disallowed' object key '%s'", broadcaster->key)); - } - - if (broadcaster->value.getTag() == JSON_TRUE) { - it->second = true; - } - else if (broadcaster->value.getTag() == JSON_FALSE) { - it->second = false; - } - else if (broadcaster->value.getTag() != JSON_NULL) { - return req.Fail(StringFromFormat("Unsupported 'disallowed' object type for key '%s'", broadcaster->key)); - } - } - - json.pushDict("disallowed"); - - for (const auto[name, status] : disallowed_config) { - if (status) - json.writeBool(name, true); - } - - json.end(); -} diff --git a/Core/Debugger/WebSocket/ClientConfigSubscriber.h b/Core/Debugger/WebSocket/ClientConfigSubscriber.h deleted file mode 100644 index 055464b6d..000000000 --- a/Core/Debugger/WebSocket/ClientConfigSubscriber.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "Core/Debugger/WebSocket/WebSocketUtils.h" - -DebuggerSubscriber *WebSocketClientConfigInit(DebuggerEventHandlerMap &map); - -void WebSocketBroadcastConfigSet(DebuggerRequest &req); -void WebSocketBroadcastConfigGet(DebuggerRequest &req); diff --git a/Core/Debugger/WebSocket/GPURecordSubscriber.cpp b/Core/Debugger/WebSocket/GPURecordSubscriber.cpp index 30516ba81..f1aad51e1 100644 --- a/Core/Debugger/WebSocket/GPURecordSubscriber.cpp +++ b/Core/Debugger/WebSocket/GPURecordSubscriber.cpp @@ -44,7 +44,7 @@ DebuggerSubscriber *WebSocketGPURecordInit(DebuggerEventHandlerMap &map) { WebSocketGPURecordState::~WebSocketGPURecordState() { // Clear the callback to hopefully avoid a crash. if (pending_) - GPURecord::ClearCallback(); + GPURecord::SetCallback(nullptr); } // Begin recording (gpu.record.dump) @@ -56,21 +56,18 @@ WebSocketGPURecordState::~WebSocketGPURecordState() { // // Note: recording may take a moment. void WebSocketGPURecordState::Dump(DebuggerRequest &req) { - if (!PSP_IsInited()) { + if (!PSP_IsInited()) return req.Fail("CPU not started"); - } - bool result = GPURecord::RecordNextFrame([=](const Path &filename) { + if (!GPURecord::Activate()) + return req.Fail("Recording already in progress"); + + pending_ = true; + GPURecord::SetCallback([=](const Path &filename) { lastFilename_ = filename; pending_ = false; }); - if (!result) { - return req.Fail("Recording already in progress"); - } - - pending_ = true; - const JsonNode *value = req.data.get("ticket"); lastTicket_ = value ? json_stringify(value) : ""; } diff --git a/Core/Debugger/WebSocket/GameBroadcaster.cpp b/Core/Debugger/WebSocket/GameBroadcaster.cpp index c71f13d57..c8b403976 100644 --- a/Core/Debugger/WebSocket/GameBroadcaster.cpp +++ b/Core/Debugger/WebSocket/GameBroadcaster.cpp @@ -64,7 +64,7 @@ struct GameStatusEvent { // - version: string disc version. // - title: string game title. -// Game resumed (game.resume) +// Game resumed (game.pause) // // Note: this is not the same as stepping. This means the user resumed from the pause menu. // diff --git a/Core/Debugger/WebSocket/GameSubscriber.cpp b/Core/Debugger/WebSocket/GameSubscriber.cpp index dae7f871a..6d4d356cf 100644 --- a/Core/Debugger/WebSocket/GameSubscriber.cpp +++ b/Core/Debugger/WebSocket/GameSubscriber.cpp @@ -96,17 +96,6 @@ void WebSocketGameStatus(DebuggerRequest &req) { // - version: string, typically starts with "v" and may have git build info. void WebSocketVersion(DebuggerRequest &req) { JsonWriter &json = req.Respond(); - - std::string version = req.client->version; - if (!req.ParamString("version", &version, DebuggerParamType::OPTIONAL_LOOSE)) - return; - std::string name = req.client->name; - if (!req.ParamString("name", &name, DebuggerParamType::OPTIONAL_LOOSE)) - return; - - req.client->version = version; - req.client->name = name; - json.writeString("name", "PPSSPP"); json.writeString("version", PPSSPP_GIT_VERSION); } diff --git a/Core/Debugger/WebSocket/InputSubscriber.cpp b/Core/Debugger/WebSocket/InputSubscriber.cpp index e15c12446..1ef926068 100644 --- a/Core/Debugger/WebSocket/InputSubscriber.cpp +++ b/Core/Debugger/WebSocket/InputSubscriber.cpp @@ -128,7 +128,7 @@ DebuggerSubscriber *WebSocketInputInit(DebuggerEventHandlerMap &map) { // - back: back button on headset. // - playpause: play/pause button on headset. // -// Response (same event name) with no extra data. +// Empty response. void WebSocketInputState::ButtonsSend(DebuggerRequest &req) { const JsonNode *jsonButtons = req.data.get("buttons"); if (!jsonButtons) { @@ -166,7 +166,7 @@ void WebSocketInputState::ButtonsSend(DebuggerRequest &req) { // - button: required string indicating button name (see input.buttons.send.) // - duration: optional integer indicating frames to press for, defaults to 1. // -// Response (same event name) with no extra data once released. +// Empty response once released. void WebSocketInputState::ButtonsPress(DebuggerRequest &req) { std::string button; if (!req.ParamString("button", &button)) @@ -238,7 +238,7 @@ static bool AnalogValue(DebuggerRequest &req, float *value, const char *name) { // - y: required number from -1.0 to 1.0. // - stick: optional string, either "left" (default) or "right". // -// Response (same event name) with no extra data. +// Empty response. void WebSocketInputState::AnalogSend(DebuggerRequest &req) { std::string stick = "left"; if (!req.ParamString("stick", &stick, DebuggerParamType::OPTIONAL)) diff --git a/Core/Debugger/WebSocket/LogBroadcaster.cpp b/Core/Debugger/WebSocket/LogBroadcaster.cpp index b3d4359c8..07070be7b 100644 --- a/Core/Debugger/WebSocket/LogBroadcaster.cpp +++ b/Core/Debugger/WebSocket/LogBroadcaster.cpp @@ -95,7 +95,7 @@ struct DebuggerLogEvent { j.writeString("timestamp", l.timestamp); j.writeString("header", l.header); j.writeString("message", l.msg); - j.writeInt("level", (int)l.level); + j.writeInt("level", l.level); j.writeString("channel", l.log); j.end(); return j.str(); diff --git a/Core/Debugger/WebSocket/ReplaySubscriber.cpp b/Core/Debugger/WebSocket/ReplaySubscriber.cpp index db45d0509..3b548a25e 100644 --- a/Core/Debugger/WebSocket/ReplaySubscriber.cpp +++ b/Core/Debugger/WebSocket/ReplaySubscriber.cpp @@ -43,7 +43,7 @@ DebuggerSubscriber *WebSocketReplayInit(DebuggerEventHandlerMap &map) { // // No parameters. // -// Response (same event name) with no extra data. +// Empty response. void WebSocketReplayBegin(DebuggerRequest &req) { ReplayBeginSave(); req.Respond(); @@ -142,7 +142,7 @@ void WebSocketReplayTimeGet(DebuggerRequest &req) { // Parameters: // - value: unsigned integer. // -// Response (same event name) with no extra data. +// Empty response. void WebSocketReplayTimeSet(DebuggerRequest &req) { if (!PSP_IsInited()) return req.Fail("Game not running"); diff --git a/Core/Debugger/WebSocket/SteppingBroadcaster.cpp b/Core/Debugger/WebSocket/SteppingBroadcaster.cpp index 6e7e4aa71..5d255d4f8 100644 --- a/Core/Debugger/WebSocket/SteppingBroadcaster.cpp +++ b/Core/Debugger/WebSocket/SteppingBroadcaster.cpp @@ -48,8 +48,6 @@ private: // Sent unexpectedly with these properties: // - pc: number value of PC register (inaccurate unless stepping.) // - ticks: number of CPU cycles into emulation. -// - reason: a value submitted to Core_EnableStepping ("jit.branchdebug", "savestate.load", "ui.lost_focus", etc.) -// - relatedAddress: an address (often zero, but it can be a value of PC saved at some point, a related memory address, etc.) // CPU has resumed from stepping (cpu.resume) // diff --git a/Core/Debugger/WebSocket/WebSocketUtils.h b/Core/Debugger/WebSocket/WebSocketUtils.h index 3a4e5fc26..38edc24a6 100644 --- a/Core/Debugger/WebSocket/WebSocketUtils.h +++ b/Core/Debugger/WebSocket/WebSocketUtils.h @@ -33,16 +33,8 @@ using namespace json; -struct WebSocketClientInfo { - WebSocketClientInfo() = default; - - std::string name; - std::string version; - std::map disallowed; -}; - struct DebuggerErrorEvent { - DebuggerErrorEvent(const std::string m, LogLevel l, const JsonGet data = JsonValue(JSON_NULL)) + DebuggerErrorEvent(const std::string m, LogTypes::LOG_LEVELS l, const JsonGet data = JsonValue(JSON_NULL)) : message(m), level(l) { // Need to format right away, before it's out of scope. if (data) { @@ -53,7 +45,7 @@ struct DebuggerErrorEvent { } std::string message; - LogLevel level; + LogTypes::LOG_LEVELS level; std::string ticketRaw; operator std::string() const { @@ -61,7 +53,7 @@ struct DebuggerErrorEvent { j.begin(); j.writeString("event", "error"); j.writeString("message", message); - j.writeInt("level", (int)level); + j.writeInt("level", level); if (!ticketRaw.empty()) { j.writeRaw("ticket", ticketRaw); } @@ -78,17 +70,16 @@ enum class DebuggerParamType { }; struct DebuggerRequest { - DebuggerRequest(const char *n, net::WebSocketServer *w, const JsonGet &d, WebSocketClientInfo *client_info) - : name(n), ws(w), data(d), client(client_info) { + DebuggerRequest(const char *n, net::WebSocketServer *w, const JsonGet &d) + : name(n), ws(w), data(d) { } const char *name; net::WebSocketServer *ws; const JsonGet data; - WebSocketClientInfo *client; void Fail(const std::string &message) { - ws->Send(DebuggerErrorEvent(message, LogLevel::LERROR, data)); + ws->Send(DebuggerErrorEvent(message, LogTypes::LERROR, data)); responseSent_ = true; } diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index dd05b2441..964f7ae30 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -42,7 +42,7 @@ PSPDialog::~PSPDialog() { void PSPDialog::InitCommon() { UpdateCommon(); - if (GetCommonParam() && GetCommonParam()->language != g_Config.GetPSPLanguage()) { + if (GetCommonParam() && GetCommonParam()->language != g_Config.iLanguage) { WARN_LOG(SCEUTILITY, "Game requested language %d, ignoring and using user language", GetCommonParam()->language); } } diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index 84cef563d..0f43cfbc4 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -19,15 +19,12 @@ #include "Common/CommonTypes.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" -#include "Common/System/OSD.h" #include "Core/ELF/ParamSFO.h" #include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/System.h" #include "Core/FileSystems/MetaFileSystem.h" #include "Core/Dialog/PSPGamedataInstallDialog.h" -#include "Common/Data/Text/I18n.h" -#include "UI/OnScreenDisplay.h" std::string saveBasePath = "ms0:/PSP/SAVEDATA/"; @@ -39,8 +36,6 @@ const static u32 GAMEDATA_BYTES_PER_READ = 32768; // If this is too high, some games (e.g. Senjou no Valkyria 3) will lag. const static u32 GAMEDATA_READS_PER_UPDATE = 20; -const u32 PSP_UTILITY_GAMEDATA_MODE_SHOW_PROGRESS = 1; - const u32 ERROR_UTILITY_GAMEDATA_MEMSTRICK_REMOVED = 0x80111901; const u32 ERROR_UTILITY_GAMEDATA_MEMSTRICK_WRITE_PROTECTED = 0x80111903; const u32 ERROR_UTILITY_GAMEDATA_INVALID_MODE = 0x80111908; @@ -276,37 +271,10 @@ void PSPGamedataInstallDialog::UpdateProgress() { else progressValue = 100; - if (param->mode == PSP_UTILITY_GAMEDATA_MODE_SHOW_PROGRESS) { - RenderProgress(progressValue); - } - param->progress = progressValue; param.NotifyWrite("DialogResult"); } -void PSPGamedataInstallDialog::RenderProgress(int percentage) { - StartDraw(); - - float barWidth = 380; - float barX = (480 - barWidth) / 2; - float barWidthDone = barWidth * percentage / 100; - float barH = 10.0; - float barY = 272 / 2 - barH / 2; - - PPGeDrawRect(barX - 3, barY - 3, barX + barWidth + 3, barY + barH + 3, 0x30000000); - PPGeDrawRect(barX, barY, barX + barWidth, barY + barH, 0xFF707070); - PPGeDrawRect(barX, barY, barX + barWidthDone, barY + barH, 0xFFE0E0E0); - - auto di = GetI18NCategory(I18NCat::DIALOG); - - fadeValue = 255; - PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_HCENTER, 0.6f); - - PPGeDrawText(di->T("Installing..."), 480 / 2, barY + barH + 10, textStyle); - - EndDraw(); -} - void PSPGamedataInstallDialog::DoState(PointerWrap &p) { auto s = p.Section("PSPGamedataInstallDialog", 0, 4); if (!s) diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h index bf076c751..c73db2a01 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.h +++ b/Core/Dialog/PSPGamedataInstallDialog.h @@ -54,7 +54,6 @@ protected: private: void UpdateProgress(); - void RenderProgress(int percentage); void OpenNextFile(); void CopyCurrentFileData(); void CloseCurrentFile(); diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 555d63832..7e07dd2b9 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -975,7 +975,7 @@ int PSPOskDialog::Update(int animSpeed) { int selectedRow = selectedChar / numKeyCols[currentKeyboard]; int selectedExtra = selectedChar % numKeyCols[currentKeyboard]; -#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) // Windows: Fall back to the OSK/continue normally if we're in fullscreen. // The dialog box doesn't work right if in fullscreen. if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) { diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 58f107b21..1ed8b80d9 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -22,7 +22,7 @@ #include "Common/Data/Format/ZIMLoad.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/StringUtils.h" #include "Core/Config.h" #include "Core/Reporting.h" @@ -456,7 +456,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD if (!pspFileSystem.GetFileInfo(dirPath).exists) { if (!pspFileSystem.MkDir(dirPath)) { auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Unable to write savedata, disk may be full")); + System_NotifyUserMessage(err->T("Unable to write savedata, disk may be full")); } } @@ -485,7 +485,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD if (EncryptData(decryptMode, cryptedData, &cryptedSize, &aligned_len, cryptedHash, (hasKey ? param->key : 0)) != 0) { auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Save encryption failed. This save won't work on real PSP"), 6.0f); + System_NotifyUserMessage(err->T("Save encryption failed. This save won't work on real PSP"), 6.0f); ERROR_LOG(SCEUTILITY,"Save encryption failed. This save won't work on real PSP"); delete[] cryptedData; cryptedData = 0; @@ -496,18 +496,13 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD std::string sfopath = dirPath + "/" + SFO_FILENAME; std::shared_ptr sfoFile = LoadCachedSFO(sfopath, true); - bool subWrite = param->mode == SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE || param->mode == SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA; - bool wasCrypted = GetSaveCryptMode(param, saveDirName) != 0; - // Update values - if(!subWrite){ - sfoFile->SetValue("TITLE", param->sfoParam.title, 128); - sfoFile->SetValue("SAVEDATA_TITLE", param->sfoParam.savedataTitle, 128); - sfoFile->SetValue("SAVEDATA_DETAIL", param->sfoParam.detail, 1024); - sfoFile->SetValue("PARENTAL_LEVEL", param->sfoParam.parentalLevel, 4); - sfoFile->SetValue("CATEGORY", "MS", 4); - sfoFile->SetValue("SAVEDATA_DIRECTORY", GetSaveDir(param, saveDirName), 64); - } + sfoFile->SetValue("TITLE", param->sfoParam.title, 128); + sfoFile->SetValue("SAVEDATA_TITLE", param->sfoParam.savedataTitle, 128); + sfoFile->SetValue("SAVEDATA_DETAIL", param->sfoParam.detail, 1024); + sfoFile->SetValue("PARENTAL_LEVEL", param->sfoParam.parentalLevel, 4); + sfoFile->SetValue("CATEGORY", "MS", 4); + sfoFile->SetValue("SAVEDATA_DIRECTORY", GetSaveDir(param, saveDirName), 64); // Always write and update the file list. // For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding @@ -547,7 +542,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD sfoFile->WriteSFO(&sfoData, &sfoSize); // Calc SFO hash for PSP. - if (cryptedData != 0 || (subWrite && wasCrypted)) { + if (cryptedData != 0) { int offset = sfoFile->GetDataOffset(sfoData, "SAVEDATA_PARAMS"); if(offset >= 0) UpdateHash(sfoData, (int)sfoSize, offset, DetermineCryptMode(param)); @@ -780,8 +775,8 @@ u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, con // Don't notify the user if we're not going to upgrade the save. if (!g_Config.bEncryptSave) { auto di = GetI18NCategory(I18NCat::DIALOG); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("When you save, it will load on a PSP, but not an older PPSSPP"), 6.0f); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Old savedata detected"), 6.0f); + System_NotifyUserMessage(di->T("When you save, it will load on a PSP, but not an older PPSSPP"), 6.0f); + System_NotifyUserMessage(di->T("Old savedata detected"), 6.0f); } } else { if (decryptMode == 5 && prevCryptMode == 3) { @@ -792,8 +787,8 @@ u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, con if (g_Config.bSavedataUpgrade) { decryptMode = prevCryptMode; auto di = GetI18NCategory(I18NCat::DIALOG); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("When you save, it will not work on outdated PSP Firmware anymore"), 6.0f); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Old savedata detected"), 6.0f); + System_NotifyUserMessage(di->T("When you save, it will not work on outdated PSP Firmware anymore"), 6.0f); + System_NotifyUserMessage(di->T("Old savedata detected"), 6.0f); } } hasKey = decryptMode > 1; @@ -952,7 +947,7 @@ int SavedataParam::EncryptData(unsigned int mode, return -5; /* Verify encryption */ - if (sceSdCleanList_(ctx2) < 0) + if (sceChnnlsv_21BE78B4_(ctx2) < 0) return -6; /* Build the file hash from this PSP */ @@ -994,7 +989,7 @@ int SavedataParam::DecryptSave(unsigned int mode, unsigned char *data, int *data return -6; /* Verify that it decrypted correctly */ - if (sceSdCleanList_(ctx2) < 0) + if (sceChnnlsv_21BE78B4_(ctx2) < 0) return -7; if (expectedHash) { diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index dcba8b789..b842f6798 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -154,44 +154,25 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) { u16 hi = 0; bool found = false; for (int t = r + 1; t < numRelocs; t++) { - int t_type = rels[t].r_info & 0xF; - if (t_type == R_MIPS_HI16) - continue; - - u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite]; - - // In MotorStorm: Arctic Edge (US), these are sometimes R_MIPS_16 (instead of LO16.) - // It appears the PSP takes any relocation that is not a HI16. - if (t_type != R_MIPS_LO16) { - if (t_type != R_MIPS_16) { - // Let's play it safe for now and skip. We've only seen this type. - ERROR_LOG_REPORT(LOADER, "ELF relocation HI16/%d pair (instead of LO16) at %08x / %08x", t_type, addr, corrLoAddr); - continue; - } else { - WARN_LOG_REPORT(LOADER, "ELF relocation HI16/%d(16) pair (instead of LO16) at %08x / %08x", t_type, addr, corrLoAddr); + if ((rels[t].r_info & 0xF) == R_MIPS_LO16) { + u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite]; + if (log) { + DEBUG_LOG(LOADER, "Corresponding lo found at %08x", corrLoAddr); + } + if (Memory::IsValidAddress(corrLoAddr)) { + s16 lo = (s16)relocOps[t]; + cur += lo; + cur += relocateTo; + addrToHiLo(cur, hi, lo); + found = true; + break; + } else { + ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr); } - } - - // Should have matching index and segment info, according to llvm, which makes sense. - if ((rels[t].r_info >> 8) != (rels[r].r_info >> 8)) { - WARN_LOG_REPORT(LOADER, "ELF relocation HI16/LO16 with mismatching r_info lo=%08x, hi=%08x", rels[t].r_info, rels[r].r_info); - } - if (log) { - DEBUG_LOG(LOADER, "Corresponding lo found at %08x", corrLoAddr); - } - if (Memory::IsValidAddress(corrLoAddr)) { - s16 lo = (s16)relocOps[t]; - cur += lo; - cur += relocateTo; - addrToHiLo(cur, hi, lo); - found = true; - break; - } else { - ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr); } } if (!found) { - ERROR_LOG_REPORT(LOADER, "R_MIPS_HI16: could not find R_MIPS_LO16 (r=%d of %d, addr=%08x)", r, numRelocs, addr); + ERROR_LOG_REPORT(LOADER, "R_MIPS_HI16: could not find R_MIPS_LO16"); } op = (op & 0xFFFF0000) | hi; } @@ -223,7 +204,7 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) { default: { char temp[256]; - MIPSDisAsm(MIPSOpcode(op), 0, temp, sizeof(temp)); + MIPSDisAsm(MIPSOpcode(op), 0, temp); ERROR_LOG_REPORT(LOADER, "ARGH IT'S AN UNKNOWN RELOCATION!!!!!!!! %08x, type=%d : %s", addr, type, temp); } break; @@ -256,7 +237,7 @@ void ElfReader::LoadRelocations2(int rel_seg) buf = (u8*)GetSegmentPtr(rel_seg); if (!buf) { - ERROR_LOG_REPORT(LOADER, "Rel2 segment invalid"); + ERROR_LOG(LOADER, "Rel2 segment invalid"); return; } end = buf+ph->p_filesz; @@ -310,7 +291,7 @@ void ElfReader::LoadRelocations2(int rel_seg) addr_seg = seg; relocate_to = addr_seg >= (int)ARRAY_SIZE(segmentVAddr) ? 0 : segmentVAddr[addr_seg]; if (!Memory::IsValidAddress(relocate_to)) { - ERROR_LOG_REPORT(LOADER, "ELF: Bad address to relocate to: %08x (segment %d)", relocate_to, addr_seg); + ERROR_LOG(LOADER, "ELF: Bad address to relocate to: %08x (segment %d)", relocate_to, addr_seg); continue; } @@ -342,7 +323,7 @@ void ElfReader::LoadRelocations2(int rel_seg) rel_offset = rel_base+segmentVAddr[off_seg]; if (!Memory::IsValidAddress(rel_offset)) { - ERROR_LOG_REPORT(LOADER, "ELF: Bad rel_offset: %08x", rel_offset); + ERROR_LOG(LOADER, "ELF: Bad rel_offset: %08x", rel_offset); continue; } @@ -395,7 +376,7 @@ void ElfReader::LoadRelocations2(int rel_seg) } Memory::Write_U32(op, rel_offset); - NotifyMemInfo(MemBlockFlags::WRITE, rel_offset, 4, "Relocation2"); + NotifyMemInfo(MemBlockFlags::WRITE, addr, 4, "Relocation2"); rcount += 1; } } @@ -564,7 +545,7 @@ int ElfReader::LoadInto(u32 loadAddress, bool fromTop) if (s->sh_flags & SHF_ALLOC) { - std::string tag = name && name[0] ? StringFromFormat("%s/%s", modName.c_str(), name) : StringFromFormat("%s/%08x", modName.c_str(), writeAddr); + std::string tag = name && name[0] ? StringFromFormat("ELF/%s", name) : StringFromFormat("ELF/%08x", writeAddr); NotifyMemInfo(MemBlockFlags::SUB_ALLOC, writeAddr, s->sh_size, tag.c_str(), tag.size()); DEBUG_LOG(LOADER,"Data Section found: %s Sitting at %08x, size %08x", name, writeAddr, (u32)s->sh_size); } diff --git a/Core/FileLoaders/HTTPFileLoader.h b/Core/FileLoaders/HTTPFileLoader.h index e4bf8ee9b..ec92b8b9d 100644 --- a/Core/FileLoaders/HTTPFileLoader.h +++ b/Core/FileLoaders/HTTPFileLoader.h @@ -71,7 +71,7 @@ private: s64 filepos_ = 0; Url url_; http::Client client_; - net::RequestProgress progress_; + http::RequestProgress progress_; ::Path filename_; bool connected_ = false; bool cancel_ = false; diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp index b5a1ca0a8..71c2d2a11 100644 --- a/Core/FileSystems/BlockDevices.cpp +++ b/Core/FileSystems/BlockDevices.cpp @@ -21,14 +21,11 @@ #include "Common/Data/Text/I18n.h" #include "Common/File/FileUtil.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Log.h" #include "Common/Swap.h" -#include "Common/File/FileUtil.h" -#include "Common/File/DirListing.h" #include "Core/Loaders.h" #include "Core/FileSystems/BlockDevices.h" -#include "libchdr/chd.h" extern "C" { @@ -40,41 +37,49 @@ extern "C" std::mutex NPDRMDemoBlockDevice::mutex_; BlockDevice *constructBlockDevice(FileLoader *fileLoader) { + // Check for CISO if (!fileLoader->Exists()) return nullptr; - char buffer[8]{}; - size_t size = fileLoader->ReadAt(0, 1, 8, buffer); - if (size != 8) { - // Bad or empty file - return nullptr; - } - - // Check for CISO - if (!memcmp(buffer, "CISO", 4)) { + char buffer[4]{}; + size_t size = fileLoader->ReadAt(0, 1, 4, buffer); + if (size == 4 && !memcmp(buffer, "CISO", 4)) return new CISOFileBlockDevice(fileLoader); - } else if (!memcmp(buffer, "\x00PBP", 4)) { + if (size == 4 && !memcmp(buffer, "\x00PBP", 4)) { uint32_t psarOffset = 0; size = fileLoader->ReadAt(0x24, 1, 4, &psarOffset); if (size == 4 && psarOffset < fileLoader->FileSize()) return new NPDRMDemoBlockDevice(fileLoader); - } else if (!memcmp(buffer, "MComprHD", 8)) { - return new CHDFileBlockDevice(fileLoader); + } + return new FileBlockDevice(fileLoader); +} + +u32 BlockDevice::CalculateCRC(volatile bool *cancel) { + u32 crc = crc32(0, Z_NULL, 0); + + u8 block[2048]; + for (u32 i = 0; i < GetNumBlocks(); ++i) { + if (cancel && *cancel) + return 0; + if (!ReadBlock(i, block, true)) { + ERROR_LOG(FILESYS, "Failed to read block for CRC"); + return 0; + } + crc = crc32(crc, block, 2048); } - // Should be just a regular ISO. Let's open it as a plain block device and let the other systems take over. - return new FileBlockDevice(fileLoader); + return crc; } void BlockDevice::NotifyReadError() { auto err = GetI18NCategory(I18NCat::ERRORS); if (!reportedError_) { - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Game disc read error - ISO corrupt"), fileLoader_->GetPath().ToVisualString(), 6.0f); + System_NotifyUserMessage(err->T("Game disc read error - ISO corrupt"), 6.0f); reportedError_ = true; } } FileBlockDevice::FileBlockDevice(FileLoader *fileLoader) - : BlockDevice(fileLoader) { + : fileLoader_(fileLoader) { filesize_ = fileLoader->FileSize(); } @@ -132,7 +137,7 @@ typedef struct ciso_header static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024; CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader) - : BlockDevice(fileLoader) + : fileLoader_(fileLoader) { // CISO format is fairly simple, but most tools do not write the header_size. @@ -377,7 +382,7 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) { } NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader) - : BlockDevice(fileLoader) + : fileLoader_(fileLoader) { std::lock_guard guard(mutex_); MAC_KEY mkey; @@ -388,7 +393,7 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader) fileLoader_->ReadAt(0x24, 1, 4, &psarOffset); size_t readSize = fileLoader_->ReadAt(psarOffset, 1, 256, &np_header); - if (readSize != 256){ + if(readSize!=256){ ERROR_LOG(LOADER, "Invalid NPUMDIMG header!"); } @@ -440,6 +445,7 @@ NPDRMDemoBlockDevice::NPDRMDemoBlockDevice(FileLoader *fileLoader) } currentBlock = -1; + } NPDRMDemoBlockDevice::~NPDRMDemoBlockDevice() @@ -514,150 +520,3 @@ bool NPDRMDemoBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached) return true; } - -/* - * CHD file - */ -static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 }; - -struct CHDImpl { - chd_file *chd = nullptr; - const chd_header *header = nullptr; -}; - -CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader) - : BlockDevice(fileLoader), impl_(new CHDImpl()) -{ - Path paths[8]; - paths[0] = fileLoader->GetPath(); - int depth = 0; - - /* - // TODO: Support parent/child CHD files. - - // Default, in case of failure - numBlocks = 0; - - chd_header childHeader; - - chd_error err = chd_read_header(paths[0].c_str(), &childHeader); - if (err != CHDERR_NONE) { - ERROR_LOG(LOADER, "Error loading CHD header for '%s': %s", paths[0].c_str(), chd_error_string(err)); - NotifyReadError(); - return; - } - - if (memcmp(nullsha1, childHeader.parentsha1, sizeof(childHeader.sha1)) != 0) { - chd_header parentHeader; - - // Look for parent CHD in current directory - Path chdDir = paths[0].NavigateUp(); - - std::vector files; - if (File::GetFilesInDir(chdDir, &files)) { - parentHeader.length = 0; - - for (const auto &file : files) { - std::string extension = file.fullName.GetFileExtension(); - if (extension != ".chd") { - continue; - } - - if (chd_read_header(filepath.c_str(), &parentHeader) == CHDERR_NONE && - memcmp(parentHeader.sha1, childHeader.parentsha1, sizeof(parentHeader.sha1)) == 0) { - // ERROR_LOG(LOADER, "Checking '%s'", filepath.c_str()); - paths[++depth] = filepath; - break; - } - } - - // Check if parentHeader was opened - if (parentHeader.length == 0) { - ERROR_LOG(LOADER, "Error loading CHD '%s': parents not found", fileLoader->GetPath().c_str()); - NotifyReadError(); - return; - } - memcpy(childHeader.parentsha1, parentHeader.parentsha1, sizeof(childHeader.parentsha1)); - } while (memcmp(nullsha1, childHeader.parentsha1, sizeof(childHeader.sha1)) != 0); - } - */ - - chd_file *parent = NULL; - chd_file *child = NULL; - - FILE *file = File::OpenCFile(paths[depth], "rb"); - if (!file) { - ERROR_LOG(LOADER, "Error opening CHD file '%s'", paths[depth].c_str()); - NotifyReadError(); - return; - } - chd_error err = chd_open_file(file, CHD_OPEN_READ, NULL, &child); - if (err != CHDERR_NONE) { - ERROR_LOG(LOADER, "Error loading CHD '%s': %s", paths[depth].c_str(), chd_error_string(err)); - NotifyReadError(); - return; - } - - // We won't enter this loop until we enable the parent/child stuff above. - for (int d = depth - 1; d >= 0; d--) { - parent = child; - child = NULL; - // TODO: Use chd_open_file - err = chd_open(paths[d].c_str(), CHD_OPEN_READ, parent, &child); - if (err != CHDERR_NONE) { - ERROR_LOG(LOADER, "Error loading CHD '%s': %s", paths[d].c_str(), chd_error_string(err)); - NotifyReadError(); - return; - } - } - impl_->chd = child; - - impl_->header = chd_get_header(impl_->chd); - readBuffer = new u8[impl_->header->hunkbytes]; - currentHunk = -1; - blocksPerHunk = impl_->header->hunkbytes / impl_->header->unitbytes; - numBlocks = impl_->header->unitcount; -} - -CHDFileBlockDevice::~CHDFileBlockDevice() -{ - if (numBlocks > 0) { - chd_close(impl_->chd); - delete[] readBuffer; - } -} - -bool CHDFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached) -{ - if ((u32)blockNumber >= numBlocks) { - memset(outPtr, 0, GetBlockSize()); - return false; - } - u32 hunk = blockNumber / blocksPerHunk; - u32 blockInHunk = blockNumber % blocksPerHunk; - - if (currentHunk != hunk) { - chd_error err = chd_read(impl_->chd, hunk, readBuffer); - if (err != CHDERR_NONE) { - ERROR_LOG(LOADER, "CHD read failed: %d %d %s", blockNumber, hunk, chd_error_string(err)); - NotifyReadError(); - } - } - memcpy(outPtr, readBuffer + blockInHunk * impl_->header->unitbytes, GetBlockSize()); - - return true; -} - -bool CHDFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) { - if (minBlock >= numBlocks) { - memset(outPtr, 0, GetBlockSize() * count); - return false; - } - - for (int i = 0; i < count; i++) { - if (!ReadBlock(minBlock + i, outPtr + i * GetBlockSize())) { - return false; - } - } - return true; -} diff --git a/Core/FileSystems/BlockDevices.h b/Core/FileSystems/BlockDevices.h index 9dca25e8e..3268b27fa 100644 --- a/Core/FileSystems/BlockDevices.h +++ b/Core/FileSystems/BlockDevices.h @@ -32,7 +32,6 @@ class FileLoader; class BlockDevice { public: - BlockDevice(FileLoader *fileLoader) : fileLoader_(fileLoader) {} virtual ~BlockDevice() {} virtual bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) = 0; virtual bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) { @@ -45,16 +44,13 @@ public: return true; } int GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses - virtual u32 GetNumBlocks() const = 0; - virtual u64 GetUncompressedSize() const { - return (u64)GetNumBlocks() * (u64)GetBlockSize(); - } - virtual bool IsDisc() const = 0; + virtual u32 GetNumBlocks() = 0; + virtual bool IsDisc() = 0; + u32 CalculateCRC(volatile bool *cancel = nullptr); void NotifyReadError(); protected: - FileLoader *fileLoader_; bool reportedError_ = false; }; @@ -64,10 +60,11 @@ public: ~CISOFileBlockDevice(); bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override; - u32 GetNumBlocks() const override { return numBlocks; } - bool IsDisc() const override { return true; } + u32 GetNumBlocks() override { return numBlocks; } + bool IsDisc() override { return true; } private: + FileLoader *fileLoader_; u32 *index; u8 *readBuffer; u8 *zlibBuffer; @@ -87,12 +84,11 @@ public: ~FileBlockDevice(); bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override; - u32 GetNumBlocks() const override {return (u32)(filesize_ / GetBlockSize());} - bool IsDisc() const override { return true; } - u64 GetUncompressedSize() const override { - return filesize_; - } + u32 GetNumBlocks() override {return (u32)(filesize_ / GetBlockSize());} + bool IsDisc() override { return true; } + private: + FileLoader *fileLoader_; u64 filesize_; }; @@ -113,10 +109,11 @@ public: ~NPDRMDemoBlockDevice(); bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; - u32 GetNumBlocks() const override {return (u32)lbaSize;} - bool IsDisc() const override { return false; } + u32 GetNumBlocks() override {return (u32)lbaSize;} + bool IsDisc() override { return false; } private: + FileLoader *fileLoader_; static std::mutex mutex_; u32 lbaSize; @@ -134,23 +131,5 @@ private: u8 *tempBuf; }; -struct CHDImpl; - -class CHDFileBlockDevice : public BlockDevice { -public: - CHDFileBlockDevice(FileLoader *fileLoader); - ~CHDFileBlockDevice(); - bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override; - bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override; - u32 GetNumBlocks() const override { return numBlocks; } - bool IsDisc() const override { return true; } - -private: - std::unique_ptr impl_; - u8 *readBuffer; - u32 currentHunk; - u32 blocksPerHunk; - u32 numBlocks; -}; BlockDevice *constructBlockDevice(FileLoader *fileLoader); diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 0ead3b15f..4e700d4a3 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -33,7 +33,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/StringUtils.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/File/FileUtil.h" #include "Common/File/DiskFree.h" #include "Common/File/VFS/VFS.h" @@ -192,7 +192,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File if (w32err == ERROR_DISK_FULL || w32err == ERROR_NOT_ENOUGH_QUOTA) { // This is returned when the disk is full. auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data")); + System_NotifyUserMessage(err->T("Disk full while writing data")); error = SCE_KERNEL_ERROR_ERRNO_NO_PERM; } else if (!success) { error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; @@ -290,7 +290,7 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File } else if (errno == ENOSPC) { // This is returned when the disk is full. auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data")); + System_NotifyUserMessage(err->T("Disk full while writing data")); error = SCE_KERNEL_ERROR_ERRNO_NO_PERM; } else { error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; @@ -365,7 +365,7 @@ size_t DirectoryFileHandle::Write(const u8* pointer, s64 size) if (diskFull) { ERROR_LOG(FILESYS, "Disk full"); auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Disk full while writing data")); + System_NotifyUserMessage(err->T("Disk full while writing data")); // We only return an error when the disk is actually full. // When writing this would cause the disk to be full, so it wasn't written, we return 0. if (MemoryStick_FreeSpace() == 0) { @@ -842,7 +842,7 @@ std::vector DirectoryFileSystem::GetDirListing(const std::string &p if (entry.name.size() > 2 && !startsWithNoCase(entry.name, gameID)) { continue; } - } else if (file.name == "GAME" || file.name == "TEXTURES" || file.name == "PPSSPP_STATE" || file.name == "PLUGINS" || file.name == "SYSTEM" || equalsNoCase(file.name, "Cheats")) { + } else if (file.name == "GAME" || file.name == "TEXTURES" || file.name == "PPSSPP_STATE" || equalsNoCase(file.name, "Cheats")) { // The game scans these folders on startup which can take time. Skip them. continue; } diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 06ebac25a..6d8d830ce 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -177,14 +177,6 @@ ISOFileSystem::~ISOFileSystem() { delete treeroot; } -std::string ISOFileSystem::TreeEntry::BuildPath() { - if (parent) { - return parent->BuildPath() + "/" + name; - } else { - return name; - } -} - void ISOFileSystem::ReadDirectory(TreeEntry *root) { for (u32 secnum = root->startsector, endsector = root->startsector + (root->dirsize + 2047) / 2048; secnum < endsector; ++secnum) { u8 theSector[2048]; @@ -236,12 +228,12 @@ void ISOFileSystem::ReadDirectory(TreeEntry *root) { entry->startsector = dir.firstDataSector; entry->dirsize = dir.dataLength; entry->valid = isFile; // Can pre-mark as valid if file, as we don't recurse into those. - VERBOSE_LOG(FILESYS, "%s: %s %08x %08x %d", entry->isDirectory ? "D" : "F", entry->name.c_str(), (u32)dir.firstDataSector, entry->startingPosition, entry->startingPosition); + VERBOSE_LOG(FILESYS, "%s: %s %08x %08x %i", entry->isDirectory ? "D" : "F", entry->name.c_str(), (u32)dir.firstDataSector, entry->startingPosition, entry->startingPosition); // Round down to avoid any false reports. if (isFile && dir.firstDataSector + (dir.dataLength / 2048) > blockDevice->GetNumBlocks()) { blockDevice->NotifyReadError(); - ERROR_LOG(FILESYS, "File '%s' starts or ends outside ISO. firstDataSector: %d len: %d", entry->BuildPath().c_str(), (int)dir.firstDataSector, (int)dir.dataLength); + ERROR_LOG(FILESYS, "File '%s' starts or ends outside ISO", entry->name.c_str()); } if (entry->isDirectory && !relative) { diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 613bfcf15..c7813bf1a 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -60,9 +60,6 @@ private: struct TreeEntry { ~TreeEntry(); - // Recursive function that reconstructs the path by looking at the parent pointers. - std::string BuildPath(); - std::string name; u32 flags = 0; u32 startingPosition = 0; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index c35f0e59e..395fea433 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -575,7 +575,7 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type) std::lock_guard guard(lock); IFileSystem *sys = GetHandleOwner(handle); if (sys) - return sys->SeekFile(handle, position, type); + return sys->SeekFile(handle,position,type); else return 0; } diff --git a/Core/FileSystems/VirtualDiscFileSystem.cpp b/Core/FileSystems/VirtualDiscFileSystem.cpp index df73ad544..42684a0fc 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.cpp +++ b/Core/FileSystems/VirtualDiscFileSystem.cpp @@ -813,7 +813,7 @@ bool VirtualDiscFileSystem::RemoveFile(const std::string &filename) return false; } -void VirtualDiscFileSystem::HandlerLogger(void *arg, HandlerHandle handle, LogLevel level, const char *msg) { +void VirtualDiscFileSystem::HandlerLogger(void *arg, HandlerHandle handle, LogTypes::LOG_LEVELS level, const char *msg) { VirtualDiscFileSystem *sys = static_cast(arg); // TODO: Probably could do this smarter / use a lookup. @@ -826,9 +826,9 @@ void VirtualDiscFileSystem::HandlerLogger(void *arg, HandlerHandle handle, LogLe } if (filename != NULL) { - GENERIC_LOG(LogType::FILESYS, level, "%s: %s", filename, msg); + GENERIC_LOG(LogTypes::FILESYS, level, "%s: %s", filename, msg); } else { - GENERIC_LOG(LogType::FILESYS, level, "%s", msg); + GENERIC_LOG(LogTypes::FILESYS, level, "%s", msg); } } diff --git a/Core/FileSystems/VirtualDiscFileSystem.h b/Core/FileSystems/VirtualDiscFileSystem.h index 409858817..eb3ef16e8 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -64,9 +64,9 @@ private: typedef void *HandlerLibrary; typedef int HandlerHandle; typedef s64 HandlerOffset; - typedef void (*HandlerLogFunc)(void *arg, HandlerHandle handle, LogLevel level, const char *msg); + typedef void (*HandlerLogFunc)(void *arg, HandlerHandle handle, LogTypes::LOG_LEVELS level, const char *msg); - static void HandlerLogger(void *arg, HandlerHandle handle, LogLevel level, const char *msg); + static void HandlerLogger(void *arg, HandlerHandle handle, LogTypes::LOG_LEVELS level, const char *msg); // The primary purpose of handlers is to make it easier to work with large archives. // However, they have other uses as well, such as patching individual files. diff --git a/Core/FrameTiming.cpp b/Core/FrameTiming.cpp deleted file mode 100644 index 8a9b10e63..000000000 --- a/Core/FrameTiming.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Frame timing -// -// A frame on the main thread should look a bit like this: -// -// 1. -- Wait for the right time to start the frame (alternatively, see this is step 8). -// 2. Sample inputs (on some platforms, this is done continouously during step 3) -// 3. Run CPU -// 4. Submit GPU commands (there's no reason to ever wait before this). -// 5. -- Wait for the right time to present -// 6. Send Present command -// 7. Do other end-of-frame stuff -// -// To minimize latency, we should *maximize* 1 and *minimize* 5 (while still keeping some margin to soak up hitches). -// Additionally, if too many completed frames have been buffered up, we need a feedback mechanism, so we can temporarily -// artificially increase 1 in order to "catch the CPU up". -// -// There are some other things that can influence the frame timing: -// * Unthrottling. If vsync is off or the backend can change present mode dynamically, we can simply disable all waits during unthrottle. -// * Frame skipping. This gets complicated. -// * The game not actually asking for flips, like in static loading screens - -#include "Common/Profiler/Profiler.h" -#include "Common/Log.h" -#include "Common/TimeUtil.h" - -#include "Core/RetroAchievements.h" -#include "Core/CoreParameter.h" -#include "Core/Core.h" -#include "Core/Config.h" -#include "Core/HW/Display.h" -#include "Core/FrameTiming.h" - -FrameTiming g_frameTiming; - -inline Draw::PresentMode GetBestImmediateMode(Draw::PresentMode supportedModes) { - if (supportedModes & Draw::PresentMode::MAILBOX) { - return Draw::PresentMode::MAILBOX; - } else { - return Draw::PresentMode::IMMEDIATE; - } -} - -void FrameTiming::Reset(Draw::DrawContext *draw) { - if (g_Config.bVSync || !(draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::MAILBOX | Draw::PresentMode::IMMEDIATE))) { - presentMode = Draw::PresentMode::FIFO; - presentInterval = 1; - } else { - presentMode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported); - presentInterval = 0; - } -} - -Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval) { - Draw::PresentMode mode = Draw::PresentMode::FIFO; - - if (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::IMMEDIATE | Draw::PresentMode::MAILBOX)) { - // Switch to immediate if desired and possible. - bool wantInstant = false; - if (!g_Config.bVSync) { - wantInstant = true; - } - - if (PSP_CoreParameter().fastForward) { - wantInstant = true; - } - if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) { - int limit; - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) - limit = g_Config.iFpsLimit1; - else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) - limit = g_Config.iFpsLimit2; - else - limit = PSP_CoreParameter().analogFpsLimit; - - // For an alternative speed that is a clean factor of 60, the user probably still wants vsync. - // TODO: Should take the user's display refresh rate into account... - if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) { - wantInstant = true; - } - } - - if (wantInstant && g_Config.bVSync && !draw->GetDeviceCaps().presentInstantModeChange) { - // If in vsync mode (which will be FIFO), and the backend can't switch immediately, - // stick to FIFO. - wantInstant = false; - } - - // The outer if checks that instant modes are available. - if (wantInstant) { - mode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported); - } - } - - *interval = (mode == Draw::PresentMode::FIFO) ? 1 : 0; - return mode; -} diff --git a/Core/FrameTiming.h b/Core/FrameTiming.h deleted file mode 100644 index 04e938e89..000000000 --- a/Core/FrameTiming.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Common/GPU/thin3d.h" - -// See big comment in the CPP file. - -namespace Draw { -class DrawContext; -} - -struct FrameTiming { - // Some backends won't allow changing this willy nilly. - Draw::PresentMode presentMode; - int presentInterval; - - void Reset(Draw::DrawContext *draw); -}; - -extern FrameTiming g_frameTiming; - -Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 5fd835d1b..ce7a04c34 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -540,9 +540,6 @@ void HLEReturnFromMipsCall() { const static u32 deadbeefRegs[12] = {0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF}; inline static void SetDeadbeefRegs() { - // Not exactly the same, but any time a syscall happens, it should clear ll. - currentMIPS->llBit = 0; - if (g_Config.bSkipDeadbeefFilling) return; @@ -853,7 +850,7 @@ size_t hleFormatLogArgs(char *message, size_t sz, const char *argmask) { return used; } -void hleDoLogInternal(LogType t, LogLevel level, u64 res, const char *file, int line, const char *reportTag, char retmask, const char *reason, const char *formatted_reason) { +void hleDoLogInternal(LogTypes::LOG_TYPE t, LogTypes::LOG_LEVELS level, u64 res, const char *file, int line, const char *reportTag, char retmask, const char *reason, const char *formatted_reason) { char formatted_args[4096]; const char *funcName = "?"; u32 funcFlags = 0; diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index b11efca78..0331fb7b9 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -130,11 +130,13 @@ u64 hleDelayResult(u64 result, const char *reason, int usec); void hleEatCycles(int cycles); void hleEatMicro(int usec); -inline int hleDelayResult(int result, const char *reason, int usec) { +inline int hleDelayResult(int result, const char *reason, int usec) +{ return hleDelayResult((u32) result, reason, usec); } -inline s64 hleDelayResult(s64 result, const char *reason, int usec) { +inline s64 hleDelayResult(s64 result, const char *reason, int usec) +{ return hleDelayResult((u64) result, reason, usec); } @@ -155,11 +157,11 @@ const HLEFunction *GetSyscallFuncPointer(MIPSOpcode op); // For jit, takes arg: const HLEFunction * void *GetQuickSyscallFunc(MIPSOpcode op); -void hleDoLogInternal(LogType t, LogLevel level, u64 res, const char *file, int line, const char *reportTag, char retmask, const char *reason, const char *formatted_reason); +void hleDoLogInternal(LogTypes::LOG_TYPE t, LogTypes::LOG_LEVELS level, u64 res, const char *file, int line, const char *reportTag, char retmask, const char *reason, const char *formatted_reason); template -T hleDoLog(LogType t, LogLevel level, T res, const char *file, int line, const char *reportTag, char retmask, const char *reason, ...) { - if ((int)level > MAX_LOGLEVEL || !GenericLogEnabled(level, t)) { +T hleDoLog(LogTypes::LOG_TYPE t, LogTypes::LOG_LEVELS level, T res, const char *file, int line, const char *reportTag, char retmask, const char *reason, ...) { + if (level > MAX_LOGLEVEL || !GenericLogEnabled(level, t)) { return res; } @@ -186,8 +188,8 @@ T hleDoLog(LogType t, LogLevel level, T res, const char *file, int line, const c } template -T hleDoLog(LogType t, LogLevel level, T res, const char *file, int line, const char *reportTag, char retmask) { - if (((int)level > MAX_LOGLEVEL || !GenericLogEnabled(level, t)) && !reportTag) { +T hleDoLog(LogTypes::LOG_TYPE t, LogTypes::LOG_LEVELS level, T res, const char *file, int line, const char *reportTag, char retmask) { + if ((level > MAX_LOGLEVEL || !GenericLogEnabled(level, t)) && !reportTag) { return res; } @@ -216,7 +218,7 @@ T hleDoLog(LogType t, LogLevel level, T res, const char *file, int line, const c #define HLE_LOG_LVERBOSE LVERBOSE #endif -#define hleLogHelper(t, level, res, retmask, ...) hleDoLog(LogType::t, LogLevel::level, res, __FILE__, __LINE__, nullptr, retmask, ##__VA_ARGS__) +#define hleLogHelper(t, level, res, retmask, ...) hleDoLog(LogTypes::t, LogTypes::level, res, __FILE__, __LINE__, nullptr, retmask, ##__VA_ARGS__) #define hleLogError(t, res, ...) hleLogHelper(t, LERROR, res, 'x', ##__VA_ARGS__) #define hleLogWarning(t, res, ...) hleLogHelper(t, LWARNING, res, 'x', ##__VA_ARGS__) #define hleLogDebug(t, res, ...) hleLogHelper(t, HLE_LOG_LDEBUG, res, 'x', ##__VA_ARGS__) @@ -228,7 +230,7 @@ T hleDoLog(LogType t, LogLevel level, T res, const char *file, int line, const c #define hleLogSuccessVerboseX(t, res, ...) hleLogHelper(t, HLE_LOG_LVERBOSE, res, 'x', ##__VA_ARGS__) #define hleLogSuccessVerboseI(t, res, ...) hleLogHelper(t, HLE_LOG_LVERBOSE, res, 'i', ##__VA_ARGS__) -#define hleReportError(t, res, ...) hleDoLog(LogType::t, LogLevel::LERROR, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) -#define hleReportWarning(t, res, ...) hleDoLog(LogType::t, LogLevel::LWARNING, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) -#define hleReportDebug(t, res, ...) hleDoLog(LogType::t, LogLevel::HLE_LOG_LDEBUG, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) -#define hleReportVerbose(t, res, ...) hleDoLog(LogType::t, LogLevel::HLE_LOG_LVERBOSE, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) +#define hleReportError(t, res, ...) hleDoLog(LogTypes::t, LogTypes::LERROR, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) +#define hleReportWarning(t, res, ...) hleDoLog(LogTypes::t, LogTypes::LWARNING, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) +#define hleReportDebug(t, res, ...) hleDoLog(LogTypes::t, LogTypes::HLE_LOG_LDEBUG, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) +#define hleReportVerbose(t, res, ...) hleDoLog(LogTypes::t, LogTypes::HLE_LOG_LVERBOSE, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index 0e0999c0f..d12f07d0c 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -183,9 +183,9 @@ const HLEFunction KDebugForKernel[] = {0X24C32559, nullptr, "sceKernelDipsw", '?', "" }, {0XD636B827, nullptr, "sceKernelRemoveByDebugSection", '?', "" }, {0X5282DD5E, nullptr, "sceKernelDipswSet", '?', "" }, - {0X9F8703E4, nullptr, "sceKernelDipswCpTime", '?', "" }, - {0X333DCEC7, nullptr, "sceKernelSm1RegisterOperations", '?', "" }, - {0XE892D9A1, nullptr, "sceKernelSm1ReferOperations", '?', "" }, + {0X9F8703E4, nullptr, "KDebugForKernel_9F8703E4", '?', "" }, + {0X333DCEC7, nullptr, "KDebugForKernel_333DCEC7", '?', "" }, + {0XE892D9A1, nullptr, "KDebugForKernel_E892D9A1", '?', "" }, {0XA126F497, nullptr, "KDebugForKernel_A126F497", '?', "" }, {0XB7251823, nullptr, "sceKernelAcceptMbogoSig", '?', "" }, }; diff --git a/Core/HLE/KernelThreadDebugInterface.h b/Core/HLE/KernelThreadDebugInterface.h index 41260ad7c..aa48bdb8b 100644 --- a/Core/HLE/KernelThreadDebugInterface.h +++ b/Core/HLE/KernelThreadDebugInterface.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - #include #include "Core/HLE/sceKernelThread.h" #include "Core/MIPS/MIPSDebugInterface.h" diff --git a/Core/HLE/Plugins.cpp b/Core/HLE/Plugins.cpp index 90edd6d96..0f5b682a9 100644 --- a/Core/HLE/Plugins.cpp +++ b/Core/HLE/Plugins.cpp @@ -105,17 +105,15 @@ static std::vector FindPlugins(const std::string &gameID, const std: std::set matches; std::string gameIni; - if (ini.GetOrCreateSection("games")->Get(gameID.c_str(), &gameIni, "")) { + if (ini.GetOrCreateSection("games")->Get("ALL", &gameIni, "")) { if (!strcasecmp(gameIni.c_str(), "true")) { matches.insert("plugin.ini"); - } else if (!strcasecmp(gameIni.c_str(), "false")){ - continue; } else if (!gameIni.empty()) { matches.insert(gameIni); } } - if (ini.GetOrCreateSection("games")->Get("ALL", &gameIni, "")) { + if (ini.GetOrCreateSection("games")->Get(gameID.c_str(), &gameIni, "")) { if (!strcasecmp(gameIni.c_str(), "true")) { matches.insert("plugin.ini"); } else if (!gameIni.empty()) { diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 4695d1392..30afa6e26 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -159,19 +159,16 @@ static int Replace_memcpy() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - // It's pretty common that games will copy video data. - // Detect that by manually reading the tag when the size looks right. - if (bytes == 512 * 272 * 4) { - char tagData[128]; - size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy/", srcPtr, bytes); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); - if (!strcmp(tagData, "ReplaceMemcpy/VideoDecode") || !strcmp(tagData, "ReplaceMemcpy/VideoDecodeRange")) { + // It's pretty common that games will copy video data. + if (!strcmp(tagData, "ReplaceMemcpy/VideoDecode") || !strcmp(tagData, "ReplaceMemcpy/VideoDecodeRange")) { + if (bytes == 512 * 272 * 4) { gpu->PerformWriteFormattedFromMemory(destPtr, bytes, 512, GE_FORMAT_8888); } - } else { - NotifyMemInfoCopy(destPtr, srcPtr, bytes, "ReplaceMemcpy/"); } } @@ -215,19 +212,16 @@ static int Replace_memcpy_jak() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - // It's pretty common that games will copy video data. - // Detect that by manually reading the tag when the size looks right. - if (bytes == 512 * 272 * 4) { - char tagData[128]; - size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy/", srcPtr, bytes); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); - if (!strcmp(tagData, "ReplaceMemcpy/VideoDecode") || !strcmp(tagData, "ReplaceMemcpy/VideoDecodeRange")) { + // It's pretty common that games will copy video data. + if (!strcmp(tagData, "ReplaceMemcpy/VideoDecode") || !strcmp(tagData, "ReplaceMemcpy/VideoDecodeRange")) { + if (bytes == 512 * 272 * 4) { gpu->PerformWriteFormattedFromMemory(destPtr, bytes, 512, GE_FORMAT_8888); } - } else { - NotifyMemInfoCopy(destPtr, srcPtr, bytes, "ReplaceMemcpy/"); } } @@ -258,7 +252,10 @@ static int Replace_memcpy16() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - NotifyMemInfoCopy(destPtr, srcPtr, bytes, "ReplaceMemcpy16/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy16/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); } return 10 + bytes / 4; // approximation @@ -297,7 +294,10 @@ static int Replace_memcpy_swizzled() { RETURN(0); if (MemBlockInfoDetailed(pitch * h)) { - NotifyMemInfoCopy(destPtr, srcPtr, pitch * h, "ReplaceMemcpySwizzle/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpySwizzle/", srcPtr, pitch * h); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, tagData, tagSize); } return 10 + (pitch * h) / 4; // approximation @@ -326,7 +326,10 @@ static int Replace_memmove() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - NotifyMemInfoCopy(destPtr, srcPtr, bytes, "ReplaceMemmove/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemmove/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); } return 10 + bytes / 4; // approximation @@ -1587,10 +1590,7 @@ std::vector GetReplacementFuncIndexes(u64 hash, int funcSize) { return emptyResult; } -const ReplacementTableEntry *GetReplacementFunc(size_t i) { - if (i >= ARRAY_SIZE(entries)) { - return nullptr; - } +const ReplacementTableEntry *GetReplacementFunc(int i) { return &entries[i]; } diff --git a/Core/HLE/ReplaceTables.h b/Core/HLE/ReplaceTables.h index 980f506b6..94ee26d69 100644 --- a/Core/HLE/ReplaceTables.h +++ b/Core/HLE/ReplaceTables.h @@ -64,7 +64,7 @@ void Replacement_Shutdown(); int GetNumReplacementFuncs(); std::vector GetReplacementFuncIndexes(u64 hash, int funcSize); -const ReplacementTableEntry *GetReplacementFunc(size_t index); +const ReplacementTableEntry *GetReplacementFunc(int index); void WriteReplaceInstructions(u32 address, u64 hash, int size); void RestoreReplacedInstruction(u32 address); diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 9a1cfc94b..6862893e0 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -57,7 +57,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Serialize/SerializeFuncs.h" @@ -1385,7 +1385,7 @@ int friendFinder(){ g_adhocServerIP.in.sin_addr.s_addr = INADDR_NONE; if (g_Config.bEnableWlan && !net::DNSResolve(g_Config.proAdhocServer, "", &resolved, err)) { ERROR_LOG(SCENET, "DNS Error Resolving %s\n", g_Config.proAdhocServer.c_str()); - g_OSD.Show(OSDType::MESSAGE_ERROR, n->T("DNS Error Resolving ") + g_Config.proAdhocServer); + System_NotifyUserMessage(n->T("DNS Error Resolving ") + g_Config.proAdhocServer, 2.0f, 0x0000ff); } if (resolved) { for (auto ptr = resolved; ptr != NULL; ptr = ptr->ai_next) { @@ -1447,7 +1447,7 @@ int friendFinder(){ shutdown((int)metasocket, SD_BOTH); closesocket((int)metasocket); metasocket = (int)INVALID_SOCKET; - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Disconnected from AdhocServer")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(error) + ")"); + System_NotifyUserMessage(std::string(n->T("Disconnected from AdhocServer")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(error) + ")", 2.0, 0x0000ff); // Mark all friends as timedout since we won't be able to detects disconnected friends anymore without being connected to Adhoc Server peerlock.lock(); timeoutFriendsRecursive(friends); @@ -2087,7 +2087,7 @@ int setSockKeepAlive(int sock, bool keepalive, const int keepinvl, const int kee int optval = keepalive ? 1 : 0; int optlen = sizeof(optval); int result = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&optval, optlen); -#if !PPSSPP_PLATFORM(SWITCH) && !PPSSPP_PLATFORM(OPENBSD) +#if !PPSSPP_PLATFORM(SWITCH) if (result == 0 && keepalive) { if (getsockopt(sock, SOL_SOCKET, SO_TYPE, (char*)&optval, (socklen_t*)&optlen) == 0 && optval == SOCK_STREAM) { optlen = sizeof(optval); @@ -2099,7 +2099,7 @@ int setSockKeepAlive(int sock, bool keepalive, const int keepinvl, const int kee setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (char*)&optval, optlen); } } -#endif // !PPSSPP_PLATFORM(SWITCH) && !PPSSPP_PLATFORM(OPENBSD) +#endif // !PPSSPP_PLATFORM(SWITCH) return result; } @@ -2191,7 +2191,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ iResult = bind((int)metasocket, &g_localhostIP.addr, sizeof(g_localhostIP.addr)); if (iResult == SOCKET_ERROR) { ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", ip2str(g_localhostIP.in.sin_addr).c_str(), iResult); - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to Bind Localhost IP")) + " " + ip2str(g_localhostIP.in.sin_addr).c_str()); + System_NotifyUserMessage(std::string(n->T("Failed to Bind Localhost IP")) + " " + ip2str(g_localhostIP.in.sin_addr).c_str(), 2.0, 0x0000ff); } } @@ -2246,7 +2246,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ } if (!done) { ERROR_LOG(SCENET, "Socket error (%i) when connecting to AdhocServer [%s/%s:%u]", errorcode, g_Config.proAdhocServer.c_str(), ip2str(g_adhocServerIP.in.sin_addr).c_str(), ntohs(g_adhocServerIP.in.sin_port)); - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to connect to Adhoc Server")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(errorcode) + ")"); + System_NotifyUserMessage(std::string(n->T("Failed to connect to Adhoc Server")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(errorcode) + ")", 1.0f, 0x0000ff); return iResult; } } @@ -2268,9 +2268,10 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ socklen_t addrLen = sizeof(LocalIP); memset(&LocalIP, 0, addrLen); getsockname((int)metasocket, &LocalIP, &addrLen); - g_OSD.Show(OSDType::MESSAGE_SUCCESS, n->T("Network Initialized"), 1.0); + System_NotifyUserMessage(n->T("Network Initialized"), 1.0); return 0; - } else { + } + else{ return SOCKET_ERROR; } } diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index bb80a10a6..c448d0189 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -84,7 +84,7 @@ #define EALREADY WSAEALREADY #define ETIMEDOUT WSAETIMEDOUT #define EOPNOTSUPP WSAEOPNOTSUPP -inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEALREADY || errcode == WSAEINVAL); } // WSAEINVAL should be treated as WSAEALREADY during connect for backward-compatibility with Winsock 1.1 +inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEALREADY); } inline bool isDisconnected(int errcode) { return (errcode == WSAECONNRESET || errcode == WSAECONNABORTED || errcode == WSAESHUTDOWN); } #else #define INVALID_SOCKET -1 diff --git a/Core/HLE/proAdhocServer.cpp b/Core/HLE/proAdhocServer.cpp index ca4e46089..e2cfa93c5 100644 --- a/Core/HLE/proAdhocServer.cpp +++ b/Core/HLE/proAdhocServer.cpp @@ -57,7 +57,7 @@ extern "C" struct hostent *gethostbyname(const char *name); #include "Common/Data/Text/I18n.h" #include "Common/Thread/ThreadUtil.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/File/FileUtil.h" #include "Common/TimeUtil.h" @@ -1858,7 +1858,7 @@ int create_listen_socket(uint16_t port) else { ERROR_LOG(SCENET, "AdhocServer: Bind returned %i (Socket error %d)", bindresult, errno); auto n = GetI18NCategory(I18NCat::NETWORKING); - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("AdhocServer Failed to Bind Port")) + " " + std::to_string(port)); + System_NotifyUserMessage(std::string(n->T("AdhocServer Failed to Bind Port")) + " " + std::to_string(port), 3.0, 0x0000ff); } // Close Socket diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 52fa4ebe6..bf1628113 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -657,8 +657,6 @@ const int PSP_NUM_ATRAC_IDS = 6; static bool atracInited = true; static Atrac *atracIDs[PSP_NUM_ATRAC_IDS]; static u32 atracIDTypes[PSP_NUM_ATRAC_IDS]; -static int atracLibVersion = 0; -static u32 atracLibCrc = 0; void __AtracInit() { atracInited = true; @@ -682,14 +680,8 @@ void __AtracInit() { #endif // USE_FFMPEG } -void __AtracLoadModule(int version, u32 crc) { - atracLibVersion = version; - atracLibCrc = crc; - INFO_LOG(ME, "AtracInit, atracLibVersion 0x%0x, atracLibcrc %x", atracLibVersion, atracLibCrc); -} - void __AtracDoState(PointerWrap &p) { - auto s = p.Section("sceAtrac", 1, 2); + auto s = p.Section("sceAtrac", 1); if (!s) return; @@ -705,14 +697,6 @@ void __AtracDoState(PointerWrap &p) { } } DoArray(p, atracIDTypes, PSP_NUM_ATRAC_IDS); - if (s < 2) { - atracLibVersion = 0; - atracLibCrc = 0; - } - else { - Do(p, atracLibVersion); - Do(p, atracLibCrc); - } } void __AtracShutdown() { @@ -1061,8 +1045,8 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { Atrac *atrac = getAtrac(atracID); if (!atrac) return 0; - int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset - atrac->FirstOffsetExtra()); - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset + atrac->FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData"); + int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset); + Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, bufPtr, addbytes, "AtracAddStreamData"); atrac->first_.size += bytesToAdd; if (atrac->first_.size >= atrac->first_.filesize) { atrac->first_.size = atrac->first_.filesize; @@ -1629,9 +1613,6 @@ static u32 sceAtracGetNextSample(int atracID, u32 outNAddr) { } if (numSamples > atrac->SamplesPerFrame()) numSamples = atrac->SamplesPerFrame(); - if (atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && numSamples + atrac->currentSample_ > atrac->endSample_) { - atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; - } if (Memory::IsValidAddress(outNAddr)) Memory::Write_U32(numSamples, outNAddr); DEBUG_LOG(ME, "sceAtracGetNextSample(%i, %08x): %d samples left", atracID, outNAddr, numSamples); @@ -1990,6 +1971,7 @@ static int _AtracSetData(Atrac *atrac, u32 buffer, u32 readSize, u32 bufferSize, // Already logged. return ret; } + return hleLogSuccessInfoI(ME, successCode, "%s %s audio", codecName, channelName); } @@ -2393,7 +2375,7 @@ static u32 _sceAtracGetContextAddress(int atracID) { if (!atrac->context_.IsValid()) { // allocate a new context_ u32 contextsize = 256; - atrac->context_ = kernelMemory.Alloc(contextsize, false, StringFromFormat("AtracCtx/%d", atracID).c_str()); + atrac->context_ = kernelMemory.Alloc(contextsize, false, "Atrac Context"); if (atrac->context_.IsValid()) Memory::Memset(atrac->context_.ptr, 0, 256, "AtracContextClear"); diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index f0914c1c6..1f48b48ce 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -90,5 +90,4 @@ typedef struct u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd); u32 _AtracDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains); -int _AtracGetIDByContext(u32 contextAddr); -void __AtracLoadModule(int version, u32 crc); +int _AtracGetIDByContext(u32 contextAddr); \ No newline at end of file diff --git a/Core/HLE/sceChnnlsv.cpp b/Core/HLE/sceChnnlsv.cpp index b82e44715..fc7383768 100644 --- a/Core/HLE/sceChnnlsv.cpp +++ b/Core/HLE/sceChnnlsv.cpp @@ -497,14 +497,14 @@ int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen) return res; } -static int sceSdCleanList(u32 ctxAddr) { +static int sceChnnlsv_21BE78B4(u32 ctxAddr) { auto ctx = PSPPointer::Create(ctxAddr); if (!ctx.IsValid()) return hleLogError(SCEMISC, 0, "Invalid pointer"); - return hleLogSuccessI(SCEMISC, sceSdCleanList_(*ctx)); + return hleLogSuccessI(SCEMISC, sceChnnlsv_21BE78B4_(*ctx)); } -int sceSdCleanList_(pspChnnlsvContext2& ctx) +int sceChnnlsv_21BE78B4_(pspChnnlsvContext2& ctx) { memset(ctx.cryptedData, 0, 16); ctx.unkn = 0; @@ -520,7 +520,7 @@ const HLEFunction sceChnnlsv[] = {0XC4C494F8, &WrapI_UUU, "sceSdGetLastIndex", 'i', "xxx" }, {0XABFDFC8B, &WrapI_UIIUU, "sceSdCreateList", 'i', "xiixx"}, {0X850A7FA1, &WrapI_UUI, "sceSdSetMember", 'i', "xxi" }, - {0X21BE78B4, &WrapI_U, "sceSdCleanList", 'i', "x" }, + {0X21BE78B4, &WrapI_U, "sceChnnlsv_21BE78B4", 'i', "x" }, }; void Register_sceChnnlsv() diff --git a/Core/HLE/sceChnnlsv.h b/Core/HLE/sceChnnlsv.h index 3636e14b0..14def2e78 100644 --- a/Core/HLE/sceChnnlsv.h +++ b/Core/HLE/sceChnnlsv.h @@ -38,7 +38,7 @@ int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value); int sceSdRemoveValue_(pspChnnlsvContext1& ctx, u8* data, int length); int sceSdCreateList_(pspChnnlsvContext2& ctx2, int mode, int uknw, u8* data, u8* cryptkey); int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen); -int sceSdCleanList_(pspChnnlsvContext2& ctx); +int sceChnnlsv_21BE78B4_(pspChnnlsvContext2& ctx); int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key); void Register_sceChnnlsv(); diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 9b4375023..e2d60a723 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -103,8 +103,6 @@ static u8 vibrationRightDropout = 160; // Not related to sceCtrl*RapidFire(), although it may do the same thing. static bool emuRapidFire = false; static u32 emuRapidFireFrames = 0; -static bool emuRapidFireToggle = true; -static u32 emuRapidFireInterval = 5; // These buttons are not affected by rapid fire (neither is analog.) const u32 CTRL_EMU_RAPIDFIRE_MASK = CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT; @@ -115,7 +113,7 @@ static void __CtrlUpdateLatch() u64 t = CoreTiming::GetGlobalTimeUs(); u32 buttons = ctrlCurrent.buttons; - if (emuRapidFire && emuRapidFireToggle) + if (emuRapidFire && (emuRapidFireFrames % 10) < 5) buttons &= CTRL_EMU_RAPIDFIRE_MASK; ReplayApplyCtrl(buttons, ctrlCurrent.analog, t); @@ -175,19 +173,6 @@ u32 __CtrlPeekButtons() return ctrlCurrent.buttons; } -u32 __CtrlPeekButtonsVisual() -{ - u32 buttons; - { - std::lock_guard guard(ctrlMutex); - buttons = ctrlCurrent.buttons; - } - - if (emuRapidFire && emuRapidFireToggle) - buttons &= CTRL_EMU_RAPIDFIRE_MASK; - return buttons; -} - void __CtrlPeekAnalog(int stick, float *x, float *y) { std::lock_guard guard(ctrlMutex); @@ -206,12 +191,9 @@ u32 __CtrlReadLatch() void __CtrlUpdateButtons(u32 bitsToSet, u32 bitsToClear) { - bitsToClear &= CTRL_MASK_USER; - bitsToSet &= CTRL_MASK_USER; - std::lock_guard guard(ctrlMutex); - // There's no atomic operation for this, so mutex it is. - ctrlCurrent.buttons = (ctrlCurrent.buttons & ~bitsToClear) | bitsToSet; + ctrlCurrent.buttons &= ~(bitsToClear & CTRL_MASK_USER); + ctrlCurrent.buttons |= (bitsToSet & CTRL_MASK_USER); } void __CtrlSetAnalogXY(int stick, float x, float y) @@ -224,11 +206,9 @@ void __CtrlSetAnalogXY(int stick, float x, float y) ctrlCurrent.analog[stick][CTRL_ANALOG_Y] = scaledY; } -void __CtrlSetRapidFire(bool state, int interval) +void __CtrlSetRapidFire(bool state) { emuRapidFire = state; - emuRapidFireToggle = true; - emuRapidFireInterval = interval; } bool __CtrlGetRapidFire() @@ -318,10 +298,6 @@ retry: static void __CtrlVblank() { emuRapidFireFrames++; - if (emuRapidFireFrames >= emuRapidFireInterval) { - emuRapidFireFrames = 0; - emuRapidFireToggle = !emuRapidFireToggle; - } // Reduce gamepad Vibration by set % each frame leftVibration *= (float)vibrationLeftDropout / 256.0f; diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index e633dd62d..02feaceb4 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -73,12 +73,11 @@ void __CtrlUpdateButtons(u32 bitsToSet, u32 bitsToClear); void __CtrlSetAnalogXY(int stick, float x, float y); // Call this to enable rapid-fire. This will cause buttons other than arrows to alternate. -void __CtrlSetRapidFire(bool state, int interval); +void __CtrlSetRapidFire(bool state); bool __CtrlGetRapidFire(); // For use by internal UI like MsgDialog u32 __CtrlPeekButtons(); -u32 __CtrlPeekButtonsVisual(); // also incorporates rapid-fire void __CtrlPeekAnalog(int stick, float *x, float *y); u32 __CtrlReadLatch(); diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 0a754793b..3ad5060da 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -30,7 +30,6 @@ #include "Common/Data/Text/I18n.h" #include "Common/Profiler/Profiler.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeMap.h" @@ -38,7 +37,6 @@ #include "Core/Config.h" #include "Core/CoreTiming.h" #include "Core/CoreParameter.h" -#include "Core/FrameTiming.h" #include "Core/Reporting.h" #include "Core/Core.h" #include "Core/System.h" @@ -50,7 +48,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HW/Display.h" #include "Core/Util/PPGeDraw.h" -#include "Core/RetroAchievements.h" #include "GPU/GPU.h" #include "GPU/GPUState.h" @@ -349,29 +346,15 @@ void __DisplaySetWasPaused() { wasPaused = true; } -// TOOD: Should return 59.997? static int FrameTimingLimit() { - bool challenge = Achievements::ChallengeModeActive(); - - auto fixRate = [=](int limit) { - int minRate = challenge ? 60 : 1; - if (limit != 0) { - return std::max(limit, minRate); - } else { - return limit; - } - }; - - // Note: Fast-forward is OK in hardcore mode. + if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) + return g_Config.iFpsLimit1; + if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) + return g_Config.iFpsLimit2; + if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG) + return PSP_CoreParameter().analogFpsLimit; if (PSP_CoreParameter().fastForward) return 0; - // Can't slow down in hardcore mode. - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) - return fixRate(g_Config.iFpsLimit1); - if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) - return fixRate(g_Config.iFpsLimit2); - if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG) - return fixRate(PSP_CoreParameter().analogFpsLimit); return framerate; } @@ -389,11 +372,12 @@ static void DoFrameDropLogging(float scaledTimestep) { } } -// All the throttling and frameskipping logic is here. -// This is called just before we drop out of the main loop, in order to allow the submit and present to happen. -static void DoFrameTiming(bool throttle, bool *skipFrame, float scaledTimestep) { +// Let's collect all the throttling and frameskipping logic here. +static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) { PROFILE_THIS_SCOPE("timing"); - *skipFrame = false; + int fpsLimit = FrameTimingLimit(); + throttle = FrameTimingThrottled(); + skipFrame = false; // Check if the frameskipping code should be enabled. If neither throttling or frameskipping is on, // we have nothing to do here. @@ -401,6 +385,11 @@ static void DoFrameTiming(bool throttle, bool *skipFrame, float scaledTimestep) if (!throttle && !doFrameSkip) return; + float scaledTimestep = timestep; + if (fpsLimit > 0 && fpsLimit != framerate) { + scaledTimestep *= (float)framerate / fpsLimit; + } + if (lastFrameTime == 0.0 || wasPaused) { nextFrameTime = time_now_d() + scaledTimestep; } else { @@ -422,16 +411,19 @@ static void DoFrameTiming(bool throttle, bool *skipFrame, float scaledTimestep) // autoframeskip // Argh, we are falling behind! Let's skip a frame and see if we catch up. if (curFrameTime > nextFrameTime && doFrameSkip) { - *skipFrame = true; + skipFrame = true; } } else if (frameSkipNum >= 1) { // fixed frameskip if (numSkippedFrames >= frameSkipNum) - *skipFrame = false; + skipFrame = false; else - *skipFrame = true; + skipFrame = true; } + // TODO: This is NOT where we should wait, really! We should mark each outgoing frame with the desired + // timestamp to push it to display, and sleep in the render thread to achieve that. + if (curFrameTime < nextFrameTime && throttle) { // If time gap is huge just jump (somebody fast-forwarded) if (nextFrameTime - curFrameTime > 2*scaledTimestep) { @@ -489,18 +481,16 @@ static void DoFrameIdleTiming() { #endif } - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::FRAME_GRAPH || coreCollectDebugStats) { + if (g_Config.bDrawFrameGraph || coreCollectDebugStats) { DisplayNotifySleep(time_now_d() - before); } } } + void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; - // This should be a good place to do it. Should happen once per vblank. Here or in leave? Not sure it matters much. - Achievements::FrameUpdate(); - VERBOSE_LOG(SCEDISPLAY, "Enter VBlank %i", vbCount); DisplayFireVblankStart(); @@ -543,26 +533,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { } } -static void NotifyUserIfSlow() { - // Let the user know if we're running slow, so they know to adjust settings. - // Sometimes users just think the sound emulation is broken. - static bool hasNotifiedSlow = false; - if (!g_Config.bHideSlowWarnings && - !hasNotifiedSlow && - PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL && - DisplayIsRunningSlow()) { -#ifndef _DEBUG - auto err = GetI18NCategory(I18NCat::ERRORS); - if (g_Config.bSoftwareRendering) { - g_OSD.Show(OSDType::MESSAGE_INFO, err->T("Running slow: Try turning off Software Rendering"), 5.0f); - } else { - g_OSD.Show(OSDType::MESSAGE_INFO, err->T("Running slow: try frameskip, sound is choppy when slow")); - } -#endif - hasNotifiedSlow = true; - } -} - void __DisplayFlip(int cyclesLate) { flippedThisFrame = true; // We flip only if the framebuffer was dirty. This eliminates flicker when using @@ -577,21 +547,12 @@ void __DisplayFlip(int cyclesLate) { bool fastForwardSkipFlip = g_Config.iFastForwardMode != (int)FastForwardMode::CONTINUOUS; - if (gpu) { - Draw::DrawContext *draw = gpu->GetDrawContext(); + bool fifo = gpu && gpu->GetDrawContext() && gpu->GetDrawContext()->GetPresentationMode() == Draw::PresentationMode::FIFO; - if (draw) { - g_frameTiming.presentMode = ComputePresentMode(draw, &g_frameTiming.presentInterval); - if (!draw->GetDeviceCaps().presentInstantModeChange && g_frameTiming.presentMode == Draw::PresentMode::FIFO) { - // Some backends can't just flip into MAILBOX/IMMEDIATE mode instantly. - // Vulkan doesn't support the interval setting, so we force skipping the flip. - // TODO: We'll clean this up in a more backend-independent way later. - fastForwardSkipFlip = true; - } - } else { - g_frameTiming.presentMode = Draw::PresentMode::FIFO; - g_frameTiming.presentInterval = 1; - } + if (fifo && GetGPUBackend() == GPUBackend::VULKAN) { + // Vulkan doesn't support the interval setting, so we force skipping the flip. + // TODO: We'll clean this up in a more backend-independent way later. + fastForwardSkipFlip = true; } if (!g_Config.bSkipBufferEffects) { @@ -600,92 +561,96 @@ void __DisplayFlip(int cyclesLate) { const bool fbDirty = gpu->FramebufferDirty(); - bool needFlip = fbDirty || noRecentFlip || postEffectRequiresFlip; - if (!needFlip) { - // Okay, there's no new frame to draw, game might be sitting in a static loading screen - // or similar, and not long enough to trigger noRecentFlip. But audio may be playing, so we need to time still. - DoFrameIdleTiming(); - return; - } + if (fbDirty || noRecentFlip || postEffectRequiresFlip) { + int frameSleepPos = DisplayGetSleepPos(); + double frameSleepStart = time_now_d(); + DisplayFireFlip(); - // Debugger integration - int frameSleepPos = DisplayGetSleepPos(); - double frameSleepStart = time_now_d(); - DisplayFireFlip(); - - NotifyUserIfSlow(); - - bool forceNoFlip = false; - float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); - // Avoid skipping on devices that have 58 or 59 FPS, except when alternate speed is set. - bool refreshRateNeedsSkip = FrameTimingLimit() != framerate && FrameTimingLimit() > refreshRate; - // Alternative to frameskip fast-forward, where we draw everything. - // Useful if skipping a frame breaks graphics or for checking drawing speed. - if (fastForwardSkipFlip && (!FrameTimingThrottled() || refreshRateNeedsSkip)) { - static double lastFlip = 0; - double now = time_now_d(); - if ((now - lastFlip) < 1.0f / refreshRate) { - forceNoFlip = true; - } else { - lastFlip = now; + // Let the user know if we're running slow, so they know to adjust settings. + // Sometimes users just think the sound emulation is broken. + static bool hasNotifiedSlow = false; + if (!g_Config.bHideSlowWarnings && + !hasNotifiedSlow && + PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL && + DisplayIsRunningSlow()) { +#ifndef _DEBUG + auto err = GetI18NCategory(I18NCat::ERRORS); + if (g_Config.bSoftwareRendering) { + System_NotifyUserMessage(err->T("Running slow: Try turning off Software Rendering"), 6.0f, 0xFF30D0D0); + } else { + System_NotifyUserMessage(err->T("Running slow: try frameskip, sound is choppy when slow"), 6.0f, 0xFF30D0D0); + } +#endif + hasNotifiedSlow = true; } - } - // Setting CORE_NEXTFRAME (which Core_NextFrame does) causes a swap. - const bool fbReallyDirty = gpu->FramebufferReallyDirty(); - if (fbReallyDirty || noRecentFlip || postEffectRequiresFlip) { - // Check first though, might've just quit / been paused. - if (!forceNoFlip && Core_NextFrame()) { - gpu->CopyDisplayToOutput(fbReallyDirty); - if (fbReallyDirty) { - DisplayFireActualFlip(); + bool forceNoFlip = false; + float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); + // Avoid skipping on devices that have 58 or 59 FPS, except when alternate speed is set. + bool refreshRateNeedsSkip = FrameTimingLimit() != framerate && FrameTimingLimit() > refreshRate; + // Alternative to frameskip fast-forward, where we draw everything. + // Useful if skipping a frame breaks graphics or for checking drawing speed. + if (fastForwardSkipFlip && (!FrameTimingThrottled() || refreshRateNeedsSkip)) { + static double lastFlip = 0; + double now = time_now_d(); + if ((now - lastFlip) < 1.0f / refreshRate) { + forceNoFlip = true; + } else { + lastFlip = now; } } - } - if (fbDirty) { - gpuStats.numFlips++; - } + // Setting CORE_NEXTFRAME causes a swap. + const bool fbReallyDirty = gpu->FramebufferReallyDirty(); + if (fbReallyDirty || noRecentFlip || postEffectRequiresFlip) { + // Check first though, might've just quit / been paused. + if (!forceNoFlip && Core_NextFrame()) { + gpu->CopyDisplayToOutput(fbReallyDirty); + if (fbReallyDirty) { + DisplayFireActualFlip(); + } + } + } - bool throttle = FrameTimingThrottled(); + if (fbDirty) { + gpuStats.numFlips++; + } - int fpsLimit = FrameTimingLimit(); - float scaledTimestep = (float)numVBlanksSinceFlip * timePerVblank; - if (fpsLimit > 0 && fpsLimit != framerate) { - scaledTimestep *= (float)framerate / fpsLimit; - } - bool skipFrame; - DoFrameTiming(throttle, &skipFrame, scaledTimestep); + bool throttle, skipFrame; + DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * timePerVblank); - int maxFrameskip = 8; - int frameSkipNum = DisplayCalculateFrameSkip(); - if (throttle) { - // 4 here means 1 drawn, 4 skipped - so 12 fps minimum. - maxFrameskip = frameSkipNum; - } - if (numSkippedFrames >= maxFrameskip || GPURecord::IsActivePending()) { - skipFrame = false; - } + int maxFrameskip = 8; + int frameSkipNum = DisplayCalculateFrameSkip(); + if (throttle) { + // 4 here means 1 drawn, 4 skipped - so 12 fps minimum. + maxFrameskip = frameSkipNum; + } + if (numSkippedFrames >= maxFrameskip || GPURecord::IsActivePending()) { + skipFrame = false; + } - if (skipFrame) { - // Tell the emulated GPU to skip the next frame. - gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME; - numSkippedFrames++; + if (skipFrame) { + gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME; + numSkippedFrames++; + } else { + gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME; + numSkippedFrames = 0; + } + + // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). + // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great + // place to do housekeeping. + + CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); + numVBlanksSinceFlip = 0; + + if (g_Config.bDrawFrameGraph || coreCollectDebugStats) { + // Track how long we sleep (whether vsync or sleep_ms.) + DisplayNotifySleep(time_now_d() - frameSleepStart, frameSleepPos); + } } else { - gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME; - numSkippedFrames = 0; - } - - // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). - // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great - // place to do housekeeping. - - CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); - numVBlanksSinceFlip = 0; - - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::FRAME_GRAPH || coreCollectDebugStats) { - // Track how long we sleep (whether vsync or sleep_ms.) - DisplayNotifySleep(time_now_d() - frameSleepStart, frameSleepPos); + // Okay, there's no new frame to draw. But audio may be playing, so we need to time still. + DoFrameIdleTiming(); } } @@ -735,8 +700,6 @@ void hleLagSync(u64 userdata, int cyclesLate) { #ifndef _WIN32 const double left = goal - now; usleep((long)(left * 1000000.0)); -#else - yield(); #endif now = time_now_d(); } @@ -745,7 +708,7 @@ void hleLagSync(u64 userdata, int cyclesLate) { const int over = (int)((now - goal) * 1000000); ScheduleLagSync(over - emuOver); - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::FRAME_GRAPH || coreCollectDebugStats) { + if (g_Config.bDrawFrameGraph || coreCollectDebugStats) { DisplayNotifySleep(now - before); } } diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 8feb1fc89..f7bcf0d0f 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -51,11 +51,12 @@ static int __DmacMemcpy(u32 dst, u32 src, u32 size) { } if (!skip && size != 0) { currentMIPS->InvalidateICache(src, size); - if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) { - memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); - } if (MemBlockInfoDetailed(size)) { - NotifyMemInfoCopy(dst, src, size, "DmacMemcpy/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "DmacMemcpy/", src, size); + Memory::Memcpy(dst, src, size, tagData, tagSize); + } else { + Memory::Memcpy(dst, src, size, "DmacMemcpy"); } currentMIPS->InvalidateICache(dst, size); } diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index ffd89f69f..48e612f9f 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -1176,19 +1176,6 @@ static int sceFontFindOptimumFont(u32 libHandle, u32 fontStylePtr, u32 errorCode Font *optimumFont = 0; Font *nearestFont = 0; float nearestDist = std::numeric_limits::infinity(); - - if (PSP_CoreParameter().compat.flags().Fontltn12Hack && requestedStyle->fontLanguage == 2) { - for (size_t j = 0; j < internalFonts.size(); j++) { - const auto tempmatchStyle = internalFonts[j]->GetFontStyle(); - const std::string str(tempmatchStyle.fontFileName); - if (str == "ltn12.pgf") { - optimumFont = internalFonts[j]; - *errorCode = 0; - return GetInternalFontIndex(optimumFont); - } - } - } - for (size_t i = 0; i < internalFonts.size(); i++) { MatchQuality q = internalFonts[i]->MatchesStyle(*requestedStyle); if (q != MATCH_NONE) { diff --git a/Core/HLE/sceHeap.cpp b/Core/HLE/sceHeap.cpp index 28cc63ee4..e51f6b1d8 100644 --- a/Core/HLE/sceHeap.cpp +++ b/Core/HLE/sceHeap.cpp @@ -19,7 +19,6 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeMap.h" -#include "Common/StringUtils.h" #include "Core/MemMap.h" #include "Core/Reporting.h" #include "Core/HLE/HLE.h" @@ -194,7 +193,7 @@ static int sceHeapCreateHeap(const char* name, u32 heapSize, int attr, u32 param Heap *heap = new Heap; heap->size = allocSize; heap->fromtop = (attr & PSP_HEAP_ATTR_HIGHMEM) != 0; - u32 addr = userMemory.Alloc(heap->size, heap->fromtop, StringFromFormat("Heap/%s", name).c_str()); + u32 addr = userMemory.Alloc(heap->size, heap->fromtop, "Heap"); if (addr == (u32)-1) { ERROR_LOG(HLE, "sceHeapCreateHeap(): Failed to allocate %i bytes memory", allocSize); delete heap; diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index 5cb102a8d..c5ab64a24 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -40,7 +40,7 @@ static u32 backlightOffTime; void __ImposeInit() { - language = g_Config.GetPSPLanguage(); + language = g_Config.iLanguage; if (PSP_CoreParameter().compat.flags().EnglishOrJapaneseOnly) { if (language != PSP_SYSTEMPARAM_LANGUAGE_ENGLISH && language != PSP_SYSTEMPARAM_LANGUAGE_JAPANESE) { language = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; @@ -76,7 +76,7 @@ static u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr) static u32 sceImposeSetLanguageMode(u32 languageVal, u32 buttonVal) { language = languageVal; buttonValue = buttonVal; - if (language != g_Config.GetPSPLanguage()) { + if (language != g_Config.iLanguage) { return hleLogWarning(SCEUTILITY, 0, "ignoring requested language"); } return hleLogSuccessI(SCEUTILITY, 0); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 3935de704..d1d83ba45 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -1037,14 +1037,7 @@ static u32 npdrmRead(FileNode *f, u8 *data, int size) { static bool __IoRead(int &result, int id, u32 data_addr, int size, int &us) { PROFILE_THIS_SCOPE("io_rw"); // Low estimate, may be improved later from the ReadFile result. - - if (PSP_CoreParameter().compat.flags().ForceUMDReadSpeed || g_Config.iIOTimingMethod == IOTIMING_UMDSLOWREALISTIC) { - us = size / 4.2; - } - else { - us = size / 100; - } - + us = size / 100; if (us < 100) { us = 100; } @@ -1186,7 +1179,7 @@ static bool __IoWrite(int &result, int id, u32 data_addr, int size, int &us) { if (id == PSP_STDOUT || id == PSP_STDERR) { const char *str = (const char *) data_ptr; const int str_size = size <= 0 ? 0 : (str[validSize - 1] == '\n' ? validSize - 1 : validSize); - INFO_LOG(PRINTF, "%s: %.*s", id == 1 ? "stdout" : "stderr", str_size, str); + INFO_LOG(SCEIO, "%s: %.*s", id == 1 ? "stdout" : "stderr", str_size, str); result = validSize; return true; } @@ -1212,7 +1205,7 @@ static bool __IoWrite(int &result, int id, u32 data_addr, int size, int &us) { if (f->isTTY) { const char *str = (const char *)data_ptr; const int str_size = size <= 0 ? 0 : (str[validSize - 1] == '\n' ? validSize - 1 : validSize); - INFO_LOG(PRINTF, "%s: %.*s", "tty", str_size, str); + INFO_LOG(SCEIO, "%s: %.*s", "tty", str_size, str); result = validSize; return true; } @@ -1493,12 +1486,6 @@ static u32 sceIoLseek32Async(int id, int offset, int whence) { } static FileNode *__IoOpen(int &error, const char *filename, int flags, int mode) { - if (!filename) { - // To prevent crashes. Not sure about the correct value. - error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; - return nullptr; - } - int access = FILEACCESS_NONE; if (flags & PSP_O_RDONLY) access |= FILEACCESS_READ; @@ -2546,7 +2533,7 @@ static u32 sceIoDclose(int id) { return kernelObjects.Destroy(id); } -int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) { +static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) { u32 error; FileNode *f = __IoGetFd(id, error); if (error) { @@ -2559,7 +2546,7 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out } // TODO: Move this into each command, probably? - usec += 100; + usec = 100; //KD Hearts: //56:46:434 HLE\sceIo.cpp:886 E[HLE]: UNIMPL 0=sceIoIoctrl id: 0000011f, cmd 04100001, indataPtr 08b313d8, inlen 00000010, outdataPtr 00000000, outLen 0 @@ -2587,28 +2574,25 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out pspFileSystem.SeekFile(f->handle, (s32)f->pgd_offset, FILEMOVE_BEGIN); pspFileSystem.ReadFile(f->handle, pgd_header, 0x90); f->pgdInfo = pgd_open(pgd_header, 2, key_ptr); - if (!f->pgdInfo) { - ERROR_LOG(SCEIO, "Not a valid PGD file. Examining."); + if(f->pgdInfo==NULL){ + ERROR_LOG(SCEIO, "Not a valid PGD file. Open as normal file."); f->npdrm = false; pspFileSystem.SeekFile(f->handle, (s32)0, FILEMOVE_BEGIN); - if (memcmp(pgd_header, pgd_magic, 4) == 0) { - ERROR_LOG(SCEIO, "File is PGD file, but there's likely a key mismatch. Returning error."); + if(memcmp(pgd_header, pgd_magic, 4)==0){ // File is PGD file, but key mismatch return ERROR_PGD_INVALID_HEADER; - } else { - WARN_LOG(SCEIO, "File is not encrypted, proceeding."); + }else{ // File is decrypted. return 0; } - } else { - // Everything OK. + }else{ + // Everthing OK. f->npdrm = true; f->pgdInfo->data_offset += f->pgd_offset; return 0; } break; } - // Set PGD offset. Called from sceNpDrmEdataSetupKey case 0x04100002: f->pgd_offset = indataPtr; @@ -2755,7 +2739,7 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out // Even if the size is 4, it still actually reads a 16 byte struct, it seems. //if (GetIOTimingMethod() == IOTIMING_REALISTIC) // Need a check for io timing method? - usec += 15000;// Fantasy Golf Pangya Portable(KS) needs a delay over 15000us. + usec = 15000;// Fantasy Golf Pangya Portable(KS) needs a delay over 15000us. if (Memory::IsValidAddress(indataPtr) && inlen >= 4) { struct SeekInfo { @@ -2944,7 +2928,7 @@ static int IoAsyncFinish(int id) { break; case IoAsyncOp::IOCTL: - us = 0; // __IoIoctl will add 100. + us = 100; f->asyncResult = __IoIoctl(id, params.ioctl.cmd, params.ioctl.inAddr, params.ioctl.inSize, params.ioctl.outAddr, params.ioctl.outSize, us); DEBUG_LOG(SCEIO, "ASYNC sceIoIoctlAsync(%08x, %08x, %08x, %08x, %08x, %08x)", id, params.ioctl.cmd, params.ioctl.inAddr, params.ioctl.inSize, params.ioctl.outAddr, params.ioctl.outSize); break; @@ -3051,7 +3035,7 @@ const HLEFunction IoFileMgrForKernel[] = { {0x3251EA56, &WrapU_IU, "sceIoPollAsync", 'i', "iP", HLE_KERNEL_SYSCALL }, {0xE23EEC33, &WrapI_IU, "sceIoWaitAsync", 'i', "iP", HLE_KERNEL_SYSCALL }, {0x35DBD746, &WrapI_IU, "sceIoWaitAsyncCB", 'i', "iP", HLE_KERNEL_SYSCALL }, - {0xBD17474F, nullptr, "sceIoGetIobUserLevel", '?', "" }, + {0xBD17474F, nullptr, "IoFileMgrForKernel_BD17474F", '?', "" }, {0x76DA16E3, nullptr, "IoFileMgrForKernel_76DA16E3", '?', "" }, }; diff --git a/Core/HLE/sceIo.h b/Core/HLE/sceIo.h index d6a4d6a82..3169efe90 100644 --- a/Core/HLE/sceIo.h +++ b/Core/HLE/sceIo.h @@ -29,11 +29,6 @@ struct tm; u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen); -// Called by sceIoIoctl, which normally applies the delay this function writes to usec. -// If you need to call sceIoIoctl from a HLE function implementation more than once, use -// __IoIoctl directly to avoid double-delays. -int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec); - u32 __IoGetFileHandleFromId(u32 id, u32 &outError); void __IoCopyDate(ScePspDateTime& date_out, const tm& date_in); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 40fc161a0..f83efc63c 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -85,7 +85,8 @@ #include "sceDmac.h" #include "sceMp4.h" #include "sceOpenPSID.h" -#include "Core/Util/PPGeDraw.h" + +#include "../Util/PPGeDraw.h" /* 17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816 @@ -523,9 +524,9 @@ void KernelObjectPool::List() { char buffer[256]; if (pool[i]) { pool[i]->GetQuickInfo(buffer, sizeof(buffer)); - DEBUG_LOG(SCEKERNEL, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer); + INFO_LOG(SCEKERNEL, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer); } else { - ERROR_LOG(SCEKERNEL, "KO %i: bad object", i + handleOffset); + strcpy(buffer, "WTF? Zero Pointer"); } } } @@ -654,7 +655,6 @@ static int sceKernelReferSystemStatus(u32 statusPtr) { return 0; } -// Unused - believed to be the returned struct from sceKernelReferThreadProfiler. struct DebugProfilerRegs { u32 enable; u32 systemck; @@ -678,19 +678,23 @@ struct DebugProfilerRegs { u32 local_bus; }; -static u32 sceKernelReferThreadProfiler() { - // This seems to simply has no parameter: - // https://pspdev.github.io/pspsdk/group__ThreadMan.html#ga8fd30da51b9dc0507ac4dae04a7e4a17 - // In testing it just returns null in around 140-150 cycles. See issue #17623. - DEBUG_LOG(SCEKERNEL, "0=sceKernelReferThreadProfiler()"); - hleEatCycles(140); +static u32 sceKernelReferThreadProfiler(u32 statusPtr) { + ERROR_LOG(SCEKERNEL, "FAKE sceKernelReferThreadProfiler()"); + + // Can we confirm that the struct above is the right struct? + // If so, re-enable this code. + //auto regs = PSPPointer::Create(statusPtr); + // TODO: fill the struct. + //if (regs.IsValid()) { + // memset((DebugProfilerRegs *)regs, 0, sizeof(DebugProfilerRegs)); + // regs.NotifyWrite("ThreadProfiler"); + //} return 0; } -static int sceKernelReferGlobalProfiler() { - DEBUG_LOG(SCEKERNEL, "0=sceKernelReferGlobalProfiler()"); - // See sceKernelReferThreadProfiler(), similar. - hleEatCycles(140); +static int sceKernelReferGlobalProfiler(u32 statusPtr) { + ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelReferGlobalProfiler(%08x)", statusPtr); + // Ignore for now return 0; } @@ -776,9 +780,9 @@ const HLEFunction ThreadManForUser[] = {0XDB738F35, &WrapI_U, "sceKernelGetSystemTime", 'i', "x" }, {0X369ED59D, &WrapU_V, "sceKernelGetSystemTimeLow", 'x', "" }, - {0X8218B4DD, &WrapI_V, "sceKernelReferGlobalProfiler", 'i', "" }, + {0X8218B4DD, &WrapI_U, "sceKernelReferGlobalProfiler", 'i', "x" }, {0X627E6F3A, &WrapI_U, "sceKernelReferSystemStatus", 'i', "x" }, - {0X64D4540E, &WrapU_V, "sceKernelReferThreadProfiler", 'x', "" }, + {0X64D4540E, &WrapU_U, "sceKernelReferThreadProfiler", 'x', "x" }, //Fifa Street 2 uses alarms {0X6652B8CA, &WrapI_UUU, "sceKernelSetAlarm", 'i', "xxx" }, diff --git a/Core/HLE/sceKernelHeap.cpp b/Core/HLE/sceKernelHeap.cpp index 1663c81ee..b90bfdc03 100644 --- a/Core/HLE/sceKernelHeap.cpp +++ b/Core/HLE/sceKernelHeap.cpp @@ -2,13 +2,11 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" -#include "Common/StringUtils.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceKernel.h" #include "Core/HLE/sceKernelHeap.h" #include "Core/HLE/sceKernelMemory.h" -#include "Core/Reporting.h" #include "Core/Util/BlockAllocator.h" static const u32 KERNEL_HEAP_BLOCK_HEADER_SIZE = 8; @@ -53,7 +51,7 @@ static int sceKernelCreateHeap(int partitionId, int size, int flags, const char return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "invalid partition"); // TODO: This should probably actually use flags? Name? - u32 addr = allocator->Alloc(allocSize, g_fromBottom, StringFromFormat("KernelHeap/%s", Name).c_str()); + u32 addr = allocator->Alloc(allocSize, g_fromBottom, "SysMemForKernel-Heap"); if (addr == (u32)-1) { // TODO: Validate error code. return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_NO_MEMORY, "fFailed to allocate %d bytes of memory", size); @@ -114,9 +112,9 @@ static u32 sceKernelPartitionMaxFreeMemSize(int partitionId) { return hleLogWarning(SCEKERNEL, allocator->GetLargestFreeBlockSize()); } -static u32 sceKernelGetUidmanCB() +static u32 SysMemForKernel_536AD5E1() { - ERROR_LOG_REPORT(SCEKERNEL, "UNIMP sceKernelGetUidmanCB"); + ERROR_LOG(SCEKERNEL, "UNIMP SysMemForKernel_536AD5E1"); return 0; } @@ -167,9 +165,9 @@ const HLEFunction SysMemForKernel[] = { { 0x9697CD32, &WrapU_I, "sceKernelPartitionTotalFreeMemSize", 'x', "i" , HLE_KERNEL_SYSCALL }, { 0xE6581468, &WrapU_I, "sceKernelPartitionMaxFreeMemSize", 'x', "i" , HLE_KERNEL_SYSCALL }, { 0X3FC9AE6A, &WrapU_V, "sceKernelDevkitVersion", 'x', "" , HLE_KERNEL_SYSCALL }, - { 0X536AD5E1, &WrapU_V, "sceKernelGetUidmanCB", 'i', "i" , HLE_KERNEL_SYSCALL }, + { 0X536AD5E1, &WrapU_V, "SysMemForKernel_536AD5E1", 'i', "i" , HLE_KERNEL_SYSCALL }, { 0X7B749390, &WrapI_IU, "sceKernelFreeHeapMemory", 'i', "ix" , HLE_KERNEL_SYSCALL }, - { 0XEB7A74DB, &WrapI_IUU, "sceKernelAllocHeapMemoryWithOption", 'i', "ixp" , HLE_KERNEL_SYSCALL }, + { 0XEB7A74DB , &WrapI_IUU, "sceKernelAllocHeapMemoryWithOption", 'i', "ixp" , HLE_KERNEL_SYSCALL }, }; void Register_SysMemForKernel() { diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 76e1788e3..ec4b452a6 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -657,7 +657,10 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) } if (MemBlockInfoDetailed(size)) { - NotifyMemInfoCopy(dst, src, size, "KernelMemcpy/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "KernelMemcpy/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tagData, tagSize); } return dst; @@ -690,7 +693,10 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) { memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); } if (MemBlockInfoDetailed(size)) { - NotifyMemInfoCopy(dst, src, size, "KernelMemcpy/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "KernelMemcpy/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tagData, tagSize); } return dst; } @@ -791,7 +797,10 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) { memmove(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); } if (MemBlockInfoDetailed(size)) { - NotifyMemInfoCopy(dst, src, size, "KernelMemmove/"); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "KernelMemmove/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tagData, tagSize); } return 0; } diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 72b1a3faa..d2ca49384 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -678,7 +678,7 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 int alignedSize = ((int)blockSize + alignment - 1) & ~(alignment - 1); u32 totalSize = alignedSize * numBlocks; bool atEnd = (attr & PSP_FPL_ATTR_HIGHMEM) != 0; - u32 address = allocator->Alloc(totalSize, atEnd, StringFromFormat("FPL/%s", name).c_str()); + u32 address = allocator->Alloc(totalSize, atEnd, "FPL"); if (address == (u32)-1) { DEBUG_LOG(SCEKERNEL, "sceKernelCreateFpl(\"%s\", partition=%i, attr=%08x, bsize=%i, nb=%i) FAILED - out of ram", name, mpid, attr, blockSize, numBlocks); @@ -1211,9 +1211,9 @@ static int sceKernelPrintf(const char *formatString) result.resize(result.size() - 1); if (supported) - INFO_LOG(PRINTF, "sceKernelPrintf: %s", result.c_str()); + INFO_LOG(SCEKERNEL, "sceKernelPrintf: %s", result.c_str()); else - ERROR_LOG(PRINTF, "UNIMPL sceKernelPrintf(%s, %08x, %08x, %08x)", format.c_str(), PARAM(1), PARAM(2), PARAM(3)); + ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelPrintf(%s, %08x, %08x, %08x)", format.c_str(), PARAM(1), PARAM(2), PARAM(3)); return 0; } @@ -1521,7 +1521,7 @@ SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize // We ignore the upalign to 256 and do it ourselves by 8. u32 allocSize = vplSize; - u32 memBlockPtr = allocator->Alloc(allocSize, (attr & PSP_VPL_ATTR_HIGHMEM) != 0, StringFromFormat("VPL/%s", name).c_str()); + u32 memBlockPtr = allocator->Alloc(allocSize, (attr & PSP_VPL_ATTR_HIGHMEM) != 0, "VPL"); if (memBlockPtr == (u32)-1) return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_NO_MEMORY, "failed to allocate %i bytes of pool data", vplSize); @@ -2124,7 +2124,7 @@ SceUID sceKernelCreateTlspl(const char *name, u32 partition, u32 attr, u32 block u32 alignedSize = (blockSize + alignment - 1) & ~(alignment - 1); u32 totalSize = alignedSize * count; - u32 blockPtr = allocator->Alloc(totalSize, (attr & PSP_TLSPL_ATTR_HIGHMEM) != 0, StringFromFormat("TLS/%s", name).c_str()); + u32 blockPtr = allocator->Alloc(totalSize, (attr & PSP_TLSPL_ATTR_HIGHMEM) != 0, name); #ifdef _DEBUG allocator->ListBlocks(); #endif diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index cbb81ed09..37773c66c 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -61,7 +61,6 @@ #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceMpeg.h" #include "Core/HLE/scePsmf.h" -#include "Core/HLE/sceAtrac.h" #include "Core/HLE/sceIo.h" #include "Core/HLE/KernelWaitHelpers.h" #include "Core/ELF/ParamSFO.h" @@ -1186,13 +1185,9 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load if (!strcmp(head->modname, "sceMpeg_library")) { __MpegLoadModule(ver, module->crc); } - if (!strcmp(head->modname, "scePsmfP_library") || !strcmp(head->modname, "scePsmfPlayer") || !strcmp(head->modname, "libpsmfplayer") || !strcmp(head->modname, "psmf_jk") || !strcmp(head->modname, "jkPsmfP_library")) { - __PsmfPlayerLoadModule(devkitVersion, module->crc); + if (!strcmp(head->modname, "scePsmfP_library") || !strcmp(head->modname, "scePsmfPlayer")) { + __PsmfPlayerLoadModule(head->devkitversion, module->crc); } - if (!strcmp(head->modname, "sceATRAC3plus_Library")) { - __AtracLoadModule(ver, module->crc); - } - } const u8 *in = ptr; @@ -1636,13 +1631,9 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load if (!strcmp(modinfo->name, "sceMpeg_library")) { __MpegLoadModule(modinfo->moduleVersion, module->crc); } - if (!strcmp(modinfo->name, "scePsmfP_library") || !strcmp(modinfo->name, "scePsmfPlayer") || !strcmp(modinfo->name, "libpsmfplayer") || !strcmp(modinfo->name, "psmf_jk") || !strcmp(modinfo->name, "jkPsmfP_library")){ + if (!strcmp(modinfo->name, "scePsmfP_library") || !strcmp(modinfo->name, "scePsmfPlayer")) { __PsmfPlayerLoadModule(devkitVersion, module->crc); } - if (!strcmp(modinfo->name, "sceATRAC3plus_Library")) { - __AtracLoadModule(modinfo->moduleVersion, module->crc); - } - } System_Notify(SystemNotification::SYMBOL_MAP_UPDATED); @@ -2717,8 +2708,8 @@ const HLEFunction ModuleMgrForKernel[] = {0x50F0C1EC, &WrapV_UUUUU, "sceKernelStartModule", 'v', "xxxxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL }, {0x977DE386, &WrapU_CUU, "sceKernelLoadModule", 'x', "sxx", HLE_KERNEL_SYSCALL }, {0xA1A78C58, &WrapU_CUU, "sceKernelLoadModuleForLoadExecVSHDisc", 'x', "sxx", HLE_KERNEL_SYSCALL }, //fix for tiger x dragon - {0xCC1D3699, &WrapU_UUU, "sceKernelStopUnloadSelfModule", 'x', "xxx", HLE_KERNEL_SYSCALL }, // used in Dissidia final fantasy chinese patch - {0XD1FF982A, &WrapU_UUUUU, "sceKernelStopModule", 'x', "xxxxx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, // used in Dissidia final fantasy chinese patch + {0xCC1D3699, &WrapU_UUU, "sceKernelSelfStopUnloadModule", 'x', "xxx", HLE_KERNEL_SYSCALL }, // used in Dissidia final fantasy chinese patch + {0XD1FF982A, &WrapU_UUUUU, "sceKernelStopModule", 'x', "xxxxx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, // used in Dissidia final fantasy chinese patch {0x748CBED9, &WrapU_UU, "sceKernelQueryModuleInfo", 'x', "xx", HLE_KERNEL_SYSCALL }, {0x644395E2, &WrapU_UUU, "sceKernelGetModuleIdList", 'x', "xxx", HLE_KERNEL_SYSCALL }, {0X2E0911AA, &WrapU_U, "sceKernelUnloadModule", 'x', "x" , HLE_KERNEL_SYSCALL }, diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 5b44e57bb..0ff34c629 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -687,7 +687,7 @@ int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, if (size != 0) { // We ignore the upalign to 256. u32 allocSize = size; - memBlockPtr = allocator->Alloc(allocSize, (attr & SCE_KERNEL_MPA_HIGHMEM) != 0, StringFromFormat("MsgPipe/%s", name).c_str()); + memBlockPtr = allocator->Alloc(allocSize, (attr & SCE_KERNEL_MPA_HIGHMEM) != 0, "MsgPipe"); if (memBlockPtr == (u32)-1) return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_NO_MEMORY, "failed to allocate %i bytes for buffer", size); } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 40a575da7..995ead966 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -401,7 +401,15 @@ public: FreeStack(); bool fromTop = (nt.attr & PSP_THREAD_ATTR_LOW_STACK) == 0; - currentStack.start = StackAllocator().Alloc(stackSize, fromTop, StringFromFormat("stack/%s", nt.name).c_str()); + if (nt.attr & PSP_THREAD_ATTR_KERNEL) + { + // Allocate stacks for kernel threads (idle) in kernel RAM + currentStack.start = kernelMemory.Alloc(stackSize, fromTop, (std::string("stack/") + nt.name).c_str()); + } + else + { + currentStack.start = userMemory.Alloc(stackSize, fromTop, (std::string("stack/") + nt.name).c_str()); + } if (currentStack.start == (u32)-1) { currentStack.start = 0; @@ -445,14 +453,18 @@ public: Memory::Memset(nt.initialStack, 0, nt.stackSize, "ThreadFreeStack"); } - StackAllocator().Free(currentStack.start); + if (nt.attr & PSP_THREAD_ATTR_KERNEL) { + kernelMemory.Free(currentStack.start); + } else { + userMemory.Free(currentStack.start); + } currentStack.start = 0; } } bool PushExtendedStack(u32 size) { - u32 stack = userMemory.Alloc(size, true, StringFromFormat("extended/%s", nt.name).c_str()); + u32 stack = userMemory.Alloc(size, true, (std::string("extended/") + nt.name).c_str()); if (stack == (u32)-1) return false; @@ -497,13 +509,6 @@ public: FreeStack(); } - BlockAllocator &StackAllocator() { - if (nt.attr & PSP_THREAD_ATTR_KERNEL) { - return kernelMemory; - } - return userMemory; - } - void setReturnValue(u32 retval); void setReturnValue(u64 retval); void resumeFromWait(); diff --git a/Core/HLE/sceMd5.cpp b/Core/HLE/sceMd5.cpp index 532428bfe..cd71adcd8 100644 --- a/Core/HLE/sceMd5.cpp +++ b/Core/HLE/sceMd5.cpp @@ -15,14 +15,13 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "Common/Crypto/md5.h" -#include "Common/Crypto/sha1.h" -#include "Common/Data/Random/Rng.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceMd5.h" #include "Core/MemMap.h" #include "Core/Reporting.h" +#include "Common/Crypto/md5.h" +#include "Common/Crypto/sha1.h" #ifdef USE_CRT_DBG #undef new @@ -58,7 +57,7 @@ static int sceMd5Digest(u32 dataAddr, u32 len, u32 digestAddr) { if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr)) return -1; - ppsspp_md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr)); + md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr)); return 0; } @@ -70,7 +69,7 @@ static int sceMd5BlockInit(u32 ctxAddr) { // TODO: Until I know how large a context is, we just go all lazy and use a global context, // which will work just fine unless games do several MD5 concurrently. - ppsspp_md5_starts(&md5_ctx); + md5_starts(&md5_ctx); return 0; } @@ -79,7 +78,7 @@ static int sceMd5BlockUpdate(u32 ctxAddr, u32 dataPtr, u32 len) { if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataPtr)) return -1; - ppsspp_md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len); + md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len); return 0; } @@ -88,7 +87,7 @@ static int sceMd5BlockResult(u32 ctxAddr, u32 digestAddr) { if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr)) return -1; - ppsspp_md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr)); + md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr)); return 0; } @@ -98,7 +97,7 @@ int sceKernelUtilsMd5Digest(u32 dataAddr, int len, u32 digestAddr) { if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr)) return -1; - ppsspp_md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr)); + md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr)); return 0; } @@ -110,7 +109,7 @@ int sceKernelUtilsMd5BlockInit(u32 ctxAddr) { // TODO: Until I know how large a context is, we just go all lazy and use a global context, // which will work just fine unless games do several MD5 concurrently. - ppsspp_md5_starts(&md5_ctx); + md5_starts(&md5_ctx); return 0; } @@ -119,7 +118,7 @@ int sceKernelUtilsMd5BlockUpdate(u32 ctxAddr, u32 dataPtr, int len) { if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataPtr)) return -1; - ppsspp_md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len); + md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len); return 0; } @@ -128,7 +127,7 @@ int sceKernelUtilsMd5BlockResult(u32 ctxAddr, u32 digestAddr) { if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr)) return -1; - ppsspp_md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr)); + md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr)); return 0; } diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 8e4586a6d..cecc9e4d1 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -636,7 +636,7 @@ static int sceMpegQueryStreamOffset(u32 mpeg, u32 bufferAddr, u32 offsetAddr) DEBUG_LOG(ME, "sceMpegQueryStreamOffset(%08x, %08x, %08x)", mpeg, bufferAddr, offsetAddr); - // Kinda destructive, no? Shouldn't this just do what sceMpegQueryStreamSize does? + // Kinda destructive, no? AnalyzeMpeg(Memory::GetPointerWriteUnchecked(bufferAddr), Memory::ValidSize(bufferAddr, 32768), ctx); if (ctx->mpegMagic != PSMF_MAGIC) { @@ -667,8 +667,7 @@ static u32 sceMpegQueryStreamSize(u32 bufferAddr, u32 sizeAddr) DEBUG_LOG(ME, "sceMpegQueryStreamSize(%08x, %08x)", bufferAddr, sizeAddr); MpegContext ctx; - ctx.mediaengine = nullptr; // makes sure we don't actually load the stream. - ctx.isAnalyzed = false; + ctx.mediaengine = 0; AnalyzeMpeg(Memory::GetPointerWriteUnchecked(bufferAddr), Memory::ValidSize(bufferAddr, 32768), &ctx); @@ -1206,7 +1205,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr // Flush structs back to memory avcAu.write(auAddr); - if (mpegLibVersion >= 0x0105 && mpegLibVersion < 0x010a) { + if (mpegLibVersion >= 0x0105) { //Killzone - Liberation expect , issue #16727 Memory::Write_U32(1, initAddr); } diff --git a/Core/HLE/sceMt19937.cpp b/Core/HLE/sceMt19937.cpp index 64adebcf8..f22fcfeb1 100644 --- a/Core/HLE/sceMt19937.cpp +++ b/Core/HLE/sceMt19937.cpp @@ -15,7 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "Common/Data/Random/Rng.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceMt19937.h" diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 2e256fffb..13b87f6b6 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -15,7 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#if __linux__ || __APPLE__ || defined(__OpenBSD__) +#if __linux__ || __APPLE__ #include #include #include diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 14bca6838..67e570c3a 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -21,7 +21,6 @@ #endif #if !defined(_WIN32) -#include #include #endif @@ -39,7 +38,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeMap.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Thread/ThreadUtil.h" #include "Common/TimeUtil.h" @@ -277,7 +276,7 @@ static void __GameModeNotify(u64 userdata, int cyclesLate) { if (peer != NULL) truncate_cpy(name, sizeof(name), (const char*)peer->nickname.data); WARN_LOG(SCENET, "GameMode: Unknown Source Port from [%s][%s:%u -> %u] (Result=%i, Size=%i)", name, mac2str(&sendermac).c_str(), senderport, ADHOC_GAMEMODE_PORT, ret, bufsz); - g_OSD.Show(OSDType::MESSAGE_WARNING, std::string(n->T("GM: Data from Unknown Port")) + std::string(" [") + std::string(name) + std::string("]:") + std::to_string(senderport) + std::string(" -> ") + std::to_string(ADHOC_GAMEMODE_PORT) + std::string(" (") + std::to_string(portOffset) + std::string(")")); + System_NotifyUserMessage(std::string(n->T("GM: Data from Unknown Port")) + std::string(" [") + std::string(name) + std::string("]:") + std::to_string(senderport) + std::string(" -> ") + std::to_string(ADHOC_GAMEMODE_PORT) + std::string(" (") + std::to_string(portOffset) + std::string(")"), 2.0, 0x0080ff); peerlock.unlock(); } // Keeping track of the source port for further communication, in case it was re-mapped by router or ISP for some reason. @@ -1492,8 +1491,7 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f changeBlockingMode(usocket, 1); // Success - INFO_LOG(SCENET, "sceNetAdhocPdpCreate - PSP Socket id: %i, Host Socket id: %i", i + 1, usocket); - return i + 1; + return hleLogDebug(SCENET, i + 1, "success"); } // Free Memory for Internal Data @@ -1508,7 +1506,7 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f if (iResult == SOCKET_ERROR) { ERROR_LOG(SCENET, "Socket error (%i) when binding port %u", errno, ntohs(addr.sin_port)); auto n = GetI18NCategory(I18NCat::NETWORKING); - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to Bind Port")) + " " + std::to_string(port + portOffset) + "\n" + std::string(n->T("Please change your Port Offset"))); + System_NotifyUserMessage(std::string(n->T("Failed to Bind Port")) + " " + std::to_string(port + portOffset) + "\n" + std::string(n->T("Please change your Port Offset")), 3.0, 0x0000ff); return hleLogDebug(SCENET, ERROR_NET_ADHOC_PORT_NOT_AVAIL, "port not available"); } @@ -2472,8 +2470,7 @@ u32 NetAdhocctl_Disconnect() { // Library initialized if (netAdhocctlInited) { int iResult, error; - // We might need to have at least 16ms (1 frame?) delay before the game calls the next Adhocctl syscall for Tekken 6 not to stuck when exiting Lobby - hleEatMicro(16667); + hleEatMicro(1000); if (isAdhocctlBusy && CoreTiming::IsScheduled(adhocctlNotifyEvent)) { return ERROR_NET_ADHOCCTL_BUSY; @@ -2542,8 +2539,12 @@ u32 NetAdhocctl_Disconnect() { adhocctlCurrentMode = ADHOCCTL_MODE_NONE; // Notify Event Handlers (even if we weren't connected, not doing this will freeze games like God Eater, which expect this behaviour) // FIXME: When there are no handler the state will immediately became ADHOCCTL_STATE_DISCONNECTED ? - // Note: Metal Gear Acid [2] never register a handler until it's successfully connected to a group and have a connected socket to other player, thus adhocctlHandlers is always empty here. - notifyAdhocctlHandlers(ADHOCCTL_EVENT_DISCONNECT, 0); + if (adhocctlHandlers.empty()) { + adhocctlState = ADHOCCTL_STATE_DISCONNECTED; + } + else { + notifyAdhocctlHandlers(ADHOCCTL_EVENT_DISCONNECT, 0); + } // Return Success, some games might ignore returned value and always treat it as success, otherwise repeatedly calling this function return 0; @@ -3511,9 +3512,8 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, if (g_Config.bForcedFirstConnect && internal->attemptCount == 1) hleDelayResult(i + 1, "delayed ptpopen", rexmt_int); - // Return PTP Socket id - INFO_LOG(SCENET, "sceNetAdhocPtpOpen - PSP Socket id: %i, Host Socket id: %i", i + 1, tcpsocket); - return i + 1; + // Return PTP Socket Pointer + return hleLogDebug(SCENET, i + 1, "success"); } // Free Memory @@ -3523,7 +3523,7 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, else { ERROR_LOG(SCENET, "Socket error (%i) when binding port %u", errno, ntohs(addr.sin_port)); auto n = GetI18NCategory(I18NCat::NETWORKING); - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to Bind Port")) + " " + std::to_string(sport + portOffset) + "\n" + std::string(n->T("Please change your Port Offset"))); + System_NotifyUserMessage(std::string(n->T("Failed to Bind Port")) + " " + std::to_string(sport + portOffset) + "\n" + std::string(n->T("Please change your Port Offset")), 3.0, 0x0000ff); } // Close Socket @@ -3638,7 +3638,7 @@ int AcceptPtpSocket(int ptpId, int newsocket, sockaddr_in& peeraddr, SceNetEther // Switch to non-blocking for futher usage changeBlockingMode(newsocket, 1); - INFO_LOG(SCENET, "sceNetAdhocPtpAccept[%i->%i(%i):%u]: Established (%s:%u) - state: %d", ptpId, i + 1, newsocket, internal->data.ptp.lport, ip2str(peeraddr.sin_addr).c_str(), internal->data.ptp.pport, internal->data.ptp.state); + INFO_LOG(SCENET, "sceNetAdhocPtpAccept[%i->%i:%u]: Established (%s:%u) - state: %d", ptpId, i + 1, internal->data.ptp.lport, ip2str(peeraddr.sin_addr).c_str(), internal->data.ptp.pport, internal->data.ptp.state); // Return Socket return i + 1; @@ -4105,9 +4105,8 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int // Switch to non-blocking for futher usage changeBlockingMode(tcpsocket, 1); - // Return PTP Socket id - INFO_LOG(SCENET, "sceNetAdhocPtpListen - PSP Socket id: %i, Host Socket id: %i", i + 1, tcpsocket); - return i + 1; + // Return PTP Socket Pointer + return hleLogDebug(SCENET, i + 1, "success"); } // Free Memory @@ -4117,7 +4116,7 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int } else { auto n = GetI18NCategory(I18NCat::NETWORKING); - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string(n->T("Failed to Bind Port")) + " " + std::to_string(sport + portOffset) + "\n" + std::string(n->T("Please change your Port Offset"))); + System_NotifyUserMessage(std::string(n->T("Failed to Bind Port")) + " " + std::to_string(sport + portOffset) + "\n" + std::string(n->T("Please change your Port Offset")), 3.0, 0x0000ff); } if (iResult == SOCKET_ERROR) { @@ -7782,7 +7781,7 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi if (peer != NULL) truncate_cpy(name, sizeof(name), (const char*)peer->nickname.data); WARN_LOG(SCENET, "InputLoop[%d]: Unknown Source Port from [%s][%s:%u -> %u] (Recved=%i, Length=%i)", matchingId, name, mac2str(&sendermac).c_str(), senderport, context->port, recvresult, rxbuflen); - g_OSD.Show(OSDType::MESSAGE_WARNING, std::string(n->T("AM: Data from Unknown Port")) + std::string(" [") + std::string(name) + std::string("]:") + std::to_string(senderport) + std::string(" -> ") + std::to_string(context->port) + std::string(" (") + std::to_string(portOffset) + std::string(")")); + System_NotifyUserMessage(std::string(n->T("AM: Data from Unknown Port")) + std::string(" [") + std::string(name) + std::string("]:") + std::to_string(senderport) + std::string(" -> ") + std::to_string(context->port) + std::string(" (") + std::to_string(portOffset) + std::string(")"), 2.0, 0x0080ff); } // Keep tracks of re-mapped peer's ports for further communication. // Note: This will only works if this player were able to receives data on normal port from other players (ie. this player's port wasn't remapped) diff --git a/Core/HLE/sceNp2.cpp b/Core/HLE/sceNp2.cpp index 70b349145..59f7b0cfd 100644 --- a/Core/HLE/sceNp2.cpp +++ b/Core/HLE/sceNp2.cpp @@ -131,8 +131,7 @@ static int sceNpMatching2ContextStart(int ctxId) //npMatching2Ctx.started = true; Url url("http://static-resource.np.community.playstation.net/np/resource/psp-title/" + std::string(npTitleId.data) + "_00/matching/" + std::string(npTitleId.data) + "_00-matching.xml"); http::Client client; - bool cancelled = false; - net::RequestProgress progress(&cancelled); + http::RequestProgress progress; if (!client.Resolve(url.Host().c_str(), url.Port())) { return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP failed to resolve %s", url.Resource().c_str()); } diff --git a/Core/HLE/sceOpenPSID.cpp b/Core/HLE/sceOpenPSID.cpp index f15b7bc14..9d47b4837 100644 --- a/Core/HLE/sceOpenPSID.cpp +++ b/Core/HLE/sceOpenPSID.cpp @@ -20,7 +20,6 @@ #include "Core/HLE/proAdhoc.h" #include "Core/HLE/sceOpenPSID.h" #include "Core/MemMapHelpers.h" -#include "Core/Reporting.h" SceOpenPSID dummyOpenPSID = { 0x10, 0x02, 0xA3, 0x44, 0x13, 0xF5, 0x93, 0xB0, 0xCC, 0x6E, 0xD1, 0x32, 0x27, 0x85, 0x0F, 0x9D }; @@ -80,8 +79,8 @@ static s32 sceDdrdb_F013F8BF(u32 pDataPtr, u32 pSigPtr) { } // unkPtr might be a pointer to OpenPSID -static s32 sceOpenPSIDGetProductCode(u32 unkPtr) { - ERROR_LOG_REPORT(HLE, "UNIMPL %s(%08x)", __FUNCTION__, unkPtr); +static s32 sceOpenPSID_B29330DE(u32 unkPtr) { + ERROR_LOG(HLE, "UNIMPL %s(%08x)", __FUNCTION__, unkPtr); return 0; } @@ -89,8 +88,8 @@ static s32 sceOpenPSIDGetProductCode(u32 unkPtr) { const HLEFunction sceOpenPSID[] = { - {0xC69BEBCE, &WrapI_U, "sceOpenPSIDGetOpenPSID", 'i', "x" }, - {0xB29330DE, &WrapI_U, "sceOpenPSIDGetProductCode", 'i', "x" }, + {0XC69BEBCE, &WrapI_U, "sceOpenPSIDGetOpenPSID", 'i', "x" }, + {0xB29330DE, &WrapI_U, "sceOpenPSID_B29330DE", 'i', "x" }, }; void Register_sceOpenPSID() diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 8fe35ed5d..f4bcb0916 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -740,12 +740,8 @@ void __PsmfPlayerDoState(PointerWrap &p) { void __PsmfShutdown() { for (auto it = psmfMap.begin(), end = psmfMap.end(); it != end; ++it) delete it->second; - for (auto it = psmfPlayerMap.begin(), end = psmfPlayerMap.end(); it != end; ++it) { - // Don't bother freeing, may already be freed. - if (it->second->finishThread) - it->second->finishThread->Forget(); + for (auto it = psmfPlayerMap.begin(), end = psmfPlayerMap.end(); it != end; ++it) delete it->second; - } psmfMap.clear(); psmfPlayerMap.clear(); } diff --git a/Core/HLE/scePspNpDrm_user.cpp b/Core/HLE/scePspNpDrm_user.cpp index f35f6b523..6b844a1de 100644 --- a/Core/HLE/scePspNpDrm_user.cpp +++ b/Core/HLE/scePspNpDrm_user.cpp @@ -25,16 +25,10 @@ static int sceNpDrmRenameCheck(const char *filename) static int sceNpDrmEdataSetupKey(u32 edataFd) { INFO_LOG(HLE, "call sceNpDrmEdataSetupKey %x", edataFd); - int usec = 0; - // set PGD offset - int retval = __IoIoctl(edataFd, 0x04100002, 0x90, 0, 0, 0, usec); - if (retval != 0) { - return hleDelayResult(retval, "io ctrl command", usec); - } - // call PGD open - // Note that usec accumulates. - retval = __IoIoctl(edataFd, 0x04100001, 0, 0, 0, 0, usec); - return hleDelayResult(retval, "io ctrl command", usec); + /* set PGD offset */ + sceIoIoctl(edataFd, 0x04100002, 0x90, 0, 0, 0); + /* call PGD open */ + return sceIoIoctl(edataFd, 0x04100001, 0, 0, 0, 0); } static int sceNpDrmEdataGetDataSize(u32 edataFd) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index d8a320ee5..c7dc08805 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -296,7 +296,7 @@ static u32 _sceSasCore(u32 core, u32 outAddr) { __SasEnqueueMix(outAddr); - return hleLogSuccessVerboseI(SCESAS, delaySasResult(0)); + return hleLogSuccessI(SCESAS, delaySasResult(0)); } // Another way of running the mixer, the inoutAddr should be both input and output @@ -315,12 +315,12 @@ static u32 _sceSasCoreWithMix(u32 core, u32 inoutAddr, int leftVolume, int right __SasEnqueueMix(inoutAddr, inoutAddr, leftVolume, rightVolume); - return hleLogSuccessVerboseI(SCESAS, delaySasResult(0)); + return hleLogSuccessI(SCESAS, delaySasResult(0)); } static u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) { if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { - return hleLogVerbose(SCESAS, ERROR_SAS_INVALID_VOICE, "invalid voicenum"); + return hleLogWarning(SCESAS, ERROR_SAS_INVALID_VOICE, "invalid voicenum"); } if (size == 0 || ((u32)size & 0xF) != 0) { @@ -363,11 +363,8 @@ static u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loo v.type = VOICETYPE_VAG; v.vagAddr = vagAddr; // Real VAG header is 0x30 bytes behind the vagAddr v.vagSize = size; - v.loop = loop != 0; - if (v.on) { - v.playing = true; - } - v.vag.Start(vagAddr, size, loop != 0); + v.loop = loop ? true : false; + v.ChangedParams(vagAddr == prevVagAddr); return 0; } @@ -404,6 +401,7 @@ static u32 sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int v.pcmLoopPos = loopPos >= 0 ? loopPos : 0; v.loop = loopPos >= 0 ? true : false; v.playing = true; + v.ChangedParams(pcmAddr == prevPcmAddr); return 0; } @@ -426,7 +424,7 @@ static u32 sceSasSetPause(u32 core, u32 voicebit, int pause) { for (int i = 0; voicebit != 0; i++, voicebit >>= 1) { if (i < PSP_SAS_VOICES_MAX && i >= 0) { if ((voicebit & 1) != 0) - sas->voices[i].paused = pause != 0; + sas->voices[i].paused = pause ? true : false; } } @@ -468,6 +466,7 @@ static u32 sceSasSetPitch(u32 core, int voiceNum, int pitch) { __SasDrain(); SasVoice &v = sas->voices[voiceNum]; v.pitch = pitch; + v.ChangedParams(false); return 0; } @@ -524,6 +523,7 @@ static u32 sceSasSetNoise(u32 core, int voiceNum, int freq) { SasVoice &v = sas->voices[voiceNum]; v.type = VOICETYPE_NOISE; v.noiseFreq = freq; + v.ChangedParams(true); return 0; } diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index cffc28370..b85f962a0 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -34,7 +34,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/KernelWaitHelpers.h" -#include "Core/RetroAchievements.h" #include "Core/FileSystems/BlockDevices.h" #include "Core/FileSystems/MetaFileSystem.h" @@ -55,7 +54,7 @@ static int umdInsertChangeEvent = -1; static std::vector umdWaitingThreads; static std::map umdPausedWaits; -bool g_UMDReplacePermit = false; +bool UMDReplacePermit = false; bool UMDInserted = true; struct PspUmdInfo { @@ -80,7 +79,6 @@ void __UmdInit() driveCBId = 0; umdWaitingThreads.clear(); umdPausedWaits.clear(); - g_UMDReplacePermit = false; __KernelRegisterWaitTypeFuncs(WAITTYPE_UMD, __UmdBeginCallback, __UmdEndCallback); } @@ -105,8 +103,8 @@ void __UmdDoState(PointerWrap &p) Do(p, umdPausedWaits); if (s > 1) { - Do(p, g_UMDReplacePermit); - if (g_UMDReplacePermit) { + Do(p, UMDReplacePermit); + if (UMDReplacePermit) { System_Notify(SystemNotification::UI); } } @@ -485,16 +483,13 @@ static u32 sceUmdGetErrorStat() return umdErrorStat; } -void __UmdReplace(const Path &filepath) { +void __UmdReplace(Path filepath) { std::string error = ""; - FileLoader *fileLoader; - if (!UmdReplace(filepath, &fileLoader, error)) { + if (!UmdReplace(filepath, error)) { ERROR_LOG(SCEIO, "UMD Replace failed: %s", error.c_str()); return; } - Achievements::ChangeUMD(filepath, fileLoader); - UMDInserted = false; // Wake any threads waiting for the disc to be removed. UmdWakeThreads(); @@ -507,15 +502,14 @@ void __UmdReplace(const Path &filepath) { } bool getUMDReplacePermit() { - return g_UMDReplacePermit; + return UMDReplacePermit; } static u32 sceUmdReplaceProhibit() { - DEBUG_LOG(SCEIO, "sceUmdReplaceProhibit()"); - if (g_UMDReplacePermit) { - INFO_LOG(SCEIO, "sceUmdReplaceProhibit() - prohibited"); - g_UMDReplacePermit = false; + DEBUG_LOG(SCEIO,"sceUmdReplaceProhibit()"); + if (UMDReplacePermit) { + UMDReplacePermit = false; System_Notify(SystemNotification::SWITCH_UMD_UPDATED); } return 0; @@ -523,10 +517,9 @@ static u32 sceUmdReplaceProhibit() static u32 sceUmdReplacePermit() { - DEBUG_LOG(SCEIO, "sceUmdReplacePermit()"); - if (!g_UMDReplacePermit) { - INFO_LOG(SCEIO, "sceUmdReplacePermit() - permitted"); - g_UMDReplacePermit = true; + DEBUG_LOG(SCEIO,"sceUmdReplacePermit()"); + if (!UMDReplacePermit) { + UMDReplacePermit = true; System_Notify(SystemNotification::SWITCH_UMD_UPDATED); } return 0; diff --git a/Core/HLE/sceUmd.h b/Core/HLE/sceUmd.h index e33bdaae9..91e9bcafd 100644 --- a/Core/HLE/sceUmd.h +++ b/Core/HLE/sceUmd.h @@ -43,7 +43,7 @@ enum pspUmdType { void __UmdInit(); void __UmdDoState(PointerWrap &p); -void __UmdReplace(const Path &filepath); +void __UmdReplace(Path filepath); bool getUMDReplacePermit(); void Register_sceUmdUser(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 0672de41b..1ff229a9c 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -304,8 +304,6 @@ void __UtilityShutdown() { npSigninDialog->Shutdown(true); if (accessThread) { - // Don't need to free it during shutdown, may have already been freed. - accessThread->Forget(); delete accessThread; accessThread = nullptr; accessThreadState = "shutdown"; @@ -794,7 +792,7 @@ static int sceUtilityGamedataInstallUpdate(int animSpeed) { } static int sceUtilityGamedataInstallGetStatus() { - if (currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { + if (!currentDialogActive || currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { // This is called incorrectly all the time by some games. So let's not bother warning. hleEatCycles(200); return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); @@ -900,7 +898,7 @@ static u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) param = g_Config.bDayLightSavings?PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_SAVING:PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_STD; break; case PSP_SYSTEMPARAM_ID_INT_LANGUAGE: - param = g_Config.GetPSPLanguage(); + param = g_Config.iLanguage; if (PSP_CoreParameter().compat.flags().EnglishOrJapaneseOnly) { if (param != PSP_SYSTEMPARAM_LANGUAGE_ENGLISH && param != PSP_SYSTEMPARAM_LANGUAGE_JAPANESE) { param = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; diff --git a/Core/HW/AsyncIOManager.h b/Core/HW/AsyncIOManager.h index 1145db17a..59d50050c 100644 --- a/Core/HW/AsyncIOManager.h +++ b/Core/HW/AsyncIOManager.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - #include #include #include diff --git a/Core/HW/Display.cpp b/Core/HW/Display.cpp index 1831ee3f2..acead8d78 100644 --- a/Core/HW/Display.cpp +++ b/Core/HW/Display.cpp @@ -92,7 +92,7 @@ static void CalculateFPS() { } } - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::FRAME_GRAPH || coreCollectDebugStats) { + if (g_Config.bDrawFrameGraph || coreCollectDebugStats) { frameTimeHistory[frameTimeHistoryPos++] = now - lastFrameTimeHistory; lastFrameTimeHistory = now; frameTimeHistoryPos = frameTimeHistoryPos % frameTimeHistorySize; @@ -182,10 +182,6 @@ void DisplayNotifySleep(double t, int pos) { void __DisplayGetDebugStats(char *stats, size_t bufsize) { char statbuf[4096]; - if (!gpu) { - snprintf(stats, bufsize, "N/A"); - return; - } gpu->GetStats(statbuf, sizeof(statbuf)); snprintf(stats, bufsize, diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 39ab2564c..a8a2f6d56 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -71,8 +71,6 @@ void VagDecoder::DecodeBlock(const u8 *&read_pointer) { return; } - _dbg_assert_(curBlock_ < numBlocks_); - const u8 *readp = read_pointer; int predict_nr = *readp++; int shift_factor = predict_nr & 0xf; @@ -127,7 +125,6 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { WARN_LOG_REPORT(SASMIX, "Bad VAG samples address? %08x / %d", read_, numBlocks_); return; } - const u8 *readp = Memory::GetPointerUnchecked(read_); const u8 *origp = readp; @@ -149,7 +146,6 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { return; } } - _dbg_assert_(curSample < 28); outSamples[i] = samples[curSample++]; } @@ -324,13 +320,13 @@ static int getSustainLevel(int bitfield1) { void ADSREnvelope::SetEnvelope(int flag, int a, int d, int s, int r) { if ((flag & 0x1) != 0) - attackType = (SasADSRCurveMode)a; + attackType = a; if ((flag & 0x2) != 0) - decayType = (SasADSRCurveMode)d; + decayType = d; if ((flag & 0x4) != 0) - sustainType = (SasADSRCurveMode)s; + sustainType = s; if ((flag & 0x8) != 0) - releaseType = (SasADSRCurveMode)r; + releaseType = r; if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) { sustainType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; @@ -350,13 +346,13 @@ void ADSREnvelope::SetRate(int flag, int a, int d, int s, int r) { void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) { attackRate = getAttackRate(ADSREnv1); - attackType = (SasADSRCurveMode)getAttackType(ADSREnv1); + attackType = getAttackType(ADSREnv1); decayRate = getDecayRate(ADSREnv1); decayType = PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE; sustainRate = getSustainRate(ADSREnv2); - sustainType = (SasADSRCurveMode)getSustainType(ADSREnv2); + sustainType = getSustainType(ADSREnv2); releaseRate = getReleaseRate(ADSREnv2); - releaseType = (SasADSRCurveMode)getReleaseType(ADSREnv2); + releaseType = getReleaseType(ADSREnv2); sustainLevel = getSustainLevel(ADSREnv1); if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) { @@ -375,7 +371,6 @@ SasInstance::SasInstance() { memset(&waveformEffect, 0, sizeof(waveformEffect)); waveformEffect.type = PSP_SAS_EFFECT_TYPE_OFF; waveformEffect.isDryOn = 1; - memset(mixTemp_, 0, sizeof(mixTemp_)); // just to avoid a static analysis warning. } SasInstance::~SasInstance() { @@ -388,26 +383,7 @@ void SasInstance::GetDebugText(char *text, size_t bufsize) { char *p = voiceBuf; for (int i = 0; i < maxVoices; i++) { if (voices[i].playing) { - uint32_t readAddr = voices[i].GetReadAddress(); - const char *indicator = ""; - switch (voices[i].type) { - case VOICETYPE_VAG: - if (readAddr < voices[i].vagAddr || readAddr > voices[i].vagAddr + voices[i].vagSize) { - indicator = " (BAD!)"; - } - break; - default: - break; - } - p += snprintf(p, sizeof(voiceBuf) - (p - voiceBuf), " %d: Pitch %04x L/R,FX: %d,%d|%d,%d VAG: %08x:%d:%08x%s Height:%d%%\n", i, - voices[i].pitch, voices[i].volumeLeft, voices[i].volumeRight, voices[i].effectLeft, voices[i].effectRight, - voices[i].vagAddr, voices[i].vagSize, voices[i].GetReadAddress(), indicator, (int)((int64_t)voices[i].envelope.GetHeight() * 100 / PSP_SAS_ENVELOPE_HEIGHT_MAX)); - p += snprintf(p, sizeof(voiceBuf) - (p - voiceBuf), " - ADSR: %s/%s/%s/%s\n", - ADSRCurveModeAsString(voices[i].envelope.attackType), - ADSRCurveModeAsString(voices[i].envelope.decayType), - ADSRCurveModeAsString(voices[i].envelope.sustainType), - ADSRCurveModeAsString(voices[i].envelope.releaseType) - ); + p += snprintf(p, sizeof(voiceBuf) - (p - voiceBuf), " %d: Pitch %d L/R,FX: %d,%d|%d,%d VAG: %08x:%d:%08x Height:%d%%\n", i, voices[i].pitch, voices[i].volumeLeft, voices[i].volumeRight, voices[i].effectLeft, voices[i].effectRight, voices[i].vagAddr, voices[i].vagSize, voices[i].vag.GetReadPtr(), (int)((int64_t)voices[i].envelope.GetHeight() * 100 / PSP_SAS_ENVELOPE_HEIGHT_MAX)); } } @@ -816,6 +792,15 @@ void SasVoice::KeyOff() { envelope.KeyOff(); } +void SasVoice::ChangedParams(bool changedVag) { + if (!playing && on) { + playing = true; + if (changedVag) + vag.Start(vagAddr, vagSize, loop); + } + // TODO: restart VAG somehow +} + void SasVoice::DoState(PointerWrap &p) { auto s = p.Section("SasVoice", 1, 3); if (!s) @@ -866,6 +851,20 @@ void SasVoice::DoState(PointerWrap &p) { atrac3.DoState(p); } +ADSREnvelope::ADSREnvelope() + : attackRate(0), + decayRate(0), + sustainRate(0), + releaseRate(0), + attackType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE), + decayType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE), + sustainType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE), + sustainLevel(0), + releaseType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE), + state_(STATE_OFF), + height_(0) { +} + void ADSREnvelope::WalkCurve(int type, int rate) { s64 expDelta; switch (type) { @@ -1000,15 +999,3 @@ void ADSREnvelope::DoState(PointerWrap &p) { } Do(p, height_); } - -const char *ADSRCurveModeAsString(SasADSRCurveMode mode) { - switch (mode) { - case PSP_SAS_ADSR_CURVE_MODE_DIRECT: return "D"; - case PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE: return "L+"; - case PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE: return "L-"; - case PSP_SAS_ADSR_CURVE_MODE_LINEAR_BENT: return "LB"; - case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE: return "E-"; - case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE: return "E+"; - default: return "N/A"; - } -} diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 6a9ee882b..bae8b738d 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -28,41 +28,36 @@ class PointerWrap; -// General constants. enum { PSP_SAS_VOICES_MAX = 32, - PSP_SAS_VOL_MAX = 0x1000, - PSP_SAS_MAX_GRAIN = 2048, // Matches the max value of the parameter to sceSasInit + PSP_SAS_PITCH_MIN = 0x0000, PSP_SAS_PITCH_BASE = 0x1000, PSP_SAS_PITCH_MASK = 0xFFF, PSP_SAS_PITCH_BASE_SHIFT = 12, PSP_SAS_PITCH_MAX = 0x4000, - PSP_SAS_ENVELOPE_HEIGHT_MAX = 0x40000000, - PSP_SAS_ENVELOPE_FREQ_MAX = 0x7FFFFFFF, -}; -// The type of these are baked into savestates. -enum SasADSRCurveMode : int { + PSP_SAS_VOL_MAX = 0x1000, + PSP_SAS_MAX_GRAIN = 2048, // Matches the max value of the parameter to sceSasInit + PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE = 0, PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE = 1, PSP_SAS_ADSR_CURVE_MODE_LINEAR_BENT = 2, PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE = 3, PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE = 4, PSP_SAS_ADSR_CURVE_MODE_DIRECT = 5, -}; -enum { PSP_SAS_ADSR_ATTACK = 1, PSP_SAS_ADSR_DECAY = 2, PSP_SAS_ADSR_SUSTAIN = 4, PSP_SAS_ADSR_RELEASE = 8, -}; -enum SasEffectType { + PSP_SAS_ENVELOPE_HEIGHT_MAX = 0x40000000, + PSP_SAS_ENVELOPE_FREQ_MAX = 0x7FFFFFFF, + PSP_SAS_EFFECT_TYPE_OFF = -1, PSP_SAS_EFFECT_TYPE_ROOM = 0, - PSP_SAS_EFFECT_TYPE_STUDIO_SMALL = 1, + PSP_SAS_EFFECT_TYPE_STUDIO_SMALL= 1, PSP_SAS_EFFECT_TYPE_STUDIO_MEDIUM = 2, PSP_SAS_EFFECT_TYPE_STUDIO_LARGE = 3, PSP_SAS_EFFECT_TYPE_HALL = 4, @@ -71,9 +66,7 @@ enum SasEffectType { PSP_SAS_EFFECT_TYPE_DELAY = 7, PSP_SAS_EFFECT_TYPE_PIPE = 8, PSP_SAS_EFFECT_TYPE_MAX = 8, -}; -enum SasOutputMode { PSP_SAS_OUTPUTMODE_MIXED = 0, PSP_SAS_OUTPUTMODE_RAW = 1, }; @@ -156,6 +149,7 @@ private: class ADSREnvelope { public: + ADSREnvelope(); void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2); void SetEnvelope(int flag, int a, int d, int s, int r); void SetRate(int flag, int a, int d, int s, int r); @@ -183,17 +177,6 @@ public: void DoState(PointerWrap &p); - int attackRate = 0; - int decayRate = 0; - int sustainRate = 0; - int sustainLevel = 0; - int releaseRate = 0; - - SasADSRCurveMode attackType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE; - SasADSRCurveMode decayType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; - SasADSRCurveMode sustainType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; - SasADSRCurveMode releaseType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; - private: // Actual PSP values. enum ADSRState { @@ -209,8 +192,18 @@ private: }; void SetState(ADSRState state); - ADSRState state_ = STATE_OFF; - s64 height_ = 0; // s64 to avoid having to care about overflow when calculating. TODO: this should be fine as s32 + int attackRate; + int decayRate; + int sustainRate; + int releaseRate; + int attackType; + int decayType; + int sustainType; + int sustainLevel; + int releaseType; + + ADSRState state_; + s64 height_; // s64 to avoid having to care about overflow when calculating. TODO: this should be fine as s32 }; // A SAS voice. @@ -243,21 +236,13 @@ struct SasVoice { void Reset(); void KeyOn(); void KeyOff(); + void ChangedParams(bool changedVag); void DoState(PointerWrap &p); void ReadSamples(s16 *output, int numSamples); bool HaveSamplesEnded() const; - // For debugging. - u32 GetReadAddress() const { - if (type == VOICETYPE_VAG) { - return vag.GetReadPtr(); - } else { - return 0; // TODO. - } - } - bool playing; bool paused; // a voice can be playing AND paused. In that case, it won't play. bool on; // key-on, key-off. @@ -288,7 +273,6 @@ struct SasVoice { ADSREnvelope envelope; - // TODO: Union these two? VagDecoder vag; SasAtrac3 atrac3; }; @@ -334,5 +318,3 @@ private: int grainSize = 0; int16_t mixTemp_[PSP_SAS_MAX_GRAIN * 4 + 2 + 8]; // some extra margin for very high pitches. }; - -const char *ADSRCurveModeAsString(SasADSRCurveMode mode); diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 7d46dfb51..9f4c48285 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -45,8 +45,8 @@ KeyMapping g_controllerMap; // Incremented on modification, so we know when to update menus. int g_controllerMapGeneration = 0; std::set g_seenPads; -std::map g_padNames; -std::set g_seenDeviceIds; +std::map g_padNames; +std::set g_seenDeviceIds; // Utility for UI navigation void SingleInputMappingFromPspButton(int btn, std::vector *mappings, bool ignoreMouse) { @@ -67,16 +67,13 @@ void UpdateNativeMenuKeys() { std::vector confirmKeys, cancelKeys; std::vector tabLeft, tabRight; std::vector upKeys, downKeys, leftKeys, rightKeys; - std::vector infoKeys; - - // Mouse mapping might be problematic in UI, so let's ignore mouse for UI int confirmKey = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CROSS : CTRL_CIRCLE; int cancelKey = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CIRCLE : CTRL_CROSS; + // Mouse mapping might be problematic in UI, so let's ignore mouse for UI SingleInputMappingFromPspButton(confirmKey, &confirmKeys, true); SingleInputMappingFromPspButton(cancelKey, &cancelKeys, true); - SingleInputMappingFromPspButton(CTRL_TRIANGLE, &infoKeys, true); SingleInputMappingFromPspButton(CTRL_LTRIGGER, &tabLeft, true); SingleInputMappingFromPspButton(CTRL_RTRIGGER, &tabRight, true); SingleInputMappingFromPspButton(CTRL_UP, &upKeys, true); @@ -119,24 +116,12 @@ void UpdateNativeMenuKeys() { cancelKeys.push_back(hardcodedCancelKeys[i]); } - const InputMapping hardcodedInfoKeys[] = { - InputMapping(DEVICE_ID_KEYBOARD, NKCODE_S), - InputMapping(DEVICE_ID_KEYBOARD, NKCODE_NUMPAD_ADD), - InputMapping(DEVICE_ID_PAD_0, NKCODE_BUTTON_Y), // Also triangle - }; - - for (size_t i = 0; i < ARRAY_SIZE(hardcodedInfoKeys); i++) { - if (std::find(infoKeys.begin(), infoKeys.end(), hardcodedInfoKeys[i]) == infoKeys.end()) - infoKeys.push_back(hardcodedInfoKeys[i]); - } - SetDPadKeys(upKeys, downKeys, leftKeys, rightKeys); SetConfirmCancelKeys(confirmKeys, cancelKeys); SetTabLeftRightKeys(tabLeft, tabRight); - SetInfoKeys(infoKeys); - std::unordered_map flipYByDeviceId; - for (InputDeviceID deviceId : g_seenDeviceIds) { + std::unordered_map flipYByDeviceId; + for (int deviceId : g_seenDeviceIds) { auto analogs = MappedAxesForDevice(deviceId); flipYByDeviceId[deviceId] = analogs.leftY.direction; } @@ -415,8 +400,7 @@ const KeyMap_IntStrPair psp_button_names[] = { {VIRTKEY_REWIND, "Rewind"}, {VIRTKEY_SAVE_STATE, "Save State"}, {VIRTKEY_LOAD_STATE, "Load State"}, - {VIRTKEY_PREVIOUS_SLOT, "Previous Slot"}, - {VIRTKEY_NEXT_SLOT, "Next Slot"}, + {VIRTKEY_NEXT_SLOT, "Next Slot"}, #if !defined(MOBILE_DEVICE) {VIRTKEY_TOGGLE_FULLSCREEN, "Toggle Fullscreen"}, #endif @@ -446,9 +430,6 @@ const KeyMap_IntStrPair psp_button_names[] = { {VIRTKEY_SCREEN_ROTATION_HORIZONTAL180, "Display Landscape Reversed"}, #endif - {VIRTKEY_TOGGLE_WLAN, "Toggle WLAN"}, - {VIRTKEY_EXIT_APP, "Exit App"}, - {CTRL_HOME, "Home"}, {CTRL_HOLD, "Hold"}, {CTRL_WLAN, "Wlan"}, @@ -459,7 +440,6 @@ const KeyMap_IntStrPair psp_button_names[] = { {CTRL_NOTE, "Note"}, }; -// key here can be other things than InputKeyCode. static std::string FindName(int key, const KeyMap_IntStrPair list[], size_t size) { for (size_t i = 0; i < size; i++) { if (list[i].key == key) @@ -468,7 +448,7 @@ static std::string FindName(int key, const KeyMap_IntStrPair list[], size_t size return StringFromFormat("%02x?", key); } -std::string GetKeyName(InputKeyCode keyCode) { +std::string GetKeyName(int keyCode) { return FindName(keyCode, key_names, ARRAY_SIZE(key_names)); } @@ -532,11 +512,11 @@ bool InputMappingsFromPspButton(int btn, std::vector *mapping return false; } bool mapped = false; - for (auto &iter2 : iter->second) { - bool ignore = ignoreMouse && iter2.HasMouse(); + for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) { + bool ignore = ignoreMouse && iter2->HasMouse(); if (mappings && !ignore) { mapped = true; - mappings->push_back(iter2); + mappings->push_back(*iter2); } } return mapped; @@ -551,7 +531,9 @@ bool PspButtonHasMappings(int btn) { return !iter->second.empty(); } -MappedAnalogAxes MappedAxesForDevice(InputDeviceID deviceId) { +MappedAnalogAxes MappedAxesForDevice(int deviceId) { + MappedAnalogAxes result{}; + // Find the axisId mapped for a specific virtual button. auto findAxisId = [&](int btn) -> MappedAnalogAxis { MappedAnalogAxis info{ -1 }; @@ -577,7 +559,6 @@ MappedAnalogAxes MappedAxesForDevice(InputDeviceID deviceId) { return MappedAnalogAxis{ -1 }; }; - MappedAnalogAxes result; std::lock_guard guard(g_controllerMapLock); result.leftX = findAxisIdPair(VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX); result.leftY = findAxisIdPair(VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX); @@ -596,7 +577,7 @@ void RemoveButtonMapping(int btn) { } } -bool IsKeyMapped(InputDeviceID device, int key) { +bool IsKeyMapped(int device, int key) { std::lock_guard guard(g_controllerMapLock); for (auto &iter : g_controllerMap) { for (auto &mappedKey : iter.second) { @@ -636,7 +617,6 @@ bool ReplaceSingleKeyMapping(int btn, int index, MultiInputMapping key) { } void DeleteNthMapping(int key, int number) { - std::lock_guard guard(g_controllerMapLock); auto iter = g_controllerMap.find(key); if (iter != g_controllerMap.end()) { if (number < iter->second.size()) { @@ -715,8 +695,6 @@ void LoadFromIni(IniFile &file) { return; } - std::lock_guard guard(g_controllerMapLock); - Section *controls = file.GetOrCreateSection("ControlMapping"); for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) { std::string value; @@ -748,8 +726,6 @@ void LoadFromIni(IniFile &file) { void SaveToIni(IniFile &file) { Section *controls = file.GetOrCreateSection("ControlMapping"); - std::lock_guard guard(g_controllerMapLock); - for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) { std::vector keys; InputMappingsFromPspButton(psp_button_names[i].key, &keys, false); @@ -801,8 +777,7 @@ bool HasBuiltinController(const std::string &name) { return IsOuya(name) || IsXperiaPlay(name) || IsNvidiaShield(name) || IsMOQII7S(name) || IsRetroid(name); } -void NotifyPadConnected(InputDeviceID deviceId, const std::string &name) { - std::lock_guard guard(g_controllerMapLock); +void NotifyPadConnected(int deviceId, const std::string &name) { g_seenPads.insert(name); g_padNames[deviceId] = name; } @@ -818,8 +793,6 @@ void AutoConfForPad(const std::string &name) { SetDefaultKeyMap(DEFAULT_MAPPING_ANDROID_XBOX, false); } else if (name == "Retro Station Controller") { SetDefaultKeyMap(DEFAULT_MAPPING_RETRO_STATION_CONTROLLER, false); - } else { - SetDefaultKeyMap(DEFAULT_MAPPING_ANDROID_PAD, false); } #else // TODO: Should actually check for XInput? @@ -837,12 +810,10 @@ void AutoConfForPad(const std::string &name) { } const std::set &GetSeenPads() { - std::lock_guard guard(g_controllerMapLock); return g_seenPads; } -std::string PadName(InputDeviceID deviceId) { - std::lock_guard guard(g_controllerMapLock); +std::string PadName(int deviceId) { auto it = g_padNames.find(deviceId); if (it != g_padNames.end()) return it->second; @@ -906,9 +877,9 @@ const char *GetVirtKeyName(int vkey) { return g_vKeyNames[index]; } -MultiInputMapping MultiInputMapping::FromConfigString(std::string_view str) { +MultiInputMapping MultiInputMapping::FromConfigString(const std::string &str) { MultiInputMapping out; - std::vector parts; + std::vector parts; SplitString(str, ':', parts); for (auto iter : parts) { out.mappings.push_back(InputMapping::FromConfigString(iter)); diff --git a/Core/KeyMap.h b/Core/KeyMap.h index 3459433b2..7813ada3e 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -71,9 +71,6 @@ enum { VIRTKEY_SPEED_ANALOG = 0x40000024, VIRTKEY_VR_CAMERA_ADJUST = 0x40000025, VIRTKEY_VR_CAMERA_RESET = 0x40000026, - VIRTKEY_PREVIOUS_SLOT = 0x40000027, - VIRTKEY_TOGGLE_WLAN = 0x40000028, - VIRTKEY_EXIT_APP = 0x40000029, VIRTKEY_LAST, VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST }; @@ -114,8 +111,9 @@ namespace KeyMap { mappings.push_back(mapping); } - static MultiInputMapping FromConfigString(std::string_view str); + static MultiInputMapping FromConfigString(const std::string &str); std::string ToConfigString() const; + std::string ToVisualString() const; bool operator <(const MultiInputMapping &other) { @@ -156,7 +154,7 @@ namespace KeyMap { // Once the multimappings are inserted here, they must not be empty. // If one would be, delete the whole entry from the map instead. // This is automatically handled by SetInputMapping. - extern std::set g_seenDeviceIds; + extern std::set g_seenDeviceIds; extern int g_controllerMapGeneration; // Key & Button names struct KeyMap_IntStrPair { @@ -165,7 +163,7 @@ namespace KeyMap { }; // Use if you need to display the textual name - std::string GetKeyName(InputKeyCode keyCode); + std::string GetKeyName(int keyCode); std::string GetKeyOrAxisName(const InputMapping &mapping); std::string GetAxisName(int axisId); std::string GetPspButtonName(int btn); @@ -190,7 +188,7 @@ namespace KeyMap { // Return false if bind was a duplicate and got removed bool ReplaceSingleKeyMapping(int btn, int index, MultiInputMapping key); - MappedAnalogAxes MappedAxesForDevice(InputDeviceID deviceId); + MappedAnalogAxes MappedAxesForDevice(int deviceId); void LoadFromIni(IniFile &iniFile); void SaveToIni(IniFile &iniFile); @@ -203,7 +201,7 @@ namespace KeyMap { void UpdateNativeMenuKeys(); - void NotifyPadConnected(InputDeviceID deviceId, const std::string &name); + void NotifyPadConnected(int deviceId, const std::string &name); bool IsNvidiaShield(const std::string &name); bool IsNvidiaShieldTV(const std::string &name); bool IsXperiaPlay(const std::string &name); @@ -213,10 +211,10 @@ namespace KeyMap { bool HasBuiltinController(const std::string &name); const std::set &GetSeenPads(); - std::string PadName(InputDeviceID deviceId); + std::string PadName(int deviceId); void AutoConfForPad(const std::string &name); - bool IsKeyMapped(InputDeviceID device, int key); + bool IsKeyMapped(int device, int key); bool HasChanged(int &prevGeneration); } diff --git a/Core/KeyMapDefaults.cpp b/Core/KeyMapDefaults.cpp index 3c08f2c94..63c429430 100644 --- a/Core/KeyMapDefaults.cpp +++ b/Core/KeyMapDefaults.cpp @@ -338,7 +338,7 @@ static const DefMappingStruct defaultVRRightController[] = { {VIRTKEY_AXIS_X_MAX, NKCODE_DPAD_RIGHT}, }; -static void SetDefaultKeyMap(InputDeviceID deviceId, const DefMappingStruct *array, size_t count, bool replace) { +static void SetDefaultKeyMap(int deviceId, const DefMappingStruct *array, size_t count, bool replace) { for (size_t i = 0; i < count; i++) { if (array[i].direction == 0) SetInputMapping(array[i].pspKey, MultiInputMapping(InputMapping(deviceId, array[i].keyOrAxis)), replace); diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 6bb5f5d34..344f672b0 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -18,7 +18,6 @@ #include #include -#include "Common/File/AndroidContentURI.h" #include "Common/File/FileUtil.h" #include "Common/File/Path.h" #include "Common/StringUtils.h" @@ -94,8 +93,6 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin return IdentifiedFileType::PSP_ISO; } else if (extension == ".cso") { return IdentifiedFileType::PSP_ISO; - } else if (extension == ".chd") { - return IdentifiedFileType::PSP_ISO; } else if (extension == ".ppst") { return IdentifiedFileType::PPSSPP_SAVESTATE; } else if (extension == ".ppdmp") { @@ -262,13 +259,15 @@ Path ResolvePBPFile(const Path &filename) { bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { FileLoader *&fileLoader = *fileLoaderPtr; + // Note that this can modify filename! IdentifiedFileType type = Identify_File(fileLoader, error_string); switch (type) { case IdentifiedFileType::PSP_PBP_DIRECTORY: { + // TODO: Perhaps we should/can never get here now? fileLoader = ResolveFileLoaderTarget(fileLoader); if (fileLoader->Exists()) { - INFO_LOG(LOADER, "File is a PBP in a directory: %s", fileLoader->GetPath().c_str()); + INFO_LOG(LOADER, "File is a PBP in a directory!"); IdentifiedFileType ebootType = Identify_File(fileLoader, error_string); if (ebootType == IdentifiedFileType::PSP_ISO_NP) { InitMemoryForGameISO(fileLoader); @@ -286,9 +285,6 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { } std::string dir = fileLoader->GetPath().GetDirectory(); - if (fileLoader->GetPath().Type() == PathType::CONTENT_URI) { - dir = AndroidContentURI(dir).FilePath(); - } size_t pos = dir.find("PSP/GAME/"); if (pos != std::string::npos) { dir = ResolvePBPDirectory(Path(dir)).ToString(); @@ -387,7 +383,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { return false; } -bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &error) { +bool UmdReplace(const Path &filepath, std::string &error) { IFileSystem *currentUMD = pspFileSystem.GetSystem("disc0:"); if (!currentUMD) { @@ -406,7 +402,6 @@ bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &erro loadedFile = ResolveFileLoaderTarget(loadedFile); - *fileLoader = loadedFile; std::string errorString; IdentifiedFileType type = Identify_File(loadedFile, &errorString); @@ -419,6 +414,7 @@ bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &erro error = "reinit memory failed"; return false; } + break; default: error = "Unsupported file type: " + std::to_string((int)type) + " " + errorString; diff --git a/Core/Loaders.h b/Core/Loaders.h index 5bc90d3e2..2bef2858f 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -157,4 +157,4 @@ void RegisterFileLoaderFactory(std::string prefix, std::unique_ptr= n) { - WARN_LOG(CPU, "JIT: Invalid VFPU swizzle: %08x : %d / %d at PC = %08x (%s)", prefix, regnum, n, GetCompilerPC(), MIPSDisasmAt(GetCompilerPC()).c_str()); + WARN_LOG(CPU, "JIT: Invalid VFPU swizzle: %08x : %d / %d at PC = %08x (%s)", prefix, regnum, n, GetCompilerPC(), MIPSDisasmAt(GetCompilerPC())); regnum = 0; } @@ -1310,13 +1310,10 @@ namespace MIPSComp // Set these BEFORE disable! if (imm - 128 == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } else { //ERROR @@ -1372,13 +1369,10 @@ namespace MIPSComp if (imm == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } } diff --git a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp index 1f4f783e7..f11f1c503 100644 --- a/Core/MIPS/ARM/ArmCompVFPUNEON.cpp +++ b/Core/MIPS/ARM/ArmCompVFPUNEON.cpp @@ -722,13 +722,10 @@ void ArmJit::CompNEON_Mftv(MIPSOpcode op) { // Set these BEFORE disable! if (imm - 128 == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } else { //ERROR @@ -760,13 +757,10 @@ void ArmJit::CompNEON_Vmtvc(MIPSOpcode op) { if (imm - 128 == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } } diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 4cfbc2512..05d5d0c14 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -132,9 +132,6 @@ void ArmJit::DoState(PointerWrap &p) if (!s) return; - if (p.mode == PointerWrap::MODE_READ && !js.startDefaultPrefix) { - WARN_LOG(CPU, "Jit: An uneaten prefix was previously detected. Jitting in unknown-prefix mode."); - } Do(p, js.startDefaultPrefix); if (s >= 2) { Do(p, js.hasSetRounding); @@ -160,16 +157,8 @@ void ArmJit::FlushAll() FlushPrefixV(); } -void ArmJit::FlushPrefixV() { - if (js.startDefaultPrefix && !js.blockWrotePrefixes && js.HasNoPrefix()) { - // They started default, we never modified in memory, and they're default now. - // No reason to modify memory. This is common at end of blocks. Just clear dirty. - js.prefixSFlag = (JitState::PrefixState)(js.prefixSFlag & ~JitState::PREFIX_DIRTY); - js.prefixTFlag = (JitState::PrefixState)(js.prefixTFlag & ~JitState::PREFIX_DIRTY); - js.prefixDFlag = (JitState::PrefixState)(js.prefixDFlag & ~JitState::PREFIX_DIRTY); - return; - } - +void ArmJit::FlushPrefixV() +{ if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) { gpr.SetRegImm(SCRATCHREG1, js.prefixS); STR(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_SPREFIX])); @@ -187,9 +176,6 @@ void ArmJit::FlushPrefixV() { STR(SCRATCHREG1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_DPREFIX])); js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } - - // If we got here, we must've written prefixes to memory in this block. - js.blockWrotePrefixes = true; } void ArmJit::ClearCache() @@ -255,7 +241,6 @@ void ArmJit::Compile(u32 em_address) { int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); - _assert_msg_(b->originalAddress == em_address, "original %08x != em_address %08x (block %d)", b->originalAddress, em_address, b->blockNum); blocks.FinalizeBlock(block_num, jo.enableBlocklink); EndWrite(); @@ -302,8 +287,7 @@ MIPSOpcode ArmJit::GetOffsetInstruction(int offset) { const u8 *ArmJit::DoJit(u32 em_address, JitBlock *b) { js.cancel = false; - js.blockStart = em_address; - js.compilerPC = em_address; + js.blockStart = js.compilerPC = mips_->pc; js.lastContinuedPC = 0; js.initialBlockSize = 0; js.nextExit = 0; @@ -311,7 +295,6 @@ const u8 *ArmJit::DoJit(u32 em_address, JitBlock *b) js.curBlock = b; js.compiling = true; js.inDelaySlot = false; - js.blockWrotePrefixes = false; js.PrefixStart(); // We add a downcount flag check before the block, used when entering from a linked block. @@ -400,7 +383,7 @@ const u8 *ArmJit::DoJit(u32 em_address, JitBlock *b) if (logBlocks > 0 && dontLogBlocks == 0) { INFO_LOG(JIT, "=============== mips ==============="); for (u32 cpc = em_address; cpc != GetCompilerPC() + 4; cpc += 4) { - MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp, sizeof(temp), true); + MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp, true); INFO_LOG(JIT, "M: %08x %s", cpc, temp); } } @@ -561,7 +544,7 @@ void ArmJit::Comp_ReplacementFunc(MIPSOpcode op) const ReplacementTableEntry *entry = GetReplacementFunc(index); if (!entry) { - ERROR_LOG_REPORT_ONCE(replFunc, HLE, "Invalid replacement op %08x at %08x", op.encoding, js.compilerPC); + ERROR_LOG(HLE, "Invalid replacement op %08x", op.encoding); return; } @@ -650,10 +633,6 @@ void ArmJit::Comp_Generic(MIPSOpcode op) // If it does eat them, it'll happen in MIPSCompileOp(). if ((info & OUT_EAT_PREFIX) == 0) js.PrefixUnknown(); - - // Even if DISABLE'd, we want to set this flag so we overwrite. - if ((info & OUT_VFPU_PREFIX) != 0) - js.blockWrotePrefixes = true; } } @@ -745,9 +724,7 @@ void ArmJit::UpdateRoundingMode(u32 fcr31) { // I don't think this gives us that much benefit. void ArmJit::WriteExit(u32 destination, int exit_num) { - // NOTE: Can't blindly check for bad destination addresses here, sometimes exits with bad destinations are written intentionally (like breaks). - _assert_msg_(exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num. dest=%08x", destination); - + // TODO: Check destination is valid and trigger exception. WriteDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 04f1ac79d..829f53ef7 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -61,7 +61,6 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; - void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; diff --git a/Core/MIPS/ARM/ArmRegCacheFPU.cpp b/Core/MIPS/ARM/ArmRegCacheFPU.cpp index c3df5301e..f2478595c 100644 --- a/Core/MIPS/ARM/ArmRegCacheFPU.cpp +++ b/Core/MIPS/ARM/ArmRegCacheFPU.cpp @@ -584,11 +584,11 @@ ARMReg ArmRegCacheFPU::R(int mipsReg) { return (ARMReg)(mr[mipsReg].reg + S0); } else { if (mipsReg < 32) { - ERROR_LOG(JIT, "FReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg, js_->compilerPC, MIPSDisasmAt(js_->compilerPC).c_str()); + ERROR_LOG(JIT, "FReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg, js_->compilerPC, MIPSDisasmAt(js_->compilerPC)); } else if (mipsReg < 32 + 128) { - ERROR_LOG(JIT, "VReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC).c_str()); + ERROR_LOG(JIT, "VReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC)); } else { - ERROR_LOG(JIT, "Tempreg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 128 - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC).c_str()); + ERROR_LOG(JIT, "Tempreg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 128 - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC)); } return INVALID_REG; // BAAAD } @@ -618,7 +618,7 @@ void ArmRegCacheFPU::QFlush(int quad) { } if (qr[quad].isDirty && !qr[quad].isTemp) { - INFO_LOG(JIT, "Flushing Q%i (%s)", quad, GetVectorNotation(qr[quad].mipsVec, qr[quad].sz).c_str()); + INFO_LOG(JIT, "Flushing Q%i (%s)", quad, GetVectorNotation(qr[quad].mipsVec, qr[quad].sz)); ARMReg q = QuadAsQ(quad); // Unlike reads, when writing to the register file we need to be careful to write the correct @@ -881,7 +881,7 @@ ARMReg ArmRegCacheFPU::QMapReg(int vreg, VectorSize sz, int flags) { // We didn't find the extra register, but we got a list of regs to flush. Flush 'em. // Here we can check for opportunities to do a "transpose-flush" of row vectors, etc. if (!quadsToFlush.empty()) { - INFO_LOG(JIT, "New mapping %s collided with %d quads, flushing them.", GetVectorNotation(vreg, sz).c_str(), (int)quadsToFlush.size()); + INFO_LOG(JIT, "New mapping %s collided with %d quads, flushing them.", GetVectorNotation(vreg, sz), (int)quadsToFlush.size()); } for (size_t i = 0; i < quadsToFlush.size(); i++) { QFlush(quadsToFlush[i]); @@ -973,7 +973,7 @@ ARMReg ArmRegCacheFPU::QMapReg(int vreg, VectorSize sz, int flags) { qr[quad].isDirty = (flags & MAP_DIRTY) != 0; qr[quad].spillLock = true; - INFO_LOG(JIT, "Mapped Q%i to vfpu %i (%s), sz=%i, dirty=%i", quad, vreg, GetVectorNotation(vreg, sz).c_str(), (int)sz, qr[quad].isDirty); + INFO_LOG(JIT, "Mapped Q%i to vfpu %i (%s), sz=%i, dirty=%i", quad, vreg, GetVectorNotation(vreg, sz), (int)sz, qr[quad].isDirty); if (sz == V_Single || sz == V_Pair) { return D_0(QuadAsQ(quad)); } else { diff --git a/Core/MIPS/ARM64/Arm64Asm.cpp b/Core/MIPS/ARM64/Arm64Asm.cpp index 5a0b12ce6..9f70435a7 100644 --- a/Core/MIPS/ARM64/Arm64Asm.cpp +++ b/Core/MIPS/ARM64/Arm64Asm.cpp @@ -312,7 +312,7 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) { // Leave this at the end, add more stuff above. if (enableDisasm) { - std::vector lines = DisassembleArm64(start, (int)(GetCodePtr() - start)); + std::vector lines = DisassembleArm64(start, GetCodePtr() - start); for (auto s : lines) { INFO_LOG(JIT, "%s", s.c_str()); } diff --git a/Core/MIPS/ARM64/Arm64CompFPU.cpp b/Core/MIPS/ARM64/Arm64CompFPU.cpp index 2756f5e8e..c1cd96958 100644 --- a/Core/MIPS/ARM64/Arm64CompFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompFPU.cpp @@ -292,7 +292,7 @@ void Arm64Jit::Comp_FPU2op(MIPSOpcode op) { fp.FMOV(fpr.R(fd), S0); } else { fp.FCMP(fpr.R(fs), fpr.R(fs)); - fp.FCVTS(fpr.R(fd), fpr.R(fs), ROUND_N); + fp.FCVTS(fpr.R(fd), fpr.R(fs), ROUND_Z); FixupBranch skip_nan = B(CC_VC); MOVI2R(SCRATCH1, 0x7FFFFFFF); fp.FMOV(fpr.R(fd), SCRATCH1); diff --git a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp index 9824f0700..08e7d541a 100644 --- a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp +++ b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp @@ -434,12 +434,6 @@ namespace MIPSComp { } } - void Arm64Jit::Comp_StoreSync(MIPSOpcode op) { - CONDITIONAL_DISABLE(LSU); - - DISABLE; - } - void Arm64Jit::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/ARM64/Arm64CompVFPU.cpp b/Core/MIPS/ARM64/Arm64CompVFPU.cpp index d5dd416d6..fafd4fa20 100644 --- a/Core/MIPS/ARM64/Arm64CompVFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompVFPU.cpp @@ -134,7 +134,7 @@ namespace MIPSComp { // Prefix may say "z, z, z, z" but if this is a pair, we force to x. // TODO: But some ops seem to use const 0 instead? if (regnum >= n) { - WARN_LOG(CPU, "JIT: Invalid VFPU swizzle: %08x : %d / %d at PC = %08x (%s)", prefix, regnum, n, GetCompilerPC(), MIPSDisasmAt(GetCompilerPC()).c_str()); + WARN_LOG(CPU, "JIT: Invalid VFPU swizzle: %08x : %d / %d at PC = %08x (%s)", prefix, regnum, n, GetCompilerPC(), MIPSDisasmAt(GetCompilerPC())); regnum = 0; } @@ -1062,13 +1062,10 @@ namespace MIPSComp { // Set these BEFORE disable! if (imm - 128 == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } else { //ERROR @@ -1122,13 +1119,10 @@ namespace MIPSComp { if (imm == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } } @@ -1504,7 +1498,7 @@ namespace MIPSComp { void Arm64Jit::Comp_VCrossQuat(MIPSOpcode op) { // This op does not support prefixes anyway. CONDITIONAL_DISABLE(VFPU_VEC); - if (!js.HasNoPrefix()) + if (js.HasUnknownPrefix()) DISABLE; VectorSize sz = GetVecSize(op); @@ -1521,26 +1515,20 @@ namespace MIPSComp { if (sz == V_Triple) { MIPSReg temp3 = fpr.GetTempV(); - MIPSReg temp4 = fpr.GetTempV(); fpr.MapRegV(temp3, MAP_DIRTY | MAP_NOINIT); - fpr.MapRegV(temp4, MAP_DIRTY | MAP_NOINIT); // Cross product vcrsp.t - // Note: using FMSUB here causes accuracy issues, see #18203. - // Compute X: s[1] * t[2] - s[2] * t[1] - fp.FMUL(fpr.V(temp3), fpr.V(sregs[1]), fpr.V(tregs[2])); - fp.FMUL(fpr.V(temp4), fpr.V(sregs[2]), fpr.V(tregs[1])); - fp.FSUB(S0, fpr.V(temp3), fpr.V(temp4)); + // Compute X + fp.FMUL(S0, fpr.V(sregs[1]), fpr.V(tregs[2])); + fp.FMSUB(S0, fpr.V(sregs[2]), fpr.V(tregs[1]), S0); - // Compute Y: s[2] * t[0] - s[0] * t[2] - fp.FMUL(fpr.V(temp3), fpr.V(sregs[2]), fpr.V(tregs[0])); - fp.FMUL(fpr.V(temp4), fpr.V(sregs[0]), fpr.V(tregs[2])); - fp.FSUB(S1, fpr.V(temp3), fpr.V(temp4)); + // Compute Y + fp.FMUL(S1, fpr.V(sregs[2]), fpr.V(tregs[0])); + fp.FMSUB(S1, fpr.V(sregs[0]), fpr.V(tregs[2]), S1); - // Compute Z: s[0] * t[1] - s[1] * t[0] + // Compute Z fp.FMUL(fpr.V(temp3), fpr.V(sregs[0]), fpr.V(tregs[1])); - fp.FMUL(fpr.V(temp4), fpr.V(sregs[1]), fpr.V(tregs[0])); - fp.FSUB(fpr.V(temp3), fpr.V(temp3), fpr.V(temp4)); + fp.FMSUB(fpr.V(temp3), fpr.V(sregs[1]), fpr.V(tregs[0]), fpr.V(temp3)); fpr.MapRegsAndSpillLockV(dregs, sz, MAP_NOINIT); fp.FMOV(fpr.V(dregs[0]), S0); diff --git a/Core/MIPS/ARM64/Arm64IRAsm.cpp b/Core/MIPS/ARM64/Arm64IRAsm.cpp deleted file mode 100644 index d623c6cd5..000000000 --- a/Core/MIPS/ARM64/Arm64IRAsm.cpp +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include "Common/Log.h" -#include "Core/CoreTiming.h" -#include "Core/MemMap.h" -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/System.h" - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -static const bool enableDebug = false; -static const bool enableDisasm = false; - -static void ShowPC(void *membase, void *jitbase) { - static int count = 0; - if (currentMIPS) { - u32 downcount = currentMIPS->downcount; - ERROR_LOG(JIT, "[%08x] ShowPC Downcount : %08x %d %p %p", currentMIPS->pc, downcount, count, membase, jitbase); - } else { - ERROR_LOG(JIT, "Universe corrupt?"); - } - //if (count > 2000) - // exit(0); - count++; -} - -void Arm64JitBackend::GenerateFixedCode(MIPSState *mipsState) { - // This will be used as a writable scratch area, always 32-bit accessible. - const u8 *start = AlignCodePage(); - if (DebugProfilerEnabled()) { - ProtectMemoryPages(start, GetMemoryProtectPageSize(), MEM_PROT_READ | MEM_PROT_WRITE); - hooks_.profilerPC = (uint32_t *)GetWritableCodePtr(); - Write32(0); - hooks_.profilerStatus = (IRProfilerStatus *)GetWritableCodePtr(); - Write32(0); - } - - const u8 *disasmStart = AlignCodePage(); - BeginWrite(GetMemoryProtectPageSize()); - - if (jo.useStaticAlloc) { - saveStaticRegisters_ = AlignCode16(); - STR(INDEX_UNSIGNED, DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - regs_.EmitSaveStaticRegisters(); - RET(); - - loadStaticRegisters_ = AlignCode16(); - regs_.EmitLoadStaticRegisters(); - LDR(INDEX_UNSIGNED, DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - RET(); - } else { - saveStaticRegisters_ = nullptr; - loadStaticRegisters_ = nullptr; - } - - restoreRoundingMode_ = AlignCode16(); - { - MRS(SCRATCH2_64, FIELD_FPCR); - // We are not in flush-to-zero mode outside the JIT, so let's turn it off. - uint32_t mask = ~(4 << 22); - // Assume we're always in round-to-nearest mode beforehand. - mask &= ~(3 << 22); - ANDI2R(SCRATCH2, SCRATCH2, mask); - _MSR(FIELD_FPCR, SCRATCH2_64); - RET(); - } - - applyRoundingMode_ = AlignCode16(); - { - LDR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, fcr31)); - ANDI2R(SCRATCH2, SCRATCH1, 3); - FixupBranch skip1 = TBZ(SCRATCH1, 24); - ADDI2R(SCRATCH2, SCRATCH2, 4); - SetJumpTarget(skip1); - - // We can skip if the rounding mode is nearest (0) and flush is not set. - // (as restoreRoundingMode cleared it out anyway) - FixupBranch skip = CBZ(SCRATCH2); - - // MIPS Rounding Mode: ARM Rounding Mode - // 0: Round nearest 0 - // 1: Round to zero 3 - // 2: Round up (ceil) 1 - // 3: Round down (floor) 2 - ANDI2R(SCRATCH1, SCRATCH2, 3); - CMPI2R(SCRATCH1, 1); - - FixupBranch skipadd = B(CC_NEQ); - ADDI2R(SCRATCH2, SCRATCH2, 2); - SetJumpTarget(skipadd); - FixupBranch skipsub = B(CC_LE); - SUBI2R(SCRATCH2, SCRATCH2, 1); - SetJumpTarget(skipsub); - - // Actually change the system FPCR register - MRS(SCRATCH1_64, FIELD_FPCR); - // Clear both flush-to-zero and rounding before re-setting them. - ANDI2R(SCRATCH1, SCRATCH1, ~((4 | 3) << 22)); - ORR(SCRATCH1, SCRATCH1, SCRATCH2, ArithOption(SCRATCH2, ST_LSL, 22)); - _MSR(FIELD_FPCR, SCRATCH1_64); - - SetJumpTarget(skip); - RET(); - } - - updateRoundingMode_ = AlignCode16(); - { - LDR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, fcr31)); - - // Set SCRATCH2 to FZ:RM (FZ is bit 24, and RM are lowest 2 bits.) - ANDI2R(SCRATCH2, SCRATCH1, 3); - FixupBranch skip = TBZ(SCRATCH1, 24); - ADDI2R(SCRATCH2, SCRATCH2, 4); - SetJumpTarget(skip); - - // Update currentRoundingFunc_ with the right convertS0ToSCRATCH1_ func. - MOVP2R(SCRATCH1_64, convertS0ToSCRATCH1_); - LSL(SCRATCH2, SCRATCH2, 3); - LDR(SCRATCH2_64, SCRATCH1_64, SCRATCH2); - MOVP2R(SCRATCH1_64, ¤tRoundingFunc_); - STR(INDEX_UNSIGNED, SCRATCH2_64, SCRATCH1_64, 0); - RET(); - } - - hooks_.enterDispatcher = (IRNativeFuncNoArg)AlignCode16(); - - uint32_t regs_to_save = Arm64Gen::ALL_CALLEE_SAVED; - uint32_t regs_to_save_fp = Arm64Gen::ALL_CALLEE_SAVED_FP; - fp_.ABI_PushRegisters(regs_to_save, regs_to_save_fp); - - // Fixed registers, these are always kept when in Jit context. - MOVP2R(MEMBASEREG, Memory::base); - MOVP2R(CTXREG, mipsState); - // Pre-subtract this to save time later. - MOVI2R(JITBASEREG, (intptr_t)GetBasePtr() - MIPS_EMUHACK_OPCODE); - - LoadStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - MovFromPC(SCRATCH1); - WriteDebugPC(SCRATCH1); - outerLoopPCInSCRATCH1_ = GetCodePtr(); - MovToPC(SCRATCH1); - outerLoop_ = GetCodePtr(); - SaveStaticRegisters(); // Advance can change the downcount, so must save/restore - RestoreRoundingMode(true); - WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE); - QuickCallFunction(SCRATCH1_64, &CoreTiming::Advance); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - ApplyRoundingMode(true); - LoadStaticRegisters(); - - dispatcherCheckCoreState_ = GetCodePtr(); - - MOVP2R(SCRATCH1_64, &coreState); - LDR(INDEX_UNSIGNED, SCRATCH1, SCRATCH1_64, 0); - FixupBranch badCoreState = CBNZ(SCRATCH1); - - // Check downcount. - TBNZ(DOWNCOUNTREG, 31, outerLoop_); - FixupBranch skipToRealDispatch = B(); - - dispatcherPCInSCRATCH1_ = GetCodePtr(); - MovToPC(SCRATCH1); - - hooks_.dispatcher = GetCodePtr(); - - FixupBranch bail = TBNZ(DOWNCOUNTREG, 31); - SetJumpTarget(skipToRealDispatch); - - dispatcherNoCheck_ = GetCodePtr(); - - // Debug - if (enableDebug) { - MOV(W0, DOWNCOUNTREG); - MOV(X1, MEMBASEREG); - MOV(X2, JITBASEREG); - QuickCallFunction(SCRATCH1_64, &ShowPC); - } - - MovFromPC(SCRATCH1); - WriteDebugPC(SCRATCH1); -#ifdef MASKED_PSP_MEMORY - ANDI2R(SCRATCH1, SCRATCH1, Memory::MEMVIEW32_MASK); -#endif - hooks_.dispatchFetch = GetCodePtr(); - LDR(SCRATCH1, MEMBASEREG, SCRATCH1_64); - LSR(SCRATCH2, SCRATCH1, 24); // or UBFX(SCRATCH2, SCRATCH1, 24, 8) - // We don't mask SCRATCH1 as that's already baked into JITBASEREG. - CMP(SCRATCH2, MIPS_EMUHACK_OPCODE >> 24); - FixupBranch skipJump = B(CC_NEQ); - ADD(SCRATCH1_64, JITBASEREG, SCRATCH1_64); - BR(SCRATCH1_64); - SetJumpTarget(skipJump); - - // No block found, let's jit. We don't need to save static regs, they're all callee saved. - RestoreRoundingMode(true); - WriteDebugProfilerStatus(IRProfilerStatus::COMPILING); - QuickCallFunction(SCRATCH1_64, &MIPSComp::JitAt); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - ApplyRoundingMode(true); - - // Let's just dispatch again, we'll enter the block since we know it's there. - B(dispatcherNoCheck_); - - SetJumpTarget(bail); - - MOVP2R(SCRATCH1_64, &coreState); - LDR(INDEX_UNSIGNED, SCRATCH1, SCRATCH1_64, 0); - CBZ(SCRATCH1, outerLoop_); - - const uint8_t *quitLoop = GetCodePtr(); - SetJumpTarget(badCoreState); - - WriteDebugProfilerStatus(IRProfilerStatus::NOT_RUNNING); - SaveStaticRegisters(); - RestoreRoundingMode(true); - - fp_.ABI_PopRegisters(regs_to_save, regs_to_save_fp); - - RET(); - - hooks_.crashHandler = GetCodePtr(); - MOVP2R(SCRATCH1_64, &coreState); - MOVI2R(SCRATCH2, CORE_RUNTIME_ERROR); - STR(INDEX_UNSIGNED, SCRATCH2, SCRATCH1_64, 0); - B(quitLoop); - - // Generate some integer conversion funcs. - // MIPS order! - static const RoundingMode roundModes[8] = { ROUND_N, ROUND_Z, ROUND_P, ROUND_M, ROUND_N, ROUND_Z, ROUND_P, ROUND_M }; - for (size_t i = 0; i < ARRAY_SIZE(roundModes); ++i) { - convertS0ToSCRATCH1_[i] = AlignCode16(); - - // Invert 0x80000000 -> 0x7FFFFFFF for the NAN result. - fp_.MVNI(32, EncodeRegToDouble(SCRATCHF2), 0x80, 24); - fp_.FCMP(S0, S0); // Detect NaN - fp_.FCVTS(S0, S0, roundModes[i]); - fp_.FCSEL(S0, S0, SCRATCHF2, CC_VC); - - RET(); - } - - // Leave this at the end, add more stuff above. - if (enableDisasm) { - std::vector lines = DisassembleArm64(disasmStart, (int)(GetCodePtr() - disasmStart)); - for (auto s : lines) { - INFO_LOG(JIT, "%s", s.c_str()); - } - } - - // Let's spare the pre-generated code from unprotect-reprotect. - AlignCodePage(); - jitStartOffset_ = (int)(GetCodePtr() - start); - // Don't forget to zap the instruction cache! This must stay at the end of this function. - FlushIcache(); - EndWrite(); - - // Update our current cached rounding mode func, too. - UpdateFCR31(mipsState); -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRCompALU.cpp b/Core/MIPS/ARM64/Arm64IRCompALU.cpp deleted file mode 100644 index 4aeb2ceeb..000000000 --- a/Core/MIPS/ARM64/Arm64IRCompALU.cpp +++ /dev/null @@ -1,532 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include "Common/CPUDetect.h" -#include "Core/MemMap.h" -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -// This file contains compilation for integer / arithmetic / logic related instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -void Arm64JitBackend::CompIR_Arith(IRInst inst) { - CONDITIONAL_DISABLE; - - bool allowPtrMath = inst.constant <= 0x7FFFFFFF; -#ifdef MASKED_PSP_MEMORY - // Since we modify it, we can't safely. - allowPtrMath = false; -#endif - - switch (inst.op) { - case IROp::Add: - regs_.Map(inst); - ADD(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::Sub: - regs_.Map(inst); - SUB(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::AddConst: - if (regs_.IsGPRMappedAsPointer(inst.dest) && inst.dest == inst.src1 && allowPtrMath) { - regs_.MarkGPRAsPointerDirty(inst.dest); - ADDI2R(regs_.RPtr(inst.dest), regs_.RPtr(inst.src1), (int)inst.constant, SCRATCH1_64); - } else { - regs_.Map(inst); - ADDI2R(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant, SCRATCH1); - } - break; - - case IROp::SubConst: - if (regs_.IsGPRMappedAsPointer(inst.dest) && inst.dest == inst.src1 && allowPtrMath) { - regs_.MarkGPRAsPointerDirty(inst.dest); - SUBI2R(regs_.RPtr(inst.dest), regs_.RPtr(inst.src1), (int)inst.constant, SCRATCH1_64); - } else { - regs_.Map(inst); - SUBI2R(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant, SCRATCH1); - } - break; - - case IROp::Neg: - regs_.Map(inst); - NEG(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Assign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Mov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::Ext8to32: - regs_.Map(inst); - SXTB(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - case IROp::Ext16to32: - regs_.Map(inst); - SXTH(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Bits(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::BSwap16: - regs_.Map(inst); - REV16(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - case IROp::BSwap32: - regs_.Map(inst); - REV32(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - case IROp::Clz: - regs_.Map(inst); - CLZ(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - case IROp::ReverseBits: - regs_.Map(inst); - RBIT(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Compare(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Slt: - regs_.Map(inst); - CMP(regs_.R(inst.src1), regs_.R(inst.src2)); - CSET(regs_.R(inst.dest), CC_LT); - break; - - case IROp::SltConst: - if (inst.constant == 0) { - // Basically, getting the sign bit. - regs_.Map(inst); - UBFX(regs_.R(inst.dest), regs_.R(inst.src1), 31, 1); - } else { - regs_.Map(inst); - CMPI2R(regs_.R(inst.src1), (int32_t)inst.constant, SCRATCH1); - CSET(regs_.R(inst.dest), CC_LT); - } - break; - - case IROp::SltU: - if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) { - // This is kinda common, same as != 0. Avoid flushing src1. - regs_.SpillLockGPR(inst.src2, inst.dest); - regs_.MapGPR(inst.src2); - regs_.MapGPR(inst.dest, MIPSMap::NOINIT); - CMP(regs_.R(inst.src2), 0); - CSET(regs_.R(inst.dest), CC_NEQ); - } else { - regs_.Map(inst); - CMP(regs_.R(inst.src1), regs_.R(inst.src2)); - CSET(regs_.R(inst.dest), CC_LO); - } - break; - - case IROp::SltUConst: - if (inst.constant == 0) { - regs_.SetGPRImm(inst.dest, 0); - } else { - regs_.Map(inst); - CMPI2R(regs_.R(inst.src1), (int32_t)inst.constant, SCRATCH1); - CSET(regs_.R(inst.dest), CC_LO); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_CondAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::MovZ: - if (inst.dest != inst.src2) { - regs_.Map(inst); - CMP(regs_.R(inst.src1), 0); - CSEL(regs_.R(inst.dest), regs_.R(inst.src2), regs_.R(inst.dest), CC_EQ); - } - break; - - case IROp::MovNZ: - if (inst.dest != inst.src2) { - regs_.Map(inst); - CMP(regs_.R(inst.src1), 0); - CSEL(regs_.R(inst.dest), regs_.R(inst.src2), regs_.R(inst.dest), CC_NEQ); - } - break; - - case IROp::Max: - if (inst.src1 != inst.src2) { - regs_.Map(inst); - CMP(regs_.R(inst.src1), regs_.R(inst.src2)); - CSEL(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2), CC_GE); - } else if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::Min: - if (inst.src1 != inst.src2) { - regs_.Map(inst); - CMP(regs_.R(inst.src1), regs_.R(inst.src2)); - CSEL(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2), CC_LE); - } else if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Div(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Div: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - // INT_MIN divided by -1 = INT_MIN, anything divided by 0 = 0. - SDIV(regs_.R(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2)); - MSUB(SCRATCH1, regs_.R(inst.src2), regs_.R(IRREG_LO), regs_.R(inst.src1)); - - // Now some tweaks for divide by zero and overflow. - { - // Start with divide by zero, remainder is fine. - FixupBranch skipNonZero = CBNZ(regs_.R(inst.src2)); - MOVI2R(regs_.R(IRREG_LO), 1); - CMP(regs_.R(inst.src1), 0); - // mips->lo = numerator < 0 ? 1 : -1 - CSNEG(regs_.R(IRREG_LO), regs_.R(IRREG_LO), regs_.R(IRREG_LO), CC_LT); - SetJumpTarget(skipNonZero); - - // For overflow, we end up with remainder as zero, need to fix. - MOVI2R(SCRATCH2, 0x80000000); - CMP(regs_.R(inst.src1), SCRATCH2); - FixupBranch notMostNegative = B(CC_NEQ); - CMPI2R(regs_.R(inst.src2), -1); - // If it's not equal, keep SCRATCH1. Otherwise (equal), invert 0 = -1. - CSINV(SCRATCH1, SCRATCH1, WZR, CC_NEQ); - SetJumpTarget(notMostNegative); - } - - BFI(regs_.R64(IRREG_LO), SCRATCH1_64, 32, 32); - break; - - case IROp::DivU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - // Anything divided by 0 = 0. - UDIV(regs_.R(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2)); - MSUB(SCRATCH1, regs_.R(inst.src2), regs_.R(IRREG_LO), regs_.R(inst.src1)); - - // On divide by zero, we have to update LO - remainder is correct. - { - FixupBranch skipNonZero = CBNZ(regs_.R(inst.src2)); - MOVI2R(regs_.R(IRREG_LO), 0xFFFF); - CMP(regs_.R(inst.src1), regs_.R(IRREG_LO)); - // If it's <= 0xFFFF, keep 0xFFFF. Otherwise, invert 0 = -1. - CSINV(regs_.R(IRREG_LO), regs_.R(IRREG_LO), WZR, CC_LE); - SetJumpTarget(skipNonZero); - } - - BFI(regs_.R64(IRREG_LO), SCRATCH1_64, 32, 32); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_HiLo(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::MtLo: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - BFI(regs_.R64(IRREG_LO), regs_.R64(inst.src1), 0, 32); - break; - - case IROp::MtHi: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - BFI(regs_.R64(IRREG_LO), regs_.R64(inst.src1), 32, 32); - break; - - case IROp::MfLo: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::INIT } }); - MOV(regs_.R(inst.dest), regs_.R(IRREG_LO)); - break; - - case IROp::MfHi: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::INIT } }); - UBFX(regs_.R64(inst.dest), regs_.R64(IRREG_LO), 32, 32); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Logic(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::And: - if (inst.src1 != inst.src2) { - regs_.Map(inst); - AND(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - } else if (inst.src1 != inst.dest) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::Or: - if (inst.src1 != inst.src2) { - regs_.Map(inst); - ORR(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - } else if (inst.src1 != inst.dest) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::Xor: - if (inst.src1 == inst.src2) { - regs_.SetGPRImm(inst.dest, 0); - } else { - regs_.Map(inst); - EOR(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - } - break; - - case IROp::AndConst: - regs_.Map(inst); - ANDI2R(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant, SCRATCH1); - break; - - case IROp::OrConst: - regs_.Map(inst); - ORRI2R(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant, SCRATCH1); - break; - - case IROp::XorConst: - regs_.Map(inst); - EORI2R(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant, SCRATCH1); - break; - - case IROp::Not: - regs_.Map(inst); - MVN(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Mult(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Mult: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - SMULL(regs_.R64(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::MultU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - UMULL(regs_.R64(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::Madd: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // Accumulator is at the end, "standard" syntax. - SMADDL(regs_.R64(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2), regs_.R64(IRREG_LO)); - break; - - case IROp::MaddU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // Accumulator is at the end, "standard" syntax. - UMADDL(regs_.R64(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2), regs_.R64(IRREG_LO)); - break; - - case IROp::Msub: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // Accumulator is at the end, "standard" syntax. - SMSUBL(regs_.R64(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2), regs_.R64(IRREG_LO)); - break; - - case IROp::MsubU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // Accumulator is at the end, "standard" syntax. - UMSUBL(regs_.R64(IRREG_LO), regs_.R(inst.src1), regs_.R(inst.src2), regs_.R64(IRREG_LO)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Shift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Shl: - regs_.Map(inst); - LSLV(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::Shr: - regs_.Map(inst); - LSRV(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::Sar: - regs_.Map(inst); - ASRV(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::Ror: - regs_.Map(inst); - RORV(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - break; - - case IROp::ShlImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1), ArithOption(regs_.R(inst.src1), ST_LSL, inst.src2)); - } - break; - - case IROp::ShrImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1), ArithOption(regs_.R(inst.src1), ST_LSR, inst.src2)); - } - break; - - case IROp::SarImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1), ArithOption(regs_.R(inst.src1), ST_ASR, 31)); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1), ArithOption(regs_.R(inst.src1), ST_ASR, inst.src2)); - } - break; - - case IROp::RorImm: - if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else { - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(inst.src1), ArithOption(regs_.R(inst.src1), ST_ROR, inst.src2 & 31)); - } - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRCompBranch.cpp b/Core/MIPS/ARM64/Arm64IRCompBranch.cpp deleted file mode 100644 index c7bb4ae11..000000000 --- a/Core/MIPS/ARM64/Arm64IRCompBranch.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -// This file contains compilation for exits. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -void Arm64JitBackend::CompIR_Exit(IRInst inst) { - CONDITIONAL_DISABLE; - - ARM64Reg exitReg = INVALID_REG; - switch (inst.op) { - case IROp::ExitToConst: - FlushAll(); - WriteConstExit(inst.constant); - break; - - case IROp::ExitToReg: - exitReg = regs_.MapGPR(inst.src1); - FlushAll(); - MOV(SCRATCH1, exitReg); - B(dispatcherPCInSCRATCH1_); - break; - - case IROp::ExitToPC: - FlushAll(); - B(dispatcherCheckCoreState_); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_ExitIf(IRInst inst) { - CONDITIONAL_DISABLE; - - ARM64Reg lhs = INVALID_REG; - ARM64Reg rhs = INVALID_REG; - FixupBranch fixup; - switch (inst.op) { - case IROp::ExitToConstIfEq: - case IROp::ExitToConstIfNeq: - if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) { - lhs = regs_.MapGPR(inst.src2); - FlushAll(); - - if (inst.op == IROp::ExitToConstIfEq) - fixup = CBNZ(lhs); - else if (inst.op == IROp::ExitToConstIfNeq) - fixup = CBZ(lhs); - else - _assert_(false); - } else if (regs_.IsGPRImm(inst.src2) && regs_.GetGPRImm(inst.src2) == 0) { - lhs = regs_.MapGPR(inst.src1); - FlushAll(); - - if (inst.op == IROp::ExitToConstIfEq) - fixup = CBNZ(lhs); - else if (inst.op == IROp::ExitToConstIfNeq) - fixup = CBZ(lhs); - else - _assert_(false); - } else { - regs_.Map(inst); - lhs = regs_.R(inst.src1); - rhs = regs_.R(inst.src2); - FlushAll(); - - CMP(lhs, rhs); - if (inst.op == IROp::ExitToConstIfEq) - fixup = B(CC_NEQ); - else if (inst.op == IROp::ExitToConstIfNeq) - fixup = B(CC_EQ); - else - _assert_(false); - } - - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfGtZ: - lhs = regs_.MapGPR(inst.src1); - FlushAll(); - CMP(lhs, 0); - fixup = B(CC_LE); - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfGeZ: - // In other words, exit if sign bit is 0. - lhs = regs_.MapGPR(inst.src1); - FlushAll(); - fixup = TBNZ(lhs, 31); - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfLtZ: - // In other words, exit if sign bit is 1. - lhs = regs_.MapGPR(inst.src1); - FlushAll(); - fixup = TBZ(lhs, 31); - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfLeZ: - lhs = regs_.MapGPR(inst.src1); - FlushAll(); - CMP(lhs, 0); - fixup = B(CC_GT); - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfFpTrue: - case IROp::ExitToConstIfFpFalse: - // Note: not used. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRCompFPU.cpp b/Core/MIPS/ARM64/Arm64IRCompFPU.cpp deleted file mode 100644 index 99b502c74..000000000 --- a/Core/MIPS/ARM64/Arm64IRCompFPU.cpp +++ /dev/null @@ -1,592 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#ifndef offsetof -#include -#endif - -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -// This file contains compilation for floating point related instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -void Arm64JitBackend::CompIR_FArith(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FAdd: - regs_.Map(inst); - fp_.FADD(regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FSub: - regs_.Map(inst); - fp_.FSUB(regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FMul: - regs_.Map(inst); - fp_.FMUL(regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FDiv: - regs_.Map(inst); - fp_.FDIV(regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FSqrt: - regs_.Map(inst); - fp_.FSQRT(regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FNeg: - regs_.Map(inst); - fp_.FNEG(regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_FAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FMov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - fp_.FMOV(regs_.F(inst.dest), regs_.F(inst.src1)); - } - break; - - case IROp::FAbs: - regs_.Map(inst); - fp_.FABS(regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FSign: - regs_.Map(inst); - // We'll need this flag later. Vector could use a temp and FCMEQ. - fp_.FCMP(regs_.F(inst.src1)); - - fp_.MOVI2FDUP(EncodeRegToDouble(SCRATCHF1), 1.0f); - // Invert 0x80000000 -> 0x7FFFFFFF as a mask for sign. - fp_.MVNI(32, EncodeRegToDouble(SCRATCHF2), 0x80, 24); - // Keep the sign bit in dest, replace all other bits from 1.0f. - if (inst.dest != inst.src1) - fp_.FMOV(regs_.FD(inst.dest), regs_.FD(inst.src1)); - fp_.BIT(regs_.FD(inst.dest), EncodeRegToDouble(SCRATCHF1), EncodeRegToDouble(SCRATCHF2)); - - // It's later now, let's replace with zero if that FCmp was EQ to zero. - fp_.MOVI2FDUP(EncodeRegToDouble(SCRATCHF1), 0.0f); - fp_.FCSEL(regs_.F(inst.dest), SCRATCHF1, regs_.F(inst.dest), CC_EQ); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_FCompare(IRInst inst) { - CONDITIONAL_DISABLE; - - constexpr IRReg IRREG_VFPU_CC = IRREG_VFPU_CTRL_BASE + VFPU_CTRL_CC; - - switch (inst.op) { - case IROp::FCmp: - switch (inst.dest) { - case IRFpCompareMode::False: - regs_.SetGPRImm(IRREG_FPCOND, 0); - break; - - case IRFpCompareMode::EitherUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_VS); - break; - - case IRFpCompareMode::EqualOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_EQ); - break; - - case IRFpCompareMode::EqualUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_EQ); - // If ordered, use the above result. If unordered, use ZR+1 (being 1.) - CSINC(regs_.R(IRREG_FPCOND), regs_.R(IRREG_FPCOND), WZR, CC_VC); - break; - - case IRFpCompareMode::LessEqualOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_LS); - break; - - case IRFpCompareMode::LessEqualUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_LE); - break; - - case IRFpCompareMode::LessOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_LO); - break; - - case IRFpCompareMode::LessUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(regs_.R(IRREG_FPCOND), CC_LT); - break; - - default: - _assert_msg_(false, "Unexpected IRFpCompareMode %d", inst.dest); - } - break; - - case IROp::FCmovVfpuCC: - regs_.MapWithExtra(inst, { { 'G', IRREG_VFPU_CC, 1, MIPSMap::INIT } }); - TSTI2R(regs_.R(IRREG_VFPU_CC), 1ULL << (inst.src2 & 0xF)); - if ((inst.src2 >> 7) & 1) { - fp_.FCSEL(regs_.F(inst.dest), regs_.F(inst.dest), regs_.F(inst.src1), CC_EQ); - } else { - fp_.FCSEL(regs_.F(inst.dest), regs_.F(inst.dest), regs_.F(inst.src1), CC_NEQ); - } - break; - - case IROp::FCmpVfpuBit: - regs_.MapGPR(IRREG_VFPU_CC, MIPSMap::DIRTY); - - switch (VCondition(inst.dest & 0xF)) { - case VC_EQ: - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(SCRATCH1, CC_EQ); - break; - case VC_NE: - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(SCRATCH1, CC_NEQ); - break; - case VC_LT: - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(SCRATCH1, CC_LO); - break; - case VC_LE: - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(SCRATCH1, CC_LS); - break; - case VC_GT: - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(SCRATCH1, CC_GT); - break; - case VC_GE: - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - CSET(SCRATCH1, CC_GE); - break; - case VC_EZ: - regs_.MapFPR(inst.src1); - fp_.FCMP(regs_.F(inst.src1)); - CSET(SCRATCH1, CC_EQ); - break; - case VC_NZ: - regs_.MapFPR(inst.src1); - fp_.FCMP(regs_.F(inst.src1)); - CSET(SCRATCH1, CC_NEQ); - break; - case VC_EN: - regs_.MapFPR(inst.src1); - fp_.FCMP(regs_.F(inst.src1)); - CSET(SCRATCH1, CC_VS); - break; - case VC_NN: - regs_.MapFPR(inst.src1); - fp_.FCMP(regs_.F(inst.src1)); - CSET(SCRATCH1, CC_VC); - break; - case VC_EI: - regs_.MapFPR(inst.src1); - // Compare abs(f) >= Infinity. Could use FACGE for vector. - MOVI2R(SCRATCH1, 0x7F800000); - fp_.FMOV(SCRATCHF2, SCRATCH1); - fp_.FABS(SCRATCHF1, regs_.F(inst.src1)); - fp_.FCMP(SCRATCHF1, SCRATCHF2); - CSET(SCRATCH1, CC_GE); - break; - case VC_NI: - regs_.MapFPR(inst.src1); - // Compare abs(f) < Infinity. - MOVI2R(SCRATCH1, 0x7F800000); - fp_.FMOV(SCRATCHF2, SCRATCH1); - fp_.FABS(SCRATCHF1, regs_.F(inst.src1)); - fp_.FCMP(SCRATCHF1, SCRATCHF2); - // Less than or NAN. - CSET(SCRATCH1, CC_LT); - break; - case VC_ES: - regs_.MapFPR(inst.src1); - // Compare abs(f) < Infinity. - MOVI2R(SCRATCH1, 0x7F800000); - fp_.FMOV(SCRATCHF2, SCRATCH1); - fp_.FABS(SCRATCHF1, regs_.F(inst.src1)); - fp_.FCMP(SCRATCHF1, SCRATCHF2); - // Greater than or equal to Infinity, or NAN. - CSET(SCRATCH1, CC_HS); - break; - case VC_NS: - regs_.MapFPR(inst.src1); - // Compare abs(f) < Infinity. - MOVI2R(SCRATCH1, 0x7F800000); - fp_.FMOV(SCRATCHF2, SCRATCH1); - fp_.FABS(SCRATCHF1, regs_.F(inst.src1)); - fp_.FCMP(SCRATCHF1, SCRATCHF2); - // Less than Infinity, but not NAN. - CSET(SCRATCH1, CC_LO); - break; - case VC_TR: - MOVI2R(SCRATCH1, 1); - break; - case VC_FL: - MOVI2R(SCRATCH1, 0); - break; - } - - BFI(regs_.R(IRREG_VFPU_CC), SCRATCH1, inst.dest >> 4, 1); - break; - - case IROp::FCmpVfpuAggregate: - regs_.MapGPR(IRREG_VFPU_CC, MIPSMap::DIRTY); - if (inst.dest == 1) { - // Just replicate the lowest bit to the others. - BFI(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), 4, 1); - BFI(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), 5, 1); - } else { - MOVI2R(SCRATCH1, inst.dest); - // Grab the any bit. - TST(regs_.R(IRREG_VFPU_CC), SCRATCH1); - CSET(SCRATCH2, CC_NEQ); - // Now the all bit, by clearing our mask to zero. - BICS(WZR, SCRATCH1, regs_.R(IRREG_VFPU_CC)); - CSET(SCRATCH1, CC_EQ); - - // Insert the bits into place. - BFI(regs_.R(IRREG_VFPU_CC), SCRATCH2, 4, 1); - BFI(regs_.R(IRREG_VFPU_CC), SCRATCH1, 5, 1); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_FCondAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - // For Vec4, we could basically just ORR FCMPGE/FCMPLE together, but overlap is trickier. - regs_.Map(inst); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src2)); - FixupBranch unordered = B(CC_VS); - - switch (inst.op) { - case IROp::FMin: - fp_.FMIN(regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FMax: - fp_.FMAX(regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - default: - INVALIDOP; - break; - } - - FixupBranch orderedDone = B(); - - // Not sure if this path is fast, trying to optimize it to be small but correct. - // Probably an uncommon path. - SetJumpTarget(unordered); - fp_.AND(EncodeRegToDouble(SCRATCHF1), regs_.FD(inst.src1), regs_.FD(inst.src2)); - // SCRATCHF1 = 0xFFFFFFFF if sign bit set on both, 0x00000000 otherwise. - fp_.CMLT(32, EncodeRegToDouble(SCRATCHF1), EncodeRegToDouble(SCRATCHF1)); - - switch (inst.op) { - case IROp::FMin: - fp_.SMAX(32, EncodeRegToDouble(SCRATCHF2), regs_.FD(inst.src1), regs_.FD(inst.src2)); - fp_.SMIN(32, regs_.FD(inst.dest), regs_.FD(inst.src1), regs_.FD(inst.src2)); - break; - - case IROp::FMax: - fp_.SMIN(32, EncodeRegToDouble(SCRATCHF2), regs_.FD(inst.src1), regs_.FD(inst.src2)); - fp_.SMAX(32, regs_.FD(inst.dest), regs_.FD(inst.src1), regs_.FD(inst.src2)); - break; - - default: - INVALIDOP; - break; - } - // Replace dest with SCRATCHF2 if both were less than zero. - fp_.BIT(regs_.FD(inst.dest), EncodeRegToDouble(SCRATCHF2), EncodeRegToDouble(SCRATCHF1)); - - SetJumpTarget(orderedDone); -} - -void Arm64JitBackend::CompIR_FCvt(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FCvtWS: - // TODO: Unfortunately, we don't currently have the hasSetRounding flag, could skip lookup. - regs_.Map(inst); - fp_.FMOV(S0, regs_.F(inst.src1)); - - MOVP2R(SCRATCH1_64, ¤tRoundingFunc_); - LDR(INDEX_UNSIGNED, SCRATCH1_64, SCRATCH1_64, 0); - BLR(SCRATCH1_64); - - fp_.FMOV(regs_.F(inst.dest), S0); - break; - - case IROp::FCvtSW: - regs_.Map(inst); - fp_.SCVTF(regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FCvtScaledWS: - if (IRRoundMode(inst.src2 >> 6) == IRRoundMode::CAST_1) { - regs_.Map(inst); - // NAN would convert to zero, so detect it specifically and replace with 0x7FFFFFFF. - fp_.MVNI(32, EncodeRegToDouble(SCRATCHF2), 0x80, 24); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src1)); - fp_.FCVTZS(regs_.F(inst.dest), regs_.F(inst.src1), inst.src2 & 0x1F); - fp_.FCSEL(regs_.F(inst.dest), regs_.F(inst.dest), SCRATCHF2, CC_VC); - } else { - RoundingMode rm; - switch (IRRoundMode(inst.src2 >> 6)) { - case IRRoundMode::RINT_0: rm = RoundingMode::ROUND_N; break; - case IRRoundMode::CEIL_2: rm = RoundingMode::ROUND_P; break; - case IRRoundMode::FLOOR_3: rm = RoundingMode::ROUND_M; break; - default: - _assert_msg_(false, "Invalid rounding mode for FCvtScaledWS"); - } - - // Unfortunately, only Z has a direct scaled instruction. - // We'll have to multiply. - regs_.Map(inst); - fp_.MOVI2F(SCRATCHF1, (float)(1UL << (inst.src2 & 0x1F)), SCRATCH1); - // This is for the NAN result. - fp_.MVNI(32, EncodeRegToDouble(SCRATCHF2), 0x80, 24); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src1)); - fp_.FMUL(regs_.F(inst.dest), regs_.F(inst.src1), SCRATCHF1); - fp_.FCVTS(regs_.F(inst.dest), regs_.F(inst.dest), rm); - fp_.FCSEL(regs_.F(inst.dest), regs_.F(inst.dest), SCRATCHF2, CC_VC); - } - break; - - case IROp::FCvtScaledSW: - // TODO: This is probably proceeded by a GPR transfer, might be ideal to combine. - regs_.Map(inst); - fp_.SCVTF(regs_.F(inst.dest), regs_.F(inst.src1), inst.src2 & 0x1F); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_FRound(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.Map(inst); - // Invert 0x80000000 -> 0x7FFFFFFF for the NAN result. - fp_.MVNI(32, EncodeRegToDouble(SCRATCHF1), 0x80, 24); - fp_.FCMP(regs_.F(inst.src1), regs_.F(inst.src1)); - - // Luckily, these already saturate. - switch (inst.op) { - case IROp::FRound: - fp_.FCVTS(regs_.F(inst.dest), regs_.F(inst.src1), ROUND_N); - break; - - case IROp::FTrunc: - fp_.FCVTS(regs_.F(inst.dest), regs_.F(inst.src1), ROUND_Z); - break; - - case IROp::FCeil: - fp_.FCVTS(regs_.F(inst.dest), regs_.F(inst.src1), ROUND_P); - break; - - case IROp::FFloor: - fp_.FCVTS(regs_.F(inst.dest), regs_.F(inst.src1), ROUND_M); - break; - - default: - INVALIDOP; - break; - } - - // Switch to INT_MAX if it was NAN. - fp_.FCSEL(regs_.F(inst.dest), regs_.F(inst.dest), SCRATCHF1, CC_VC); -} - -void Arm64JitBackend::CompIR_FSat(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FSat0_1: - regs_.Map(inst); - fp_.MOVI2F(SCRATCHF1, 1.0f); - // Note that FMAX takes the larger of the two zeros, which is what we want. - fp_.MOVI2F(SCRATCHF2, 0.0f); - - fp_.FMIN(regs_.F(inst.dest), regs_.F(inst.src1), SCRATCHF1); - fp_.FMAX(regs_.F(inst.dest), regs_.F(inst.dest), SCRATCHF2); - break; - - case IROp::FSatMinus1_1: - regs_.Map(inst); - fp_.MOVI2F(SCRATCHF1, 1.0f); - fp_.FNEG(SCRATCHF2, SCRATCHF1); - - fp_.FMIN(regs_.F(inst.dest), regs_.F(inst.src1), SCRATCHF1); - fp_.FMAX(regs_.F(inst.dest), regs_.F(inst.dest), SCRATCHF2); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_FSpecial(IRInst inst) { - CONDITIONAL_DISABLE; - - auto callFuncF_F = [&](float (*func)(float)) { - regs_.FlushBeforeCall(); - WriteDebugProfilerStatus(IRProfilerStatus::MATH_HELPER); - - // It might be in a non-volatile register. - // TODO: May have to handle a transfer if SIMD here. - if (regs_.IsFPRMapped(inst.src1)) { - int lane = regs_.GetFPRLane(inst.src1); - if (lane == 0) - fp_.FMOV(S0, regs_.F(inst.src1)); - else - fp_.DUP(32, Q0, regs_.F(inst.src1), lane); - } else { - int offset = offsetof(MIPSState, f) + inst.src1 * 4; - fp_.LDR(32, INDEX_UNSIGNED, S0, CTXREG, offset); - } - QuickCallFunction(SCRATCH2_64, func); - - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - // If it's already F10, we're done - MapReg doesn't actually overwrite the reg in that case. - if (regs_.F(inst.dest) != S0) { - fp_.FMOV(regs_.F(inst.dest), S0); - } - - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - }; - - switch (inst.op) { - case IROp::FSin: - callFuncF_F(&vfpu_sin); - break; - - case IROp::FCos: - callFuncF_F(&vfpu_cos); - break; - - case IROp::FRSqrt: - regs_.Map(inst); - fp_.MOVI2F(SCRATCHF1, 1.0f); - fp_.FSQRT(regs_.F(inst.dest), regs_.F(inst.src1)); - fp_.FDIV(regs_.F(inst.dest), SCRATCHF1, regs_.F(inst.dest)); - break; - - case IROp::FRecip: - regs_.Map(inst); - fp_.MOVI2F(SCRATCHF1, 1.0f); - fp_.FDIV(regs_.F(inst.dest), SCRATCHF1, regs_.F(inst.src1)); - break; - - case IROp::FAsin: - callFuncF_F(&vfpu_asin); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_RoundingMode(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::RestoreRoundingMode: - RestoreRoundingMode(); - break; - - case IROp::ApplyRoundingMode: - ApplyRoundingMode(); - break; - - case IROp::UpdateRoundingMode: - UpdateRoundingMode(); - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRCompLoadStore.cpp b/Core/MIPS/ARM64/Arm64IRCompLoadStore.cpp deleted file mode 100644 index d0fde9f6f..000000000 --- a/Core/MIPS/ARM64/Arm64IRCompLoadStore.cpp +++ /dev/null @@ -1,453 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include "Core/MemMap.h" -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -// This file contains compilation for load/store instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -static int IROpToByteWidth(IROp op) { - switch (op) { - case IROp::Load8: - case IROp::Load8Ext: - case IROp::Store8: - return 1; - - case IROp::Load16: - case IROp::Load16Ext: - case IROp::Store16: - return 2; - - case IROp::Load32: - case IROp::Load32Linked: - case IROp::Load32Left: - case IROp::Load32Right: - case IROp::LoadFloat: - case IROp::Store32: - case IROp::Store32Conditional: - case IROp::Store32Left: - case IROp::Store32Right: - case IROp::StoreFloat: - return 4; - - case IROp::LoadVec4: - case IROp::StoreVec4: - return 16; - - default: - _assert_msg_(false, "Unexpected op: %s", GetIRMeta(op) ? GetIRMeta(op)->name : "?"); - return -1; - } -} - -Arm64JitBackend::LoadStoreArg Arm64JitBackend::PrepareSrc1Address(IRInst inst) { - const IRMeta *m = GetIRMeta(inst.op); - - bool src1IsPointer = regs_.IsGPRMappedAsPointer(inst.src1); - bool readsFromSrc1 = inst.src1 == inst.src3 && (m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0; - // If it's about to be clobbered, don't waste time pointerifying. Use displacement. - bool clobbersSrc1 = !readsFromSrc1 && regs_.IsGPRClobbered(inst.src1); - - int64_t imm = (int32_t)inst.constant; - // It can't be this negative, must be a constant address with the top bit set. - if ((imm & 0xC0000000) == 0x80000000) { - imm = (uint64_t)(uint32_t)inst.constant; - } - - LoadStoreArg addrArg; - if (inst.src1 == MIPS_REG_ZERO) { - // The constant gets applied later. - addrArg.base = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - imm &= Memory::MEMVIEW32_MASK; -#endif - } else if (!jo.enablePointerify && readsFromSrc1) { -#ifndef MASKED_PSP_MEMORY - if (imm == 0) { - addrArg.base = MEMBASEREG; - addrArg.regOffset = regs_.MapGPR(inst.src1); - addrArg.useRegisterOffset = true; - addrArg.signExtendRegOffset = false; - } -#endif - - // Since we can't modify src1, let's just use a temp reg while copying. - if (!addrArg.useRegisterOffset) { - ADDI2R(SCRATCH1, regs_.MapGPR(inst.src1), imm, SCRATCH2); -#ifdef MASKED_PSP_MEMORY - ANDI2R(SCRATCH1, SCRATCH1, Memory::MEMVIEW32_MASK, SCRATCH2); -#endif - - addrArg.base = MEMBASEREG; - addrArg.regOffset = SCRATCH1; - addrArg.useRegisterOffset = true; - addrArg.signExtendRegOffset = false; - } - } else if ((jo.cachePointers && !clobbersSrc1) || src1IsPointer) { - // The offset gets set later. - addrArg.base = regs_.MapGPRAsPointer(inst.src1); - } else { - ADDI2R(SCRATCH1, regs_.MapGPR(inst.src1), imm, SCRATCH2); -#ifdef MASKED_PSP_MEMORY - ANDI2R(SCRATCH1, SCRATCH1, Memory::MEMVIEW32_MASK, SCRATCH2); -#endif - - addrArg.base = MEMBASEREG; - addrArg.regOffset = SCRATCH1; - addrArg.useRegisterOffset = true; - addrArg.signExtendRegOffset = false; - } - - // That's src1 taken care of, and possibly imm. - // If useRegisterOffset is false, imm still needs to be accounted for. - if (!addrArg.useRegisterOffset && imm != 0) { -#ifdef MASKED_PSP_MEMORY - // In case we have an address + offset reg. - if (imm > 0) - imm &= Memory::MEMVIEW32_MASK; -#endif - - int scale = IROpToByteWidth(inst.op); - if (imm > 0 && (imm & (scale - 1)) == 0 && imm <= 0xFFF * scale) { - // Okay great, use the LDR/STR form. - addrArg.immOffset = (int)imm; - addrArg.useUnscaled = false; - } else if (imm >= -256 && imm < 256) { - // An unscaled offset (LDUR/STUR) should work fine for this range. - addrArg.immOffset = (int)imm; - addrArg.useUnscaled = true; - } else { - // No luck, we'll need to load into a register. - MOVI2R(SCRATCH1, imm); - addrArg.regOffset = SCRATCH1; - addrArg.useRegisterOffset = true; - addrArg.signExtendRegOffset = true; - } - } - - return addrArg; -} - -void Arm64JitBackend::CompIR_CondStore(IRInst inst) { - CONDITIONAL_DISABLE; - if (inst.op != IROp::Store32Conditional) - INVALIDOP; - - regs_.SpillLockGPR(IRREG_LLBIT, inst.src3, inst.src1); - LoadStoreArg addrArg = PrepareSrc1Address(inst); - ARM64Reg valueReg = regs_.MapGPR(inst.src3, MIPSMap::INIT); - - regs_.MapGPR(IRREG_LLBIT, MIPSMap::INIT); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - FixupBranch condFailed = CBZ(regs_.R(IRREG_LLBIT)); - - if (addrArg.useRegisterOffset) { - STR(valueReg, addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - STUR(valueReg, addrArg.base, addrArg.immOffset); - } else { - STR(INDEX_UNSIGNED, valueReg, addrArg.base, addrArg.immOffset); - } - - if (inst.dest != MIPS_REG_ZERO) { - MOVI2R(regs_.R(inst.dest), 1); - FixupBranch finish = B(); - - SetJumpTarget(condFailed); - MOVI2R(regs_.R(inst.dest), 0); - SetJumpTarget(finish); - } else { - SetJumpTarget(condFailed); - } -} - -void Arm64JitBackend::CompIR_FLoad(IRInst inst) { - CONDITIONAL_DISABLE; - - LoadStoreArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::LoadFloat: - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - if (addrArg.useRegisterOffset) { - fp_.LDR(32, regs_.F(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - fp_.LDUR(32, regs_.F(inst.dest), addrArg.base, addrArg.immOffset); - } else { - fp_.LDR(32, INDEX_UNSIGNED, regs_.F(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_FStore(IRInst inst) { - CONDITIONAL_DISABLE; - - LoadStoreArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::StoreFloat: - regs_.MapFPR(inst.src3); - if (addrArg.useRegisterOffset) { - fp_.STR(32, regs_.F(inst.src3), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - fp_.STUR(32, regs_.F(inst.src3), addrArg.base, addrArg.immOffset); - } else { - fp_.STR(32, INDEX_UNSIGNED, regs_.F(inst.src3), addrArg.base, addrArg.immOffset); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Load(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.SpillLockGPR(inst.dest, inst.src1); - LoadStoreArg addrArg = PrepareSrc1Address(inst); - // With NOINIT, MapReg won't subtract MEMBASEREG even if dest == src1. - regs_.MapGPR(inst.dest, MIPSMap::NOINIT); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::Load8: - if (addrArg.useRegisterOffset) { - LDRB(regs_.R(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - LDURB(regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } else { - LDRB(INDEX_UNSIGNED, regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Load8Ext: - if (addrArg.useRegisterOffset) { - LDRSB(regs_.R(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - LDURSB(regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } else { - LDRSB(INDEX_UNSIGNED, regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Load16: - if (addrArg.useRegisterOffset) { - LDRH(regs_.R(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - LDURH(regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } else { - LDRH(INDEX_UNSIGNED, regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Load16Ext: - if (addrArg.useRegisterOffset) { - LDRSH(regs_.R(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - LDURSH(regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } else { - LDRSH(INDEX_UNSIGNED, regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Load32: - if (addrArg.useRegisterOffset) { - LDR(regs_.R(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - LDUR(regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } else { - LDR(INDEX_UNSIGNED, regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Load32Linked: - if (inst.dest != MIPS_REG_ZERO) { - if (addrArg.useRegisterOffset) { - LDR(regs_.R(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - LDUR(regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } else { - LDR(INDEX_UNSIGNED, regs_.R(inst.dest), addrArg.base, addrArg.immOffset); - } - } - regs_.SetGPRImm(IRREG_LLBIT, 1); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_LoadShift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Load32Left: - case IROp::Load32Right: - // Should not happen if the pass to split is active. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Store(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.SpillLockGPR(inst.src3, inst.src1); - LoadStoreArg addrArg = PrepareSrc1Address(inst); - - ARM64Reg valueReg = regs_.TryMapTempImm(inst.src3); - if (valueReg == INVALID_REG) - valueReg = regs_.MapGPR(inst.src3); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::Store8: - if (addrArg.useRegisterOffset) { - STRB(valueReg, addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - STURB(valueReg, addrArg.base, addrArg.immOffset); - } else { - STRB(INDEX_UNSIGNED, valueReg, addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Store16: - if (addrArg.useRegisterOffset) { - STRH(valueReg, addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - STURH(valueReg, addrArg.base, addrArg.immOffset); - } else { - STRH(INDEX_UNSIGNED, valueReg, addrArg.base, addrArg.immOffset); - } - break; - - case IROp::Store32: - if (addrArg.useRegisterOffset) { - STR(valueReg, addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - STUR(valueReg, addrArg.base, addrArg.immOffset); - } else { - STR(INDEX_UNSIGNED, valueReg, addrArg.base, addrArg.immOffset); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_StoreShift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Store32Left: - case IROp::Store32Right: - // Should not happen if the pass to split is active. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_VecLoad(IRInst inst) { - CONDITIONAL_DISABLE; - - LoadStoreArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::LoadVec4: - regs_.MapVec4(inst.dest, MIPSMap::NOINIT); - if (addrArg.useRegisterOffset) { - fp_.LDR(128, regs_.FQ(inst.dest), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - fp_.LDUR(128, regs_.FQ(inst.dest), addrArg.base, addrArg.immOffset); - } else { - fp_.LDR(128, INDEX_UNSIGNED, regs_.FQ(inst.dest), addrArg.base, addrArg.immOffset); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_VecStore(IRInst inst) { - CONDITIONAL_DISABLE; - - LoadStoreArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::StoreVec4: - regs_.MapVec4(inst.src3); - if (addrArg.useRegisterOffset) { - fp_.STR(128, regs_.FQ(inst.src3), addrArg.base, ArithOption(addrArg.regOffset, false, addrArg.signExtendRegOffset)); - } else if (addrArg.useUnscaled) { - fp_.STUR(128, regs_.FQ(inst.src3), addrArg.base, addrArg.immOffset); - } else { - fp_.STR(128, INDEX_UNSIGNED, regs_.FQ(inst.src3), addrArg.base, addrArg.immOffset); - } - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRCompSystem.cpp b/Core/MIPS/ARM64/Arm64IRCompSystem.cpp deleted file mode 100644 index 8fba3c320..000000000 --- a/Core/MIPS/ARM64/Arm64IRCompSystem.cpp +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include "Common/Profiler/Profiler.h" -#include "Core/Core.h" -#include "Core/Debugger/Breakpoints.h" -#include "Core/HLE/HLE.h" -#include "Core/HLE/ReplaceTables.h" -#include "Core/MemMap.h" -#include "Core/MIPS/MIPSAnalyst.h" -#include "Core/MIPS/IR/IRInterpreter.h" -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -// This file contains compilation for basic PC/downcount accounting, syscalls, debug funcs, etc. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -void Arm64JitBackend::CompIR_Basic(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Downcount: - SUBI2R(DOWNCOUNTREG, DOWNCOUNTREG, (s64)(s32)inst.constant, SCRATCH1); - break; - - case IROp::SetConst: - regs_.SetGPRImm(inst.dest, inst.constant); - break; - - case IROp::SetConstF: - { - regs_.Map(inst); - float f; - memcpy(&f, &inst.constant, sizeof(f)); - fp_.MOVI2F(regs_.F(inst.dest), f, SCRATCH1); - break; - } - - case IROp::SetPC: - regs_.Map(inst); - MovToPC(regs_.R(inst.src1)); - break; - - case IROp::SetPCConst: - lastConstPC_ = inst.constant; - MOVI2R(SCRATCH1, inst.constant); - MovToPC(SCRATCH1); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Breakpoint(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Breakpoint: - { - FlushAll(); - // Note: the constant could be a delay slot. - MOVI2R(W0, inst.constant); - QuickCallFunction(SCRATCH2_64, &IRRunBreakpoint); - - ptrdiff_t distance = dispatcherCheckCoreState_ - GetCodePointer(); - if (distance >= -0x100000 && distance < 0x100000) { - CBNZ(W0, dispatcherCheckCoreState_); - } else { - FixupBranch keepOnKeepingOn = CBZ(W0); - B(dispatcherCheckCoreState_); - SetJumpTarget(keepOnKeepingOn); - } - break; - } - - case IROp::MemoryCheck: - if (regs_.IsGPRImm(inst.src1)) { - uint32_t iaddr = regs_.GetGPRImm(inst.src1) + inst.constant; - uint32_t checkedPC = lastConstPC_ + inst.dest; - int size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - if (size == 0) { - checkedPC += 4; - size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - } - bool isWrite = MIPSAnalyst::IsOpMemoryWrite(checkedPC); - - MemCheck check; - if (CBreakPoints::GetMemCheckInRange(iaddr, size, &check)) { - if (!(check.cond & MEMCHECK_READ) && !isWrite) - break; - if (!(check.cond & (MEMCHECK_WRITE | MEMCHECK_WRITE_ONCHANGE)) && isWrite) - break; - - // We need to flush, or conditions and log expressions will see old register values. - FlushAll(); - - MOVI2R(W0, checkedPC); - MOVI2R(W1, iaddr); - QuickCallFunction(SCRATCH2_64, &IRRunMemCheck); - - ptrdiff_t distance = dispatcherCheckCoreState_ - GetCodePointer(); - if (distance >= -0x100000 && distance < 0x100000) { - CBNZ(W0, dispatcherCheckCoreState_); - } else { - FixupBranch keepOnKeepingOn = CBZ(W0); - B(dispatcherCheckCoreState_); - SetJumpTarget(keepOnKeepingOn); - } - } - } else { - uint32_t checkedPC = lastConstPC_ + inst.dest; - int size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - if (size == 0) { - checkedPC += 4; - size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - } - bool isWrite = MIPSAnalyst::IsOpMemoryWrite(checkedPC); - - const auto memchecks = CBreakPoints::GetMemCheckRanges(isWrite); - // We can trivially skip if there are no checks for this type (i.e. read vs write.) - if (memchecks.empty()) - break; - - ARM64Reg addrBase = regs_.MapGPR(inst.src1); - ADDI2R(SCRATCH1, addrBase, inst.constant, SCRATCH2); - - // We need to flush, or conditions and log expressions will see old register values. - FlushAll(); - - std::vector hitChecks; - for (auto it : memchecks) { - if (it.end != 0) { - CMPI2R(SCRATCH1, it.start - size, SCRATCH2); - MOVI2R(SCRATCH2, it.end); - CCMP(SCRATCH1, SCRATCH2, 0xF, CC_HI); - hitChecks.push_back(B(CC_LO)); - } else { - CMPI2R(SCRATCH1, it.start, SCRATCH2); - hitChecks.push_back(B(CC_EQ)); - } - } - - FixupBranch noHits = B(); - - // Okay, now land any hit here. - for (auto &fixup : hitChecks) - SetJumpTarget(fixup); - hitChecks.clear(); - - MOVI2R(W0, checkedPC); - MOV(W1, SCRATCH1); - QuickCallFunction(SCRATCH2_64, &IRRunMemCheck); - - ptrdiff_t distance = dispatcherCheckCoreState_ - GetCodePointer(); - if (distance >= -0x100000 && distance < 0x100000) { - CBNZ(W0, dispatcherCheckCoreState_); - } else { - FixupBranch keepOnKeepingOn = CBZ(W0); - B(dispatcherCheckCoreState_); - SetJumpTarget(keepOnKeepingOn); - } - - SetJumpTarget(noHits); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_System(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Syscall: - FlushAll(); - SaveStaticRegisters(); - - WriteDebugProfilerStatus(IRProfilerStatus::SYSCALL); -#ifdef USE_PROFILER - // When profiling, we can't skip CallSyscall, since it times syscalls. - MOVI2R(W0, inst.constant); - QuickCallFunction(SCRATCH2_64, &CallSyscall); -#else - // Skip the CallSyscall where possible. - { - MIPSOpcode op(inst.constant); - void *quickFunc = GetQuickSyscallFunc(op); - if (quickFunc) { - MOVP2R(X0, GetSyscallFuncPointer(op)); - QuickCallFunction(SCRATCH2_64, (const u8 *)quickFunc); - } else { - MOVI2R(W0, inst.constant); - QuickCallFunction(SCRATCH2_64, &CallSyscall); - } - } -#endif - - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - // This is always followed by an ExitToPC, where we check coreState. - break; - - case IROp::CallReplacement: - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::REPLACEMENT); - QuickCallFunction(SCRATCH2_64, GetReplacementFunc(inst.constant)->replaceFunc); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - SUB(DOWNCOUNTREG, DOWNCOUNTREG, W0); - break; - - case IROp::Break: - FlushAll(); - // This doesn't naturally have restore/apply around it. - RestoreRoundingMode(true); - SaveStaticRegisters(); - MovFromPC(W0); - QuickCallFunction(SCRATCH2_64, &Core_Break); - LoadStaticRegisters(); - ApplyRoundingMode(true); - MovFromPC(SCRATCH1); - ADDI2R(SCRATCH1, SCRATCH1, 4, SCRATCH2); - B(dispatcherPCInSCRATCH1_); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_Transfer(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::SetCtrlVFPU: - regs_.SetGPRImm(IRREG_VFPU_CTRL_BASE + inst.dest, inst.constant); - break; - - case IROp::SetCtrlVFPUReg: - regs_.Map(inst); - MOV(regs_.R(IRREG_VFPU_CTRL_BASE + inst.dest), regs_.R(inst.src1)); - break; - - case IROp::SetCtrlVFPUFReg: - regs_.Map(inst); - fp_.FMOV(regs_.R(IRREG_VFPU_CTRL_BASE + inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FpCondFromReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - MOV(regs_.R(IRREG_FPCOND), regs_.R(inst.src1)); - break; - - case IROp::FpCondToReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::INIT } }); - MOV(regs_.R(inst.dest), regs_.R(IRREG_FPCOND)); - break; - - case IROp::FpCtrlFromReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - ANDI2R(SCRATCH1, regs_.R(inst.src1), 0x0181FFFF, SCRATCH2); - // Extract the new fpcond value. - UBFX(regs_.R(IRREG_FPCOND), SCRATCH1, 23, 1); - STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, IRREG_FCR31 * 4); - break; - - case IROp::FpCtrlToReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::INIT } }); - // Load fcr31 and clear the fpcond bit. - LDR(INDEX_UNSIGNED, regs_.R(inst.dest), CTXREG, IRREG_FCR31 * 4); - BFI(regs_.R(inst.dest), regs_.R(IRREG_FPCOND), 23, 1); - // Also update mips->fcr31 while we're here. - STR(INDEX_UNSIGNED, regs_.R(inst.dest), CTXREG, IRREG_FCR31 * 4); - break; - - case IROp::VfpuCtrlToReg: - regs_.Map(inst); - MOV(regs_.R(inst.dest), regs_.R(IRREG_VFPU_CTRL_BASE + inst.src1)); - break; - - case IROp::FMovFromGPR: - if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) { - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - fp_.MOVI2F(regs_.F(inst.dest), 0.0f, SCRATCH1); - } else { - regs_.Map(inst); - fp_.FMOV(regs_.F(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::FMovToGPR: - regs_.Map(inst); - fp_.FMOV(regs_.R(inst.dest), regs_.F(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_ValidateAddress(IRInst inst) { - CONDITIONAL_DISABLE; - - bool isWrite = inst.src2 & 1; - int alignment = 0; - switch (inst.op) { - case IROp::ValidateAddress8: - alignment = 1; - break; - - case IROp::ValidateAddress16: - alignment = 2; - break; - - case IROp::ValidateAddress32: - alignment = 4; - break; - - case IROp::ValidateAddress128: - alignment = 16; - break; - - default: - INVALIDOP; - break; - } - - if (regs_.IsGPRMappedAsPointer(inst.src1)) { - if (!jo.enablePointerify) { - SUB(SCRATCH1_64, regs_.RPtr(inst.src1), MEMBASEREG); - ADDI2R(SCRATCH1, SCRATCH1, inst.constant, SCRATCH2); - } else { - ADDI2R(SCRATCH1, regs_.R(inst.src1), inst.constant, SCRATCH2); - } - } else { - regs_.Map(inst); - ADDI2R(SCRATCH1, regs_.R(inst.src1), inst.constant, SCRATCH2); - } - ANDI2R(SCRATCH1, SCRATCH1, 0x3FFFFFFF, SCRATCH2); - - std::vector validJumps; - - FixupBranch unaligned; - if (alignment == 2) { - unaligned = TBNZ(SCRATCH1, 0); - } else if (alignment != 1) { - TSTI2R(SCRATCH1, alignment - 1, SCRATCH2); - unaligned = B(CC_NEQ); - } - - CMPI2R(SCRATCH1, PSP_GetUserMemoryEnd() - alignment, SCRATCH2); - FixupBranch tooHighRAM = B(CC_HI); - CMPI2R(SCRATCH1, PSP_GetKernelMemoryBase(), SCRATCH2); - validJumps.push_back(B(CC_HS)); - - CMPI2R(SCRATCH1, PSP_GetVidMemEnd() - alignment, SCRATCH2); - FixupBranch tooHighVid = B(CC_HI); - CMPI2R(SCRATCH1, PSP_GetVidMemBase(), SCRATCH2); - validJumps.push_back(B(CC_HS)); - - CMPI2R(SCRATCH1, PSP_GetScratchpadMemoryEnd() - alignment, SCRATCH2); - FixupBranch tooHighScratch = B(CC_HI); - CMPI2R(SCRATCH1, PSP_GetScratchpadMemoryBase(), SCRATCH2); - validJumps.push_back(B(CC_HS)); - - if (alignment != 1) - SetJumpTarget(unaligned); - SetJumpTarget(tooHighRAM); - SetJumpTarget(tooHighVid); - SetJumpTarget(tooHighScratch); - - // If we got here, something unusual and bad happened, so we'll always go back to the dispatcher. - // Because of that, we can avoid flushing outside this case. - auto regsCopy = regs_; - regsCopy.FlushAll(); - - // Ignores the return value, always returns to the dispatcher. - // Otherwise would need a thunk to restore regs. - MOV(W0, SCRATCH1); - MOVI2R(W1, alignment); - MOVI2R(W2, isWrite ? 1 : 0); - QuickCallFunction(SCRATCH2, &ReportBadAddress); - B(dispatcherCheckCoreState_); - - for (FixupBranch &b : validJumps) - SetJumpTarget(b); -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRCompVec.cpp b/Core/MIPS/ARM64/Arm64IRCompVec.cpp deleted file mode 100644 index 08665051c..000000000 --- a/Core/MIPS/ARM64/Arm64IRCompVec.cpp +++ /dev/null @@ -1,772 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include -#include "Common/CPUDetect.h" -#include "Core/MemMap.h" -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -// This file contains compilation for vector instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -static bool Overlap(IRReg r1, int l1, IRReg r2, int l2) { - return r1 < r2 + l2 && r1 + l1 > r2; -} - -void Arm64JitBackend::CompIR_VecArith(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Add: - regs_.Map(inst); - fp_.FADD(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2)); - break; - - case IROp::Vec4Sub: - regs_.Map(inst); - fp_.FSUB(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2)); - break; - - case IROp::Vec4Mul: - regs_.Map(inst); - fp_.FMUL(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2)); - break; - - case IROp::Vec4Div: - regs_.Map(inst); - fp_.FDIV(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2)); - break; - - case IROp::Vec4Scale: - if (Overlap(inst.dest, 4, inst.src2, 1) || Overlap(inst.src1, 4, inst.src2, 1)) { - // ARM64 can handle this, but we have to map specially. - regs_.SpillLockFPR(inst.dest, inst.src1); - regs_.MapVec4(inst.src1); - regs_.MapVec4(inst.src2 & ~3); - regs_.MapVec4(inst.dest, MIPSMap::NOINIT); - fp_.FMUL(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2 & ~3), inst.src2 & 3); - } else { - regs_.Map(inst); - fp_.FMUL(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2), 0); - } - break; - - case IROp::Vec4Neg: - regs_.Map(inst); - fp_.FNEG(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - break; - - case IROp::Vec4Abs: - regs_.Map(inst); - fp_.FABS(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -enum class Arm64Shuffle { - DUP0_AAAA, - DUP1_BBBB, - DUP2_CCCC, - DUP3_DDDD, - MOV_ABCD, - TRN1_AACC, - TRN2_BBDD, - UZP1_ACAC, - UZP2_BDBD, - ZIP1_AABB, - ZIP2_CCDD, - REV64_BADC, - EXT4_BCDA, - EXT8_CDAB, - EXT12_DABC, - - // These steps are more expensive and use a temp. - REV64_EXT8_CDBA, - REV64_EXT8_DCAB, - EXT4_UZP1_BDAC, - EXT4_UZP2_CABD, - EXT8_ZIP1_ACBD, - EXT8_ZIP2_CADB, - - // Any that don't fully replace dest must be after this point. - INS0_TO_1, - INS0_TO_2, - INS0_TO_3, - INS1_TO_0, - INS1_TO_2, - INS1_TO_3, - INS2_TO_0, - INS2_TO_1, - INS2_TO_3, - INS3_TO_0, - INS3_TO_1, - INS3_TO_2, - XTN2, - - // These hacks to prevent 4 instructions, but scoring isn't smart enough to avoid. - EXT12_ZIP1_ADBA, - DUP3_UZP1_DDAC, - - COUNT_NORMAL = EXT12_ZIP1_ADBA, - COUNT_SIMPLE = REV64_EXT8_CDBA, - COUNT_NOPREV = INS0_TO_1, -}; - -uint8_t Arm64ShuffleMask(Arm64Shuffle method) { - // Hopefully optimized into a lookup table, this is a bit less confusing to read... - switch (method) { - case Arm64Shuffle::DUP0_AAAA: return 0x00; - case Arm64Shuffle::DUP1_BBBB: return 0x55; - case Arm64Shuffle::DUP2_CCCC: return 0xAA; - case Arm64Shuffle::DUP3_DDDD: return 0xFF; - case Arm64Shuffle::MOV_ABCD: return 0xE4; - case Arm64Shuffle::TRN1_AACC: return 0xA0; - case Arm64Shuffle::TRN2_BBDD: return 0xF5; - case Arm64Shuffle::UZP1_ACAC: return 0x88; - case Arm64Shuffle::UZP2_BDBD: return 0xDD; - case Arm64Shuffle::ZIP1_AABB: return 0x50; - case Arm64Shuffle::ZIP2_CCDD: return 0xFA; - case Arm64Shuffle::REV64_BADC: return 0xB1; - case Arm64Shuffle::EXT4_BCDA: return 0x39; - case Arm64Shuffle::EXT8_CDAB: return 0x4E; - case Arm64Shuffle::EXT12_DABC: return 0x93; - case Arm64Shuffle::REV64_EXT8_CDBA: return 0x1E; - case Arm64Shuffle::REV64_EXT8_DCAB: return 0x4B; - case Arm64Shuffle::EXT4_UZP1_BDAC: return 0x8D; - case Arm64Shuffle::EXT4_UZP2_CABD: return 0xD2; - case Arm64Shuffle::EXT8_ZIP1_ACBD: return 0xD8; - case Arm64Shuffle::EXT8_ZIP2_CADB: return 0x72; - case Arm64Shuffle::INS0_TO_1: return 0xE0; - case Arm64Shuffle::INS0_TO_2: return 0xC4; - case Arm64Shuffle::INS0_TO_3: return 0x24; - case Arm64Shuffle::INS1_TO_0: return 0xE5; - case Arm64Shuffle::INS1_TO_2: return 0xD4; - case Arm64Shuffle::INS1_TO_3: return 0x64; - case Arm64Shuffle::INS2_TO_0: return 0xE6; - case Arm64Shuffle::INS2_TO_1: return 0xE8; - case Arm64Shuffle::INS2_TO_3: return 0xA4; - case Arm64Shuffle::INS3_TO_0: return 0xE7; - case Arm64Shuffle::INS3_TO_1: return 0xEC; - case Arm64Shuffle::INS3_TO_2: return 0xF4; - case Arm64Shuffle::XTN2: return 0x84; - case Arm64Shuffle::EXT12_ZIP1_ADBA: return 0x1C; - case Arm64Shuffle::DUP3_UZP1_DDAC: return 0x8F; - default: - _assert_(false); - return 0; - } -} - -void Arm64ShuffleApply(ARM64FloatEmitter &fp, Arm64Shuffle method, ARM64Reg vd, ARM64Reg vs) { - switch (method) { - case Arm64Shuffle::DUP0_AAAA: fp.DUP(32, vd, vs, 0); return; - case Arm64Shuffle::DUP1_BBBB: fp.DUP(32, vd, vs, 1); return; - case Arm64Shuffle::DUP2_CCCC: fp.DUP(32, vd, vs, 2); return; - case Arm64Shuffle::DUP3_DDDD: fp.DUP(32, vd, vs, 3); return; - case Arm64Shuffle::MOV_ABCD: _assert_(vd != vs); fp.MOV(vd, vs); return; - case Arm64Shuffle::TRN1_AACC: fp.TRN1(32, vd, vs, vs); return; - case Arm64Shuffle::TRN2_BBDD: fp.TRN2(32, vd, vs, vs); return; - case Arm64Shuffle::UZP1_ACAC: fp.UZP1(32, vd, vs, vs); return; - case Arm64Shuffle::UZP2_BDBD: fp.UZP2(32, vd, vs, vs); return; - case Arm64Shuffle::ZIP1_AABB: fp.ZIP1(32, vd, vs, vs); return; - case Arm64Shuffle::ZIP2_CCDD: fp.ZIP2(32, vd, vs, vs); return; - case Arm64Shuffle::REV64_BADC: fp.REV64(32, vd, vs); return; - case Arm64Shuffle::EXT4_BCDA: fp.EXT(vd, vs, vs, 4); return; - case Arm64Shuffle::EXT8_CDAB: fp.EXT(vd, vs, vs, 8); return; - case Arm64Shuffle::EXT12_DABC: fp.EXT(vd, vs, vs, 12); return; - - case Arm64Shuffle::REV64_EXT8_CDBA: - fp.REV64(32, EncodeRegToQuad(SCRATCHF1), vs); - fp.EXT(vd, vs, EncodeRegToQuad(SCRATCHF1), 8); - return; - - case Arm64Shuffle::REV64_EXT8_DCAB: - fp.REV64(32, EncodeRegToQuad(SCRATCHF1), vs); - fp.EXT(vd, EncodeRegToQuad(SCRATCHF1), vs, 8); - return; - - case Arm64Shuffle::EXT4_UZP1_BDAC: - fp.EXT(EncodeRegToQuad(SCRATCHF1), vs, vs, 4); - fp.UZP1(32, vd, EncodeRegToQuad(SCRATCHF1), vs); - return; - - case Arm64Shuffle::EXT4_UZP2_CABD: - fp.EXT(EncodeRegToQuad(SCRATCHF1), vs, vs, 4); - fp.UZP2(32, vd, EncodeRegToQuad(SCRATCHF1), vs); - return; - - case Arm64Shuffle::EXT8_ZIP1_ACBD: - fp.EXT(EncodeRegToQuad(SCRATCHF1), vs, vs, 8); - fp.ZIP1(32, vd, vs, EncodeRegToQuad(SCRATCHF1)); - return; - - case Arm64Shuffle::EXT8_ZIP2_CADB: - fp.EXT(EncodeRegToQuad(SCRATCHF1), vs, vs, 8); - fp.ZIP2(32, vd, vs, EncodeRegToQuad(SCRATCHF1)); - return; - - case Arm64Shuffle::INS0_TO_1: fp.INS(32, vd, 1, vs, 0); return; - case Arm64Shuffle::INS0_TO_2: fp.INS(32, vd, 2, vs, 0); return; - case Arm64Shuffle::INS0_TO_3: fp.INS(32, vd, 3, vs, 0); return; - case Arm64Shuffle::INS1_TO_0: fp.INS(32, vd, 0, vs, 1); return; - case Arm64Shuffle::INS1_TO_2: fp.INS(32, vd, 2, vs, 1); return; - case Arm64Shuffle::INS1_TO_3: fp.INS(32, vd, 3, vs, 1); return; - case Arm64Shuffle::INS2_TO_0: fp.INS(32, vd, 0, vs, 2); return; - case Arm64Shuffle::INS2_TO_1: fp.INS(32, vd, 1, vs, 2); return; - case Arm64Shuffle::INS2_TO_3: fp.INS(32, vd, 3, vs, 2); return; - case Arm64Shuffle::INS3_TO_0: fp.INS(32, vd, 0, vs, 3); return; - case Arm64Shuffle::INS3_TO_1: fp.INS(32, vd, 1, vs, 3); return; - case Arm64Shuffle::INS3_TO_2: fp.INS(32, vd, 2, vs, 3); return; - - case Arm64Shuffle::XTN2: fp.XTN2(32, vd, vs); return; - - case Arm64Shuffle::EXT12_ZIP1_ADBA: - fp.EXT(EncodeRegToQuad(SCRATCHF1), vs, vs, 12); - fp.ZIP1(32, vd, vs, EncodeRegToQuad(SCRATCHF1)); - return; - - case Arm64Shuffle::DUP3_UZP1_DDAC: - fp.DUP(32, EncodeRegToQuad(SCRATCHF1), vs, 3); - fp.UZP1(32, vd, EncodeRegToQuad(SCRATCHF1), vs); - return; - - default: - _assert_(false); - return; - } -} - -uint8_t Arm64ShuffleResult(uint8_t mask, uint8_t prev) { - if (prev == 0xE4) - return mask; - - uint8_t result = 0; - for (int i = 0; i < 4; ++i) { - int takeLane = (mask >> (i * 2)) & 3; - int lane = (prev >> (takeLane * 2)) & 3; - result |= lane << (i * 2); - } - return result; -} - -int Arm64ShuffleScore(uint8_t shuf, uint8_t goal, int steps = 1) { - if (shuf == goal) - return 100; - - int score = 0; - bool needs[4]{}; - bool gets[4]{}; - for (int i = 0; i < 4; ++i) { - uint8_t mask = 3 << (i * 2); - needs[(goal & mask) >> (i * 2)] = true; - gets[(shuf & mask) >> (i * 2)] = true; - if ((shuf & mask) == (goal & mask)) - score += 4; - } - - for (int i = 0; i < 4; ++i) { - if (needs[i] && !gets[i]) - return 0; - } - - // We need to look one level deeper to solve some, such as 1B (common) well. - if (steps > 0) { - int bestNextScore = 0; - for (int m = 0; m < (int)Arm64Shuffle::COUNT_NORMAL; ++m) { - uint8_t next = Arm64ShuffleResult(Arm64ShuffleMask((Arm64Shuffle)m), shuf); - int nextScore = Arm64ShuffleScore(next, goal, steps - 1); - if (nextScore > score) { - bestNextScore = nextScore; - if (bestNextScore == 100) { - // Take the earliest that gives us two steps, it's cheaper (not 2 instructions.) - score = 0; - break; - } - } - } - - score += bestNextScore / 2; - } - - return score; -} - -Arm64Shuffle Arm64BestShuffle(uint8_t goal, uint8_t prev, bool needsCopy) { - // A couple special cases for optimal shuffles. - if (goal == 0x7C && prev == 0xE4) - return Arm64Shuffle::REV64_BADC; - if (goal == 0x2B && prev == 0xE4) - return Arm64Shuffle::EXT8_CDAB; - if ((goal == 0x07 || goal == 0x1C) && prev == 0xE4) - return Arm64Shuffle::EXT12_ZIP1_ADBA; - if ((goal == 0x8F || goal == 0x2F) && prev == 0xE4) - return Arm64Shuffle::DUP3_UZP1_DDAC; - - // needsCopy true means insert isn't possible. - int attempts = needsCopy ? (int)Arm64Shuffle::COUNT_NOPREV : (int)Arm64Shuffle::COUNT_NORMAL; - - Arm64Shuffle best = Arm64Shuffle::MOV_ABCD; - int bestScore = 0; - for (int m = 0; m < attempts; ++m) { - uint8_t result = Arm64ShuffleResult(Arm64ShuffleMask((Arm64Shuffle)m), prev); - int score = Arm64ShuffleScore(result, goal); - // Slightly discount options that involve an extra instruction. - if (m >= (int)Arm64Shuffle::COUNT_SIMPLE && m < (int)Arm64Shuffle::COUNT_NOPREV) - score--; - if (score > bestScore) { - best = (Arm64Shuffle)m; - bestScore = score; - } - } - - _assert_(bestScore > 0); - return best; -} - - -static void Arm64ShufflePerform(ARM64FloatEmitter &fp, ARM64Reg vd, ARM64Reg vs, u8 shuf) { - // This performs all shuffles within 3 "steps" (some are two instructions, though.) - _assert_msg_(shuf != 0xE4, "Non-shuffles shouldn't get here"); - - uint8_t state = 0xE4; - // If they're not the same, the first step needs to be a copy. - bool needsCopy = vd != vs; - for (int i = 0; i < 4 && state != shuf; ++i) { - // Figure out the next step and write it out. - Arm64Shuffle method = Arm64BestShuffle(shuf, state, needsCopy); - Arm64ShuffleApply(fp, method, vd, needsCopy ? vs : vd); - - // Update our state to where we've ended up, for next time. - needsCopy = false; - state = Arm64ShuffleResult(Arm64ShuffleMask(method), state); - } - - _assert_msg_(state == shuf, "Arm64ShufflePerform failed to resolve shuffle"); -} - -void Arm64JitBackend::CompIR_VecAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Init: - regs_.Map(inst); - switch (Vec4Init(inst.src1)) { - case Vec4Init::AllZERO: - fp_.MOVI(32, regs_.FQ(inst.dest), 0); - break; - - case Vec4Init::AllONE: - case Vec4Init::AllMinusONE: - fp_.MOVI2FDUP(regs_.FQ(inst.dest), 1.0f, INVALID_REG, Vec4Init(inst.src1) == Vec4Init::AllMinusONE); - break; - - case Vec4Init::Set_1000: - case Vec4Init::Set_0100: - case Vec4Init::Set_0010: - case Vec4Init::Set_0001: - fp_.MOVI(32, regs_.FQ(inst.dest), 0); - fp_.MOVI2FDUP(EncodeRegToQuad(SCRATCHF1), 1.0f); - fp_.INS(32, regs_.FQ(inst.dest), inst.src1 - (int)Vec4Init::Set_1000, EncodeRegToQuad(SCRATCHF1), inst.src1 - (int)Vec4Init::Set_1000); - break; - - default: - _assert_msg_(false, "Unexpected Vec4Init value %d", inst.src1); - DISABLE; - } - break; - - case IROp::Vec4Shuffle: - // There's not really an easy shuffle op on ARM64... - if (regs_.GetFPRLaneCount(inst.src1) == 1 && (inst.src1 & 3) == 0 && inst.src2 == 0x00) { - // This is a broadcast. If dest == src1, this won't clear it. - regs_.SpillLockFPR(inst.src1); - regs_.MapVec4(inst.dest, MIPSMap::NOINIT); - fp_.DUP(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), 0); - } else if (inst.src2 == 0xE4) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - } - } else { - regs_.Map(inst); - Arm64ShufflePerform(fp_, regs_.FQ(inst.dest), regs_.FQ(inst.src1), inst.src2); - } - break; - - case IROp::Vec4Blend: - regs_.Map(inst); - if (inst.src1 == inst.src2) { - // Shouldn't really happen, just making sure the below doesn't have to think about it. - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - break; - } - - // To reduce overlap cases to consider, let's inverse src1/src2 if dest == src2. - // Thus, dest could be src1, but no other overlap is possible. - if (inst.dest == inst.src2) { - std::swap(inst.src1, inst.src2); - inst.constant ^= 0xF; - } - - switch (inst.constant & 0xF) { - case 0b0000: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - break; - - case 0b0001: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(32, regs_.FQ(inst.dest), 0, regs_.FQ(inst.src2), 0); - break; - - case 0b0010: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(32, regs_.FQ(inst.dest), 1, regs_.FQ(inst.src2), 1); - break; - - case 0b0011: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(64, regs_.FQ(inst.dest), 0, regs_.FQ(inst.src2), 0); - break; - - case 0b0100: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(32, regs_.FQ(inst.dest), 2, regs_.FQ(inst.src2), 2); - break; - - case 0b0101: - // To get AbCd: REV64 to BADC, then TRN2 xAxC, xbxd. - fp_.REV64(32, EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src2)); - fp_.TRN2(32, regs_.FQ(inst.dest), EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1)); - break; - - case 0b0110: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(32, regs_.FQ(inst.dest), 1, regs_.FQ(inst.src2), 1); - fp_.INS(32, regs_.FQ(inst.dest), 2, regs_.FQ(inst.src2), 2); - break; - - case 0b0111: - if (inst.dest != inst.src1) { - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 3, regs_.FQ(inst.src1), 3); - } else { - fp_.MOV(EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1)); - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 3, EncodeRegToQuad(SCRATCHF1), 3); - } - break; - - case 0b1000: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(32, regs_.FQ(inst.dest), 3, regs_.FQ(inst.src2), 3); - break; - - case 0b1001: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(32, regs_.FQ(inst.dest), 0, regs_.FQ(inst.src2), 0); - fp_.INS(32, regs_.FQ(inst.dest), 3, regs_.FQ(inst.src2), 3); - break; - - case 0b1010: - // To get aBcD: REV64 to badc, then TRN2 xaxc, xBxD. - fp_.REV64(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.TRN2(32, regs_.FQ(inst.dest), regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - break; - - case 0b1011: - if (inst.dest != inst.src1) { - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 2, regs_.FQ(inst.src1), 2); - } else { - fp_.MOV(EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1)); - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 2, EncodeRegToQuad(SCRATCHF1), 2); - } - break; - - case 0b1100: - if (inst.dest != inst.src1) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - fp_.INS(64, regs_.FQ(inst.dest), 1, regs_.FQ(inst.src2), 1); - break; - - case 0b1101: - if (inst.dest != inst.src1) { - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 1, regs_.FQ(inst.src1), 1); - } else { - fp_.MOV(EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1)); - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 1, EncodeRegToQuad(SCRATCHF1), 1); - } - break; - - case 0b1110: - if (inst.dest != inst.src1) { - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 0, regs_.FQ(inst.src1), 0); - } else { - fp_.MOV(EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1)); - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - fp_.INS(32, regs_.FQ(inst.dest), 0, EncodeRegToQuad(SCRATCHF1), 0); - } - break; - - case 0b1111: - if (inst.dest != inst.src2) - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src2)); - break; - } - break; - - case IROp::Vec4Mov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - fp_.MOV(regs_.FQ(inst.dest), regs_.FQ(inst.src1)); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_VecClamp(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4ClampToZero: - regs_.Map(inst); - fp_.MOVI(32, EncodeRegToQuad(SCRATCHF1), 0); - fp_.SMAX(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), EncodeRegToQuad(SCRATCHF1)); - break; - - case IROp::Vec2ClampToZero: - regs_.Map(inst); - fp_.MOVI(32, EncodeRegToDouble(SCRATCHF1), 0); - fp_.SMAX(32, regs_.FD(inst.dest), regs_.FD(inst.src1), EncodeRegToDouble(SCRATCHF1)); - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_VecHoriz(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Dot: - if (Overlap(inst.dest, 1, inst.src1, 4) || Overlap(inst.dest, 1, inst.src2, 4)) { - // To avoid overlap problems, map a little carefully. - regs_.SpillLockFPR(inst.src1, inst.src2); - regs_.MapVec4(inst.src1); - regs_.MapVec4(inst.src2); - regs_.MapVec4(inst.dest & ~3, MIPSMap::DIRTY); - fp_.FMUL(32, EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1), regs_.FQ(inst.src2)); - fp_.FADDP(32, EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - fp_.FADDP(32, EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - fp_.INS(32, regs_.FQ(inst.dest & ~3), inst.dest & 3, EncodeRegToQuad(SCRATCHF1), 0); - } else { - regs_.Map(inst); - fp_.FMUL(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), regs_.FQ(inst.src2)); - fp_.FADDP(32, regs_.FQ(inst.dest), regs_.FQ(inst.dest), regs_.FQ(inst.dest)); - fp_.FADDP(32, regs_.FQ(inst.dest), regs_.FQ(inst.dest), regs_.FQ(inst.dest)); - } - break; - - default: - INVALIDOP; - break; - } -} - -void Arm64JitBackend::CompIR_VecPack(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4DuplicateUpperBitsAndShift1: - // This operation swizzles the high 8 bits and converts to a signed int. - // It's always after Vec4Unpack8To32. - // 000A000B000C000D -> AAAABBBBCCCCDDDD and then shift right one (to match INT_MAX.) - regs_.Map(inst); - // First, USHR+ORR to get 0A0A0B0B0C0C0D0D. - fp_.USHR(32, EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1), 16); - fp_.ORR(EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1)); - // Now again, but by 8. - fp_.USHR(32, regs_.FQ(inst.dest), EncodeRegToQuad(SCRATCHF1), 8); - fp_.ORR(regs_.FQ(inst.dest), regs_.FQ(inst.dest), EncodeRegToQuad(SCRATCHF1)); - // Finally, shift away the sign. The goal is to saturate 0xFF -> 0x7FFFFFFF. - fp_.USHR(32, regs_.FQ(inst.dest), regs_.FQ(inst.dest), 1); - break; - - case IROp::Vec2Pack31To16: - // Same as Vec2Pack32To16, but we shift left 1 first to nuke the sign bit. - if (Overlap(inst.dest, 1, inst.src1, 2)) { - regs_.MapVec2(inst.src1, MIPSMap::DIRTY); - fp_.SHL(32, EncodeRegToDouble(SCRATCHF1), regs_.FD(inst.src1), 1); - fp_.UZP2(16, EncodeRegToDouble(SCRATCHF1), EncodeRegToDouble(SCRATCHF1), EncodeRegToDouble(SCRATCHF1)); - fp_.INS(32, regs_.FD(inst.dest & ~1), inst.dest & 1, EncodeRegToDouble(SCRATCHF1), 0); - } else { - regs_.Map(inst); - fp_.SHL(32, regs_.FD(inst.dest), regs_.FD(inst.src1), 1); - fp_.UZP2(16, regs_.FD(inst.dest), regs_.FD(inst.dest), regs_.FD(inst.dest)); - } - break; - - case IROp::Vec2Pack32To16: - // Viewed as 16 bit lanes: xAxB -> AB00... that's UZP2. - if (Overlap(inst.dest, 1, inst.src1, 2)) { - regs_.MapVec2(inst.src1, MIPSMap::DIRTY); - fp_.UZP2(16, EncodeRegToDouble(SCRATCHF1), regs_.FD(inst.src1), regs_.FD(inst.src1)); - fp_.INS(32, regs_.FD(inst.dest & ~1), inst.dest & 1, EncodeRegToDouble(SCRATCHF1), 0); - } else { - regs_.Map(inst); - fp_.UZP2(16, regs_.FD(inst.dest), regs_.FD(inst.src1), regs_.FD(inst.src1)); - } - break; - - case IROp::Vec4Pack31To8: - if (Overlap(inst.dest, 1, inst.src1, 4)) { - regs_.MapVec4(inst.src1, MIPSMap::DIRTY); - } else { - regs_.Map(inst); - } - - // Viewed as 8-bit lanes, after a shift by 23: AxxxBxxxCxxxDxxx. - // So: UZP1 -> AxBxCxDx -> UZP1 again -> ABCD - fp_.USHR(32, EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1), 23); - fp_.UZP1(8, EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - // Second one directly to dest, if we can. - if (Overlap(inst.dest, 1, inst.src1, 4)) { - fp_.UZP1(8, EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - fp_.INS(32, regs_.FQ(inst.dest & ~3), inst.dest & 3, EncodeRegToQuad(SCRATCHF1), 0); - } else { - fp_.UZP1(8, regs_.FQ(inst.dest), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - } - break; - - case IROp::Vec4Pack32To8: - if (Overlap(inst.dest, 1, inst.src1, 4)) { - regs_.MapVec4(inst.src1, MIPSMap::DIRTY); - } else { - regs_.Map(inst); - } - - // Viewed as 8-bit lanes, after a shift by 24: AxxxBxxxCxxxDxxx. - // Same as Vec4Pack31To8, just a different shift. - fp_.USHR(32, EncodeRegToQuad(SCRATCHF1), regs_.FQ(inst.src1), 24); - fp_.UZP1(8, EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - // Second one directly to dest, if we can. - if (Overlap(inst.dest, 1, inst.src1, 4)) { - fp_.UZP1(8, EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - fp_.INS(32, regs_.FQ(inst.dest & ~3), inst.dest & 3, EncodeRegToQuad(SCRATCHF1), 0); - } else { - fp_.UZP1(8, regs_.FQ(inst.dest), EncodeRegToQuad(SCRATCHF1), EncodeRegToQuad(SCRATCHF1)); - } - break; - - case IROp::Vec2Unpack16To31: - // Viewed as 16-bit: ABxx -> 0A0B, then shift a zero into the sign place. - if (Overlap(inst.dest, 2, inst.src1, 1)) { - regs_.MapVec2(inst.dest, MIPSMap::DIRTY); - } else { - regs_.Map(inst); - } - if (inst.src1 == inst.dest + 1) { - fp_.USHLL2(16, regs_.FQ(inst.dest), regs_.FD(inst.src1), 15); - } else { - fp_.USHLL(16, regs_.FQ(inst.dest), regs_.FD(inst.src1), 15); - } - break; - - case IROp::Vec2Unpack16To32: - // Just Vec2Unpack16To31, without the shift. - if (Overlap(inst.dest, 2, inst.src1, 1)) { - regs_.MapVec2(inst.dest, MIPSMap::DIRTY); - } else { - regs_.Map(inst); - } - if (inst.src1 == inst.dest + 1) { - fp_.SHLL2(16, regs_.FQ(inst.dest), regs_.FD(inst.src1)); - } else { - fp_.SHLL(16, regs_.FQ(inst.dest), regs_.FD(inst.src1)); - } - break; - - case IROp::Vec4Unpack8To32: - // Viewed as 8-bit: ABCD -> 000A000B000C000D. - if (Overlap(inst.dest, 4, inst.src1, 1)) { - regs_.MapVec4(inst.dest, MIPSMap::DIRTY); - if (inst.dest == inst.src1 + 2) { - fp_.SHLL2(8, regs_.FQ(inst.dest), regs_.FD(inst.src1 & ~3)); - } else if (inst.dest != inst.src1) { - fp_.DUP(32, regs_.FQ(inst.dest), regs_.FQ(inst.src1), inst.src1 & 3); - fp_.SHLL(8, regs_.FQ(inst.dest), regs_.FD(inst.dest)); - } else { - fp_.SHLL(8, regs_.FQ(inst.dest), regs_.FD(inst.src1)); - } - fp_.SHLL(16, regs_.FQ(inst.dest), regs_.FD(inst.dest)); - } else { - regs_.Map(inst); - // Two steps: ABCD -> 0A0B0C0D, then to 000A000B000C000D. - fp_.SHLL(8, regs_.FQ(inst.dest), regs_.FD(inst.src1)); - fp_.SHLL(16, regs_.FQ(inst.dest), regs_.FD(inst.dest)); - } - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRJit.cpp b/Core/MIPS/ARM64/Arm64IRJit.cpp deleted file mode 100644 index 0e8a3d408..000000000 --- a/Core/MIPS/ARM64/Arm64IRJit.cpp +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include -#include "Core/MemMap.h" -#include "Core/MIPS/MIPSTables.h" -#include "Core/MIPS/ARM64/Arm64IRJit.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -#include -// for std::min - -namespace MIPSComp { - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -// Invalidations just need at most two MOVs and B. -static constexpr int MIN_BLOCK_NORMAL_LEN = 12; -// As long as we can fit a B, we should be fine. -static constexpr int MIN_BLOCK_EXIT_LEN = 4; - -Arm64JitBackend::Arm64JitBackend(JitOptions &jitopt, IRBlockCache &blocks) - : IRNativeBackend(blocks), jo(jitopt), regs_(&jo), fp_(this) { - // Automatically disable incompatible options. - if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { - jo.enablePointerify = false; - } -#ifdef MASKED_PSP_MEMORY - jo.enablePointerify = false; -#endif - - // Since we store the offset, this is as big as it can be. - AllocCodeSpace(1024 * 1024 * 16); - - regs_.Init(this, &fp_); -} - -Arm64JitBackend::~Arm64JitBackend() {} - -void Arm64JitBackend::UpdateFCR31(MIPSState *mipsState) { - currentRoundingFunc_ = convertS0ToSCRATCH1_[mipsState->fcr31 & 3]; -} - -static void NoBlockExits() { - _assert_msg_(false, "Never exited block, invalid IR?"); -} - -bool Arm64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload) { - if (GetSpaceLeft() < 0x800) - return false; - - BeginWrite(std::min(GetSpaceLeft(), (size_t)block->GetNumInstructions() * 32)); - - u32 startPC = block->GetOriginalStart(); - bool wroteCheckedOffset = false; - if (jo.enableBlocklink && !jo.useBackJump) { - SetBlockCheckedOffset(block_num, (int)GetOffset(GetCodePointer())); - wroteCheckedOffset = true; - - WriteDebugPC(startPC); - - // Check the sign bit to check if negative. - FixupBranch normalEntry = TBZ(DOWNCOUNTREG, 31); - MOVI2R(SCRATCH1, startPC); - B(outerLoopPCInSCRATCH1_); - SetJumpTarget(normalEntry); - } - - // Don't worry, the codespace isn't large enough to overflow offsets. - const u8 *blockStart = GetCodePointer(); - block->SetTargetOffset((int)GetOffset(blockStart)); - compilingBlockNum_ = block_num; - lastConstPC_ = 0; - - regs_.Start(block); - - std::vector addresses; - for (int i = 0; i < block->GetNumInstructions(); ++i) { - const IRInst &inst = block->GetInstructions()[i]; - regs_.SetIRIndex(i); - addresses.push_back(GetCodePtr()); - - CompileIRInst(inst); - - if (jo.Disabled(JitDisable::REGALLOC_GPR) || jo.Disabled(JitDisable::REGALLOC_FPR)) - regs_.FlushAll(jo.Disabled(JitDisable::REGALLOC_GPR), jo.Disabled(JitDisable::REGALLOC_FPR)); - - // Safety check, in case we get a bunch of really large jit ops without a lot of branching. - if (GetSpaceLeft() < 0x800) { - compilingBlockNum_ = -1; - return false; - } - } - - // We should've written an exit above. If we didn't, bad things will happen. - // Only check if debug stats are enabled - needlessly wastes jit space. - if (DebugStatsEnabled()) { - QuickCallFunction(SCRATCH2_64, &NoBlockExits); - B(hooks_.crashHandler); - } - - int len = (int)GetOffset(GetCodePointer()) - block->GetTargetOffset(); - if (len < MIN_BLOCK_NORMAL_LEN) { - // We need at least 10 bytes to invalidate blocks with. - ReserveCodeSpace(MIN_BLOCK_NORMAL_LEN - len); - } - - if (!wroteCheckedOffset) { - // Always record this, even if block link disabled - it's used for size calc. - SetBlockCheckedOffset(block_num, (int)GetOffset(GetCodePointer())); - } - - if (jo.enableBlocklink && jo.useBackJump) { - WriteDebugPC(startPC); - - // Small blocks are common, check if it's < 32KB long. - ptrdiff_t distance = blockStart - GetCodePointer(); - if (distance >= -0x8000 && distance < 0x8000) { - TBZ(DOWNCOUNTREG, 31, blockStart); - } else { - FixupBranch toDispatch = TBNZ(DOWNCOUNTREG, 31); - B(blockStart); - SetJumpTarget(toDispatch); - } - - MOVI2R(SCRATCH1, startPC); - B(outerLoopPCInSCRATCH1_); - } - - if (logBlocks_ > 0) { - --logBlocks_; - - std::map addressesLookup; - for (int i = 0; i < (int)addresses.size(); ++i) - addressesLookup[addresses[i]] = i; - - INFO_LOG(JIT, "=============== ARM64 (%08x, %d bytes) ===============", startPC, len); - for (const u8 *p = blockStart; p < GetCodePointer(); ) { - auto it = addressesLookup.find(p); - if (it != addressesLookup.end()) { - const IRInst &inst = block->GetInstructions()[it->second]; - - char temp[512]; - DisassembleIR(temp, sizeof(temp), inst); - INFO_LOG(JIT, "IR: #%d %s", it->second, temp); - } - - auto next = std::next(it); - const u8 *nextp = next == addressesLookup.end() ? GetCodePointer() : next->first; - - auto lines = DisassembleArm64(p, (int)(nextp - p)); - for (const auto &line : lines) - INFO_LOG(JIT, " A: %s", line.c_str()); - p = nextp; - } - } - - EndWrite(); - FlushIcache(); - compilingBlockNum_ = -1; - - return true; -} - -void Arm64JitBackend::WriteConstExit(uint32_t pc) { - int block_num = blocks_.GetBlockNumberFromStartAddress(pc); - const IRNativeBlock *nativeBlock = GetNativeBlock(block_num); - - int exitStart = (int)GetOffset(GetCodePointer()); - if (block_num >= 0 && jo.enableBlocklink && nativeBlock && nativeBlock->checkedOffset != 0) { - B(GetBasePtr() + nativeBlock->checkedOffset); - } else { - MOVI2R(SCRATCH1, pc); - B(dispatcherPCInSCRATCH1_); - } - - if (jo.enableBlocklink) { - // In case of compression or early link, make sure it's large enough. - int len = (int)GetOffset(GetCodePointer()) - exitStart; - if (len < MIN_BLOCK_EXIT_LEN) { - ReserveCodeSpace(MIN_BLOCK_EXIT_LEN - len); - len = MIN_BLOCK_EXIT_LEN; - } - - AddLinkableExit(compilingBlockNum_, pc, exitStart, len); - } -} - -void Arm64JitBackend::OverwriteExit(int srcOffset, int len, int block_num) { - _dbg_assert_(len >= MIN_BLOCK_EXIT_LEN); - - const IRNativeBlock *nativeBlock = GetNativeBlock(block_num); - if (nativeBlock) { - u8 *writable = GetWritablePtrFromCodePtr(GetBasePtr()) + srcOffset; - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, len, MEM_PROT_READ | MEM_PROT_WRITE); - } - - ARM64XEmitter emitter(GetBasePtr() + srcOffset, writable); - emitter.B(GetBasePtr() + nativeBlock->checkedOffset); - int bytesWritten = (int)(emitter.GetWritableCodePtr() - writable); - _dbg_assert_(bytesWritten <= MIN_BLOCK_EXIT_LEN); - if (bytesWritten < len) - emitter.ReserveCodeSpace(len - bytesWritten); - emitter.FlushIcache(); - - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, 16, MEM_PROT_READ | MEM_PROT_EXEC); - } - } -} - -void Arm64JitBackend::CompIR_Generic(IRInst inst) { - // If we got here, we're going the slow way. - uint64_t value; - memcpy(&value, &inst, sizeof(inst)); - - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::IR_INTERPRET); - MOVI2R(X0, value); - QuickCallFunction(SCRATCH2_64, &DoIRInst); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - - // We only need to check the return value if it's a potential exit. - if ((GetIRMeta(inst.op)->flags & IRFLAG_EXIT) != 0) { - MOV(SCRATCH1, X0); - - ptrdiff_t distance = dispatcherPCInSCRATCH1_ - GetCodePointer(); - if (distance >= -0x100000 && distance < 0x100000) { - // Convenient, we can do a simple branch if within 1MB. - CBNZ(W0, dispatcherPCInSCRATCH1_); - } else { - // That's a shame, we need a long branch. - FixupBranch keepOnKeepingOn = CBZ(W0); - B(dispatcherPCInSCRATCH1_); - SetJumpTarget(keepOnKeepingOn); - } - } -} - -void Arm64JitBackend::CompIR_Interpret(IRInst inst) { - MIPSOpcode op(inst.constant); - - // IR protects us against this being a branching instruction (well, hopefully.) - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::INTERPRET); - if (DebugStatsEnabled()) { - MOVP2R(X0, MIPSGetName(op)); - QuickCallFunction(SCRATCH2_64, &NotifyMIPSInterpret); - } - MOVI2R(X0, inst.constant); - QuickCallFunction(SCRATCH2_64, MIPSGetInterpretFunc(op)); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); -} - -void Arm64JitBackend::FlushAll() { - regs_.FlushAll(); -} - -bool Arm64JitBackend::DescribeCodePtr(const u8 *ptr, std::string &name) const { - // Used in disassembly viewer and profiling tools. - // Don't use spaces; profilers get confused or truncate them. - if (ptr == dispatcherPCInSCRATCH1_) { - name = "dispatcherPCInSCRATCH1"; - } else if (ptr == outerLoopPCInSCRATCH1_) { - name = "outerLoopPCInSCRATCH1"; - } else if (ptr == dispatcherNoCheck_) { - name = "dispatcherNoCheck"; - } else if (ptr == saveStaticRegisters_) { - name = "saveStaticRegisters"; - } else if (ptr == loadStaticRegisters_) { - name = "loadStaticRegisters"; - } else if (ptr == restoreRoundingMode_) { - name = "restoreRoundingMode"; - } else if (ptr == applyRoundingMode_) { - name = "applyRoundingMode"; - } else if (ptr == updateRoundingMode_) { - name = "updateRoundingMode"; - } else if (ptr == currentRoundingFunc_) { - name = "currentRoundingFunc"; - } else if (ptr >= convertS0ToSCRATCH1_[0] && ptr <= convertS0ToSCRATCH1_[7]) { - name = "convertS0ToSCRATCH1"; - } else if (ptr >= GetBasePtr() && ptr < GetBasePtr() + jitStartOffset_) { - name = "fixedCode"; - } else { - return IRNativeBackend::DescribeCodePtr(ptr, name); - } - return true; -} - -void Arm64JitBackend::ClearAllBlocks() { - ClearCodeSpace(jitStartOffset_); - FlushIcacheSection(region + jitStartOffset_, region + region_size - jitStartOffset_); - EraseAllLinks(-1); -} - -void Arm64JitBackend::InvalidateBlock(IRBlock *block, int block_num) { - int offset = block->GetTargetOffset(); - u8 *writable = GetWritablePtrFromCodePtr(GetBasePtr()) + offset; - - // Overwrite the block with a jump to compile it again. - u32 pc = block->GetOriginalStart(); - if (pc != 0) { - // Hopefully we always have at least 16 bytes, which should be all we need. - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, MIN_BLOCK_NORMAL_LEN, MEM_PROT_READ | MEM_PROT_WRITE); - } - - ARM64XEmitter emitter(GetBasePtr() + offset, writable); - emitter.MOVI2R(SCRATCH1, pc); - emitter.B(dispatcherPCInSCRATCH1_); - int bytesWritten = (int)(emitter.GetWritableCodePtr() - writable); - if (bytesWritten < MIN_BLOCK_NORMAL_LEN) - emitter.ReserveCodeSpace(MIN_BLOCK_NORMAL_LEN - bytesWritten); - emitter.FlushIcache(); - - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, MIN_BLOCK_NORMAL_LEN, MEM_PROT_READ | MEM_PROT_EXEC); - } - } - - EraseAllLinks(block_num); -} - -void Arm64JitBackend::RestoreRoundingMode(bool force) { - QuickCallFunction(SCRATCH2_64, restoreRoundingMode_); -} - -void Arm64JitBackend::ApplyRoundingMode(bool force) { - QuickCallFunction(SCRATCH2_64, applyRoundingMode_); -} - -void Arm64JitBackend::UpdateRoundingMode(bool force) { - QuickCallFunction(SCRATCH2_64, updateRoundingMode_); -} - -void Arm64JitBackend::MovFromPC(ARM64Reg r) { - LDR(INDEX_UNSIGNED, r, CTXREG, offsetof(MIPSState, pc)); -} - -void Arm64JitBackend::MovToPC(ARM64Reg r) { - STR(INDEX_UNSIGNED, r, CTXREG, offsetof(MIPSState, pc)); -} - -void Arm64JitBackend::WriteDebugPC(uint32_t pc) { - if (hooks_.profilerPC) { - int offset = (int)((const u8 *)hooks_.profilerPC - GetBasePtr()); - MOVI2R(SCRATCH2, MIPS_EMUHACK_OPCODE + offset); - MOVI2R(SCRATCH1, pc); - STR(SCRATCH1, JITBASEREG, SCRATCH2); - } -} - -void Arm64JitBackend::WriteDebugPC(ARM64Reg r) { - if (hooks_.profilerPC) { - int offset = (int)((const u8 *)hooks_.profilerPC - GetBasePtr()); - MOVI2R(SCRATCH2, MIPS_EMUHACK_OPCODE + offset); - STR(r, JITBASEREG, SCRATCH2); - } -} - -void Arm64JitBackend::WriteDebugProfilerStatus(IRProfilerStatus status) { - if (hooks_.profilerPC) { - int offset = (int)((const u8 *)hooks_.profilerStatus - GetBasePtr()); - MOVI2R(SCRATCH2, MIPS_EMUHACK_OPCODE + offset); - MOVI2R(SCRATCH1, (int)status); - STR(SCRATCH1, JITBASEREG, SCRATCH2); - } -} - -void Arm64JitBackend::SaveStaticRegisters() { - if (jo.useStaticAlloc) { - QuickCallFunction(SCRATCH2_64, saveStaticRegisters_); - } else { - // Inline the single operation - STR(INDEX_UNSIGNED, DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - } -} - -void Arm64JitBackend::LoadStaticRegisters() { - if (jo.useStaticAlloc) { - QuickCallFunction(SCRATCH2_64, loadStaticRegisters_); - } else { - LDR(INDEX_UNSIGNED, DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRJit.h b/Core/MIPS/ARM64/Arm64IRJit.h deleted file mode 100644 index 055e52556..000000000 --- a/Core/MIPS/ARM64/Arm64IRJit.h +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include -#include -#include "Common/Arm64Emitter.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRNativeCommon.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" - -namespace MIPSComp { - -class Arm64JitBackend : public Arm64Gen::ARM64CodeBlock, public IRNativeBackend { -public: - Arm64JitBackend(JitOptions &jo, IRBlockCache &blocks); - ~Arm64JitBackend(); - - bool DescribeCodePtr(const u8 *ptr, std::string &name) const override; - - void GenerateFixedCode(MIPSState *mipsState) override; - bool CompileBlock(IRBlock *block, int block_num, bool preload) override; - void ClearAllBlocks() override; - void InvalidateBlock(IRBlock *block, int block_num) override; - - void UpdateFCR31(MIPSState *mipsState) override; - -protected: - const CodeBlockCommon &CodeBlock() const override { - return *this; - } - -private: - void RestoreRoundingMode(bool force = false); - void ApplyRoundingMode(bool force = false); - void UpdateRoundingMode(bool force = false); - void MovFromPC(Arm64Gen::ARM64Reg r); - void MovToPC(Arm64Gen::ARM64Reg r); - // Destroys SCRATCH2. - void WriteDebugPC(uint32_t pc); - void WriteDebugPC(Arm64Gen::ARM64Reg r); - // Destroys SCRATCH2. - void WriteDebugProfilerStatus(IRProfilerStatus status); - - void SaveStaticRegisters(); - void LoadStaticRegisters(); - - // Note: destroys SCRATCH1. - void FlushAll(); - - void WriteConstExit(uint32_t pc); - void OverwriteExit(int srcOffset, int len, int block_num) override; - - void CompIR_Arith(IRInst inst) override; - void CompIR_Assign(IRInst inst) override; - void CompIR_Basic(IRInst inst) override; - void CompIR_Bits(IRInst inst) override; - void CompIR_Breakpoint(IRInst inst) override; - void CompIR_Compare(IRInst inst) override; - void CompIR_CondAssign(IRInst inst) override; - void CompIR_CondStore(IRInst inst) override; - void CompIR_Div(IRInst inst) override; - void CompIR_Exit(IRInst inst) override; - void CompIR_ExitIf(IRInst inst) override; - void CompIR_FArith(IRInst inst) override; - void CompIR_FAssign(IRInst inst) override; - void CompIR_FCompare(IRInst inst) override; - void CompIR_FCondAssign(IRInst inst) override; - void CompIR_FCvt(IRInst inst) override; - void CompIR_FLoad(IRInst inst) override; - void CompIR_FRound(IRInst inst) override; - void CompIR_FSat(IRInst inst) override; - void CompIR_FSpecial(IRInst inst) override; - void CompIR_FStore(IRInst inst) override; - void CompIR_Generic(IRInst inst) override; - void CompIR_HiLo(IRInst inst) override; - void CompIR_Interpret(IRInst inst) override; - void CompIR_Load(IRInst inst) override; - void CompIR_LoadShift(IRInst inst) override; - void CompIR_Logic(IRInst inst) override; - void CompIR_Mult(IRInst inst) override; - void CompIR_RoundingMode(IRInst inst) override; - void CompIR_Shift(IRInst inst) override; - void CompIR_Store(IRInst inst) override; - void CompIR_StoreShift(IRInst inst) override; - void CompIR_System(IRInst inst) override; - void CompIR_Transfer(IRInst inst) override; - void CompIR_VecArith(IRInst inst) override; - void CompIR_VecAssign(IRInst inst) override; - void CompIR_VecClamp(IRInst inst) override; - void CompIR_VecHoriz(IRInst inst) override; - void CompIR_VecLoad(IRInst inst) override; - void CompIR_VecPack(IRInst inst) override; - void CompIR_VecStore(IRInst inst) override; - void CompIR_ValidateAddress(IRInst inst) override; - - struct LoadStoreArg { - Arm64Gen::ARM64Reg base = Arm64Gen::INVALID_REG; - Arm64Gen::ARM64Reg regOffset = Arm64Gen::INVALID_REG; - int immOffset = 0; - bool useUnscaled = false; - bool useRegisterOffset = false; - bool signExtendRegOffset = false; - }; - LoadStoreArg PrepareSrc1Address(IRInst inst); - - JitOptions &jo; - Arm64IRRegCache regs_; - Arm64Gen::ARM64FloatEmitter fp_; - - const u8 *outerLoop_ = nullptr; - const u8 *outerLoopPCInSCRATCH1_ = nullptr; - const u8 *dispatcherCheckCoreState_ = nullptr; - const u8 *dispatcherPCInSCRATCH1_ = nullptr; - const u8 *dispatcherNoCheck_ = nullptr; - const u8 *restoreRoundingMode_ = nullptr; - const u8 *applyRoundingMode_ = nullptr; - const u8 *updateRoundingMode_ = nullptr; - - const u8 *saveStaticRegisters_ = nullptr; - const u8 *loadStaticRegisters_ = nullptr; - - // Indexed by FPCR FZ:RN bits for convenience. Uses SCRATCH2. - const u8 *convertS0ToSCRATCH1_[8]; - - // Note: mutable state used at runtime. - const u8 *currentRoundingFunc_ = nullptr; - - int jitStartOffset_ = 0; - int compilingBlockNum_ = -1; - int logBlocks_ = 0; - // Only useful in breakpoints, where it's set immediately prior. - uint32_t lastConstPC_ = 0; -}; - -class Arm64IRJit : public IRNativeJit { -public: - Arm64IRJit(MIPSState *mipsState) - : IRNativeJit(mipsState), arm64Backend_(jo, blocks_) { - Init(arm64Backend_); - } - -private: - Arm64JitBackend arm64Backend_; -}; - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRRegCache.cpp b/Core/MIPS/ARM64/Arm64IRRegCache.cpp deleted file mode 100644 index 84564877a..000000000 --- a/Core/MIPS/ARM64/Arm64IRRegCache.cpp +++ /dev/null @@ -1,886 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#ifndef offsetof -#include -#endif - -#include "Common/CPUDetect.h" -#include "Common/LogReporting.h" -#include "Core/MemMap.h" -#include "Core/MIPS/IR/IRInst.h" -#include "Core/MIPS/IR/IRAnalysis.h" -#include "Core/MIPS/ARM64/Arm64IRRegCache.h" -#include "Core/MIPS/JitCommon/JitState.h" - -using namespace Arm64Gen; -using namespace Arm64IRJitConstants; - -Arm64IRRegCache::Arm64IRRegCache(MIPSComp::JitOptions *jo) - : IRNativeRegCacheBase(jo) { - // The S/D/Q regs overlap, so we just use one slot. The numbers don't match ARM64Reg. - config_.totalNativeRegs = NUM_X_REGS + NUM_X_FREGS; - config_.mapFPUSIMD = true; - // XMM regs are used for both FPU and Vec, so we don't need VREGs. - config_.mapUseVRegs = false; -} - -void Arm64IRRegCache::Init(ARM64XEmitter *emitter, ARM64FloatEmitter *fp) { - emit_ = emitter; - fp_ = fp; -} - -const int *Arm64IRRegCache::GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const { - if (type == MIPSLoc::REG) { - // See register alloc remarks in Arm64Asm.cpp. - base = W0; - - // W19-W23 are most suitable for static allocation. Those that are chosen for static allocation - // should be omitted here and added in GetStaticAllocations. - static const int allocationOrder[] = { - W19, W20, W21, W22, W23, W24, W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, - }; - static const int allocationOrderStaticAlloc[] = { - W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, - }; - - if (jo_->useStaticAlloc) { - count = ARRAY_SIZE(allocationOrderStaticAlloc); - return allocationOrderStaticAlloc; - } - count = ARRAY_SIZE(allocationOrder); - return allocationOrder; - } else if (type == MIPSLoc::FREG) { - base = S0 - NUM_X_REGS; - - // We don't really need four temps, probably. - // We start with S8 for call flushes. - static const int allocationOrder[] = { - // Reserve four full 128-bit temp registers, should be plenty. - S8, S9, S10, S11, // Partially callee-save (bottom 64 bits) - S12, S13, S14, S15, // Partially callee-save (bottom 64 bits) - S16, S17, S18, S19, - S20, S21, S22, S23, - S24, S25, S26, S27, - S28, S29, S30, S31, - S4, S5, S6, S7, - }; - - count = ARRAY_SIZE(allocationOrder); - return allocationOrder; - } else { - _assert_msg_(false, "Allocation order not yet implemented"); - count = 0; - return nullptr; - } -} - -const Arm64IRRegCache::StaticAllocation *Arm64IRRegCache::GetStaticAllocations(int &count) const { - static const StaticAllocation allocs[] = { - { MIPS_REG_SP, W19, MIPSLoc::REG, true }, - { MIPS_REG_V0, W20, MIPSLoc::REG }, - { MIPS_REG_V1, W21, MIPSLoc::REG }, - { MIPS_REG_A0, W22, MIPSLoc::REG }, - { MIPS_REG_A1, W23, MIPSLoc::REG }, - { MIPS_REG_RA, W24, MIPSLoc::REG }, - }; - - if (jo_->useStaticAlloc) { - count = ARRAY_SIZE(allocs); - return allocs; - } - return IRNativeRegCacheBase::GetStaticAllocations(count); -} - -void Arm64IRRegCache::EmitLoadStaticRegisters() { - int count = 0; - const StaticAllocation *allocs = GetStaticAllocations(count); - for (int i = 0; i < count; ++i) { - int offset = GetMipsRegOffset(allocs[i].mr); - if (i + 1 < count && allocs[i].mr == allocs[i + 1].mr - 1) { - _assert_(!allocs[i].pointerified && !allocs[i + 1].pointerified); - emit_->LDP(INDEX_SIGNED, FromNativeReg(allocs[i].nr), FromNativeReg(allocs[i + 1].nr), CTXREG, offset); - ++i; - } else { - emit_->LDR(INDEX_UNSIGNED, FromNativeReg(allocs[i].nr), CTXREG, offset); - if (allocs[i].pointerified && jo_->enablePointerify) { - ARM64Reg r64 = FromNativeReg64(allocs[i].nr); - uint32_t membaseHigh = (uint32_t)((uint64_t)Memory::base >> 32); - emit_->MOVK(r64, membaseHigh & 0xFFFF, SHIFT_32); - if (membaseHigh & 0xFFFF0000) - emit_->MOVK(r64, membaseHigh >> 16, SHIFT_48); - } - } - } -} - -void Arm64IRRegCache::EmitSaveStaticRegisters() { - int count = 0; - const StaticAllocation *allocs = GetStaticAllocations(count); - // This only needs to run once (by Asm) so checks don't need to be fast. - for (int i = 0; i < count; ++i) { - int offset = GetMipsRegOffset(allocs[i].mr); - if (i + 1 < count && allocs[i].mr == allocs[i + 1].mr - 1) { - emit_->STP(INDEX_SIGNED, FromNativeReg(allocs[i].nr), FromNativeReg(allocs[i + 1].nr), CTXREG, offset); - ++i; - } else { - emit_->STR(INDEX_UNSIGNED, FromNativeReg(allocs[i].nr), CTXREG, offset); - } - } -} - -void Arm64IRRegCache::FlushBeforeCall() { - // These registers are not preserved by function calls. - auto isGPRSaved = [&](IRNativeReg nreg) { - ARM64Reg ar = FromNativeReg(nreg); - return ar >= W19 && ar <= W29; - }; - auto isFPRSaved = [&](IRNativeReg nreg) { - ARM64Reg ar = FromNativeReg(nreg); - return ar >= S8 && ar <= S15; - }; - - // Go through by IR index first, to use STP where we can. - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS - 1; ++i) { - if (mr[i].nReg == -1 || mr[i + 1].nReg == -1 || mr[i].isStatic || mr[i + 1].isStatic) - continue; - // Ignore multilane regs. - if (mr[i].lane != -1 || mr[i + 1].lane != -1) - continue; - if (!nr[mr[i].nReg].isDirty || !nr[mr[i + 1].nReg].isDirty) - continue; - // Make sure not to try to pair a GPR and FPR. - if (IsValidGPR(i) != IsValidGPR(i + 1)) - continue; - - int offset = GetMipsRegOffset(i); - - // Okay, it's a maybe. Are we flushing both as GPRs? - if (!isGPRSaved(mr[i].nReg) && !isGPRSaved(mr[i + 1].nReg) && IsValidGPR(i) && offset <= 252) { - // If either is mapped as a pointer, fix it. - if (mr[i].loc == MIPSLoc::REG_AS_PTR) - AdjustNativeRegAsPtr(mr[i].nReg, false); - if (mr[i + 1].loc == MIPSLoc::REG_AS_PTR) - AdjustNativeRegAsPtr(mr[i + 1].nReg, false); - - // That means we should use STP. - emit_->STP(INDEX_SIGNED, FromNativeReg(mr[i].nReg), FromNativeReg(mr[i + 1].nReg), CTXREG, offset); - - DiscardNativeReg(mr[i].nReg); - DiscardNativeReg(mr[i + 1].nReg); - - ++i; - continue; - } - - // Perhaps as FPRs? Note: these must be single lane at this point. - // TODO: Could use STP on quads etc. too, i.e. i & i + 4. - if (!isFPRSaved(mr[i].nReg) && !isFPRSaved(mr[i + 1].nReg) && !IsValidGPR(i) && offset <= 252) { - fp_->STP(32, INDEX_SIGNED, FromNativeReg(mr[i].nReg), FromNativeReg(mr[i + 1].nReg), CTXREG, offset); - - DiscardNativeReg(mr[i].nReg); - DiscardNativeReg(mr[i + 1].nReg); - - ++i; - continue; - } - } - - // Alright, now go through any that didn't get flushed with STP. - for (int i = 0; i < 19; ++i) { - FlushNativeReg(GPRToNativeReg(ARM64Reg(W0 + i))); - } - FlushNativeReg(GPRToNativeReg(W30)); - - for (int i = 0; i < 8; ++i) { - FlushNativeReg(VFPToNativeReg(ARM64Reg(S0 + i))); - } - for (int i = 8; i < 16; ++i) { - // These are preserved but only the low 64 bits. - IRNativeReg nreg = VFPToNativeReg(ARM64Reg(S0 + i)); - if (nr[nreg].mipsReg != IRREG_INVALID && GetFPRLaneCount(nr[nreg].mipsReg - 32) > 2) - FlushNativeReg(nreg); - } - for (int i = 16; i < 32; ++i) { - FlushNativeReg(VFPToNativeReg(ARM64Reg(S0 + i))); - } -} - -ARM64Reg Arm64IRRegCache::TryMapTempImm(IRReg r) { - _dbg_assert_(IsValidGPR(r)); - - // If already mapped, no need for a temporary. - if (IsGPRMapped(r)) { - return R(r); - } - - if (mr[r].loc == MIPSLoc::IMM) { - // Can we just use zero? - if (mr[r].imm == 0) - return WZR; - - // Try our luck - check for an exact match in another xreg. - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS; ++i) { - if (mr[i].loc == MIPSLoc::REG_IMM && mr[i].imm == mr[r].imm) { - // Awesome, let's just use this reg. - return FromNativeReg(mr[i].nReg); - } - } - } - - return INVALID_REG; -} - -ARM64Reg Arm64IRRegCache::GetAndLockTempGPR() { - IRNativeReg reg = AllocateReg(MIPSLoc::REG, MIPSMap::INIT); - if (reg != -1) { - nr[reg].tempLockIRIndex = irIndex_; - } - return FromNativeReg(reg); -} - -ARM64Reg Arm64IRRegCache::GetAndLockTempFPR() { - IRNativeReg reg = AllocateReg(MIPSLoc::FREG, MIPSMap::INIT); - if (reg != -1) { - nr[reg].tempLockIRIndex = irIndex_; - } - return FromNativeReg(reg); -} - -ARM64Reg Arm64IRRegCache::MapWithFPRTemp(const IRInst &inst) { - return FromNativeReg(MapWithTemp(inst, MIPSLoc::FREG)); -} - -ARM64Reg Arm64IRRegCache::MapGPR(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidGPR(mipsReg)); - - // Okay, not mapped, so we need to allocate an arm64 register. - IRNativeReg nreg = MapNativeReg(MIPSLoc::REG, mipsReg, 1, mapFlags); - return FromNativeReg(nreg); -} - -ARM64Reg Arm64IRRegCache::MapGPR2(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidGPR(mipsReg) && IsValidGPR(mipsReg + 1)); - - // Okay, not mapped, so we need to allocate an arm64 register. - IRNativeReg nreg = MapNativeReg(MIPSLoc::REG, mipsReg, 2, mapFlags); - return FromNativeReg64(nreg); -} - -ARM64Reg Arm64IRRegCache::MapGPRAsPointer(IRReg reg) { - return FromNativeReg64(MapNativeRegAsPointer(reg)); -} - -ARM64Reg Arm64IRRegCache::MapFPR(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidFPR(mipsReg)); - _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::MEM || mr[mipsReg + 32].loc == MIPSLoc::FREG); - - IRNativeReg nreg = MapNativeReg(MIPSLoc::FREG, mipsReg + 32, 1, mapFlags); - if (nreg != -1) - return FromNativeReg(nreg); - return INVALID_REG; -} - -ARM64Reg Arm64IRRegCache::MapVec2(IRReg first, MIPSMap mapFlags) { - _dbg_assert_(IsValidFPR(first)); - _dbg_assert_((first & 1) == 0); - _dbg_assert_(mr[first + 32].loc == MIPSLoc::MEM || mr[first + 32].loc == MIPSLoc::FREG); - - IRNativeReg nreg = MapNativeReg(MIPSLoc::FREG, first + 32, 2, mapFlags); - if (nreg != -1) - return EncodeRegToDouble(FromNativeReg(nreg)); - return INVALID_REG; -} - -ARM64Reg Arm64IRRegCache::MapVec4(IRReg first, MIPSMap mapFlags) { - _dbg_assert_(IsValidFPR(first)); - _dbg_assert_((first & 3) == 0); - _dbg_assert_(mr[first + 32].loc == MIPSLoc::MEM || mr[first + 32].loc == MIPSLoc::FREG); - - IRNativeReg nreg = MapNativeReg(MIPSLoc::FREG, first + 32, 4, mapFlags); - if (nreg != -1) - return EncodeRegToQuad(FromNativeReg(nreg)); - return INVALID_REG; -} - -void Arm64IRRegCache::AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) { - _assert_(nreg >= 0 && nreg < (IRNativeReg)WZR); - ARM64Reg r = FromNativeReg64(nreg); - if (state) { - if (!jo_->enablePointerify) { -#if defined(MASKED_PSP_MEMORY) - // This destroys the value... - _dbg_assert_(!nr[nreg].isDirty); - emit_->ANDI2R(r, r, Memory::MEMVIEW32_MASK); -#endif - emit_->ADD(r, r, MEMBASEREG); - } else { - uint32_t membaseHigh = (uint32_t)((uint64_t)Memory::base >> 32); - emit_->MOVK(r, membaseHigh & 0xFFFF, SHIFT_32); - if (membaseHigh & 0xFFFF0000) - emit_->MOVK(r, membaseHigh >> 16, SHIFT_48); - } - } else { - if (!jo_->enablePointerify) { -#if defined(MASKED_PSP_MEMORY) - _dbg_assert_(!nr[nreg].isDirty); -#endif - emit_->SUB(r, r, MEMBASEREG); - } else { - // Nothing to do, just ignore the high 32 bits. - } - } -} - -bool Arm64IRRegCache::IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes) { - // No special flags, skip the check for a little speed. - return true; -} - -void Arm64IRRegCache::LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) { - ARM64Reg r = FromNativeReg(nreg); - _dbg_assert_(first != MIPS_REG_ZERO); - if (nreg < NUM_X_REGS) { - _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); - if (lanes == 1) - emit_->LDR(INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 2) - emit_->LDR(INDEX_UNSIGNED, EncodeRegTo64(r), CTXREG, GetMipsRegOffset(first)); - else - _assert_(false); - } else { - _dbg_assert_(nreg < NUM_X_REGS + NUM_X_FREGS); - _assert_msg_(mr[first].loc == MIPSLoc::FREG, "Cannot load this type: %d", (int)mr[first].loc); - if (lanes == 1) - fp_->LDR(32, INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 2) - fp_->LDR(64, INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 4) - fp_->LDR(128, INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else - _assert_(false); - } -} - -void Arm64IRRegCache::StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) { - ARM64Reg r = FromNativeReg(nreg); - _dbg_assert_(first != MIPS_REG_ZERO); - if (nreg < NUM_X_REGS) { - _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); - _assert_(mr[first].loc == MIPSLoc::REG || mr[first].loc == MIPSLoc::REG_IMM); - if (lanes == 1) - emit_->STR(INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 2) - emit_->STR(INDEX_UNSIGNED, EncodeRegTo64(r), CTXREG, GetMipsRegOffset(first)); - else - _assert_(false); - } else { - _dbg_assert_(nreg < NUM_X_REGS + NUM_X_FREGS); - _assert_msg_(mr[first].loc == MIPSLoc::FREG, "Cannot store this type: %d", (int)mr[first].loc); - if (lanes == 1) - fp_->STR(32, INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 2) - fp_->STR(64, INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 4) - fp_->STR(128, INDEX_UNSIGNED, r, CTXREG, GetMipsRegOffset(first)); - else - _assert_(false); - } -} - -void Arm64IRRegCache::SetNativeRegValue(IRNativeReg nreg, uint32_t imm) { - ARM64Reg r = FromNativeReg(nreg); - _dbg_assert_(nreg >= 0 && nreg < (IRNativeReg)WZR); - // On ARM64, MOVZ/MOVK is really fast. - emit_->MOVI2R(r, imm); -} - -void Arm64IRRegCache::StoreRegValue(IRReg mreg, uint32_t imm) { - _assert_(IsValidGPRNoZero(mreg)); - // Try to optimize using a different reg. - ARM64Reg storeReg = INVALID_REG; - if (imm == 0) - storeReg = WZR; - - // Could we get lucky? Check for an exact match in another xreg. - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS; ++i) { - if (mr[i].loc == MIPSLoc::REG_IMM && mr[i].imm == imm) { - // Awesome, let's just store this reg. - storeReg = (ARM64Reg)mr[i].nReg; - break; - } - } - - if (storeReg == INVALID_REG) { - emit_->MOVI2R(SCRATCH1, imm); - storeReg = SCRATCH1; - } - emit_->STR(INDEX_UNSIGNED, storeReg, CTXREG, GetMipsRegOffset(mreg)); -} - -bool Arm64IRRegCache::TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) { - bool allowed = !mr[nr[nreg].mipsReg].isStatic; - // There's currently no support for non-FREGs here. - allowed = allowed && type == MIPSLoc::FREG; - - if (dest == -1) - dest = nreg; - - if (allowed && (flags == MIPSMap::INIT || flags == MIPSMap::DIRTY)) { - // Alright, changing lane count (possibly including lane position.) - IRReg oldfirst = nr[nreg].mipsReg; - int oldlanes = 0; - while (mr[oldfirst + oldlanes].nReg == nreg) - oldlanes++; - _assert_msg_(oldlanes != 0, "TransferNativeReg encountered nreg mismatch"); - _assert_msg_(oldlanes != lanes, "TransferNativeReg transfer to same lanecount, misaligned?"); - - if (lanes == 1 && TransferVecTo1(nreg, dest, first, oldlanes)) - return true; - if (oldlanes == 1 && Transfer1ToVec(nreg, dest, first, lanes)) - return true; - } - - return IRNativeRegCacheBase::TransferNativeReg(nreg, dest, type, first, lanes, flags); -} - -bool Arm64IRRegCache::TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes) { - IRReg oldfirst = nr[nreg].mipsReg; - - // Is it worth preserving any of the old regs? - int numKept = 0; - for (int i = 0; i < oldlanes; ++i) { - // Skip whichever one this is extracting. - if (oldfirst + i == first) - continue; - // If 0 isn't being transfered, easy to keep in its original reg. - if (i == 0 && dest != nreg) { - numKept++; - continue; - } - - IRNativeReg freeReg = FindFreeReg(MIPSLoc::FREG, MIPSMap::INIT); - if (freeReg != -1 && IsRegRead(MIPSLoc::FREG, oldfirst + i)) { - // If there's one free, use it. Don't modify nreg, though. - fp_->DUP(32, FromNativeReg(freeReg), FromNativeReg(nreg), i); - - // Update accounting. - nr[freeReg].isDirty = nr[nreg].isDirty; - nr[freeReg].mipsReg = oldfirst + i; - mr[oldfirst + i].lane = -1; - mr[oldfirst + i].nReg = freeReg; - numKept++; - } - } - - // Unless all other lanes were kept, store. - if (nr[nreg].isDirty && numKept < oldlanes - 1) { - StoreNativeReg(nreg, oldfirst, oldlanes); - // Set false even for regs that were split out, since they were flushed too. - for (int i = 0; i < oldlanes; ++i) { - if (mr[oldfirst + i].nReg != -1) - nr[mr[oldfirst + i].nReg].isDirty = false; - } - } - - // Next, move the desired element into first place. - if (mr[first].lane > 0) { - fp_->DUP(32, FromNativeReg(dest), FromNativeReg(nreg), mr[first].lane); - } else if (mr[first].lane <= 0 && dest != nreg) { - fp_->DUP(32, FromNativeReg(dest), FromNativeReg(nreg), 0); - } - - // Now update accounting. - for (int i = 0; i < oldlanes; ++i) { - auto &mreg = mr[oldfirst + i]; - if (oldfirst + i == first) { - mreg.lane = -1; - mreg.nReg = dest; - } else if (mreg.nReg == nreg && i == 0 && nreg != dest) { - // Still in the same register, but no longer a vec. - mreg.lane = -1; - } else if (mreg.nReg == nreg) { - // No longer in a register. - mreg.nReg = -1; - mreg.lane = -1; - mreg.loc = MIPSLoc::MEM; - } - } - - if (dest != nreg) { - nr[dest].isDirty = nr[nreg].isDirty; - if (oldfirst == first) { - nr[nreg].mipsReg = -1; - nr[nreg].isDirty = false; - } - } - nr[dest].mipsReg = first; - - return true; -} - -bool Arm64IRRegCache::Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes) { - ARM64Reg destReg = FromNativeReg(dest); - ARM64Reg cur[4]{}; - int numInRegs = 0; - u8 blendMask = 0; - for (int i = 0; i < lanes; ++i) { - if (mr[first + i].lane != -1 || (i != 0 && mr[first + i].spillLockIRIndex >= irIndex_)) { - // Can't do it, either double mapped or overlapping vec. - return false; - } - - if (mr[first + i].nReg == -1) { - cur[i] = INVALID_REG; - blendMask |= 1 << i; - } else { - cur[i] = FromNativeReg(mr[first + i].nReg); - numInRegs++; - } - } - - // Shouldn't happen, this should only get called to transfer one in a reg. - if (numInRegs == 0) - return false; - - // If everything's currently in a reg, move it into this reg. - if (lanes == 4) { - // Go with an exhaustive approach, only 15 possibilities... - if (blendMask == 0) { - // y = yw##, x = xz##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[3])); - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[2])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[1])); - } else if (blendMask == 0b0001) { - // y = yw##, w = x###, w = xz##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[3])); - fp_->LDR(32, INDEX_UNSIGNED, cur[3], CTXREG, GetMipsRegOffset(first + 0)); - fp_->ZIP1(32, EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[2])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[1])); - } else if (blendMask == 0b0010) { - // x = xz##, z = y###, z = yw##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[2])); - fp_->LDR(32, INDEX_UNSIGNED, cur[2], CTXREG, GetMipsRegOffset(first + 1)); - fp_->ZIP1(32, EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[3])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[2])); - } else if (blendMask == 0b0011 && (first & 1) == 0) { - // z = zw##, w = xy##, dest = xyzw. Mixed lane sizes. - fp_->ZIP1(32, EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[3])); - fp_->LDR(64, INDEX_UNSIGNED, EncodeRegToDouble(cur[3]), CTXREG, GetMipsRegOffset(first + 0)); - fp_->ZIP1(64, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[2])); - } else if (blendMask == 0b0100) { - // y = yw##, w = z###, x = xz##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[3])); - fp_->LDR(32, INDEX_UNSIGNED, cur[3], CTXREG, GetMipsRegOffset(first + 2)); - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[3])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[1])); - } else if (blendMask == 0b0101 && (first & 3) == 0) { - // y = yw##, w=x#z#, w = xz##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[3])); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(cur[3]), CTXREG, GetMipsRegOffset(first)); - fp_->UZP1(32, EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[3])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[1])); - } else if (blendMask == 0b0110 && (first & 3) == 0) { - if (destReg == cur[0]) { - // w = wx##, dest = #yz#, dest = xyz#, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[3]), EncodeRegToQuad(cur[0])); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 0, EncodeRegToQuad(cur[3]), 1); - fp_->INS(32, EncodeRegToQuad(destReg), 3, EncodeRegToQuad(cur[3]), 0); - } else { - // Assumes destReg may equal cur[3]. - // x = xw##, dest = #yz#, dest = xyz#, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[3])); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 0, EncodeRegToQuad(cur[0]), 0); - fp_->INS(32, EncodeRegToQuad(destReg), 3, EncodeRegToQuad(cur[0]), 1); - } - } else if (blendMask == 0b0111 && (first & 3) == 0 && destReg != cur[3]) { - // dest = xyz#, dest = xyzw. - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 3, EncodeRegToQuad(cur[3]), 0); - } else if (blendMask == 0b1000) { - // x = xz##, z = w###, y = yw##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[2])); - fp_->LDR(32, INDEX_UNSIGNED, cur[2], CTXREG, GetMipsRegOffset(first + 3)); - fp_->ZIP1(32, EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[2])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[1])); - } else if (blendMask == 0b1001 && (first & 3) == 0) { - if (destReg == cur[1]) { - // w = zy##, dest = x##w, dest = xy#w, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[1])); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 1, EncodeRegToQuad(cur[2]), 1); - fp_->INS(32, EncodeRegToQuad(destReg), 2, EncodeRegToQuad(cur[2]), 0); - } else { - // Assumes destReg may equal cur[2]. - // y = yz##, dest = x##w, dest = xy#w, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[1]), EncodeRegToQuad(cur[2])); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 1, EncodeRegToQuad(cur[1]), 0); - fp_->INS(32, EncodeRegToQuad(destReg), 2, EncodeRegToQuad(cur[1]), 1); - } - } else if (blendMask == 0b1010 && (first & 3) == 0) { - // x = xz##, z = #y#w, z=yw##, dest = xyzw. - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[2])); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(cur[2]), CTXREG, GetMipsRegOffset(first)); - fp_->UZP2(32, EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[2]), EncodeRegToQuad(cur[2])); - fp_->ZIP1(32, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[2])); - } else if (blendMask == 0b1011 && (first & 3) == 0 && destReg != cur[2]) { - // dest = xy#w, dest = xyzw. - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 2, EncodeRegToQuad(cur[2]), 0); - } else if (blendMask == 0b1100 && (first & 1) == 0) { - // x = xy##, y = zw##, dest = xyzw. Mixed lane sizes. - fp_->ZIP1(32, EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[1])); - fp_->LDR(64, INDEX_UNSIGNED, EncodeRegToDouble(cur[1]), CTXREG, GetMipsRegOffset(first + 2)); - fp_->ZIP1(64, EncodeRegToQuad(destReg), EncodeRegToQuad(cur[0]), EncodeRegToQuad(cur[1])); - } else if (blendMask == 0b1101 && (first & 3) == 0 && destReg != cur[1]) { - // dest = x#zw, dest = xyzw. - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 1, EncodeRegToQuad(cur[1]), 0); - } else if (blendMask == 0b1110 && (first & 3) == 0 && destReg != cur[0]) { - // dest = #yzw, dest = xyzw. - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 0, EncodeRegToQuad(cur[0]), 0); - } else if (blendMask == 0b1110 && (first & 3) == 0) { - // If dest == cur[0] (which may be common), we need a temp... - IRNativeReg freeReg = FindFreeReg(MIPSLoc::FREG, MIPSMap::INIT); - // Very unfortunate. - if (freeReg == INVALID_REG) - return false; - - // free = x###, dest = #yzw, dest = xyzw. - fp_->DUP(32, EncodeRegToQuad(FromNativeReg(freeReg)), EncodeRegToQuad(cur[0]), 0); - fp_->LDR(128, INDEX_UNSIGNED, EncodeRegToQuad(destReg), CTXREG, GetMipsRegOffset(first)); - fp_->INS(32, EncodeRegToQuad(destReg), 0, EncodeRegToQuad(FromNativeReg(freeReg)), 0); - } else { - return false; - } - } else if (lanes == 2) { - if (cur[0] != INVALID_REG && cur[1] != INVALID_REG) { - fp_->ZIP1(32, EncodeRegToDouble(destReg), EncodeRegToDouble(cur[0]), EncodeRegToDouble(cur[1])); - } else if (cur[0] == INVALID_REG && dest != nreg) { - fp_->LDR(32, INDEX_UNSIGNED, destReg, CTXREG, GetMipsRegOffset(first + 0)); - fp_->INS(32, EncodeRegToDouble(destReg), 1, EncodeRegToDouble(cur[1]), 0); - } else { - IRNativeReg freeReg = FindFreeReg(MIPSLoc::FREG, MIPSMap::INIT); - if (freeReg == INVALID_REG) - return false; - - if (cur[0] == INVALID_REG) { - fp_->LDR(32, INDEX_UNSIGNED, FromNativeReg(freeReg), CTXREG, GetMipsRegOffset(first + 0)); - fp_->ZIP1(32, EncodeRegToDouble(destReg), EncodeRegToDouble(FromNativeReg(freeReg)), EncodeRegToDouble(cur[1])); - } else { - fp_->LDR(32, INDEX_UNSIGNED, FromNativeReg(freeReg), CTXREG, GetMipsRegOffset(first + 1)); - fp_->ZIP1(32, EncodeRegToDouble(destReg), EncodeRegToDouble(cur[0]), EncodeRegToDouble(FromNativeReg(freeReg))); - } - } - } else { - return false; - } - - mr[first].lane = 0; - for (int i = 0; i < lanes; ++i) { - if (mr[first + i].nReg != -1) { - // If this was dirty, the combined reg is now dirty. - if (nr[mr[first + i].nReg].isDirty) - nr[dest].isDirty = true; - - // Throw away the other register we're no longer using. - if (i != 0) - DiscardNativeReg(mr[first + i].nReg); - } - - // And set it as using the new one. - mr[first + i].lane = i; - mr[first + i].loc = MIPSLoc::FREG; - mr[first + i].nReg = dest; - } - - if (dest != nreg) { - nr[dest].mipsReg = first; - nr[nreg].mipsReg = -1; - nr[nreg].isDirty = false; - } - - return true; -} - -void Arm64IRRegCache::FlushAll(bool gprs, bool fprs) { - // Note: make sure not to change the registers when flushing: - // Branching code may expect the armreg to retain its value. - - auto needsFlush = [&](IRReg i) { - if (mr[i].loc != MIPSLoc::MEM || mr[i].isStatic) - return false; - if (mr[i].nReg == -1 || !nr[mr[i].nReg].isDirty) - return false; - return true; - }; - - // Try to flush in pairs when possible. - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS - 1; ++i) { - if (!needsFlush(i) || !needsFlush(i + 1)) - continue; - // Ignore multilane regs. Could handle with more smartness... - if (mr[i].lane != -1 || mr[i + 1].lane != -1) - continue; - - int offset = GetMipsRegOffset(i); - - // If both are imms, let's materialize a single reg and store. - if (mr[i].loc == MIPSLoc::IMM && mr[i + 1].loc == MIPSLoc::IMM) { - if ((i & 1) == 0) { - uint64_t fullImm = ((uint64_t) mr[i + 1].imm << 32) | mr[i].imm; - emit_->MOVI2R(SCRATCH1_64, fullImm); - emit_->STR(INDEX_UNSIGNED, SCRATCH1_64, CTXREG, offset); - DiscardReg(i); - DiscardReg(i + 1); - ++i; - } - continue; - } - - // Okay, two dirty regs in a row, in need of flushing. Both GPRs? - if (IsValidGPR(i) && IsValidGPR(i + 1) && offset <= 252) { - auto setupForFlush = [&](ARM64Reg &ar, IRReg r) { - if (mr[r].loc == MIPSLoc::IMM) { - ar = TryMapTempImm(r); - if (ar == INVALID_REG) { - // Both cannot be imms, so this is safe. - ar = SCRATCH1; - emit_->MOVI2R(ar, mr[r].imm); - } - } else if (mr[r].loc == MIPSLoc::REG_AS_PTR) { - AdjustNativeRegAsPtr(r, false); - ar = FromNativeReg(mr[r].nReg); - } else { - _dbg_assert_(mr[r].loc == MIPSLoc::REG || mr[r].loc == MIPSLoc::REG_IMM); - ar = FromNativeReg(mr[r].nReg); - } - }; - - ARM64Reg armRegs[2]{ INVALID_REG, INVALID_REG }; - setupForFlush(armRegs[0], i); - setupForFlush(armRegs[1], i + 1); - - emit_->STP(INDEX_SIGNED, armRegs[0], armRegs[1], CTXREG, offset); - DiscardReg(i); - DiscardReg(i + 1); - ++i; - continue; - } - - // Perhaps as FPRs? Note: these must be single lane at this point. - // TODO: Could use STP on quads etc. too, i.e. i & i + 4. - if (i >= 32 && IsValidFPR(i - 32) && IsValidFPR(i + 1 - 32) && offset <= 252) { - _dbg_assert_(mr[i].loc == MIPSLoc::FREG && mr[i + 1].loc == MIPSLoc::FREG); - fp_->STP(32, INDEX_SIGNED, FromNativeReg(mr[i].nReg), FromNativeReg(mr[i + 1].nReg), CTXREG, offset); - - DiscardNativeReg(mr[i].nReg); - DiscardNativeReg(mr[i + 1].nReg); - - ++i; - continue; - } - } - - // Flush all the rest that weren't done via STP. - IRNativeRegCacheBase::FlushAll(gprs, fprs); -} - -ARM64Reg Arm64IRRegCache::R(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM); - if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - return FromNativeReg(mr[mipsReg].nReg); - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in arm64 reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -ARM64Reg Arm64IRRegCache::R64(IRReg mipsReg) { - return EncodeRegTo64(R(mipsReg)); -} - -ARM64Reg Arm64IRRegCache::RPtr(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM || mr[mipsReg].loc == MIPSLoc::REG_AS_PTR); - if (mr[mipsReg].loc == MIPSLoc::REG_AS_PTR) { - return FromNativeReg64(mr[mipsReg].nReg); - } else if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - int r = mr[mipsReg].nReg; - _dbg_assert_(nr[r].pointerified); - if (nr[r].pointerified) { - return FromNativeReg64(mr[mipsReg].nReg); - } else { - ERROR_LOG(JIT, "Tried to use a non-pointer register as a pointer"); - return INVALID_REG; - } - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in arm64 reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -ARM64Reg Arm64IRRegCache::F(IRReg mipsReg) { - _dbg_assert_(IsValidFPR(mipsReg)); - _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::FREG); - if (mr[mipsReg + 32].loc == MIPSLoc::FREG) { - return FromNativeReg(mr[mipsReg + 32].nReg); - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in arm64 reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -ARM64Reg Arm64IRRegCache::FD(IRReg mipsReg) { - return EncodeRegToDouble(F(mipsReg)); -} - -ARM64Reg Arm64IRRegCache::FQ(IRReg mipsReg) { - return EncodeRegToQuad(F(mipsReg)); -} - -IRNativeReg Arm64IRRegCache::GPRToNativeReg(ARM64Reg r) { - _dbg_assert_msg_(r >= 0 && r < 0x40, "Not a GPR?"); - return (IRNativeReg)DecodeReg(r); -} - -IRNativeReg Arm64IRRegCache::VFPToNativeReg(ARM64Reg r) { - _dbg_assert_msg_(r >= 0x40 && r < 0xE0, "Not VFP?"); - return (IRNativeReg)(NUM_X_REGS + (int)DecodeReg(r)); -} - -ARM64Reg Arm64IRRegCache::FromNativeReg(IRNativeReg r) { - if (r >= NUM_X_REGS) - return EncodeRegToSingle((Arm64Gen::ARM64Reg)r); - return (Arm64Gen::ARM64Reg)r; -} - -ARM64Reg Arm64IRRegCache::FromNativeReg64(IRNativeReg r) { - _dbg_assert_msg_(r >= 0 && r < NUM_X_REGS, "Not a GPR?"); - return EncodeRegTo64((Arm64Gen::ARM64Reg)r); -} - -#endif diff --git a/Core/MIPS/ARM64/Arm64IRRegCache.h b/Core/MIPS/ARM64/Arm64IRRegCache.h deleted file mode 100644 index f3f0b58b6..000000000 --- a/Core/MIPS/ARM64/Arm64IRRegCache.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "ppsspp_config.h" -// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL. -#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - -#include "Common/Arm64Emitter.h" -#include "Core/MIPS/MIPS.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRRegCache.h" - -namespace Arm64IRJitConstants { - -const Arm64Gen::ARM64Reg DOWNCOUNTREG = Arm64Gen::W25; -// Note: this is actually offset from the base. -const Arm64Gen::ARM64Reg JITBASEREG = Arm64Gen::X26; -const Arm64Gen::ARM64Reg CTXREG = Arm64Gen::X27; -const Arm64Gen::ARM64Reg MEMBASEREG = Arm64Gen::X28; -const Arm64Gen::ARM64Reg SCRATCH1_64 = Arm64Gen::X16; -const Arm64Gen::ARM64Reg SCRATCH2_64 = Arm64Gen::X17; -const Arm64Gen::ARM64Reg SCRATCH1 = Arm64Gen::W16; -const Arm64Gen::ARM64Reg SCRATCH2 = Arm64Gen::W17; -// TODO: How many do we actually need? -const Arm64Gen::ARM64Reg SCRATCHF1 = Arm64Gen::S0; -const Arm64Gen::ARM64Reg SCRATCHF2 = Arm64Gen::S1; -const Arm64Gen::ARM64Reg SCRATCHF3 = Arm64Gen::S2; -const Arm64Gen::ARM64Reg SCRATCHF4 = Arm64Gen::S3; - -} // namespace X64IRJitConstants - -class Arm64IRRegCache : public IRNativeRegCacheBase { -public: - Arm64IRRegCache(MIPSComp::JitOptions *jo); - - void Init(Arm64Gen::ARM64XEmitter *emitter, Arm64Gen::ARM64FloatEmitter *fp); - - // May fail and return INVALID_REG if it needs flushing. - Arm64Gen::ARM64Reg TryMapTempImm(IRReg reg); - - // Returns an arm64 register containing the requested MIPS register. - Arm64Gen::ARM64Reg MapGPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - Arm64Gen::ARM64Reg MapGPR2(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - Arm64Gen::ARM64Reg MapGPRAsPointer(IRReg reg); - Arm64Gen::ARM64Reg MapFPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - Arm64Gen::ARM64Reg MapVec2(IRReg first, MIPSMap mapFlags = MIPSMap::INIT); - Arm64Gen::ARM64Reg MapVec4(IRReg first, MIPSMap mapFlags = MIPSMap::INIT); - - Arm64Gen::ARM64Reg MapWithFPRTemp(const IRInst &inst); - - void FlushBeforeCall(); - void FlushAll(bool gprs = true, bool fprs = true) override; - - Arm64Gen::ARM64Reg GetAndLockTempGPR(); - Arm64Gen::ARM64Reg GetAndLockTempFPR(); - - Arm64Gen::ARM64Reg R(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer - Arm64Gen::ARM64Reg R64(IRReg preg); - Arm64Gen::ARM64Reg RPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer - Arm64Gen::ARM64Reg F(IRReg preg); - Arm64Gen::ARM64Reg FD(IRReg preg); - Arm64Gen::ARM64Reg FQ(IRReg preg); - - // These are called once on startup to generate functions, that you should then call. - void EmitLoadStaticRegisters(); - void EmitSaveStaticRegisters(); - -protected: - const StaticAllocation *GetStaticAllocations(int &count) const override; - const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const override; - void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) override; - - bool IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes) override; - void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; - void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; - void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) override; - void StoreRegValue(IRReg mreg, uint32_t imm) override; - bool TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) override; - -private: - bool TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes); - bool Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes); - - IRNativeReg GPRToNativeReg(Arm64Gen::ARM64Reg r); - IRNativeReg VFPToNativeReg(Arm64Gen::ARM64Reg r); - Arm64Gen::ARM64Reg FromNativeReg(IRNativeReg r); - Arm64Gen::ARM64Reg FromNativeReg64(IRNativeReg r); - - Arm64Gen::ARM64XEmitter *emit_ = nullptr; - Arm64Gen::ARM64FloatEmitter *fp_ = nullptr; - - enum { - NUM_X_REGS = 32, - NUM_X_FREGS = 32, - }; -}; - -#endif diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 9abb69920..191f97f9e 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -16,7 +16,6 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "ppsspp_config.h" - #if PPSSPP_ARCH(ARM64) #include "Common/Profiler/Profiler.h" @@ -130,9 +129,6 @@ void Arm64Jit::DoState(PointerWrap &p) { return; Do(p, js.startDefaultPrefix); - if (p.mode == PointerWrap::MODE_READ && !js.startDefaultPrefix) { - WARN_LOG(CPU, "Jit: An uneaten prefix was previously detected. Jitting in unknown-prefix mode."); - } if (s >= 2) { Do(p, js.hasSetRounding); if (p.mode == PointerWrap::MODE_READ) { @@ -160,15 +156,6 @@ void Arm64Jit::FlushAll() { } void Arm64Jit::FlushPrefixV() { - if (js.startDefaultPrefix && !js.blockWrotePrefixes && js.HasNoPrefix()) { - // They started default, we never modified in memory, and they're default now. - // No reason to modify memory. This is common at end of blocks. Just clear dirty. - js.prefixSFlag = (JitState::PrefixState)(js.prefixSFlag & ~JitState::PREFIX_DIRTY); - js.prefixTFlag = (JitState::PrefixState)(js.prefixTFlag & ~JitState::PREFIX_DIRTY); - js.prefixDFlag = (JitState::PrefixState)(js.prefixDFlag & ~JitState::PREFIX_DIRTY); - return; - } - if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) { gpr.SetRegImm(SCRATCH1, js.prefixS); STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_SPREFIX])); @@ -186,9 +173,6 @@ void Arm64Jit::FlushPrefixV() { STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_DPREFIX])); js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } - - // If we got here, we must've written prefixes to memory in this block. - js.blockWrotePrefixes = true; } void Arm64Jit::ClearCache() { @@ -253,8 +237,8 @@ void Arm64Jit::Compile(u32 em_address) { int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); - _assert_msg_(b->originalAddress == em_address, "original %08x != em_address %08x (block %d)", b->originalAddress, em_address, b->blockNum); blocks.FinalizeBlock(block_num, jo.enableBlocklink); + EndWrite(); // Don't forget to zap the newly written instructions in the instruction cache! @@ -302,8 +286,8 @@ MIPSOpcode Arm64Jit::GetOffsetInstruction(int offset) { const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) { js.cancel = false; - js.blockStart = em_address; - js.compilerPC = em_address; + js.blockStart = mips_->pc; + js.compilerPC = mips_->pc; js.lastContinuedPC = 0; js.initialBlockSize = 0; js.nextExit = 0; @@ -311,7 +295,6 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) { js.curBlock = b; js.compiling = true; js.inDelaySlot = false; - js.blockWrotePrefixes = false; js.PrefixStart(); // We add a downcount flag check before the block, used when entering from a linked block. @@ -389,7 +372,7 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) { if (logBlocks > 0 && dontLogBlocks == 0) { INFO_LOG(JIT, "=============== mips %d ===============", blocks.GetNumBlocks()); for (u32 cpc = em_address; cpc != GetCompilerPC() + 4; cpc += 4) { - MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp, sizeof(temp), true); + MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp, true); INFO_LOG(JIT, "M: %08x %s", cpc, temp); } } @@ -562,8 +545,7 @@ void Arm64Jit::Comp_ReplacementFunc(MIPSOpcode op) const ReplacementTableEntry *entry = GetReplacementFunc(index); if (!entry) { - ERROR_LOG_REPORT_ONCE(replFunc, HLE, "Invalid replacement op %08x at %08x", op.encoding, js.compilerPC); - // TODO: What should we do here? We're way off in the weeds probably. + ERROR_LOG(HLE, "Invalid replacement op %08x", op.encoding); return; } @@ -644,10 +626,6 @@ void Arm64Jit::Comp_Generic(MIPSOpcode op) { // If it does eat them, it'll happen in MIPSCompileOp(). if ((info & OUT_EAT_PREFIX) == 0) js.PrefixUnknown(); - - // Even if DISABLE'd, we want to set this flag so we overwrite. - if ((info & OUT_VFPU_PREFIX) != 0) - js.blockWrotePrefixes = true; } } @@ -725,11 +703,8 @@ void Arm64Jit::UpdateRoundingMode(u32 fcr31) { // though, as we need to have the SUBS flag set in the end. So with block linking in the mix, // I don't think this gives us that much benefit. void Arm64Jit::WriteExit(u32 destination, int exit_num) { - // NOTE: Can't blindly check for bad destination addresses here, sometimes exits with bad destinations are written intentionally (like breaks). - _assert_msg_(exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num. dest=%08x", destination); - - // NOTE: Can't blindly check for bad destination addresses here, sometimes exits with bad destinations are written intentionally (like breaks). - WriteDownCount(); + // TODO: Check destination is valid and trigger exception. + WriteDownCount(); //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; diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index f3d6acc6a..a9c97a85a 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -62,7 +62,6 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; - void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; @@ -214,9 +213,7 @@ private: bool ReplaceJalTo(u32 dest); - // Clobbers SCRATCH2. void SaveStaticRegisters(); - // Clobbers SCRATCH2. void LoadStaticRegisters(); void WriteExit(u32 destination, int exit_num); diff --git a/Core/MIPS/ARM64/Arm64RegCache.cpp b/Core/MIPS/ARM64/Arm64RegCache.cpp index 7dc2ba1dd..ac97e33e7 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.cpp +++ b/Core/MIPS/ARM64/Arm64RegCache.cpp @@ -180,7 +180,7 @@ void Arm64RegCache::MapRegTo(ARM64Reg reg, MIPSGPReg mipsReg, int mapFlags) { ar[reg].isDirty = (mapFlags & MAP_DIRTY) ? true : false; if ((mapFlags & MAP_NOINIT) != MAP_NOINIT) { if (mipsReg == MIPS_REG_ZERO) { - // If we get a request to map the zero register, at least we won't spend + // If we get a request to load the zero register, at least we won't spend // time on a memory access... emit_->MOVI2R(reg, 0); @@ -777,7 +777,7 @@ void Arm64RegCache::FlushAll() { // Re-pointerify emit_->MOVK(EncodeRegTo64(allocs[i].ar), ((uint64_t)Memory::base) >> 32, SHIFT_32); ar[allocs[i].ar].pointerified = true; - } else if (!allocs[i].pointerified) { + } else { // If this register got pointerified on the way, mark it as not, so that after save/reload (like in an interpreter fallback), it won't be regarded as such, as it simply won't be. ar[allocs[i].ar].pointerified = false; } diff --git a/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp b/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp index 677171365..9d177ba49 100644 --- a/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp +++ b/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp @@ -319,7 +319,6 @@ void Arm64RegCacheFPU::FlushR(MIPSReg r) { if (mr[r].reg == INVALID_REG) { ERROR_LOG(JIT, "FlushR: MipsReg had bad ArmReg"); } - FlushArmReg((ARM64Reg)(S0 + mr[r].reg)); break; case ML_MEM: @@ -330,6 +329,8 @@ void Arm64RegCacheFPU::FlushR(MIPSReg r) { //BAD break; } + mr[r].loc = ML_MEM; + mr[r].reg = (int)INVALID_REG; } Arm64Gen::ARM64Reg Arm64RegCacheFPU::ARM64RegForFlush(int r) { @@ -519,11 +520,11 @@ ARM64Reg Arm64RegCacheFPU::R(int mipsReg) { return (ARM64Reg)(mr[mipsReg].reg + S0); } else { if (mipsReg < 32) { - ERROR_LOG(JIT, "FReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg, js_->compilerPC, MIPSDisasmAt(js_->compilerPC).c_str()); + ERROR_LOG(JIT, "FReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg, js_->compilerPC, MIPSDisasmAt(js_->compilerPC)); } else if (mipsReg < 32 + 128) { - ERROR_LOG(JIT, "VReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC).c_str()); + ERROR_LOG(JIT, "VReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC)); } else { - ERROR_LOG(JIT, "Tempreg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 128 - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC).c_str()); + ERROR_LOG(JIT, "Tempreg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 128 - 32, js_->compilerPC, MIPSDisasmAt(js_->compilerPC)); } return INVALID_REG; // BAAAD } diff --git a/Core/MIPS/ARM64/Arm64RegCacheFPU.h b/Core/MIPS/ARM64/Arm64RegCacheFPU.h index 40b764744..657d21861 100644 --- a/Core/MIPS/ARM64/Arm64RegCacheFPU.h +++ b/Core/MIPS/ARM64/Arm64RegCacheFPU.h @@ -17,6 +17,8 @@ #pragma once +#pragma once + #include "Core/MIPS/MIPS.h" #include "Core/MIPS/ARM64/Arm64RegCache.h" #include "Core/MIPS/MIPSVFPUUtils.h" @@ -163,6 +165,7 @@ private: MIPSComp::JitOptions *jo_; int numARMFpuReg_; + int qTime_; enum { // On ARM64, each of the 32 registers are full 128-bit. No sharing of components! diff --git a/Core/MIPS/IR/IRAnalysis.cpp b/Core/MIPS/IR/IRAnalysis.cpp deleted file mode 100644 index 8dfc6aab1..000000000 --- a/Core/MIPS/IR/IRAnalysis.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2016- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Core/MIPS/IR/IRAnalysis.h" - -// For std::min -#include - - -static bool IRReadsFrom(const IRInstMeta &inst, int reg, char type, bool *directly) { - if (inst.m.types[1] == type && inst.src1 == reg) { - if (directly) - *directly = true; - return true; - } - if (inst.m.types[2] == type && inst.src2 == reg) { - if (directly) - *directly = true; - return true; - } - if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && inst.m.types[0] == type && inst.src3 == reg) { - if (directly) - *directly = true; - return true; - } - - if (directly) - *directly = false; - if ((inst.m.flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0) - return true; - return false; -} - -bool IRReadsFromFPR(const IRInstMeta &inst, int reg, bool *directly) { - if (IRReadsFrom(inst, reg, 'F', directly)) - return true; - - // We also need to check V and 2. Indirect reads already checked, don't check again. - if (inst.m.types[1] == 'V' && reg >= inst.src1 && reg < inst.src1 + 4) - return true; - if (inst.m.types[1] == '2' && reg >= inst.src1 && reg < inst.src1 + 2) - return true; - if (inst.m.types[2] == 'V' && reg >= inst.src2 && reg < inst.src2 + 4) - return true; - if (inst.m.types[2] == '2' && reg >= inst.src2 && reg < inst.src2 + 2) - return true; - if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) { - if (inst.m.types[0] == 'V' && reg >= inst.src3 && reg <= inst.src3 + 4) - return true; - if (inst.m.types[0] == '2' && reg >= inst.src3 && reg <= inst.src3 + 2) - return true; - } - return false; -} - -static int IRReadsFromList(const IRInstMeta &inst, IRReg regs[4], char type) { - int c = 0; - - if (inst.m.types[1] == type) - regs[c++] = inst.src1; - if (inst.m.types[2] == type) - regs[c++] = inst.src2; - if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && inst.m.types[0] == type) - regs[c++] = inst.src3; - - if (inst.op == IROp::Interpret || inst.op == IROp::CallReplacement || inst.op == IROp::Syscall || inst.op == IROp::Break) - return -1; - if (inst.op == IROp::Breakpoint || inst.op == IROp::MemoryCheck) - return -1; - - return c; -} - -bool IRReadsFromGPR(const IRInstMeta &inst, int reg, bool *directly) { - return IRReadsFrom(inst, reg, 'G', directly); -} - -int IRDestGPR(const IRInstMeta &inst) { - if ((inst.m.flags & IRFLAG_SRC3) == 0 && inst.m.types[0] == 'G') { - return inst.dest; - } - return -1; -} - -bool IRWritesToGPR(const IRInstMeta &inst, int reg) { - return IRDestGPR(inst) == reg; -} - -bool IRWritesToFPR(const IRInstMeta &inst, int reg) { - // Doesn't write to anything. - if ((inst.m.flags & IRFLAG_SRC3) != 0) - return false; - - if (inst.m.types[0] == 'F' && reg == inst.dest) - return true; - if (inst.m.types[0] == 'V' && reg >= inst.dest && reg < inst.dest + 4) - return true; - if (inst.m.types[0] == '2' && reg >= inst.dest && reg < inst.dest + 2) - return true; - return false; -} - -int IRDestFPRs(const IRInstMeta &inst, IRReg regs[4]) { - // Doesn't write to anything. - if ((inst.m.flags & IRFLAG_SRC3) != 0) - return 0; - - if (inst.m.types[0] == 'F') { - regs[0] = inst.dest; - return 1; - } - if (inst.m.types[0] == 'V') { - for (int i = 0; i < 4; ++i) - regs[i] = inst.dest + i; - return 4; - } - if (inst.m.types[0] == '2') { - for (int i = 0; i < 2; ++i) - regs[i] = inst.dest + i; - return 2; - } - return 0; -} - -int IRReadsFromGPRs(const IRInstMeta &inst, IRReg regs[4]) { - return IRReadsFromList(inst, regs, 'G'); -} - -int IRReadsFromFPRs(const IRInstMeta &inst, IRReg regs[16]) { - int c = IRReadsFromList(inst, regs, 'F'); - if (c != 0) - return c; - - // We also need to check V and 2. Indirect reads already checked, don't check again. - if (inst.m.types[1] == 'V' || inst.m.types[1] == '2') { - for (int i = 0; i < (inst.m.types[1] == 'V' ? 4 : 2); ++i) - regs[c++] = inst.src1 + i; - } - if (inst.m.types[2] == 'V' || inst.m.types[2] == '2') { - for (int i = 0; i < (inst.m.types[2] == 'V' ? 4 : 2); ++i) - regs[c++] = inst.src2 + i; - } - if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) { - if (inst.m.types[0] == 'V' || inst.m.types[0] == '2') { - for (int i = 0; i < (inst.m.types[0] == 'V' ? 4 : 2); ++i) - regs[c++] = inst.src3 + i; - } - } - return c; -} - -IRUsage IRNextGPRUsage(int gpr, const IRSituation &info) { - // Exclude any "special" regs from this logic for now. - if (gpr >= 32) - return IRUsage::UNKNOWN; - - int count = std::min(info.numInstructions - info.currentIndex, info.lookaheadCount); - for (int i = 0; i < count; ++i) { - const IRInstMeta inst = GetIRMeta(info.instructions[info.currentIndex + i]); - if (IRReadsFromGPR(inst, gpr)) - return IRUsage::READ; - // We say WRITE when the current instruction writes. It's not useful for spilling. - if (IRDestGPR(inst) == gpr) - return i == 0 ? IRUsage::WRITE : IRUsage::CLOBBERED; - } - - return IRUsage::UNUSED; -} - -IRUsage IRNextFPRUsage(int fpr, const IRSituation &info) { - // Let's only pay attention to standard FP regs and temps. - // See MIPS.h for these offsets. - if (fpr < 0 || (fpr >= 160 && fpr < 192) || fpr >= 208) - return IRUsage::UNKNOWN; - - int count = std::min(info.numInstructions - info.currentIndex, info.lookaheadCount); - for (int i = 0; i < count; ++i) { - const IRInstMeta inst = GetIRMeta(info.instructions[info.currentIndex + i]); - - if (IRReadsFromFPR(inst, fpr)) { - // Special case a broadcast that clobbers it. - if (inst.op == IROp::Vec4Shuffle && inst.src2 == 0 && inst.dest == inst.src1) - return inst.src1 == fpr ? IRUsage::READ : IRUsage::CLOBBERED; - - // If this is an exit reading a temp, ignore it. - if (fpr < IRVTEMP_PFX_S || (GetIRMeta(inst.op)->flags & IRFLAG_EXIT) == 0) - return IRUsage::READ; - } - // We say WRITE when the current instruction writes. It's not useful for spilling. - if (IRWritesToFPR(inst, fpr)) { - return i == 0 ? IRUsage::WRITE : IRUsage::CLOBBERED; - } - } - - // This means we only had exits and hit the end. - if (fpr >= IRVTEMP_PFX_S && count == info.numInstructions - info.currentIndex) - return IRUsage::CLOBBERED; - - return IRUsage::UNUSED; -} diff --git a/Core/MIPS/IR/IRAnalysis.h b/Core/MIPS/IR/IRAnalysis.h deleted file mode 100644 index a1610f7cd..000000000 --- a/Core/MIPS/IR/IRAnalysis.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2016- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "Core/MIPS/IR/IRInst.h" - -struct IRInstMeta { - union { - IRInst i; - struct { - IROp op; - union { - IRReg dest; - IRReg src3; - }; - IRReg src1; - IRReg src2; - u32 constant; - }; - }; - IRMeta m; -}; - -static_assert(offsetof(IRInst, src2) == offsetof(IRInstMeta, src2)); - -inline IRInstMeta GetIRMeta(const IRInst &inst) { - return { { inst }, *GetIRMeta(inst.op) }; -} - -bool IRReadsFromFPR(const IRInstMeta &inst, int reg, bool *directly = nullptr); -bool IRReadsFromGPR(const IRInstMeta &inst, int reg, bool *directly = nullptr); -bool IRWritesToGPR(const IRInstMeta &inst, int reg); -bool IRWritesToFPR(const IRInstMeta &inst, int reg); -int IRDestGPR(const IRInstMeta &inst); -int IRDestFPRs(const IRInstMeta &inst, IRReg regs[4]); -int IRReadsFromGPRs(const IRInstMeta &inst, IRReg regs[4]); -int IRReadsFromFPRs(const IRInstMeta &inst, IRReg regs[16]); - -struct IRSituation { - int lookaheadCount; - int currentIndex; - const IRInst *instructions; - int numInstructions; -}; - -enum class IRUsage { - UNKNOWN, - UNUSED, - READ, - WRITE, - CLOBBERED, -}; - -IRUsage IRNextGPRUsage(int gpr, const IRSituation &info); -IRUsage IRNextFPRUsage(int fpr, const IRSituation &info); diff --git a/Core/MIPS/IR/IRCompBranch.cpp b/Core/MIPS/IR/IRCompBranch.cpp index 49f0f7d5e..c21e2d6b3 100644 --- a/Core/MIPS/IR/IRCompBranch.cpp +++ b/Core/MIPS/IR/IRCompBranch.cpp @@ -455,7 +455,6 @@ void IRFrontend::Comp_Syscall(MIPSOpcode op) { } void IRFrontend::Comp_Break(MIPSOpcode op) { - ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); ir.Write(IROp::Break); js.compiling = false; } diff --git a/Core/MIPS/IR/IRCompFPU.cpp b/Core/MIPS/IR/IRCompFPU.cpp index e83f3a709..cf6b4faa7 100644 --- a/Core/MIPS/IR/IRCompFPU.cpp +++ b/Core/MIPS/IR/IRCompFPU.cpp @@ -102,7 +102,7 @@ void IRFrontend::Comp_FPUComp(MIPSOpcode op) { int opc = op & 0xF; if (opc >= 8) opc -= 8; // alias if (opc == 0) { // f, sf (signalling false) - ir.Write(IROp::FpCondFromReg, 0, MIPS_REG_ZERO); + ir.Write(IROp::ZeroFpCond); return; } @@ -152,8 +152,7 @@ void IRFrontend::Comp_FPU2op(MIPSOpcode op) { ir.Write(IROp::FAbs, fd, fs); break; case 6: //F(fd) = F(fs); break; //mov - if (fd != fs) - ir.Write(IROp::FMov, fd, fs); + ir.Write(IROp::FMov, fd, fs); break; case 7: //F(fd) = -F(fs); break; //neg ir.Write(IROp::FNeg, fd, fs); @@ -204,8 +203,7 @@ void IRFrontend::Comp_mxc1(MIPSOpcode op) { return; } if (fs == 31) { - // This needs to insert fpcond. - ir.Write(IROp::FpCtrlToReg, rt); + DISABLE; // TODO: Add a new op } else if (fs == 0) { ir.Write(IROp::SetConst, rt, ir.AddConstant(MIPSState::FCR0_VALUE)); } else { @@ -221,13 +219,9 @@ void IRFrontend::Comp_mxc1(MIPSOpcode op) { case 6: //ctc1 if (fs == 31) { // Set rounding mode - RestoreRoundingMode(); - ir.Write(IROp::FpCtrlFromReg, 0, rt); - UpdateRoundingMode(); - ApplyRoundingMode(); + DISABLE; } else { - // Maybe not strictly invalid? But likely invalid. - INVALIDOP; + Comp_Generic(op); } return; default: diff --git a/Core/MIPS/IR/IRCompLoadStore.cpp b/Core/MIPS/IR/IRCompLoadStore.cpp index 1a4aac506..cb1892d3d 100644 --- a/Core/MIPS/IR/IRCompLoadStore.cpp +++ b/Core/MIPS/IR/IRCompLoadStore.cpp @@ -105,30 +105,6 @@ namespace MIPSComp { } } - void IRFrontend::Comp_StoreSync(MIPSOpcode op) { - CONDITIONAL_DISABLE(LSU); - - int offset = _IMM16; - MIPSGPReg rt = _RT; - MIPSGPReg rs = _RS; - // Note: still does something even if loading to zero. - - CheckMemoryBreakpoint(rs, offset); - - switch (op >> 26) { - case 48: // ll - ir.Write(IROp::Load32Linked, rt, rs, ir.AddConstant(offset)); - break; - - case 56: // sc - ir.Write(IROp::Store32Conditional, rt, rs, ir.AddConstant(offset)); - break; - - default: - INVALIDOP; - } - } - void IRFrontend::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/IR/IRCompVFPU.cpp b/Core/MIPS/IR/IRCompVFPU.cpp index 6f44c2ccd..70128b4c6 100644 --- a/Core/MIPS/IR/IRCompVFPU.cpp +++ b/Core/MIPS/IR/IRCompVFPU.cpp @@ -66,12 +66,10 @@ namespace MIPSComp { return regs[1] == regs[0] + 1; } - static bool IsConsecutive3(const u8 regs[3]) { - return IsConsecutive2(regs) && regs[2] == regs[1] + 1; - } - static bool IsConsecutive4(const u8 regs[4]) { - return IsConsecutive3(regs) && regs[3] == regs[2] + 1; + return regs[1] == regs[0] + 1 && + regs[2] == regs[1] + 1 && + regs[3] == regs[2] + 1; } static bool IsVec2(VectorSize sz, const u8 regs[2]) { @@ -82,10 +80,6 @@ namespace MIPSComp { return sz == V_Quad && IsConsecutive4(regs) && (regs[0] & 3) == 0; } - static bool IsVec3of4(VectorSize sz, const u8 regs[4]) { - return sz == V_Triple && IsConsecutive3(regs) && (regs[0] & 3) == 0; - } - static bool IsMatrixVec4(MatrixSize sz, const u8 regs[16]) { if (sz != M_4x4) return false; @@ -218,54 +212,6 @@ namespace MIPSComp { ir.Write(IROp::Vec4Shuffle, vregs[0], origV[0], prefix); return; } - - if ((prefix & 0x000FF000) == 0x0000F000) { - // Handle some easy and common cases. - Vec4Init init = Vec4Init::AllZERO; - bool useInit; - switch (prefix & 0xFFF) { - case 0x00: useInit = true; init = Vec4Init::AllZERO; break; - case 0x01: useInit = true; init = Vec4Init::Set_1000; break; - case 0x04: useInit = true; init = Vec4Init::Set_0100; break; - case 0x10: useInit = true; init = Vec4Init::Set_0010; break; - case 0x40: useInit = true; init = Vec4Init::Set_0001; break; - case 0x55: useInit = true; init = Vec4Init::AllONE; break; - default: useInit = false; break; - } - - if (useInit) { - InitRegs(vregs, tempReg); - ir.Write(IROp::Vec4Init, vregs[0], (int)init); - return; - } - } - - // Check if we're just zeroing certain lanes - this is common. - u32 zeroedLanes = 0; - for (int i = 0; i < 4; ++i) { - int regnum = (prefix >> (i * 2)) & 3; - int abs = (prefix >> (8 + i)) & 1; - int negate = (prefix >> (16 + i)) & 1; - int constants = (prefix >> (12 + i)) & 1; - - if (!constants && regnum == i && !abs && !negate) - continue; - if (constants && regnum == 0 && abs == 0 && !negate) { - zeroedLanes |= 1 << i; - continue; - } - - // Nope, it has something else going on. - zeroedLanes = -1; - break; - } - - if (zeroedLanes != -1) { - InitRegs(vregs, tempReg); - ir.Write(IROp::Vec4Init, vregs[0], (int)Vec4Init::AllZERO); - ir.Write(IROp::Vec4Blend, vregs[0], origV[0], vregs[0], zeroedLanes); - return; - } } // Alright, fall back to the generic approach. @@ -292,7 +238,7 @@ namespace MIPSComp { } else { if (negate) ir.Write(IROp::FNeg, vregs[i], origV[regnum]); - else if (vregs[i] != origV[regnum]) + else ir.Write(IROp::FMov, vregs[i], origV[regnum]); } } else { @@ -336,13 +282,6 @@ namespace MIPSComp { if (js.prefixD == 0) return; - if (IsVec4(sz, regs) && js.VfpuWriteMask() != 0 && opts.preferVec4) { - // Use temps for all, we'll blend in the end (keeping in Vec4.) - for (int i = 0; i < 4; ++i) - regs[i] = IRVTEMP_PFX_D + i; - return; - } - for (int i = 0; i < n; i++) { // Hopefully this is rare, we'll just write it into a dumping ground reg. if (js.VfpuWriteMask(i)) @@ -356,13 +295,11 @@ namespace MIPSComp { // "D" prefix is really a post process. No need to allocate a temporary register (except // dummies to simulate writemask, which is done in GetVectorRegsPrefixD - void IRFrontend::ApplyPrefixD(u8 *vregs, VectorSize sz, int vectorReg) { + void IRFrontend::ApplyPrefixD(const u8 *vregs, VectorSize sz) { _assert_(js.prefixDFlag & JitState::PREFIX_KNOWN); if (!js.prefixD) return; - ApplyPrefixDMask(vregs, sz, vectorReg); - int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { if (js.VfpuWriteMask(i)) @@ -377,20 +314,6 @@ namespace MIPSComp { } } - void IRFrontend::ApplyPrefixDMask(u8 *vregs, VectorSize sz, int vectorReg) { - if (IsVec4(sz, vregs) && js.VfpuWriteMask() != 0 && opts.preferVec4) { - u8 origV[4]; - GetVectorRegs(origV, sz, vectorReg); - - // Just keep the original values where it was masked. - ir.Write(IROp::Vec4Blend, origV[0], vregs[0], origV[0], js.VfpuWriteMask()); - - // So that saturate works, change it back. - for (int i = 0; i < 4; ++i) - vregs[i] = origV[i]; - } - } - void IRFrontend::Comp_SV(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU_VFPU); s32 offset = (signed short)(op & 0xFFFC); @@ -424,48 +347,14 @@ namespace MIPSComp { CheckMemoryBreakpoint(rs, imm); - enum class LSVType { - INVALID, - LVQ, - SVQ, - LVLQ, - LVRQ, - SVLQ, - SVRQ, - }; - - LSVType optype = LSVType::INVALID; switch (op >> 26) { - case 54: optype = LSVType::LVQ; break; // lv.q - case 62: optype = LSVType::SVQ; break; // sv.q - case 53: // lvl/lvr.q - highly unusual - optype = (op & 2) == 0 ? LSVType::LVLQ : LSVType::LVRQ; - break; - case 61: // svl/svr.q - highly unusual - optype = (op & 2) == 0 ? LSVType::SVLQ : LSVType::SVRQ; - break; - } - if (optype == LSVType::INVALID) - INVALIDOP; - - if ((optype == LSVType::LVRQ || optype == LSVType::SVRQ) && opts.unalignedLoadStoreVec4) { - // We don't bother with an op for this, but we do fuse unaligned stores which happen. - MIPSOpcode nextOp = GetOffsetInstruction(1); - if ((nextOp.encoding ^ op.encoding) == 0x0000000E) { - // Okay, it's an svr.q/svl.q pair, same registers. Treat as lv.q/sv.q. - EatInstruction(nextOp); - optype = optype == LSVType::LVRQ ? LSVType::LVQ : LSVType::SVQ; - } - } - - switch (optype) { - case LSVType::LVQ: + case 54: //lv.q if (IsVec4(V_Quad, vregs)) { ir.Write(IROp::LoadVec4, vregs[0], rs, ir.AddConstant(imm)); } else { // Let's not even bother with "vertical" loads for now. if (!g_Config.bFastMemory) - ir.Write(IROp::ValidateAddress128, 0, (u8)rs, 0, (u32)imm); + ir.Write({ IROp::ValidateAddress128, { 0 }, (u8)rs, 0, (u32)imm }); ir.Write(IROp::LoadFloat, vregs[0], rs, ir.AddConstant(imm)); ir.Write(IROp::LoadFloat, vregs[1], rs, ir.AddConstant(imm + 4)); ir.Write(IROp::LoadFloat, vregs[2], rs, ir.AddConstant(imm + 8)); @@ -473,13 +362,13 @@ namespace MIPSComp { } break; - case LSVType::SVQ: + case 62: //sv.q if (IsVec4(V_Quad, vregs)) { ir.Write(IROp::StoreVec4, vregs[0], rs, ir.AddConstant(imm)); } else { // Let's not even bother with "vertical" stores for now. if (!g_Config.bFastMemory) - ir.Write(IROp::ValidateAddress128, 0, (u8)rs, 1, (u32)imm); + ir.Write({ IROp::ValidateAddress128, { 0 }, (u8)rs, 1, (u32)imm }); ir.Write(IROp::StoreFloat, vregs[0], rs, ir.AddConstant(imm)); ir.Write(IROp::StoreFloat, vregs[1], rs, ir.AddConstant(imm + 4)); ir.Write(IROp::StoreFloat, vregs[2], rs, ir.AddConstant(imm + 8)); @@ -487,11 +376,8 @@ namespace MIPSComp { } break; - case LSVType::LVLQ: - case LSVType::LVRQ: - case LSVType::SVLQ: - case LSVType::SVRQ: - // These are pretty uncommon unless paired. + case 53: // lvl/lvr.q - highly unusual + case 61: // svl/svr.q - highly unusual DISABLE; break; @@ -524,7 +410,7 @@ namespace MIPSComp { ir.Write(IROp::SetConstF, dregs[i], ir.AddConstantFloat(type == 6 ? 0.0f : 1.0f)); } } - ApplyPrefixD(dregs, sz, vd); + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_VIdt(MIPSOpcode op) { @@ -563,65 +449,28 @@ namespace MIPSComp { } } - ApplyPrefixD(dregs, sz, vd); + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_VMatrixInit(MIPSOpcode op) { CONDITIONAL_DISABLE(VFPU_XFER); MatrixSize sz = GetMtxSize(op); - if (!js.HasNoPrefix()) { + if (sz != M_4x4 || !js.HasNoPrefix()) { DISABLE; } // Matrix init (weird prefixes) // d[N,M] = CONST[N,M] + // Not really about trying here, it will work if enabled. + VectorSize vsz = GetVectorSize(sz); + u8 vecs[4]; int vd = _VD; if (IsMatrixTransposed(vd)) { // All outputs are transpositionally symmetric, so should be fine. vd = TransposeMatrixReg(vd); } - - if (sz != M_4x4) { - // 3x3 is decently common. It expands a lot, but let's set each. - u8 dregs[16]; - GetMatrixRegs(dregs, sz, vd); - - // TODO: It might be worth using Vec4Blend for 3x3 to mask w. - int n = GetMatrixSide(sz); - for (int y = 0; y < n; ++y) { - for (int x = 0; x < n; ++x) { - switch ((op >> 16) & 0xF) { - case 3: // vmidt - if (x == 0 && y == 0) - ir.Write(IROp::SetConstF, dregs[y * 4 + x], ir.AddConstantFloat(1.0f)); - else if (x == y) - ir.Write(IROp::FMov, dregs[y * 4 + x], dregs[0]); - else - ir.Write(IROp::SetConstF, dregs[y * 4 + x], ir.AddConstantFloat(0.0f)); - break; - case 6: // vmzero - // Likely to be fast. - ir.Write(IROp::SetConstF, dregs[y * 4 + x], ir.AddConstantFloat(0.0f)); - break; - case 7: // vmone - if (x == 0 && y == 0) - ir.Write(IROp::SetConstF, dregs[y * 4 + x], ir.AddConstantFloat(1.0f)); - else - ir.Write(IROp::FMov, dregs[y * 4 + x], dregs[0]); - break; - default: - INVALIDOP; - } - } - } - return; - } - - // Not really about trying here, it will work if enabled. - VectorSize vsz = GetVectorSize(sz); - u8 vecs[4]; - GetMatrixColumns(vd, sz, vecs); + GetMatrixColumns(vd, M_4x4, vecs); for (int i = 0; i < 4; i++) { u8 vec[4]; GetVectorRegs(vec, vsz, vecs[i]); @@ -682,7 +531,7 @@ namespace MIPSComp { } ir.Write(IROp::FMov, dregs[0], IRVTEMP_0); - ApplyPrefixD(dregs, V_Single, vd); + ApplyPrefixD(dregs, V_Single); } alignas(16) static const float vavg_table[4] = { 1.0f, 1.0f / 2.0f, 1.0f / 3.0f, 1.0f / 4.0f }; @@ -722,7 +571,7 @@ namespace MIPSComp { break; } - ApplyPrefixD(dregs, V_Single, _VD); + ApplyPrefixD(dregs, V_Single); } void IRFrontend::Comp_VDot(MIPSOpcode op) { @@ -747,27 +596,10 @@ namespace MIPSComp { GetVectorRegsPrefixT(tregs, sz, vt); GetVectorRegsPrefixD(dregs, V_Single, vd); - if (IsVec4(sz, sregs) && IsVec4(sz, tregs)) { - if (IsOverlapSafe(dregs[0], n, sregs, n, tregs)) { - ir.Write(IROp::Vec4Dot, dregs[0], sregs[0], tregs[0]); - } else { - ir.Write(IROp::Vec4Dot, IRVTEMP_0, sregs[0], tregs[0]); - ir.Write(IROp::FMov, dregs[0], IRVTEMP_0); - } - ApplyPrefixD(dregs, V_Single, vd); + if (IsVec4(sz, sregs) && IsVec4(sz, tregs) && IsOverlapSafe(dregs[0], n, sregs, n, tregs)) { + ir.Write(IROp::Vec4Dot, dregs[0], sregs[0], tregs[0]); + ApplyPrefixD(dregs, V_Single); return; - } else if (IsVec3of4(sz, sregs) && IsVec3of4(sz, tregs) && opts.preferVec4Dot) { - // Note: this is often worse than separate muliplies and adds on x86. - if (IsOverlapSafe(dregs[0], n, tregs) || sregs[0] == tregs[0]) { - // Nice example of this in Fat Princess (US) in block 088181A0 (hot.) - // Create a temporary copy of S with the last element zeroed. - ir.Write(IROp::Vec4Init, IRVTEMP_0, (int)Vec4Init::AllZERO); - ir.Write(IROp::Vec4Blend, IRVTEMP_0, IRVTEMP_0, sregs[0], 0x7); - // Now we can just dot like normal, with the last element effectively masked. - ir.Write(IROp::Vec4Dot, dregs[0], IRVTEMP_0, sregs[0] == tregs[0] ? IRVTEMP_0 : tregs[0]); - ApplyPrefixD(dregs, V_Single, vd); - return; - } } int temp0 = IRVTEMP_0; @@ -777,7 +609,7 @@ namespace MIPSComp { ir.Write(IROp::FMul, temp1, sregs[i], tregs[i]); ir.Write(IROp::FAdd, i == (n - 1) ? dregs[0] : temp0, temp0, temp1); } - ApplyPrefixD(dregs, V_Single, vd); + ApplyPrefixD(dregs, V_Single); } void IRFrontend::Comp_VecDo3(MIPSOpcode op) { @@ -789,72 +621,51 @@ namespace MIPSComp { // Vector arithmetic // d[N] = OP(s[N], t[N]) (see below) - enum class VecDo3Op : uint8_t { - INVALID, - VADD, - VSUB, - VDIV, - VMUL, - VMIN, - VMAX, - VSGE, - VSLT, - }; - VecDo3Op type = VecDo3Op::INVALID; - VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); - // Check that we can support the ops, and prepare temporary values for ops that need it. + bool allowSIMD = true; switch (op >> 26) { case 24: //VFPU0 switch ((op >> 23) & 7) { - case 0: type = VecDo3Op::VADD; break; - case 1: type = VecDo3Op::VSUB; break; - case 7: type = VecDo3Op::VDIV; break; - default: INVALIDOP; + case 0: // d[i] = s[i] + t[i]; break; //vadd + case 1: // d[i] = s[i] - t[i]; break; //vsub + break; + case 7: // d[i] = s[i] / t[i]; break; //vdiv + if (!js.HasNoPrefix()) { + DISABLE; + } + break; + default: + INVALIDOP; } break; case 25: //VFPU1 switch ((op >> 23) & 7) { - case 0: type = VecDo3Op::VMUL; break; - default: INVALIDOP; + case 0: // d[i] = s[i] * t[i]; break; //vmul + break; + default: + INVALIDOP; } break; case 27: //VFPU3 switch ((op >> 23) & 7) { - case 2: type = VecDo3Op::VMIN; break; - case 3: type = VecDo3Op::VMAX; break; - case 6: type = VecDo3Op::VSGE; break; - case 7: type = VecDo3Op::VSLT; break; - default: INVALIDOP; + case 2: // vmin + case 3: // vmax + allowSIMD = false; + break; + case 6: // vsge + case 7: // vslt + allowSIMD = false; + break; + default: + INVALIDOP; } break; - default: INVALIDOP; + default: + INVALIDOP; } - _assert_(type != VecDo3Op::INVALID); - bool allowSIMD = true; - switch (type) { - case VecDo3Op::VADD: - case VecDo3Op::VSUB: - case VecDo3Op::VMUL: - break; - case VecDo3Op::VDIV: - if (js.HasUnknownPrefix() || (sz != V_Single && !js.HasNoPrefix())) - DISABLE; - // If it's single, we just need to check the prefixes are within the size. - if (!IsPrefixWithinSize(js.prefixS, op) || !IsPrefixWithinSize(js.prefixT, op)) - DISABLE; - break; - case VecDo3Op::VMIN: - case VecDo3Op::VMAX: - case VecDo3Op::VSGE: - case VecDo3Op::VSLT: - allowSIMD = false; - break; - case VecDo3Op::INVALID: // Can't happen, but to avoid compiler warnings - break; - } + VectorSize sz = GetVecSize(op); + int n = GetNumVectorElements(sz); u8 sregs[4], tregs[4], dregs[4]; GetVectorRegsPrefixS(sregs, sz, _VS); @@ -871,100 +682,98 @@ namespace MIPSComp { } // If all three are consecutive 4, we're safe regardless of if we use temps so we should not check that here. - if (allowSIMD) { + if (allowSIMD && IsVec4(sz, dregs) && IsVec4(sz, sregs) && IsVec4(sz, tregs)) { IROp opFunc = IROp::Nop; - switch (type) { - case VecDo3Op::VADD: // d[i] = s[i] + t[i]; break; //vadd - opFunc = IROp::Vec4Add; - break; - case VecDo3Op::VSUB: // d[i] = s[i] - t[i]; break; //vsub - opFunc = IROp::Vec4Sub; - break; - case VecDo3Op::VDIV: // d[i] = s[i] / t[i]; break; //vdiv - opFunc = IROp::Vec4Div; - break; - case VecDo3Op::VMUL: // d[i] = s[i] * t[i]; break; //vmul - opFunc = IROp::Vec4Mul; - break; - default: - // Leave it Nop, disabled below. - break; - } - - if (IsVec4(sz, dregs) && IsVec4(sz, sregs) && IsVec4(sz, tregs)) { - if (opFunc != IROp::Nop) { - ir.Write(opFunc, dregs[0], sregs[0], tregs[0]); - } else { - DISABLE; + switch (op >> 26) { + case 24: //VFPU0 + switch ((op >> 23) & 7) { + case 0: // d[i] = s[i] + t[i]; break; //vadd + opFunc = IROp::Vec4Add; + break; + case 1: // d[i] = s[i] - t[i]; break; //vsub + opFunc = IROp::Vec4Sub; + break; + case 7: // d[i] = s[i] / t[i]; break; //vdiv + opFunc = IROp::Vec4Div; + break; } - ApplyPrefixD(dregs, sz, _VD); - return; - } else if (IsVec3of4(sz, dregs) && IsVec3of4(sz, sregs) && IsVec3of4(sz, tregs) && opts.preferVec4) { - // This is actually pretty common. Use a temp + blend. - // We could post-process this, but it's easier to do it here. - if (opFunc == IROp::Nop) + break; + case 25: //VFPU1 + switch ((op >> 23) & 7) + { + case 0: // d[i] = s[i] * t[i]; break; //vmul + opFunc = IROp::Vec4Mul; + break; + } + break; + case 27: //VFPU3 + switch ((op >> 23) & 7) + { + case 2: // vmin + case 3: // vmax + case 6: // vsge + case 7: // vslt DISABLE; - ir.Write(opFunc, IRVTEMP_0, sregs[0], tregs[0]); - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7); - ApplyPrefixD(dregs, sz, _VD); - return; + break; + } + break; } - } - if (type == VecDo3Op::VSGE || type == VecDo3Op::VSLT) { - // TODO: Consider a dedicated op? For now, we abuse FpCond a bit. - ir.Write(IROp::FpCondToReg, IRTEMP_0); + if (opFunc != IROp::Nop) { + ir.Write(opFunc, dregs[0], sregs[0], tregs[0]); + } else { + DISABLE; + } + ApplyPrefixD(dregs, sz); + return; } for (int i = 0; i < n; ++i) { - switch (type) { - case VecDo3Op::VADD: // d[i] = s[i] + t[i]; break; //vadd - ir.Write(IROp::FAdd, tempregs[i], sregs[i], tregs[i]); + switch (op >> 26) { + case 24: //VFPU0 + switch ((op >> 23) & 7) { + case 0: // d[i] = s[i] + t[i]; break; //vadd + ir.Write(IROp::FAdd, tempregs[i], sregs[i], tregs[i]); + break; + case 1: // d[i] = s[i] - t[i]; break; //vsub + ir.Write(IROp::FSub, tempregs[i], sregs[i], tregs[i]); + break; + case 7: // d[i] = s[i] / t[i]; break; //vdiv + ir.Write(IROp::FDiv, tempregs[i], sregs[i], tregs[i]); + break; + } break; - case VecDo3Op::VSUB: // d[i] = s[i] - t[i]; break; //vsub - ir.Write(IROp::FSub, tempregs[i], sregs[i], tregs[i]); + case 25: //VFPU1 + switch ((op >> 23) & 7) { + case 0: // d[i] = s[i] * t[i]; break; //vmul + ir.Write(IROp::FMul, tempregs[i], sregs[i], tregs[i]); + break; + } break; - case VecDo3Op::VDIV: // d[i] = s[i] / t[i]; break; //vdiv - ir.Write(IROp::FDiv, tempregs[i], sregs[i], tregs[i]); - break; - case VecDo3Op::VMUL: // d[i] = s[i] * t[i]; break; //vmul - ir.Write(IROp::FMul, tempregs[i], sregs[i], tregs[i]); - break; - case VecDo3Op::VMIN: // vmin - ir.Write(IROp::FMin, tempregs[i], sregs[i], tregs[i]); - break; - case VecDo3Op::VMAX: // vmax - ir.Write(IROp::FMax, tempregs[i], sregs[i], tregs[i]); - break; - case VecDo3Op::VSGE: // vsge - ir.Write(IROp::FCmp, (int)IRFpCompareMode::LessUnordered, sregs[i], tregs[i]); - ir.Write(IROp::FpCondToReg, IRTEMP_1); - ir.Write(IROp::XorConst, IRTEMP_1, IRTEMP_1, ir.AddConstant(1)); - ir.Write(IROp::FMovFromGPR, tempregs[i], IRTEMP_1); - ir.Write(IROp::FCvtSW, tempregs[i], tempregs[i]); - break; - case VecDo3Op::VSLT: // vslt - ir.Write(IROp::FCmp, (int)IRFpCompareMode::LessOrdered, sregs[i], tregs[i]); - ir.Write(IROp::FpCondToReg, IRTEMP_1); - ir.Write(IROp::FMovFromGPR, tempregs[i], IRTEMP_1); - ir.Write(IROp::FCvtSW, tempregs[i], tempregs[i]); - break; - case VecDo3Op::INVALID: // Can't happen, but to avoid compiler warnings + case 27: //VFPU3 + switch ((op >> 23) & 7) { + case 2: // vmin + ir.Write(IROp::FMin, tempregs[i], sregs[i], tregs[i]); + break; + case 3: // vmax + ir.Write(IROp::FMax, tempregs[i], sregs[i], tregs[i]); + break; + case 6: // vsge + case 7: // vslt + DISABLE; + break; + } break; } } - if (type == VecDo3Op::VSGE || type == VecDo3Op::VSLT) { - ir.Write(IROp::FpCondFromReg, IRTEMP_0); - } - for (int i = 0; i < n; i++) { if (dregs[i] != tempregs[i]) { ir.Write(IROp::FMov, dregs[i], tempregs[i]); } } - ApplyPrefixD(dregs, sz, _VD); + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_VV2Op(MIPSOpcode op) { @@ -973,12 +782,10 @@ namespace MIPSComp { if (optype == 0) { if (js.HasUnknownPrefix() || !IsPrefixWithinSize(js.prefixS, op)) DISABLE; - } else if (optype == 1 || optype == 2) { - // D prefix is fine for these, and used sometimes. - if (js.HasUnknownPrefix() || js.HasSPrefix()) + } else { + // Many of these apply the D prefix strangely or override parts of the S prefix. + if (!js.HasNoPrefix()) DISABLE; - } else if (optype == 5 && js.HasDPrefix()) { - DISABLE; } // Vector unary operation @@ -986,19 +793,13 @@ namespace MIPSComp { int vs = _VS; int vd = _VD; - VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); if (optype >= 16 && !js.HasNoPrefix()) { - // Many of these apply the D prefix strangely or override parts of the S prefix. - if (js.HasUnknownPrefix() || sz != V_Single) - DISABLE; - // If it's single, we just need to check the prefixes are within the size. - if (!IsPrefixWithinSize(js.prefixS, op)) - DISABLE; - // The negative ones seem to use negate flags as a prefix hack. - if (optype >= 24 && (js.prefixS & 0x000F0000) != 0) - DISABLE; + DISABLE; + } else if ((optype == 1 || optype == 2) && js.HasSPrefix()) { + DISABLE; + } else if (optype == 5 && js.HasDPrefix()) { + DISABLE; } // Pre-processing: Eliminate silly no-op VMOVs, common in Wipeout Pure @@ -1006,6 +807,9 @@ namespace MIPSComp { return; } + VectorSize sz = GetVecSize(op); + int n = GetNumVectorElements(sz); + u8 sregs[4]{}, dregs[4]{}; GetVectorRegsPrefixS(sregs, sz, vs); GetVectorRegsPrefixD(dregs, sz, vd); @@ -1031,42 +835,27 @@ namespace MIPSComp { break; } - if (canSIMD && !usingTemps) { - IROp irop = IROp::Nop; + if (canSIMD && !usingTemps && IsVec4(sz, sregs) && IsVec4(sz, dregs)) { switch (optype) { case 0: // vmov - irop = IROp::Vec4Mov; + ir.Write(IROp::Vec4Mov, dregs[0], sregs[0]); break; case 1: // vabs - irop = IROp::Vec4Abs; + ir.Write(IROp::Vec4Abs, dregs[0], sregs[0]); break; case 2: // vneg - irop = IROp::Vec4Neg; + ir.Write(IROp::Vec4Neg, dregs[0], sregs[0]); break; } - if (IsVec4(sz, sregs) && IsVec4(sz, dregs) && irop != IROp::Nop) { - ir.Write(irop, dregs[0], sregs[0]); - ApplyPrefixD(dregs, sz, vd); - return; - } else if (IsVec3of4(sz, sregs) && IsVec3of4(sz, dregs) && irop != IROp::Nop && opts.preferVec4) { - // This is a simple case of vmov.t, just blend. - if (irop == IROp::Vec4Mov) { - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], sregs[0], 0x7); - } else { - ir.Write(irop, IRVTEMP_0, sregs[0]); - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7); - } - ApplyPrefixD(dregs, sz, vd); - return; - } + ApplyPrefixD(dregs, sz); + return; } for (int i = 0; i < n; ++i) { switch (optype) { case 0: // d[i] = s[i]; break; //vmov // Probably for swizzle. - if (tempregs[i] != sregs[i]) - ir.Write(IROp::FMov, tempregs[i], sregs[i]); + ir.Write(IROp::FMov, tempregs[i], sregs[i]); break; case 1: // d[i] = fabsf(s[i]); break; //vabs ir.Write(IROp::FAbs, tempregs[i], sregs[i]); @@ -1125,7 +914,7 @@ namespace MIPSComp { } } - ApplyPrefixD(dregs, sz, vd); + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_Vi2f(MIPSOpcode op) { @@ -1140,19 +929,39 @@ namespace MIPSComp { VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); - uint8_t imm = (op >> 16) & 0x1f; + int imm = (op >> 16) & 0x1f; + const float mult = 1.0f / (float)(1UL << imm); u8 sregs[4], dregs[4]; GetVectorRegsPrefixS(sregs, sz, _VS); GetVectorRegsPrefixD(dregs, sz, _VD); - for (int i = 0; i < n; i++) { - if (imm == 0) - ir.Write(IROp::FCvtSW, dregs[i], sregs[i]); - else - ir.Write(IROp::FCvtScaledSW, dregs[i], sregs[i], imm); + u8 tempregs[4]; + for (int i = 0; i < n; ++i) { + if (!IsOverlapSafe(dregs[i], n, sregs)) { + tempregs[i] = IRVTEMP_PFX_T + i; // Need IRVTEMP_0 for the scaling factor + } else { + tempregs[i] = dregs[i]; + } } - ApplyPrefixD(dregs, sz, _VD); + if (mult != 1.0f) + ir.Write(IROp::SetConstF, IRVTEMP_0, ir.AddConstantFloat(mult)); + // TODO: Use the SCVTF with builtin scaling where possible. + for (int i = 0; i < n; i++) { + ir.Write(IROp::FCvtSW, tempregs[i], sregs[i]); + } + if (mult != 1.0f) { + for (int i = 0; i < n; i++) { + ir.Write(IROp::FMul, tempregs[i], tempregs[i], IRVTEMP_0); + } + } + + for (int i = 0; i < n; ++i) { + if (dregs[i] != tempregs[i]) { + ir.Write(IROp::FMov, dregs[i], tempregs[i]); + } + } + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_Vh2f(MIPSOpcode op) { @@ -1177,58 +986,12 @@ namespace MIPSComp { // d[N] = int(S[N] * mult) // Note: saturates on overflow. - VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); - - uint8_t imm = (op >> 16) & 0x1f; - - u8 sregs[4], dregs[4]; - GetVectorRegsPrefixS(sregs, sz, _VS); - GetVectorRegsPrefixD(dregs, sz, _VD); - - // Same values as FCR31. - uint8_t rmode = (op >> 21) & 3; - if (((op >> 21) & 0x1C) != 0x10) - INVALIDOP; - - if (imm != 0) { - for (int i = 0; i < n; i++) - ir.Write(IROp::FCvtScaledWS, dregs[i], sregs[i], imm | (rmode << 6)); - } else { - for (int i = 0; i < n; i++) { - switch (IRRoundMode(rmode)) { - case IRRoundMode::RINT_0: // vf2in - ir.Write(IROp::FRound, dregs[i], sregs[i]); - break; - - case IRRoundMode::CAST_1: // vf2iz - ir.Write(IROp::FTrunc, dregs[i], sregs[i]); - break; - - case IRRoundMode::CEIL_2: // vf2iu - ir.Write(IROp::FCeil, dregs[i], sregs[i]); - break; - - case IRRoundMode::FLOOR_3: // vf2id - ir.Write(IROp::FFloor, dregs[i], sregs[i]); - break; - - default: - INVALIDOP; - } - } - } - - ApplyPrefixDMask(dregs, sz, _VD); + DISABLE; } void IRFrontend::Comp_Mftv(MIPSOpcode op) { CONDITIONAL_DISABLE(VFPU_XFER); - // Vector move from VFPU / from VFPU ctrl (no prefixes) - // gpr = S - // gpr = VFPU_CTRL[i] - int imm = op & 0xFF; MIPSGPReg rt = _RT; switch ((op >> 21) & 0x1f) { @@ -1270,13 +1033,10 @@ namespace MIPSComp { if (imm - 128 == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } else { INVALIDOP; @@ -1286,6 +1046,8 @@ namespace MIPSComp { default: INVALIDOP; } + // This op is marked not to auto-eat prefix so we must do it manually. + EatPrefix(); } void IRFrontend::Comp_Vmfvc(MIPSOpcode op) { @@ -1325,13 +1087,10 @@ namespace MIPSComp { } if (imm == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } else { INVALIDOP; @@ -1392,8 +1151,7 @@ namespace MIPSComp { } for (int a = 0; a < n; a++) { for (int b = 0; b < n; b++) { - if (dregs[a * 4 + b] != sregs[a * 4 + b]) - ir.Write(IROp::FMov, dregs[a * 4 + b], sregs[a * 4 + b]); + ir.Write(IROp::FMov, dregs[a * 4 + b], sregs[a * 4 + b]); } } } @@ -1475,15 +1233,10 @@ namespace MIPSComp { } } - if (!overlap || (vs == vd && IsOverlapSafe(treg, n, dregs))) { - if (IsVec4(sz, sregs) && IsVec4(sz, dregs)) { + if (IsVec4(sz, sregs) && IsVec4(sz, dregs)) { + if (!overlap || (vs == vd && IsOverlapSafe(treg, n, dregs))) { ir.Write(IROp::Vec4Scale, dregs[0], sregs[0], treg); - ApplyPrefixD(dregs, sz, vd); - return; - } else if (IsVec3of4(sz, sregs) && IsVec3of4(sz, dregs) && opts.preferVec4) { - ir.Write(IROp::Vec4Scale, IRVTEMP_0, sregs[0], treg); - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7); - ApplyPrefixD(dregs, sz, vd); + ApplyPrefixD(dregs, sz); return; } } @@ -1499,7 +1252,7 @@ namespace MIPSComp { } } - ApplyPrefixD(dregs, sz, vd); + ApplyPrefixD(dregs, sz); } /* @@ -1670,18 +1423,28 @@ namespace MIPSComp { } } return; - } else if (msz == M_4x4 && IsMatrixVec4(msz, sregs) && IsVec4(sz, tregs)) { - IRReg t = tregs[0]; - if (homogenous) { - // This is probably even what the hardware basically does, wiring t[3] to 1.0f. - ir.Write(IROp::Vec4Init, IRVTEMP_PFX_T, (int)Vec4Init::AllONE); - ir.Write(IROp::Vec4Blend, IRVTEMP_PFX_T, IRVTEMP_PFX_T, t, 0x7); - t = IRVTEMP_PFX_T; + } else if (msz == M_4x4 && IsMatrixVec4(msz, sregs)) { + // Consecutive, which is harder. + DISABLE; + int s0 = IRVTEMP_0; + int s1 = IRVTEMP_PFX_S; + // Doesn't make complete sense to me why this works.... (because it doesn't.) + ir.Write(IROp::Vec4Scale, s0, sregs[0], tregs[0]); + for (int i = 1; i < 4; i++) { + if (!homogenous || (i != n - 1)) { + ir.Write(IROp::Vec4Scale, s1, sregs[i], tregs[i]); + ir.Write(IROp::Vec4Add, s0, s0, s1); + } else { + ir.Write(IROp::Vec4Add, s0, s0, sregs[i]); + } + } + if (IsVec4(sz, dregs)) { + ir.Write(IROp::Vec4Mov, dregs[0], s0); + } else { + for (int i = 0; i < 4; i++) { + ir.Write(IROp::FMov, dregs[i], s0 + i); + } } - for (int i = 0; i < 4; i++) - ir.Write(IROp::Vec4Dot, IRVTEMP_PFX_D + i, sregs[i * 4], t); - for (int i = 0; i < 4; i++) - ir.Write(IROp::FMov, dregs[i], IRVTEMP_PFX_D + i); return; } @@ -1719,46 +1482,8 @@ namespace MIPSComp { // d[0] = s[y]*t[z], d[1] = s[z]*t[x], d[2] = s[x]*t[y] // To do a full cross product: vcrs tmp1, s, t; vcrs tmp2 t, s; vsub d, tmp1, tmp2; // (or just use vcrsp.) - // Note: this is possibly just a swizzle prefix hack for vmul. - VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); - if (sz != V_Triple) - DISABLE; - - u8 sregs[4], dregs[4], tregs[4]; - GetVectorRegsPrefixS(sregs, sz, _VS); - GetVectorRegsPrefixT(tregs, sz, _VT); - GetVectorRegsPrefixD(dregs, sz, _VD); - - if (IsVec3of4(sz, dregs) && IsVec3of4(sz, sregs) && IsVec3of4(sz, tregs) && opts.preferVec4) { - // Use Vec4 where we can. First, apply shuffles. - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_S, sregs[0], VFPU_SWIZZLE(1, 2, 0, 3)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_T, tregs[0], VFPU_SWIZZLE(2, 0, 1, 3)); - ir.Write(IROp::Vec4Mul, IRVTEMP_0, IRVTEMP_PFX_S, IRVTEMP_PFX_T); - // Now just retain w and blend in our values. - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7); - } else { - u8 tempregs[4]{}; - if (!IsOverlapSafe(n, dregs, n, sregs, n, tregs)) { - for (int i = 0; i < n; ++i) - tempregs[i] = IRVTEMP_0 + i; - } else { - for (int i = 0; i < n; ++i) - tempregs[i] = dregs[i]; - } - - ir.Write(IROp::FMul, tempregs[0], sregs[1], tregs[2]); - ir.Write(IROp::FMul, tempregs[1], sregs[2], tregs[0]); - ir.Write(IROp::FMul, tempregs[2], sregs[0], tregs[1]); - - for (int i = 0; i < n; i++) { - if (tempregs[i] != dregs[i]) - ir.Write(IROp::FMov, dregs[i], tempregs[i]); - } - } - - ApplyPrefixD(dregs, sz, _VD); + DISABLE; } void IRFrontend::Comp_VDet(MIPSOpcode op) { @@ -1771,20 +1496,7 @@ namespace MIPSComp { // d[0] = s[0]*t[1] - s[1]*t[0] // Note: this operates on two vectors, not a 2x2 matrix. - VectorSize sz = GetVecSize(op); - if (sz != V_Pair) - DISABLE; - - u8 sregs[4], dregs[4], tregs[4]; - GetVectorRegsPrefixS(sregs, sz, _VS); - GetVectorRegsPrefixT(tregs, sz, _VT); - GetVectorRegsPrefixD(dregs, V_Single, _VD); - - ir.Write(IROp::FMul, IRVTEMP_0, sregs[1], tregs[0]); - ir.Write(IROp::FMul, dregs[0], sregs[0], tregs[1]); - ir.Write(IROp::FSub, dregs[0], dregs[0], IRVTEMP_0); - - ApplyPrefixD(dregs, V_Single, _VD); + DISABLE; } void IRFrontend::Comp_Vi2x(MIPSOpcode op) { @@ -1867,7 +1579,7 @@ namespace MIPSComp { } } - ApplyPrefixD(dregs, outsize, _VD); + ApplyPrefixD(dregs, outsize); } void IRFrontend::Comp_Vx2i(MIPSOpcode op) { @@ -1966,7 +1678,7 @@ namespace MIPSComp { ir.Write(IROp::FMov, dregs[i], tempregs[i]); } } - ApplyPrefixD(dregs, outsize, _VD); + ApplyPrefixD(dregs, outsize); } void IRFrontend::Comp_VCrossQuat(MIPSOpcode op) { @@ -1989,16 +1701,16 @@ namespace MIPSComp { GetVectorRegs(tregs, sz, _VT); GetVectorRegs(dregs, sz, _VD); - if (sz == V_Triple) { - u8 tempregs[4]{}; - for (int i = 0; i < n; ++i) { - if (!IsOverlapSafe(dregs[i], n, sregs, n, tregs)) { - tempregs[i] = IRVTEMP_PFX_T + i; // using IRTEMP0 for other things - } else { - tempregs[i] = dregs[i]; - } + u8 tempregs[4]{}; + for (int i = 0; i < n; ++i) { + if (!IsOverlapSafe(dregs[i], n, sregs, n, tregs)) { + tempregs[i] = IRVTEMP_PFX_T + i; // using IRTEMP0 for other things + } else { + tempregs[i] = dregs[i]; } + } + if (sz == V_Triple) { int temp0 = IRVTEMP_0; int temp1 = IRVTEMP_0 + 1; // Compute X @@ -2015,50 +1727,15 @@ namespace MIPSComp { ir.Write(IROp::FMul, temp0, sregs[0], tregs[1]); ir.Write(IROp::FMul, temp1, sregs[1], tregs[0]); ir.Write(IROp::FSub, tempregs[2], temp0, temp1); - - for (int i = 0; i < n; i++) { - if (tempregs[i] != dregs[i]) - ir.Write(IROp::FMov, dregs[i], tempregs[i]); - } } else if (sz == V_Quad) { - // Rather than using vdots, we organize this as SIMD multiplies and adds. - // That means flipping the logic column-wise. Also, luckily no prefix temps used. - if (!IsConsecutive4(sregs) || !IsConsecutive4(tregs) || !IsConsecutive4(dregs)) { - DISABLE; - } - - auto shuffleImm = [](int x, int y, int z, int w) { return x | (y << 2) | (z << 4) | (w << 6); }; - auto blendConst = [](int x, int y, int z, int w) { return x | (y << 1) | (z << 2) | (w << 3); }; - - // Prepare some negatives. - ir.Write(IROp::Vec4Neg, IRVTEMP_0, tregs[0]); - - // tmp = S[x,x,x,x] * T[w,-z,y,-x] - ir.Write(IROp::Vec4Blend, IRVTEMP_PFX_S, tregs[0], IRVTEMP_0, blendConst(1, 0, 1, 0)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_T, IRVTEMP_PFX_S, shuffleImm(3, 2, 1, 0)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_S, sregs[0], shuffleImm(0, 0, 0, 0)); - ir.Write(IROp::Vec4Mul, IRVTEMP_PFX_D, IRVTEMP_PFX_S, IRVTEMP_PFX_T); - - // tmp += S[y,y,y,y] * T[z,w,-x,-y] - ir.Write(IROp::Vec4Blend, IRVTEMP_PFX_S, tregs[0], IRVTEMP_0, blendConst(1, 1, 0, 0)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_T, IRVTEMP_PFX_S, shuffleImm(2, 3, 0, 1)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_S, sregs[0], shuffleImm(1, 1, 1, 1)); - ir.Write(IROp::Vec4Mul, IRVTEMP_PFX_S, IRVTEMP_PFX_S, IRVTEMP_PFX_T); - ir.Write(IROp::Vec4Add, IRVTEMP_PFX_D, IRVTEMP_PFX_D, IRVTEMP_PFX_S); - - // tmp += S[z,z,z,z] * T[-y,x,w,-z] - ir.Write(IROp::Vec4Blend, IRVTEMP_PFX_S, tregs[0], IRVTEMP_0, blendConst(0, 1, 1, 0)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_T, IRVTEMP_PFX_S, shuffleImm(1, 0, 3, 2)); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_S, sregs[0], shuffleImm(2, 2, 2, 2)); - ir.Write(IROp::Vec4Mul, IRVTEMP_PFX_S, IRVTEMP_PFX_S, IRVTEMP_PFX_T); - ir.Write(IROp::Vec4Add, IRVTEMP_PFX_D, IRVTEMP_PFX_D, IRVTEMP_PFX_S); - - // tmp += S[w,w,w,w] * T[x,y,z,w] - ir.Write(IROp::Vec4Shuffle, IRVTEMP_PFX_S, sregs[0], shuffleImm(3, 3, 3, 3)); - ir.Write(IROp::Vec4Mul, IRVTEMP_PFX_S, IRVTEMP_PFX_S, tregs[0]); - ir.Write(IROp::Vec4Add, dregs[0], IRVTEMP_PFX_D, IRVTEMP_PFX_S); + DISABLE; } else { - INVALIDOP; + DISABLE; + } + + for (int i = 0; i < n; i++) { + if (tempregs[i] != dregs[i]) + ir.Write(IROp::FMov, dregs[i], tempregs[i]); } } @@ -2106,10 +1783,6 @@ namespace MIPSComp { int tf = (op >> 19) & 1; int imm3 = (op >> 16) & 7; - if (IsVec4(sz, sregs) && IsVec4(sz, dregs)) { - // TODO: Could do a VfpuCC variant of Vec4Blend. - } - for (int i = 0; i < n; ++i) { // Simplification: Disable if overlap unsafe if (!IsOverlapSafeAllowS(dregs[i], i, n, sregs)) { @@ -2127,7 +1800,7 @@ namespace MIPSComp { ir.Write(IROp::FCmovVfpuCC, dregs[i], sregs[i], (i) | ((!tf) << 7)); } } - ApplyPrefixD(dregs, sz, _VD); + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_Viim(MIPSOpcode op) { @@ -2142,7 +1815,7 @@ namespace MIPSComp { u8 dreg; GetVectorRegsPrefixD(&dreg, V_Single, _VT); ir.Write(IROp::SetConstF, dreg, ir.AddConstantFloat((float)imm)); - ApplyPrefixD(&dreg, V_Single, _VT); + ApplyPrefixD(&dreg, V_Single); } void IRFrontend::Comp_Vfim(MIPSOpcode op) { @@ -2160,7 +1833,7 @@ namespace MIPSComp { u8 dreg; GetVectorRegsPrefixD(&dreg, V_Single, _VT); ir.Write(IROp::SetConstF, dreg, ir.AddConstantFloat(fval.f)); - ApplyPrefixD(&dreg, V_Single, _VT); + ApplyPrefixD(&dreg, V_Single); } void IRFrontend::Comp_Vcst(MIPSOpcode op) { @@ -2179,24 +1852,10 @@ namespace MIPSComp { u8 dregs[4]; GetVectorRegsPrefixD(dregs, sz, vd); - - if (IsVec4(sz, dregs)) { - ir.Write(IROp::SetConstF, IRVTEMP_0, ir.AddConstantFloat(cst_constants[conNum])); - ir.Write(IROp::Vec4Shuffle, dregs[0], IRVTEMP_0, 0); - } else if (IsVec3of4(sz, dregs) && opts.preferVec4) { - ir.Write(IROp::SetConstF, IRVTEMP_0, ir.AddConstantFloat(cst_constants[conNum])); - ir.Write(IROp::Vec4Shuffle, IRVTEMP_0, IRVTEMP_0, 0); - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7); - } else { - for (int i = 0; i < n; i++) { - // Most of the time, materializing a float is slower than copying from another float. - if (i == 0) - ir.Write(IROp::SetConstF, dregs[i], ir.AddConstantFloat(cst_constants[conNum])); - else - ir.Write(IROp::FMov, dregs[i], dregs[0]); - } + for (int i = 0; i < n; i++) { + ir.Write(IROp::SetConstF, dregs[i], ir.AddConstantFloat(cst_constants[conNum])); } - ApplyPrefixD(dregs, sz, vd); + ApplyPrefixD(dregs, sz); } // Very heavily used by FF:CC. Should be replaced by a fast approximation instead of @@ -2307,7 +1966,7 @@ namespace MIPSComp { } } - ApplyPrefixD(dregs, sz, _VD); + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_Vocp(MIPSOpcode op) { @@ -2335,32 +1994,25 @@ namespace MIPSComp { GetVectorRegsPrefixT(tregs, sz, _VS); GetVectorRegsPrefixD(dregs, sz, _VD); - if (IsVec4(sz, dregs) && IsVec4(sz, sregs) && IsVec4(sz, tregs)) { - ir.Write(IROp::Vec4Add, dregs[0], tregs[0], sregs[0]); - } else if (IsVec3of4(sz, dregs) && IsVec3of4(sz, sregs) && IsVec3of4(sz, tregs) && opts.preferVec4) { - ir.Write(IROp::Vec4Add, IRVTEMP_0, tregs[0], sregs[0]); - ir.Write(IROp::Vec4Blend, dregs[0], dregs[0], IRVTEMP_0, 0x7); - } else { - u8 tempregs[4]; - for (int i = 0; i < n; ++i) { - if (!IsOverlapSafe(dregs[i], n, sregs)) { - tempregs[i] = IRVTEMP_0 + i; - } else { - tempregs[i] = dregs[i]; - } - } - - for (int i = 0; i < n; ++i) { - ir.Write(IROp::FAdd, tempregs[i], tregs[i], sregs[i]); - } - for (int i = 0; i < n; ++i) { - if (dregs[i] != tempregs[i]) { - ir.Write(IROp::FMov, dregs[i], tempregs[i]); - } + u8 tempregs[4]; + for (int i = 0; i < n; ++i) { + if (!IsOverlapSafe(dregs[i], n, sregs)) { + tempregs[i] = IRVTEMP_0 + i; + } else { + tempregs[i] = dregs[i]; } } - ApplyPrefixD(dregs, sz, _VD); + for (int i = 0; i < n; ++i) { + ir.Write(IROp::FAdd, tempregs[i], tregs[i], sregs[i]); + } + for (int i = 0; i < n; ++i) { + if (dregs[i] != tempregs[i]) { + ir.Write(IROp::FMov, dregs[i], tempregs[i]); + } + } + + ApplyPrefixD(dregs, sz); } void IRFrontend::Comp_ColorConv(MIPSOpcode op) { @@ -2429,6 +2081,6 @@ namespace MIPSComp { ir.Write(IROp::FMov, dregs[i], tempregs[i]); } - ApplyPrefixD(dregs, sz, _VD); + ApplyPrefixD(dregs, sz); } } diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index 5b2a38960..66a3efbaf 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -32,8 +32,9 @@ namespace MIPSComp { IRFrontend::IRFrontend(bool startDefaultPrefix) { - js.startDefaultPrefix = startDefaultPrefix; + js.startDefaultPrefix = true; js.hasSetRounding = false; + // js.currentRoundingFunc = convertS0ToSCRATCH1[0]; // The debugger sets this so that "go" on a breakpoint will actually... go. // But if they reset, we can end up hitting it by mistake, since it's based on PC and ticks. @@ -63,15 +64,6 @@ void IRFrontend::FlushAll() { } void IRFrontend::FlushPrefixV() { - if (js.startDefaultPrefix && !js.blockWrotePrefixes && js.HasNoPrefix()) { - // They started default, we never modified in memory, and they're default now. - // No reason to modify memory. This is common at end of blocks. Just clear dirty. - js.prefixSFlag = (JitState::PrefixState)(js.prefixSFlag & ~JitState::PREFIX_DIRTY); - js.prefixTFlag = (JitState::PrefixState)(js.prefixTFlag & ~JitState::PREFIX_DIRTY); - js.prefixDFlag = (JitState::PrefixState)(js.prefixDFlag & ~JitState::PREFIX_DIRTY); - return; - } - if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) { ir.Write(IROp::SetCtrlVFPU, VFPU_CTRL_SPREFIX, ir.AddConstant(js.prefixS)); js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY); @@ -86,9 +78,6 @@ void IRFrontend::FlushPrefixV() { ir.Write(IROp::SetCtrlVFPU, VFPU_CTRL_DPREFIX, ir.AddConstant(js.prefixD)); js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } - - // If we got here, we must've written prefixes to memory in this block. - js.blockWrotePrefixes = true; } void IRFrontend::EatInstruction(MIPSOpcode op) { @@ -131,7 +120,8 @@ bool IRFrontend::CheckRounding(u32 blockAddress) { // Let's try that one more time. We won't get back here because we toggled the value. js.startDefaultPrefix = false; - cleanSlate = true; + // TODO: Make sure this works. + // cleanSlate = true; } return cleanSlate; @@ -189,10 +179,6 @@ void IRFrontend::Comp_Generic(MIPSOpcode op) { // If it does eat them, it'll happen in MIPSCompileOp(). if ((info & OUT_EAT_PREFIX) == 0) js.PrefixUnknown(); - - // Even if DISABLE'd, we want to set this flag so we overwrite. - if ((info & OUT_VFPU_PREFIX) != 0) - js.blockWrotePrefixes = true; } } @@ -247,7 +233,6 @@ void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &m js.curBlock = nullptr; js.compiling = true; js.hadBreakpoints = false; - js.blockWrotePrefixes = false; js.inDelaySlot = false; js.PrefixStart(); ir.Clear(); @@ -280,7 +265,6 @@ void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &m &OptimizeFPMoves, &PropagateConstants, &PurgeTemps, - &ReduceVec4Flush, // &ReorderLoadStore, // &MergeLoadStore, // &ThreeOpToTwoOp, @@ -299,7 +283,7 @@ void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &m NOTICE_LOG(JIT, "=============== mips %08x ===============", em_address); for (u32 cpc = em_address; cpc != GetCompilerPC(); cpc += 4) { temp2[0] = 0; - MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp2, sizeof(temp2), true); + MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp2, true); NOTICE_LOG(JIT, "M: %08x %s", cpc, temp2); } } @@ -339,27 +323,16 @@ void IRFrontend::CheckBreakpoint(u32 addr) { if (CBreakPoints::IsAddressBreakPoint(addr)) { FlushAll(); - // Can't skip this even at the start of a block, might impact block linking. - ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); - RestoreRoundingMode(); - // At this point, downcount HAS the delay slot, but not the instruction itself. - int downcountOffset = 0; - if (js.inDelaySlot) { - MIPSOpcode branchOp = Memory::Read_Opcode_JIT(GetCompilerPC()); - MIPSOpcode delayOp = Memory::Read_Opcode_JIT(addr); - downcountOffset = -MIPSGetInstructionCycleEstimate(delayOp); - if ((MIPSGetInfo(branchOp) & LIKELY) != 0) { - // Okay, we're in a likely branch. Also negate the branch cycles. - downcountOffset += -MIPSGetInstructionCycleEstimate(branchOp); - } - } + ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); + // 0 because we normally execute before increasing. + // TODO: In likely branches, downcount will be incorrect. + int downcountOffset = js.inDelaySlot && js.downcountAmount >= 2 ? -2 : 0; int downcountAmount = js.downcountAmount + downcountOffset; - if (downcountAmount != 0) - ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); + ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); // Note that this means downcount can't be metadata on the block. js.downcountAmount = -downcountOffset; - ir.Write(IROp::Breakpoint, 0, ir.AddConstant(addr)); + ir.Write(IROp::Breakpoint); ApplyRoundingMode(); js.hadBreakpoints = true; @@ -370,28 +343,19 @@ void IRFrontend::CheckMemoryBreakpoint(int rs, int offset) { if (CBreakPoints::HasMemChecks()) { FlushAll(); - // Can't skip this even at the start of a block, might impact block linking. - ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); - RestoreRoundingMode(); - // At this point, downcount HAS the delay slot, but not the instruction itself. - int downcountOffset = 0; - if (js.inDelaySlot) { - // We assume delay slot in compilerPC + 4. - MIPSOpcode branchOp = Memory::Read_Opcode_JIT(GetCompilerPC()); - MIPSOpcode delayOp = Memory::Read_Opcode_JIT(GetCompilerPC() + 4); - downcountOffset = -MIPSGetInstructionCycleEstimate(delayOp); - if ((MIPSGetInfo(branchOp) & LIKELY) != 0) { - // Okay, we're in a likely branch. Also negate the branch cycles. - downcountOffset += -MIPSGetInstructionCycleEstimate(branchOp); - } + ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); + // 0 because we normally execute before increasing. + int downcountOffset = js.inDelaySlot ? -2 : -1; + // TODO: In likely branches, downcount will be incorrect. This might make resume fail. + if (js.downcountAmount == 0) { + downcountOffset = 0; } int downcountAmount = js.downcountAmount + downcountOffset; - if (downcountAmount != 0) - ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); + ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); // Note that this means downcount can't be metadata on the block. js.downcountAmount = -downcountOffset; - ir.Write(IROp::MemoryCheck, js.inDelaySlot ? 4 : 0, rs, ir.AddConstant(offset)); + ir.Write(IROp::MemoryCheck, 0, rs, ir.AddConstant(offset)); ApplyRoundingMode(); js.hadBreakpoints = true; diff --git a/Core/MIPS/IR/IRFrontend.h b/Core/MIPS/IR/IRFrontend.h index 4ae7b4a09..0f9a1ab41 100644 --- a/Core/MIPS/IR/IRFrontend.h +++ b/Core/MIPS/IR/IRFrontend.h @@ -18,7 +18,6 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; - void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; @@ -126,8 +125,7 @@ private: void CompShiftVar(MIPSOpcode op, IROp shiftType); void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz, int tempReg); - void ApplyPrefixD(u8 *vregs, VectorSize sz, int vectorReg); - void ApplyPrefixDMask(u8 *vregs, VectorSize sz, int vectorReg); + void ApplyPrefixD(const u8 *vregs, VectorSize sz); void GetVectorRegsPrefixS(u8 *regs, VectorSize sz, int vectorReg); void GetVectorRegsPrefixT(u8 *regs, VectorSize sz, int vectorReg); void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg); diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index 3db8c4e4e..13b2509f1 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -1,5 +1,6 @@ #include "Common/CommonFuncs.h" #include "Core/MIPS/IR/IRInst.h" +#include "Core/MIPS/IR/IRPassSimplify.h" #include "Core/MIPS/MIPSDebugInterface.h" // Legend @@ -72,7 +73,6 @@ static const IRMeta irMeta[] = { { IROp::Load32, "Load32", "GGC" }, { IROp::Load32Left, "Load32Left", "GGC", IRFLAG_SRC3DST }, { IROp::Load32Right, "Load32Right", "GGC", IRFLAG_SRC3DST }, - { IROp::Load32Linked, "Load32Linked", "GGC" }, { IROp::LoadFloat, "LoadFloat", "FGC" }, { IROp::LoadVec4, "LoadVec4", "VGC" }, { IROp::Store8, "Store8", "GGC", IRFLAG_SRC3 }, @@ -80,7 +80,6 @@ static const IRMeta irMeta[] = { { IROp::Store32, "Store32", "GGC", IRFLAG_SRC3 }, { IROp::Store32Left, "Store32Left", "GGC", IRFLAG_SRC3 }, { IROp::Store32Right, "Store32Right", "GGC", IRFLAG_SRC3 }, - { IROp::Store32Conditional, "Store32Conditional", "GGC", IRFLAG_SRC3DST }, { IROp::StoreFloat, "StoreFloat", "FGC", IRFLAG_SRC3 }, { IROp::StoreVec4, "StoreVec4", "VGC", IRFLAG_SRC3 }, { IROp::FAdd, "FAdd", "FFF" }, @@ -106,27 +105,22 @@ static const IRMeta irMeta[] = { { IROp::FFloor, "FFloor", "FF" }, { IROp::FCvtWS, "FCvtWS", "FF" }, { IROp::FCvtSW, "FCvtSW", "FF" }, - { IROp::FCvtScaledWS, "FCvtScaledWS", "FFI" }, - { IROp::FCvtScaledSW, "FCvtScaledSW", "FFI" }, { IROp::FCmp, "FCmp", "mFF" }, { IROp::FSat0_1, "FSat(0 - 1)", "FF" }, { IROp::FSatMinus1_1, "FSat(-1 - 1)", "FF" }, { IROp::FMovFromGPR, "FMovFromGPR", "FG" }, { IROp::FMovToGPR, "FMovToGPR", "GF" }, - { IROp::FpCondFromReg, "FpCondFromReg", "_G" }, + { IROp::ZeroFpCond, "ZeroFpCond", "" }, { IROp::FpCondToReg, "FpCondToReg", "G" }, - { IROp::FpCtrlFromReg, "FpCtrlFromReg", "_G" }, - { IROp::FpCtrlToReg, "FpCtrlToReg", "G" }, - { IROp::VfpuCtrlToReg, "VfpuCtrlToReg", "GT" }, + { IROp::VfpuCtrlToReg, "VfpuCtrlToReg", "GI" }, { IROp::SetCtrlVFPU, "SetCtrlVFPU", "TC" }, { IROp::SetCtrlVFPUReg, "SetCtrlVFPUReg", "TG" }, { IROp::SetCtrlVFPUFReg, "SetCtrlVFPUFReg", "TF" }, - { IROp::FCmovVfpuCC, "FCmovVfpuCC", "FFI", IRFLAG_SRC3DST }, + { IROp::FCmovVfpuCC, "FCmovVfpuCC", "FFI" }, { IROp::FCmpVfpuBit, "FCmpVfpuBit", "IFF" }, { IROp::FCmpVfpuAggregate, "FCmpVfpuAggregate", "I" }, { IROp::Vec4Init, "Vec4Init", "Vv" }, { IROp::Vec4Shuffle, "Vec4Shuffle", "VVs" }, - { IROp::Vec4Blend, "Vec4Blend", "VVVC" }, { IROp::Vec4Mov, "Vec4Mov", "VV" }, { IROp::Vec4Add, "Vec4Add", "VVV" }, { IROp::Vec4Sub, "Vec4Sub", "VVV" }, @@ -147,10 +141,10 @@ static const IRMeta irMeta[] = { { IROp::Vec2ClampToZero, "Vec2ClampToZero", "22" }, { IROp::Vec4Pack32To8, "Vec4Pack32To8", "FV" }, { IROp::Vec4Pack31To8, "Vec4Pack31To8", "FV" }, - { IROp::Vec2Pack32To16, "Vec2Pack32To16", "F2" }, - { IROp::Vec2Pack31To16, "Vec2Pack31To16", "F2" }, + { IROp::Vec2Pack32To16, "Vec2Pack32To16", "2V" }, + { IROp::Vec2Pack31To16, "Vec2Pack31To16", "2V" }, - { IROp::Interpret, "Interpret", "_C", IRFLAG_BARRIER }, + { IROp::Interpret, "Interpret", "_C" }, { IROp::Downcount, "Downcount", "_C" }, { IROp::ExitToPC, "ExitToPC", "", IRFLAG_EXIT }, { IROp::ExitToConst, "Exit", "C", IRFLAG_EXIT }, @@ -165,14 +159,14 @@ static const IRMeta irMeta[] = { { IROp::Break, "Break", "", IRFLAG_EXIT }, { IROp::SetPC, "SetPC", "_G" }, { IROp::SetPCConst, "SetPC", "_C" }, - { IROp::CallReplacement, "CallRepl", "_C", IRFLAG_BARRIER }, - { IROp::Breakpoint, "Breakpoint", "_C", IRFLAG_BARRIER }, - { IROp::MemoryCheck, "MemoryCheck", "IGC", IRFLAG_BARRIER }, + { IROp::CallReplacement, "CallRepl", "_C" }, + { IROp::Breakpoint, "Breakpoint", "", IRFLAG_EXIT }, + { IROp::MemoryCheck, "MemoryCheck", "_GC", IRFLAG_EXIT }, - { IROp::ValidateAddress8, "ValidAddr8", "_GC", IRFLAG_BARRIER }, - { IROp::ValidateAddress16, "ValidAddr16", "_GC", IRFLAG_BARRIER }, - { IROp::ValidateAddress32, "ValidAddr32", "_GC", IRFLAG_BARRIER }, - { IROp::ValidateAddress128, "ValidAddr128", "_GC", IRFLAG_BARRIER }, + { IROp::ValidateAddress8, "ValidAddr8", "_GC", IRFLAG_EXIT }, + { IROp::ValidateAddress16, "ValidAddr16", "_GC", IRFLAG_EXIT }, + { IROp::ValidateAddress32, "ValidAddr32", "_GC", IRFLAG_EXIT }, + { IROp::ValidateAddress128, "ValidAddr128", "_GC", IRFLAG_EXIT }, { IROp::RestoreRoundingMode, "RestoreRoundingMode", "" }, { IROp::ApplyRoundingMode, "ApplyRoundingMode", "" }, @@ -214,7 +208,7 @@ int IRWriter::AddConstantFloat(float value) { return AddConstant(val); } -static std::string GetGPRName(int r) { +const char *GetGPRName(int r) { if (r < 32) { return currentDebugMIPS->GetRegName(0, r); } @@ -265,25 +259,25 @@ void DisassembleParam(char *buf, int bufSize, u8 param, char type, u32 constant) switch (type) { case 'G': - snprintf(buf, bufSize, "%s", GetGPRName(param).c_str()); + snprintf(buf, bufSize, "%s", GetGPRName(param)); break; case 'F': if (param >= 32) { - snprintf(buf, bufSize, "vf%d", param - 32); + snprintf(buf, bufSize, "v%d", param - 32); } else { snprintf(buf, bufSize, "f%d", param); } break; case 'V': if (param >= 32) { - snprintf(buf, bufSize, "vf%d..vf%d", param - 32, param - 32 + 3); + snprintf(buf, bufSize, "v%d..v%d", param - 32, param - 32 + 3); } else { snprintf(buf, bufSize, "f%d..f%d", param, param + 3); } break; case '2': if (param >= 32) { - snprintf(buf, bufSize, "vf%d,vf%d", param - 32, param - 32 + 1); + snprintf(buf, bufSize, "v%d,v%d", param - 32, param - 32 + 1); } else { snprintf(buf, bufSize, "f%d,f%d", param, param + 1); } @@ -329,20 +323,14 @@ void DisassembleIR(char *buf, size_t bufsize, IRInst inst) { char bufDst[16]; char bufSrc1[16]; char bufSrc2[16]; - // Only really used for constant. - char bufSrc3[16]; DisassembleParam(bufDst, sizeof(bufDst) - 2, inst.dest, meta->types[0], inst.constant); DisassembleParam(bufSrc1, sizeof(bufSrc1) - 2, inst.src1, meta->types[1], inst.constant); DisassembleParam(bufSrc2, sizeof(bufSrc2), inst.src2, meta->types[2], inst.constant); - DisassembleParam(bufSrc3, sizeof(bufSrc3), inst.src3, meta->types[3], inst.constant); if (meta->types[1] && meta->types[0] != '_') { strcat(bufDst, ", "); } if (meta->types[2] && meta->types[1] != '_') { strcat(bufSrc1, ", "); } - if (meta->types[3] && meta->types[2] != '_') { - strcat(bufSrc2, ", "); - } - snprintf(buf, bufsize, "%s %s%s%s%s", meta->name, bufDst, bufSrc1, bufSrc2, bufSrc3); + snprintf(buf, bufsize, "%s %s%s%s", meta->name, bufDst, bufSrc1, bufSrc2); } diff --git a/Core/MIPS/IR/IRInst.h b/Core/MIPS/IR/IRInst.h index e727697d3..8c7b67b00 100644 --- a/Core/MIPS/IR/IRInst.h +++ b/Core/MIPS/IR/IRInst.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -17,7 +16,7 @@ // even be directly JIT-ed, but the gains will probably be tiny over our older direct // MIPS->target JITs. -enum class IROp : uint8_t { +enum class IROp : u8 { Nop, SetConst, @@ -93,7 +92,6 @@ enum class IROp : uint8_t { Load32, Load32Left, Load32Right, - Load32Linked, LoadFloat, LoadVec4, @@ -102,7 +100,6 @@ enum class IROp : uint8_t { Store32, Store32Left, Store32Right, - Store32Conditional, StoreFloat, StoreVec4, @@ -130,8 +127,6 @@ enum class IROp : uint8_t { FCvtWS, FCvtSW, - FCvtScaledWS, - FCvtScaledSW, FMovFromGPR, FMovToGPR, @@ -139,12 +134,10 @@ enum class IROp : uint8_t { FSat0_1, FSatMinus1_1, - FpCondFromReg, FpCondToReg, - FpCtrlFromReg, - FpCtrlToReg, VfpuCtrlToReg, + ZeroFpCond, FCmp, FCmovVfpuCC, @@ -165,7 +158,6 @@ enum class IROp : uint8_t { // support SIMD. Vec4Init, Vec4Shuffle, - Vec4Blend, Vec4Mov, Vec4Add, Vec4Sub, @@ -253,13 +245,6 @@ enum class Vec4Init { Set_0001, }; -enum class IRRoundMode : uint8_t { - RINT_0 = 0, - CAST_1 = 1, - CEIL_2 = 2, - FLOOR_3 = 3, -}; - // Hm, unused inline IRComparison Invert(IRComparison comp) { switch (comp) { @@ -298,9 +283,7 @@ enum IRFpCompareMode { LessEqualUnordered, // ule, ngt (less equal, unordered) }; -typedef u8 IRReg; - -enum : IRReg { +enum { IRTEMP_0 = 192, IRTEMP_1, IRTEMP_2, @@ -317,6 +300,9 @@ enum : IRReg { IRVTEMP_PFX_D = 232 - 32, IRVTEMP_0 = 236 - 32, + // 16 float temps for vector S and T prefixes and things like that. + // IRVTEMP_0 = 208 - 64, // -64 to be relative to v[0] + // Hacky way to get to other state IRREG_VFPU_CTRL_BASE = 208, IRREG_VFPU_CC = 211, @@ -324,7 +310,6 @@ enum : IRReg { IRREG_HI = 243, IRREG_FCR31 = 244, IRREG_FPCOND = 245, - IRREG_LLBIT = 250, }; enum IRFlags { @@ -334,14 +319,12 @@ enum IRFlags { IRFLAG_SRC3DST = 0x0002, // Exit instruction (maybe conditional.) IRFLAG_EXIT = 0x0004, - // Instruction like Interpret which may read anything, but not an exit. - IRFLAG_BARRIER = 0x0008, }; struct IRMeta { IROp op; const char *name; - char types[5]; // GGG + const char types[4]; // GGG u32 flags; }; @@ -349,11 +332,11 @@ struct IRMeta { struct IRInst { IROp op; union { - IRReg dest; - IRReg src3; + u8 dest; + u8 src3; }; - IRReg src1; - IRReg src2; + u8 src1; + u8 src2; u32 constant; }; @@ -373,10 +356,6 @@ public: } void Write(IROp op, u8 dst = 0, u8 src1 = 0, u8 src2 = 0); - void Write(IROp op, IRReg dst, IRReg src1, IRReg src2, uint32_t c) { - AddConstant(c); - Write(op, dst, src1, src2); - } void Write(IRInst inst) { insts_.push_back(inst); } @@ -385,9 +364,6 @@ public: int AddConstant(u32 value); int AddConstantFloat(float value); - void Reserve(size_t s) { - insts_.reserve(s); - } void Clear() { insts_.clear(); } @@ -402,9 +378,6 @@ private: struct IROptions { uint32_t disableFlags; bool unalignedLoadStore; - bool unalignedLoadStoreVec4; - bool preferVec4; - bool preferVec4Dot; }; const IRMeta *GetIRMeta(IROp op); diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index 95ea05581..52ea20537 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -60,30 +60,20 @@ alignas(16) static const uint32_t lowBytesMask[4] = { 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF, }; -u32 IRRunBreakpoint(u32 pc) { +u32 RunBreakpoint(u32 pc) { // Should we skip this breakpoint? - uint32_t skipFirst = CBreakPoints::CheckSkipFirst(); - if (skipFirst == pc || skipFirst == currentMIPS->pc) + if (CBreakPoints::CheckSkipFirst() == pc) return 0; - // Did we already hit one? - if (coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME) - return 1; - - CBreakPoints::ExecBreakPoint(pc); + CBreakPoints::ExecBreakPoint(currentMIPS->pc); return coreState != CORE_RUNNING ? 1 : 0; } -u32 IRRunMemCheck(u32 pc, u32 addr) { +u32 RunMemCheck(u32 pc, u32 addr) { // Should we skip this breakpoint? - uint32_t skipFirst = CBreakPoints::CheckSkipFirst(); - if (skipFirst == pc || skipFirst == currentMIPS->pc) + if (CBreakPoints::CheckSkipFirst() == pc) return 0; - // Did we already hit one? - if (coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME) - return 1; - CBreakPoints::ExecOpMemCheck(addr, pc); return coreState != CORE_RUNNING ? 1 : 0; } @@ -228,11 +218,6 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { mips->r[inst->dest] = (mips->r[inst->dest] & destMask) | (mem >> shift); break; } - case IROp::Load32Linked: - if (inst->dest != MIPS_REG_ZERO) - mips->r[inst->dest] = Memory::ReadUnchecked_U32(mips->r[inst->src1] + inst->constant); - mips->llBit = 1; - break; case IROp::LoadFloat: mips->f[inst->dest] = Memory::ReadUnchecked_Float(mips->r[inst->src1] + inst->constant); break; @@ -266,16 +251,6 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { Memory::WriteUnchecked_U32(result, addr & 0xfffffffc); break; } - case IROp::Store32Conditional: - if (mips->llBit) { - Memory::WriteUnchecked_U32(mips->r[inst->src3], mips->r[inst->src1] + inst->constant); - if (inst->dest != MIPS_REG_ZERO) { - mips->r[inst->dest] = 1; - } - } else if (inst->dest != MIPS_REG_ZERO) { - mips->r[inst->dest] = 0; - } - break; case IROp::StoreFloat: Memory::WriteUnchecked_Float(mips->f[inst->src3], mips->r[inst->src1] + inst->constant); break; @@ -317,25 +292,16 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { { // Can't use the SSE shuffle here because it takes an immediate. pshufb with a table would work though, // or a big switch - there are only 256 shuffles possible (4^4) - float temp[4]; for (int i = 0; i < 4; i++) - temp[i] = mips->f[inst->src1 + ((inst->src2 >> (i * 2)) & 3)]; - for (int i = 0; i < 4; i++) - mips->f[inst->dest + i] = temp[i]; + mips->f[inst->dest + i] = mips->f[inst->src1 + ((inst->src2 >> (i * 2)) & 3)]; break; } - case IROp::Vec4Blend: - // Could use _mm_blendv_ps (SSE4+BMI), vbslq_f32 (ARM), __riscv_vmerge_vvm (RISC-V) - for (int i = 0; i < 4; i++) - mips->f[inst->dest + i] = ((inst->constant >> i) & 1) ? mips->f[inst->src2 + i] : mips->f[inst->src1 + i]; - break; - case IROp::Vec4Mov: { #if defined(_M_SSE) _mm_store_ps(&mips->f[inst->dest], _mm_load_ps(&mips->f[inst->src1])); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) vst1q_f32(&mips->f[inst->dest], vld1q_f32(&mips->f[inst->src1])); #else memcpy(&mips->f[inst->dest], &mips->f[inst->src1], 4 * sizeof(float)); @@ -347,7 +313,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { { #if defined(_M_SSE) _mm_store_ps(&mips->f[inst->dest], _mm_add_ps(_mm_load_ps(&mips->f[inst->src1]), _mm_load_ps(&mips->f[inst->src2]))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) vst1q_f32(&mips->f[inst->dest], vaddq_f32(vld1q_f32(&mips->f[inst->src1]), vld1q_f32(&mips->f[inst->src2]))); #else for (int i = 0; i < 4; i++) @@ -360,7 +326,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { { #if defined(_M_SSE) _mm_store_ps(&mips->f[inst->dest], _mm_sub_ps(_mm_load_ps(&mips->f[inst->src1]), _mm_load_ps(&mips->f[inst->src2]))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) vst1q_f32(&mips->f[inst->dest], vsubq_f32(vld1q_f32(&mips->f[inst->src1]), vld1q_f32(&mips->f[inst->src2]))); #else for (int i = 0; i < 4; i++) @@ -373,7 +339,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { { #if defined(_M_SSE) _mm_store_ps(&mips->f[inst->dest], _mm_mul_ps(_mm_load_ps(&mips->f[inst->src1]), _mm_load_ps(&mips->f[inst->src2]))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) vst1q_f32(&mips->f[inst->dest], vmulq_f32(vld1q_f32(&mips->f[inst->src1]), vld1q_f32(&mips->f[inst->src2]))); #else for (int i = 0; i < 4; i++) @@ -408,7 +374,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { { #if defined(_M_SSE) _mm_store_ps(&mips->f[inst->dest], _mm_xor_ps(_mm_load_ps(&mips->f[inst->src1]), _mm_load_ps((const float *)signBits))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) vst1q_f32(&mips->f[inst->dest], vnegq_f32(vld1q_f32(&mips->f[inst->src1]))); #else for (int i = 0; i < 4; i++) @@ -421,7 +387,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { { #if defined(_M_SSE) _mm_store_ps(&mips->f[inst->dest], _mm_and_ps(_mm_load_ps(&mips->f[inst->src1]), _mm_load_ps((const float *)noSignMask))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) vst1q_f32(&mips->f[inst->dest], vabsq_f32(vld1q_f32(&mips->f[inst->src1]))); #else for (int i = 0; i < 4; i++) @@ -802,28 +768,10 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { mips->f[inst->dest] = mips->f[inst->src1] / mips->f[inst->src2]; break; case IROp::FMin: - if (my_isnan(mips->f[inst->src1]) || my_isnan(mips->f[inst->src2])) { - // See interpreter for this logic: this is for vmin, we're comparing mantissa+exp. - if (mips->fs[inst->src1] < 0 && mips->fs[inst->src2] < 0) { - mips->fs[inst->dest] = std::max(mips->fs[inst->src1], mips->fs[inst->src2]); - } else { - mips->fs[inst->dest] = std::min(mips->fs[inst->src1], mips->fs[inst->src2]); - } - } else { - mips->f[inst->dest] = std::min(mips->f[inst->src1], mips->f[inst->src2]); - } + mips->f[inst->dest] = std::min(mips->f[inst->src1], mips->f[inst->src2]); break; case IROp::FMax: - if (my_isnan(mips->f[inst->src1]) || my_isnan(mips->f[inst->src2])) { - // See interpreter for this logic: this is for vmax, we're comparing mantissa+exp. - if (mips->fs[inst->src1] < 0 && mips->fs[inst->src2] < 0) { - mips->fs[inst->dest] = std::min(mips->fs[inst->src1], mips->fs[inst->src2]); - } else { - mips->fs[inst->dest] = std::max(mips->fs[inst->src1], mips->fs[inst->src2]); - } - } else { - mips->f[inst->dest] = std::max(mips->f[inst->src1], mips->f[inst->src2]); - } + mips->f[inst->dest] = std::max(mips->f[inst->src1], mips->f[inst->src2]); break; case IROp::FMov: @@ -860,23 +808,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { break; } - case IROp::FpCondFromReg: - mips->fpcond = mips->r[inst->dest]; - break; case IROp::FpCondToReg: mips->r[inst->dest] = mips->fpcond; break; - case IROp::FpCtrlFromReg: - mips->fcr31 = mips->r[inst->src1] & 0x0181FFFF; - // Extract the new fpcond value. - // TODO: Is it really helping us to keep it separate? - mips->fpcond = (mips->fcr31 >> 23) & 1; - break; - case IROp::FpCtrlToReg: - // Update the fpcond bit first. - mips->fcr31 = (mips->fcr31 & ~(1 << 23)) | ((mips->fpcond & 1) << 23); - mips->r[inst->dest] = mips->fcr31; - break; case IROp::VfpuCtrlToReg: mips->r[inst->dest] = mips->vfpuCtrl[inst->src1]; break; @@ -887,7 +821,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { mips->fi[inst->dest] = my_isinf(value) && value < 0.0f ? -2147483648LL : 2147483647LL; break; } else { - mips->fs[inst->dest] = (int)round_ieee_754(value); + mips->fs[inst->dest] = (int)floorf(value + 0.5f); } break; } @@ -976,43 +910,18 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { mips->fs[inst->dest] = my_isinf(src) && src < 0.0f ? -2147483648LL : 2147483647LL; break; } - switch (IRRoundMode(mips->fcr31 & 3)) { - case IRRoundMode::RINT_0: mips->fs[inst->dest] = (int)round_ieee_754(src); break; - case IRRoundMode::CAST_1: mips->fs[inst->dest] = (int)src; break; - case IRRoundMode::CEIL_2: mips->fs[inst->dest] = (int)ceilf(src); break; - case IRRoundMode::FLOOR_3: mips->fs[inst->dest] = (int)floorf(src); break; + switch (mips->fcr31 & 3) { + case 0: mips->fs[inst->dest] = (int)round_ieee_754(src); break; // RINT_0 + case 1: mips->fs[inst->dest] = (int)src; break; // CAST_1 + case 2: mips->fs[inst->dest] = (int)ceilf(src); break; // CEIL_2 + case 3: mips->fs[inst->dest] = (int)floorf(src); break; // FLOOR_3 } break; //cvt.w.s } - case IROp::FCvtScaledSW: - mips->f[inst->dest] = (float)mips->fs[inst->src1] * (1.0f / (1UL << (inst->src2 & 0x1F))); - break; - case IROp::FCvtScaledWS: - { - float src = mips->f[inst->src1]; - if (my_isnan(src)) { - // TODO: True for negatives too? - mips->fs[inst->dest] = 2147483647L; - break; - } - float mult = (float)(1UL << (inst->src2 & 0x1F)); - double sv = src * mult; // (float)0x7fffffff == (float)0x80000000 - // Cap/floor it to 0x7fffffff / 0x80000000 - if (sv > (double)0x7fffffff) { - mips->fs[inst->dest] = 0x7fffffff; - } else if (sv <= (double)(int)0x80000000) { - mips->fs[inst->dest] = 0x80000000; - } else { - switch (IRRoundMode(inst->src2 >> 6)) { - case IRRoundMode::RINT_0: mips->fs[inst->dest] = (int)round_ieee_754(sv); break; - case IRRoundMode::CAST_1: mips->fs[inst->dest] = src >= 0 ? (int)floor(sv) : (int)ceil(sv); break; - case IRRoundMode::CEIL_2: mips->fs[inst->dest] = (int)ceil(sv); break; - case IRRoundMode::FLOOR_3: mips->fs[inst->dest] = (int)floor(sv); break; - } - } + case IROp::ZeroFpCond: + mips->fpcond = 0; break; - } case IROp::FMovFromGPR: memcpy(&mips->f[inst->dest], &mips->r[inst->src1], 4); @@ -1053,7 +962,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { break; case IROp::Downcount: - mips->downcount -= (int)inst->constant; + mips->downcount -= inst->constant; break; case IROp::SetPC: @@ -1110,14 +1019,14 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { break; case IROp::Breakpoint: - if (IRRunBreakpoint(inst->constant)) { + if (RunBreakpoint(mips->pc)) { CoreTiming::ForceCheck(); return mips->pc; } break; case IROp::MemoryCheck: - if (IRRunMemCheck(mips->pc + inst->dest, mips->r[inst->src1] + inst->constant)) { + if (RunMemCheck(mips->pc, mips->r[inst->src1] + inst->constant)) { CoreTiming::ForceCheck(); return mips->pc; } @@ -1144,6 +1053,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { inst++; } - // We hit count. If this is a full block, it was badly constructed. + // If we got here, the block was badly constructed. + Crash(); return 0; } diff --git a/Core/MIPS/IR/IRInterpreter.h b/Core/MIPS/IR/IRInterpreter.h index 21e7f15dc..ec2c6f270 100644 --- a/Core/MIPS/IR/IRInterpreter.h +++ b/Core/MIPS/IR/IRInterpreter.h @@ -20,7 +20,4 @@ inline static u32 ReverseBits32(u32 v) { return v; } -u32 IRRunBreakpoint(u32 pc); -u32 IRRunMemCheck(u32 pc, u32 addr); - u32 IRInterpret(MIPSState *ms, const IRInst *inst, int count); diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index e64dcf3ec..66608fc86 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -15,7 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "ppsspp_config.h" #include #include "ext/xxhash.h" @@ -35,9 +34,9 @@ #include "Core/MIPS/MIPSInt.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/IR/IRRegCache.h" -#include "Core/MIPS/IR/IRInterpreter.h" #include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRNativeCommon.h" +#include "Core/MIPS/IR/IRPassSimplify.h" +#include "Core/MIPS/IR/IRInterpreter.h" #include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/Reporting.h" @@ -50,21 +49,7 @@ IRJit::IRJit(MIPSState *mipsState) : frontend_(mipsState->HasDefaultPrefix()), m IROptions opts{}; opts.disableFlags = g_Config.uJitDisableFlags; -#if PPSSPP_ARCH(RISCV64) - // Assume RISC-V always has very slow unaligned memory accesses. - opts.unalignedLoadStore = false; - opts.unalignedLoadStoreVec4 = true; - opts.preferVec4 = cpu_info.RiscV_V; -#elif PPSSPP_ARCH(ARM) opts.unalignedLoadStore = (opts.disableFlags & (uint32_t)JitDisable::LSU_UNALIGNED) == 0; - opts.unalignedLoadStoreVec4 = true; - opts.preferVec4 = cpu_info.bASIMD || cpu_info.bNEON; -#else - opts.unalignedLoadStore = (opts.disableFlags & (uint32_t)JitDisable::LSU_UNALIGNED) == 0; - // TODO: Could allow on x86 pretty easily... - opts.unalignedLoadStoreVec4 = false; - opts.preferVec4 = true; -#endif frontend_.SetOptions(opts); } @@ -84,12 +69,7 @@ void IRJit::ClearCache() { } void IRJit::InvalidateCacheAt(u32 em_address, int length) { - std::vector numbers = blocks_.FindInvalidatedBlockNumbers(em_address, length); - for (int block_num : numbers) { - auto block = blocks_.GetBlock(block_num); - int cookie = block->GetTargetOffset() < 0 ? block_num : block->GetTargetOffset(); - block->Destroy(cookie); - } + blocks_.InvalidateICache(em_address, length); } void IRJit::Compile(u32 em_address) { @@ -101,11 +81,9 @@ void IRJit::Compile(u32 em_address) { if (block_num != -1) { IRBlock *b = blocks_.GetBlock(block_num); // Okay, let's link and finalize the block now. - int cookie = b->GetTargetOffset() < 0 ? block_num : b->GetTargetOffset(); - b->Finalize(cookie); + b->Finalize(block_num); if (b->IsValid()) { // Success, we're done. - FinalizeTargetBlock(b, block_num); return; } } @@ -146,15 +124,13 @@ bool IRJit::CompileBlock(u32 em_address, std::vector &instructions, u32 b->SetOriginalSize(mipsBytes); if (preload) { // Hash, then only update page stats, don't link yet. - // TODO: Should we always hash? Then we can reuse blocks. b->UpdateHash(); + blocks_.FinalizeBlock(block_num, true); + } else { + // Overwrites the first instruction, and also updates stats. + // TODO: Should we always hash? Then we can reuse blocks. + blocks_.FinalizeBlock(block_num); } - if (!CompileTargetBlock(b, block_num, preload)) - return false; - // Overwrites the first instruction, and also updates stats. - blocks_.FinalizeBlock(block_num, preload); - if (!preload) - FinalizeTargetBlock(b, block_num); return true; } @@ -168,7 +144,6 @@ void IRJit::CompileFunction(u32 start_address, u32 length) { // We may go up and down from branches, so track all block starts done here. std::set doneAddresses; std::vector pendingAddresses; - pendingAddresses.reserve(16); pendingAddresses.push_back(start_address); while (!pendingAddresses.empty()) { u32 em_address = pendingAddresses.back(); @@ -254,7 +229,6 @@ void IRJit::RunLoopUntil(u64 globalticks) { IRBlock *block = blocks_.GetBlock(data); u32 startPC = mips_->pc; mips_->pc = IRInterpret(mips_, block->GetInstructions(), block->GetNumInstructions()); - // Note: this will "jump to zero" on a badly constructed block missing exits. if (!Memory::IsValidAddress(mips_->pc) || (mips_->pc & 3) != 0) { Core_ExecException(mips_->pc, startPC, ExecExceptionType::JUMP); break; @@ -283,20 +257,23 @@ void IRJit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { Crash(); } +bool IRJit::ReplaceJalTo(u32 dest) { + Crash(); + return false; +} + void IRBlockCache::Clear() { for (int i = 0; i < (int)blocks_.size(); ++i) { - int cookie = blocks_[i].GetTargetOffset() < 0 ? i : blocks_[i].GetTargetOffset(); - blocks_[i].Destroy(cookie); + blocks_[i].Destroy(i); } blocks_.clear(); byPage_.clear(); } -std::vector IRBlockCache::FindInvalidatedBlockNumbers(u32 address, u32 length) { +void IRBlockCache::InvalidateICache(u32 address, u32 length) { u32 startPage = AddressToPage(address); u32 endPage = AddressToPage(address + length); - std::vector found; for (u32 page = startPage; page <= endPage; ++page) { const auto iter = byPage_.find(page); if (iter == byPage_.end()) @@ -306,18 +283,15 @@ std::vector IRBlockCache::FindInvalidatedBlockNumbers(u32 address, u32 leng for (int i : blocksInPage) { if (blocks_[i].OverlapsRange(address, length)) { // Not removing from the page, hopefully doesn't build up with small recompiles. - found.push_back(i); + blocks_[i].Destroy(i); } } } - - return found; } void IRBlockCache::FinalizeBlock(int i, bool preload) { if (!preload) { - int cookie = blocks_[i].GetTargetOffset() < 0 ? i : blocks_[i].GetTargetOffset(); - blocks_[i].Finalize(cookie); + blocks_[i].Finalize(i); } u32 startAddr, size; @@ -344,7 +318,10 @@ int IRBlockCache::FindPreloadBlock(u32 em_address) { const std::vector &blocksInPage = iter->second; for (int i : blocksInPage) { - if (blocks_[i].GetOriginalStart() == em_address) { + u32 start, mipsBytes; + blocks_[i].GetRange(start, mipsBytes); + + if (start == em_address) { if (blocks_[i].HashMatches()) { return i; } @@ -354,30 +331,13 @@ int IRBlockCache::FindPreloadBlock(u32 em_address) { return -1; } -int IRBlockCache::FindByCookie(int cookie) { - if (blocks_.empty()) - return -1; - // TODO: Maybe a flag to determine target offset mode? - if (blocks_[0].GetTargetOffset() < 0) - return cookie; - - for (int i = 0; i < GetNumBlocks(); ++i) { - int offset = blocks_[i].GetTargetOffset(); - if (offset == cookie) - return i; - } - - return -1; -} - std::vector IRBlockCache::SaveAndClearEmuHackOps() { std::vector result; result.resize(blocks_.size()); for (int number = 0; number < (int)blocks_.size(); ++number) { IRBlock &b = blocks_[number]; - int cookie = b.GetTargetOffset() < 0 ? number : b.GetTargetOffset(); - if (b.IsValid() && b.RestoreOriginalFirstOp(cookie)) { + if (b.IsValid() && b.RestoreOriginalFirstOp(number)) { result[number] = number; } else { result[number] = 0; @@ -397,8 +357,7 @@ void IRBlockCache::RestoreSavedEmuHackOps(std::vector saved) { IRBlock &b = blocks_[number]; // Only if we restored it, write it back. if (b.IsValid() && saved[number] != 0 && b.HasOriginalFirstOp()) { - int cookie = b.GetTargetOffset() < 0 ? number : b.GetTargetOffset(); - b.Finalize(cookie); + b.Finalize(number); } } } @@ -412,7 +371,7 @@ JitBlockDebugInfo IRBlockCache::GetBlockDebugInfo(int blockNum) const { for (u32 addr = start; addr < start + size; addr += 4) { char temp[256]; - MIPSDisAsm(Memory::Read_Instruction(addr), addr, temp, sizeof(temp), true); + MIPSDisAsm(Memory::Read_Instruction(addr), addr, temp, true); std::string mipsDis = temp; debugInfo.origDisasm.push_back(mipsDis); } @@ -466,7 +425,9 @@ int IRBlockCache::GetBlockNumberFromStartAddress(u32 em_address, bool realBlocks const std::vector &blocksInPage = iter->second; int best = -1; for (int i : blocksInPage) { - if (blocks_[i].GetOriginalStart() == em_address) { + uint32_t start, size; + blocks_[i].GetRange(start, size); + if (start == em_address) { best = i; if (blocks_[i].IsValid()) { return i; @@ -480,8 +441,8 @@ bool IRBlock::HasOriginalFirstOp() const { return Memory::ReadUnchecked_U32(origAddr_) == origFirstOpcode_.encoding; } -bool IRBlock::RestoreOriginalFirstOp(int cookie) { - const u32 emuhack = MIPS_EMUHACK_OPCODE | cookie; +bool IRBlock::RestoreOriginalFirstOp(int number) { + const u32 emuhack = MIPS_EMUHACK_OPCODE | number; if (Memory::ReadUnchecked_U32(origAddr_) == emuhack) { Memory::Write_Opcode_JIT(origAddr_, origFirstOpcode_); return true; @@ -489,19 +450,19 @@ bool IRBlock::RestoreOriginalFirstOp(int cookie) { return false; } -void IRBlock::Finalize(int cookie) { +void IRBlock::Finalize(int number) { // Check it wasn't invalidated, in case this is after preload. // TODO: Allow reusing blocks when the code matches hash_ again, instead. if (origAddr_) { origFirstOpcode_ = Memory::Read_Opcode_JIT(origAddr_); - MIPSOpcode opcode = MIPSOpcode(MIPS_EMUHACK_OPCODE | cookie); + MIPSOpcode opcode = MIPSOpcode(MIPS_EMUHACK_OPCODE | number); Memory::Write_Opcode_JIT(origAddr_, opcode); } } -void IRBlock::Destroy(int cookie) { +void IRBlock::Destroy(int number) { if (origAddr_) { - MIPSOpcode opcode = MIPSOpcode(MIPS_EMUHACK_OPCODE | cookie); + MIPSOpcode opcode = MIPSOpcode(MIPS_EMUHACK_OPCODE | number); if (Memory::ReadUnchecked_U32(origAddr_) == opcode.encoding) Memory::Write_Opcode_JIT(origAddr_, origFirstOpcode_); @@ -535,7 +496,7 @@ bool IRBlock::OverlapsRange(u32 addr, u32 size) const { } MIPSOpcode IRJit::GetOriginalOp(MIPSOpcode op) { - IRBlock *b = blocks_.GetBlock(blocks_.FindByCookie(op.encoding & 0xFFFFFF)); + IRBlock *b = blocks_.GetBlock(op.encoding & 0xFFFFFF); if (b) { return b->GetOriginalFirstOp(); } diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index cd751ba7d..973ddf524 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -38,16 +38,15 @@ namespace MIPSComp { // TODO : Use arena allocators. For now let's just malloc. class IRBlock { public: - IRBlock() {} - IRBlock(u32 emAddr) : origAddr_(emAddr) {} + IRBlock() : instr_(nullptr), numInstructions_(0), origAddr_(0), origSize_(0) {} + IRBlock(u32 emAddr) : instr_(nullptr), numInstructions_(0), origAddr_(emAddr), origSize_(0) {} IRBlock(IRBlock &&b) { instr_ = b.instr_; - hash_ = b.hash_; + numInstructions_ = b.numInstructions_; origAddr_ = b.origAddr_; origSize_ = b.origSize_; origFirstOpcode_ = b.origFirstOpcode_; - targetOffset_ = b.targetOffset_; - numInstructions_ = b.numInstructions_; + hash_ = b.hash_; b.instr_ = nullptr; } @@ -72,12 +71,6 @@ public: void SetOriginalSize(u32 size) { origSize_ = size; } - void SetTargetOffset(int offset) { - targetOffset_ = offset; - } - int GetTargetOffset() const { - return targetOffset_; - } void UpdateHash() { hash_ = CalculateHash(); } @@ -90,9 +83,6 @@ public: start = origAddr_; size = origSize_; } - u32 GetOriginalStart() const { - return origAddr_; - } void Finalize(int number); void Destroy(int number); @@ -100,20 +90,19 @@ public: private: u64 CalculateHash() const; - IRInst *instr_ = nullptr; + IRInst *instr_; + u16 numInstructions_; + u32 origAddr_; + u32 origSize_; u64 hash_ = 0; - u32 origAddr_ = 0; - u32 origSize_ = 0; MIPSOpcode origFirstOpcode_ = MIPSOpcode(0x68FFFFFF); - int targetOffset_ = -1; - u16 numInstructions_ = 0; }; class IRBlockCache : public JitBlockCacheDebugInterface { public: IRBlockCache() {} void Clear(); - std::vector FindInvalidatedBlockNumbers(u32 address, u32 length); + void InvalidateICache(u32 address, u32 length); void FinalizeBlock(int i, bool preload = false); int GetNumBlocks() const override { return (int)blocks_.size(); } int AllocateBlock(int emAddr) { @@ -127,16 +116,8 @@ public: return nullptr; } } - const IRBlock *GetBlock(int i) const { - if (i >= 0 && i < (int)blocks_.size()) { - return &blocks_[i]; - } else { - return nullptr; - } - } int FindPreloadBlock(u32 em_address); - int FindByCookie(int cookie); std::vector SaveAndClearEmuHackOps(); void RestoreSavedEmuHackOps(std::vector saved); @@ -189,10 +170,9 @@ public: void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override; void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override; -protected: +private: bool CompileBlock(u32 em_address, std::vector &instructions, u32 &mipsBytes, bool preload); - virtual bool CompileTargetBlock(IRBlock *block, int block_num, bool preload) { return true; } - virtual void FinalizeTargetBlock(IRBlock *block, int block_num) {} + bool ReplaceJalTo(u32 dest); JitOptions jo; @@ -207,3 +187,4 @@ protected: }; } // namespace MIPSComp + diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp deleted file mode 100644 index 784d0c7ae..000000000 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ /dev/null @@ -1,799 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include -#include -#include -#include "Common/Profiler/Profiler.h" -#include "Common/StringUtils.h" -#include "Common/TimeUtil.h" -#include "Core/Core.h" -#include "Core/Debugger/SymbolMap.h" -#include "Core/MemMap.h" -#include "Core/MIPS/MIPSTables.h" -#include "Core/MIPS/IR/IRNativeCommon.h" - -using namespace MIPSComp; - -namespace MIPSComp { - -// Compile time flag to enable debug stats for not compiled ops. -static constexpr bool enableDebugStats = false; -// Compile time flag for enabling the simple IR jit profiler. -static constexpr bool enableDebugProfiler = false; - -// Used only for debugging when enableDebug is true above. -static std::map debugSeenNotCompiledIR; -static std::map debugSeenNotCompiled; -static std::map, int> debugSeenPCUsage; -static double lastDebugStatsLog = 0.0; -static constexpr double debugStatsFrequency = 5.0; - -static std::thread debugProfilerThread; -std::atomic debugProfilerThreadStatus = false; - -template -class IRProfilerTopValues { -public: - void Add(const std::pair &v, int c) { - for (int i = 0; i < N; ++i) { - if (c > counts[i]) { - counts[i] = c; - values[i] = v; - return; - } - } - } - - int counts[N]{}; - std::pair values[N]{}; -}; - -const char *IRProfilerStatusToString(IRProfilerStatus s) { - switch (s) { - case IRProfilerStatus::NOT_RUNNING: return "NOT_RUNNING"; - case IRProfilerStatus::IN_JIT: return "IN_JIT"; - case IRProfilerStatus::TIMER_ADVANCE: return "TIMER_ADVANCE"; - case IRProfilerStatus::COMPILING: return "COMPILING"; - case IRProfilerStatus::MATH_HELPER: return "MATH_HELPER"; - case IRProfilerStatus::REPLACEMENT: return "REPLACEMENT"; - case IRProfilerStatus::SYSCALL: return "SYSCALL"; - case IRProfilerStatus::INTERPRET: return "INTERPRET"; - case IRProfilerStatus::IR_INTERPRET: return "IR_INTERPRET"; - } - return "INVALID"; -} - -static void LogDebugStats() { - if (!enableDebugStats && !enableDebugProfiler) - return; - - double now = time_now_d(); - if (now < lastDebugStatsLog + debugStatsFrequency) - return; - lastDebugStatsLog = now; - - int worstIROp = -1; - int worstIRVal = 0; - for (auto it : debugSeenNotCompiledIR) { - if (it.second > worstIRVal) { - worstIRVal = it.second; - worstIROp = it.first; - } - } - debugSeenNotCompiledIR.clear(); - - const char *worstName = nullptr; - int worstVal = 0; - for (auto it : debugSeenNotCompiled) { - if (it.second > worstVal) { - worstVal = it.second; - worstName = it.first; - } - } - debugSeenNotCompiled.clear(); - - IRProfilerTopValues<4> slowestPCs; - int64_t totalCount = 0; - for (auto it : debugSeenPCUsage) { - slowestPCs.Add(it.first, it.second); - totalCount += it.second; - } - debugSeenPCUsage.clear(); - - if (worstIROp != -1) - WARN_LOG(JIT, "Most not compiled IR op: %s (%d)", GetIRMeta((IROp)worstIROp)->name, worstIRVal); - if (worstName != nullptr) - WARN_LOG(JIT, "Most not compiled op: %s (%d)", worstName, worstVal); - if (slowestPCs.counts[0] != 0) { - for (int i = 0; i < 4; ++i) { - uint32_t pc = slowestPCs.values[i].first; - const char *status = IRProfilerStatusToString(slowestPCs.values[i].second); - const std::string label = g_symbolMap ? g_symbolMap->GetDescription(pc) : ""; - WARN_LOG(JIT, "Slowest sampled PC #%d: %08x (%s)/%s (%f%%)", i, pc, label.c_str(), status, 100.0 * (double)slowestPCs.counts[i] / (double)totalCount); - } - } -} - -bool IRNativeBackend::DebugStatsEnabled() const { - return enableDebugStats; -} - -bool IRNativeBackend::DebugProfilerEnabled() const { - return enableDebugProfiler; -} - -void IRNativeBackend::NotifyMIPSInterpret(const char *name) { - _assert_(enableDebugStats); - debugSeenNotCompiled[name]++; -} - -void IRNativeBackend::DoMIPSInst(uint32_t value) { - MIPSOpcode op; - memcpy(&op, &value, sizeof(op)); - - if constexpr (enableDebugStats) - debugSeenNotCompiled[MIPSGetName(op)]++; - - MIPSInterpret(op); -} - -uint32_t IRNativeBackend::DoIRInst(uint64_t value) { - IRInst inst; - memcpy(&inst, &value, sizeof(inst)); - - if constexpr (enableDebugStats) - debugSeenNotCompiledIR[(uint8_t)inst.op]++; - - return IRInterpret(currentMIPS, &inst, 1); -} - -int IRNativeBackend::ReportBadAddress(uint32_t addr, uint32_t alignment, uint32_t isWrite) { - const auto toss = [&](MemoryExceptionType t) { - Core_MemoryException(addr, alignment, currentMIPS->pc, t); - return coreState != CORE_RUNNING ? 1 : 0; - }; - - if (!Memory::IsValidRange(addr, alignment)) { - MemoryExceptionType t = isWrite == 1 ? MemoryExceptionType::WRITE_WORD : MemoryExceptionType::READ_WORD; - if (alignment > 4) - t = isWrite ? MemoryExceptionType::WRITE_BLOCK : MemoryExceptionType::READ_BLOCK; - return toss(t); - } else if (alignment > 1 && (addr & (alignment - 1)) != 0) { - return toss(MemoryExceptionType::ALIGNMENT); - } - return 0; -} - -IRNativeBackend::IRNativeBackend(IRBlockCache &blocks) : blocks_(blocks) {} - -IRNativeBackend::~IRNativeBackend() { - if (debugProfilerThreadStatus) { - debugProfilerThreadStatus = false; - debugProfilerThread.join(); - } -} - -void IRNativeBackend::CompileIRInst(IRInst inst) { - switch (inst.op) { - case IROp::Nop: - break; - - case IROp::SetConst: - case IROp::SetConstF: - case IROp::Downcount: - case IROp::SetPC: - case IROp::SetPCConst: - CompIR_Basic(inst); - break; - - case IROp::Add: - case IROp::Sub: - case IROp::AddConst: - case IROp::SubConst: - case IROp::Neg: - CompIR_Arith(inst); - break; - - case IROp::And: - case IROp::Or: - case IROp::Xor: - case IROp::AndConst: - case IROp::OrConst: - case IROp::XorConst: - case IROp::Not: - CompIR_Logic(inst); - break; - - case IROp::Mov: - case IROp::Ext8to32: - case IROp::Ext16to32: - CompIR_Assign(inst); - break; - - case IROp::ReverseBits: - case IROp::BSwap16: - case IROp::BSwap32: - case IROp::Clz: - CompIR_Bits(inst); - break; - - case IROp::Shl: - case IROp::Shr: - case IROp::Sar: - case IROp::Ror: - case IROp::ShlImm: - case IROp::ShrImm: - case IROp::SarImm: - case IROp::RorImm: - CompIR_Shift(inst); - break; - - case IROp::Slt: - case IROp::SltConst: - case IROp::SltU: - case IROp::SltUConst: - CompIR_Compare(inst); - break; - - case IROp::MovZ: - case IROp::MovNZ: - case IROp::Max: - case IROp::Min: - CompIR_CondAssign(inst); - break; - - case IROp::MtLo: - case IROp::MtHi: - case IROp::MfLo: - case IROp::MfHi: - CompIR_HiLo(inst); - break; - - case IROp::Mult: - case IROp::MultU: - case IROp::Madd: - case IROp::MaddU: - case IROp::Msub: - case IROp::MsubU: - CompIR_Mult(inst); - break; - - case IROp::Div: - case IROp::DivU: - CompIR_Div(inst); - break; - - case IROp::Load8: - case IROp::Load8Ext: - case IROp::Load16: - case IROp::Load16Ext: - case IROp::Load32: - case IROp::Load32Linked: - CompIR_Load(inst); - break; - - case IROp::Load32Left: - case IROp::Load32Right: - CompIR_LoadShift(inst); - break; - - case IROp::LoadFloat: - CompIR_FLoad(inst); - break; - - case IROp::LoadVec4: - CompIR_VecLoad(inst); - break; - - case IROp::Store8: - case IROp::Store16: - case IROp::Store32: - CompIR_Store(inst); - break; - - case IROp::Store32Conditional: - CompIR_CondStore(inst); - break; - - case IROp::Store32Left: - case IROp::Store32Right: - CompIR_StoreShift(inst); - break; - - case IROp::StoreFloat: - CompIR_FStore(inst); - break; - - case IROp::StoreVec4: - CompIR_VecStore(inst); - break; - - case IROp::FAdd: - case IROp::FSub: - case IROp::FMul: - case IROp::FDiv: - case IROp::FSqrt: - case IROp::FNeg: - CompIR_FArith(inst); - break; - - case IROp::FMin: - case IROp::FMax: - CompIR_FCondAssign(inst); - break; - - case IROp::FMov: - case IROp::FAbs: - case IROp::FSign: - CompIR_FAssign(inst); - break; - - case IROp::FRound: - case IROp::FTrunc: - case IROp::FCeil: - case IROp::FFloor: - CompIR_FRound(inst); - break; - - case IROp::FCvtWS: - case IROp::FCvtSW: - case IROp::FCvtScaledWS: - case IROp::FCvtScaledSW: - CompIR_FCvt(inst); - break; - - case IROp::FSat0_1: - case IROp::FSatMinus1_1: - CompIR_FSat(inst); - break; - - case IROp::FCmp: - case IROp::FCmovVfpuCC: - case IROp::FCmpVfpuBit: - case IROp::FCmpVfpuAggregate: - CompIR_FCompare(inst); - break; - - case IROp::RestoreRoundingMode: - case IROp::ApplyRoundingMode: - case IROp::UpdateRoundingMode: - CompIR_RoundingMode(inst); - break; - - case IROp::SetCtrlVFPU: - case IROp::SetCtrlVFPUReg: - case IROp::SetCtrlVFPUFReg: - case IROp::FpCondFromReg: - case IROp::FpCondToReg: - case IROp::FpCtrlFromReg: - case IROp::FpCtrlToReg: - case IROp::VfpuCtrlToReg: - case IROp::FMovFromGPR: - case IROp::FMovToGPR: - CompIR_Transfer(inst); - break; - - case IROp::Vec4Init: - case IROp::Vec4Shuffle: - case IROp::Vec4Blend: - case IROp::Vec4Mov: - CompIR_VecAssign(inst); - break; - - case IROp::Vec4Add: - case IROp::Vec4Sub: - case IROp::Vec4Mul: - case IROp::Vec4Div: - case IROp::Vec4Scale: - case IROp::Vec4Neg: - case IROp::Vec4Abs: - CompIR_VecArith(inst); - break; - - case IROp::Vec4Dot: - CompIR_VecHoriz(inst); - break; - - case IROp::Vec2Unpack16To31: - case IROp::Vec2Unpack16To32: - case IROp::Vec4Unpack8To32: - case IROp::Vec4DuplicateUpperBitsAndShift1: - case IROp::Vec4Pack31To8: - case IROp::Vec4Pack32To8: - case IROp::Vec2Pack31To16: - case IROp::Vec2Pack32To16: - CompIR_VecPack(inst); - break; - - case IROp::Vec4ClampToZero: - case IROp::Vec2ClampToZero: - CompIR_VecClamp(inst); - break; - - case IROp::FSin: - case IROp::FCos: - case IROp::FRSqrt: - case IROp::FRecip: - case IROp::FAsin: - CompIR_FSpecial(inst); - break; - - case IROp::Interpret: - CompIR_Interpret(inst); - break; - - case IROp::Syscall: - case IROp::CallReplacement: - case IROp::Break: - CompIR_System(inst); - break; - - case IROp::Breakpoint: - case IROp::MemoryCheck: - CompIR_Breakpoint(inst); - break; - - case IROp::ValidateAddress8: - case IROp::ValidateAddress16: - case IROp::ValidateAddress32: - case IROp::ValidateAddress128: - CompIR_ValidateAddress(inst); - break; - - case IROp::ExitToConst: - case IROp::ExitToReg: - case IROp::ExitToPC: - CompIR_Exit(inst); - break; - - case IROp::ExitToConstIfEq: - case IROp::ExitToConstIfNeq: - case IROp::ExitToConstIfGtZ: - case IROp::ExitToConstIfGeZ: - case IROp::ExitToConstIfLtZ: - case IROp::ExitToConstIfLeZ: - case IROp::ExitToConstIfFpTrue: - case IROp::ExitToConstIfFpFalse: - CompIR_ExitIf(inst); - break; - - default: - _assert_msg_(false, "Unexpected IR op %d", (int)inst.op); - CompIR_Generic(inst); - break; - } -} - -IRNativeJit::IRNativeJit(MIPSState *mipsState) - : IRJit(mipsState), debugInterface_(blocks_) {} - -void IRNativeJit::Init(IRNativeBackend &backend) { - backend_ = &backend; - debugInterface_.Init(backend_); - backend_->GenerateFixedCode(mips_); - - // Wanted this to be a reference, but vtbls get in the way. Shouldn't change. - hooks_ = backend.GetNativeHooks(); - - if (enableDebugProfiler && hooks_.profilerPC) { - debugProfilerThreadStatus = true; - debugProfilerThread = std::thread([&] { - // Spin, spin spin... maybe could at least hook into sleeps. - while (debugProfilerThreadStatus) { - IRProfilerStatus stat = *hooks_.profilerStatus; - uint32_t pc = *hooks_.profilerPC; - if (stat != IRProfilerStatus::NOT_RUNNING && stat != IRProfilerStatus::SYSCALL) { - debugSeenPCUsage[std::make_pair(pc, stat)]++; - } - } - }); - } -} - -bool IRNativeJit::CompileTargetBlock(IRBlock *block, int block_num, bool preload) { - return backend_->CompileBlock(block, block_num, preload); -} - -void IRNativeJit::FinalizeTargetBlock(IRBlock *block, int block_num) { - backend_->FinalizeBlock(block, block_num, jo); -} - -void IRNativeJit::RunLoopUntil(u64 globalticks) { - if constexpr (enableDebugStats || enableDebugProfiler) { - LogDebugStats(); - } - - PROFILE_THIS_SCOPE("jit"); - hooks_.enterDispatcher(); -} - -void IRNativeJit::ClearCache() { - IRJit::ClearCache(); - backend_->ClearAllBlocks(); -} - -void IRNativeJit::InvalidateCacheAt(u32 em_address, int length) { - std::vector numbers = blocks_.FindInvalidatedBlockNumbers(em_address, length); - for (int block_num : numbers) { - auto block = blocks_.GetBlock(block_num); - backend_->InvalidateBlock(block, block_num); - block->Destroy(block->GetTargetOffset()); - } -} - -bool IRNativeJit::DescribeCodePtr(const u8 *ptr, std::string &name) { - if (ptr != nullptr && backend_->DescribeCodePtr(ptr, name)) - return true; - - int offset = backend_->OffsetFromCodePtr(ptr); - if (offset == -1) - return false; - - int block_num = -1; - int block_offset = INT_MAX; - for (int i = 0; i < blocks_.GetNumBlocks(); ++i) { - const auto &b = blocks_.GetBlock(i); - int b_start = b->GetTargetOffset(); - if (b_start > offset) - continue; - - int b_end = backend_->GetNativeBlock(i)->checkedOffset; - int b_offset = offset - b_start; - if (b_end > b_start && b_end >= offset) { - // For sure within the block. - block_num = i; - block_offset = b_offset; - break; - } - - if (b_offset < block_offset) { - // Possibly within the block, unless in some other block... - block_num = i; - block_offset = b_offset; - } - } - - // Used by profiling tools that don't like spaces. - if (block_num == -1) { - name = "unknownOrDeletedBlock"; - return true; - } - - const IRBlock *block = blocks_.GetBlock(block_num); - if (block) { - u32 start = 0, size = 0; - block->GetRange(start, size); - - // It helps to know which func this block is inside. - const std::string label = g_symbolMap ? g_symbolMap->GetDescription(start) : ""; - if (!label.empty()) - name = StringFromFormat("block%d_%08x_%s_0x%x", block_num, start, label.c_str(), block_offset); - else - name = StringFromFormat("block%d_%08x_0x%x", block_num, start, block_offset); - return true; - } - return false; -} - -bool IRNativeJit::CodeInRange(const u8 *ptr) const { - return backend_->CodeInRange(ptr); -} - -bool IRNativeJit::IsAtDispatchFetch(const u8 *ptr) const { - return ptr == backend_->GetNativeHooks().dispatchFetch; -} - -const u8 *IRNativeJit::GetDispatcher() const { - return backend_->GetNativeHooks().dispatcher; -} - -const u8 *IRNativeJit::GetCrashHandler() const { - return backend_->GetNativeHooks().crashHandler; -} - -void IRNativeJit::UpdateFCR31() { - backend_->UpdateFCR31(mips_); -} - -JitBlockCacheDebugInterface *IRNativeJit::GetBlockCacheDebugInterface() { - return &debugInterface_; -} - -bool IRNativeBackend::CodeInRange(const u8 *ptr) const { - return CodeBlock().IsInSpace(ptr); -} - -bool IRNativeBackend::DescribeCodePtr(const u8 *ptr, std::string &name) const { - if (!CodeBlock().IsInSpace(ptr)) - return false; - - // Used in disassembly viewer. - if (ptr == (const uint8_t *)hooks_.enterDispatcher) { - name = "enterDispatcher"; - } else if (ptr == hooks_.dispatcher) { - name = "dispatcher"; - } else if (ptr == hooks_.dispatchFetch) { - name = "dispatchFetch"; - } else if (ptr == hooks_.crashHandler) { - name = "crashHandler"; - } else { - return false; - } - return true; -} - -int IRNativeBackend::OffsetFromCodePtr(const u8 *ptr) { - auto &codeBlock = CodeBlock(); - if (!codeBlock.IsInSpace(ptr)) - return -1; - return (int)codeBlock.GetOffset(ptr); -} - -void IRNativeBackend::FinalizeBlock(IRBlock *block, int block_num, const JitOptions &jo) { - if (jo.enableBlocklink) { - uint32_t pc = block->GetOriginalStart(); - - // First, link other blocks to this one now that it's finalized. - auto incoming = linksTo_.equal_range(pc); - for (auto it = incoming.first; it != incoming.second; ++it) { - auto &exits = nativeBlocks_[it->second].exits; - for (auto &blockExit : exits) { - if (blockExit.dest == pc) - OverwriteExit(blockExit.offset, blockExit.len, block_num); - } - } - - // And also any blocks from this one, in case we're finalizing it later. - auto &outgoing = nativeBlocks_[block_num].exits; - for (auto &blockExit : outgoing) { - int dstBlockNum = blocks_.GetBlockNumberFromStartAddress(blockExit.dest); - const IRNativeBlock *nativeBlock = GetNativeBlock(dstBlockNum); - if (nativeBlock) - OverwriteExit(blockExit.offset, blockExit.len, dstBlockNum); - } - } -} - -const IRNativeBlock *IRNativeBackend::GetNativeBlock(int block_num) const { - if (block_num < 0 || block_num >= (int)nativeBlocks_.size()) - return nullptr; - return &nativeBlocks_[block_num]; -} - -void IRNativeBackend::SetBlockCheckedOffset(int block_num, int offset) { - if (block_num >= (int)nativeBlocks_.size()) - nativeBlocks_.resize(block_num + 1); - - nativeBlocks_[block_num].checkedOffset = offset; -} - -void IRNativeBackend::AddLinkableExit(int block_num, uint32_t pc, int exitStartOffset, int exitLen) { - linksTo_.insert(std::make_pair(pc, block_num)); - - if (block_num >= (int)nativeBlocks_.size()) - nativeBlocks_.resize(block_num + 1); - IRNativeBlockExit blockExit; - blockExit.offset = exitStartOffset; - blockExit.len = exitLen; - blockExit.dest = pc; - nativeBlocks_[block_num].exits.push_back(blockExit); -} - -void IRNativeBackend::EraseAllLinks(int block_num) { - if (block_num == -1) { - linksTo_.clear(); - nativeBlocks_.clear(); - } else { - linksTo_.erase(block_num); - if (block_num < (int)nativeBlocks_.size()) - nativeBlocks_[block_num].exits.clear(); - } -} - -IRNativeBlockCacheDebugInterface::IRNativeBlockCacheDebugInterface(const IRBlockCache &irBlocks) - : irBlocks_(irBlocks) {} - -void IRNativeBlockCacheDebugInterface::Init(const IRNativeBackend *backend) { - codeBlock_ = &backend->CodeBlock(); - backend_ = backend; -} - -int IRNativeBlockCacheDebugInterface::GetNumBlocks() const { - return irBlocks_.GetNumBlocks(); -} - -int IRNativeBlockCacheDebugInterface::GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly) const { - return irBlocks_.GetBlockNumberFromStartAddress(em_address, realBlocksOnly); -} - -void IRNativeBlockCacheDebugInterface::GetBlockCodeRange(int blockNum, int *startOffset, int *size) const { - int blockOffset = irBlocks_.GetBlock(blockNum)->GetTargetOffset(); - int endOffset = backend_->GetNativeBlock(blockNum)->checkedOffset; - - // If endOffset is before, the checked entry is before the block start. - if (endOffset < blockOffset) { - // We assume linear allocation. Maybe a bit dangerous, should always be right. - if (blockNum + 1 >= GetNumBlocks()) { - // Last block, get from current code pointer. - endOffset = (int)codeBlock_->GetOffset(codeBlock_->GetCodePtr()); - } else { - endOffset = irBlocks_.GetBlock(blockNum + 1)->GetTargetOffset(); - _assert_msg_(endOffset >= blockOffset, "Next block not sequential, block=%d/%08x, next=%d/%08x", blockNum, blockOffset, blockNum + 1, endOffset); - } - } - - *startOffset = blockOffset; - *size = endOffset - blockOffset; -} - -JitBlockDebugInfo IRNativeBlockCacheDebugInterface::GetBlockDebugInfo(int blockNum) const { - JitBlockDebugInfo debugInfo = irBlocks_.GetBlockDebugInfo(blockNum); - - int blockOffset, codeSize; - GetBlockCodeRange(blockNum, &blockOffset, &codeSize); - - const u8 *blockStart = codeBlock_->GetBasePtr() + blockOffset; -#if PPSSPP_ARCH(ARM) - debugInfo.targetDisasm = DisassembleArm2(blockStart, codeSize); -#elif PPSSPP_ARCH(ARM64) - debugInfo.targetDisasm = DisassembleArm64(blockStart, codeSize); -#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - debugInfo.targetDisasm = DisassembleX86(blockStart, codeSize); -#elif PPSSPP_ARCH(RISCV64) - debugInfo.targetDisasm = DisassembleRV64(blockStart, codeSize); -#endif - return debugInfo; -} - -void IRNativeBlockCacheDebugInterface::ComputeStats(BlockCacheStats &bcStats) const { - double totalBloat = 0.0; - double maxBloat = 0.0; - double minBloat = 1000000000.0; - int numBlocks = GetNumBlocks(); - for (int i = 0; i < numBlocks; ++i) { - const IRBlock &b = *irBlocks_.GetBlock(i); - - // Native size, not IR size. - int blockOffset, codeSize; - GetBlockCodeRange(i, &blockOffset, &codeSize); - if (codeSize == 0) - continue; - - // MIPS (PSP) size. - u32 origAddr, origSize; - b.GetRange(origAddr, origSize); - - double bloat = (double)codeSize / (double)origSize; - if (bloat < minBloat) { - minBloat = bloat; - bcStats.minBloatBlock = origAddr; - } - if (bloat > maxBloat) { - maxBloat = bloat; - bcStats.maxBloatBlock = origAddr; - } - totalBloat += bloat; - bcStats.bloatMap[(float)bloat] = origAddr; - } - bcStats.numBlocks = numBlocks; - bcStats.minBloat = (float)minBloat; - bcStats.maxBloat = (float)maxBloat; - bcStats.avgBloat = (float)(totalBloat / (double)numBlocks); -} - -} // namespace MIPSComp diff --git a/Core/MIPS/IR/IRNativeCommon.h b/Core/MIPS/IR/IRNativeCommon.h deleted file mode 100644 index 4afc50369..000000000 --- a/Core/MIPS/IR/IRNativeCommon.h +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/JitCommon/JitBlockCache.h" - -namespace MIPSComp { - -typedef void (*IRNativeFuncNoArg)(); - -enum class IRProfilerStatus : int32_t { - NOT_RUNNING, - IN_JIT, - TIMER_ADVANCE, - COMPILING, - MATH_HELPER, - REPLACEMENT, - SYSCALL, - INTERPRET, - IR_INTERPRET, -}; - -struct IRNativeHooks { - IRNativeFuncNoArg enterDispatcher = nullptr; - - const uint8_t *dispatcher = nullptr; - const uint8_t *dispatchFetch = nullptr; - const uint8_t *crashHandler = nullptr; - - uint32_t *profilerPC = nullptr; - IRProfilerStatus *profilerStatus = nullptr; -}; - -struct IRNativeBlockExit { - int offset; - int len; - uint32_t dest; -}; - -struct IRNativeBlock { - int checkedOffset = 0; - std::vector exits; -}; - -class IRNativeBackend { -public: - IRNativeBackend(IRBlockCache &blocks); - virtual ~IRNativeBackend(); - - void CompileIRInst(IRInst inst); - - virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) const; - bool CodeInRange(const u8 *ptr) const; - int OffsetFromCodePtr(const u8 *ptr); - - virtual void GenerateFixedCode(MIPSState *mipsState) = 0; - virtual bool CompileBlock(IRBlock *block, int block_num, bool preload) = 0; - virtual void ClearAllBlocks() = 0; - virtual void InvalidateBlock(IRBlock *block, int block_num) = 0; - void FinalizeBlock(IRBlock *block, int block_num, const JitOptions &jo); - - virtual void UpdateFCR31(MIPSState *mipsState) {} - - const IRNativeHooks &GetNativeHooks() const { - return hooks_; - } - - const IRNativeBlock *GetNativeBlock(int block_num) const; - void SetBlockCheckedOffset(int block_num, int offset); - - virtual const CodeBlockCommon &CodeBlock() const = 0; - -protected: - virtual void CompIR_Arith(IRInst inst) = 0; - virtual void CompIR_Assign(IRInst inst) = 0; - virtual void CompIR_Basic(IRInst inst) = 0; - virtual void CompIR_Bits(IRInst inst) = 0; - virtual void CompIR_Breakpoint(IRInst inst) = 0; - virtual void CompIR_Compare(IRInst inst) = 0; - virtual void CompIR_CondAssign(IRInst inst) = 0; - virtual void CompIR_CondStore(IRInst inst) = 0; - virtual void CompIR_Div(IRInst inst) = 0; - virtual void CompIR_Exit(IRInst inst) = 0; - virtual void CompIR_ExitIf(IRInst inst) = 0; - virtual void CompIR_FArith(IRInst inst) = 0; - virtual void CompIR_FAssign(IRInst inst) = 0; - virtual void CompIR_FCompare(IRInst inst) = 0; - virtual void CompIR_FCondAssign(IRInst inst) = 0; - virtual void CompIR_FCvt(IRInst inst) = 0; - virtual void CompIR_FLoad(IRInst inst) = 0; - virtual void CompIR_FRound(IRInst inst) = 0; - virtual void CompIR_FSat(IRInst inst) = 0; - virtual void CompIR_FSpecial(IRInst inst) = 0; - virtual void CompIR_FStore(IRInst inst) = 0; - virtual void CompIR_Generic(IRInst inst) = 0; - virtual void CompIR_HiLo(IRInst inst) = 0; - virtual void CompIR_Interpret(IRInst inst) = 0; - virtual void CompIR_Load(IRInst inst) = 0; - virtual void CompIR_LoadShift(IRInst inst) = 0; - virtual void CompIR_Logic(IRInst inst) = 0; - virtual void CompIR_Mult(IRInst inst) = 0; - virtual void CompIR_RoundingMode(IRInst inst) = 0; - virtual void CompIR_Shift(IRInst inst) = 0; - virtual void CompIR_Store(IRInst inst) = 0; - virtual void CompIR_StoreShift(IRInst inst) = 0; - virtual void CompIR_System(IRInst inst) = 0; - virtual void CompIR_Transfer(IRInst inst) = 0; - virtual void CompIR_VecArith(IRInst inst) = 0; - virtual void CompIR_VecAssign(IRInst inst) = 0; - virtual void CompIR_VecClamp(IRInst inst) = 0; - virtual void CompIR_VecHoriz(IRInst inst) = 0; - virtual void CompIR_VecLoad(IRInst inst) = 0; - virtual void CompIR_VecPack(IRInst inst) = 0; - virtual void CompIR_VecStore(IRInst inst) = 0; - virtual void CompIR_ValidateAddress(IRInst inst) = 0; - - virtual void OverwriteExit(int srcOffset, int len, int block_num) = 0; - - // Returns true when debugging statistics should be compiled in. - bool DebugStatsEnabled() const; - bool DebugProfilerEnabled() const; - - // Callback (compile when DebugStatsEnabled()) to log a base interpreter hit. - // Call the func returned by MIPSGetInterpretFunc(op) directly for interpret. - static void NotifyMIPSInterpret(const char *name); - - // Callback to log AND perform a base interpreter op. Alternative to NotifyMIPSInterpret(). - static void DoMIPSInst(uint32_t op); - - // Callback to log AND perform an IR interpreter inst. Returns 0 or a PC to jump to. - static uint32_t DoIRInst(uint64_t inst); - - static int ReportBadAddress(uint32_t addr, uint32_t alignment, uint32_t isWrite); - - void AddLinkableExit(int block_num, uint32_t pc, int exitStartOffset, int exitLen); - void EraseAllLinks(int block_num); - - IRNativeHooks hooks_; - IRBlockCache &blocks_; - std::vector nativeBlocks_; - std::unordered_multimap linksTo_; -}; - -class IRNativeBlockCacheDebugInterface : public JitBlockCacheDebugInterface { -public: - IRNativeBlockCacheDebugInterface(const MIPSComp::IRBlockCache &irBlocks); - void Init(const IRNativeBackend *backend); - int GetNumBlocks() const; - int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const; - JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const; - void ComputeStats(BlockCacheStats &bcStats) const; - -private: - void GetBlockCodeRange(int blockNum, int *startOffset, int *size) const; - - const MIPSComp::IRBlockCache &irBlocks_; - const CodeBlockCommon *codeBlock_ = nullptr; - const IRNativeBackend *backend_ = nullptr; -}; - -class IRNativeJit : public IRJit { -public: - IRNativeJit(MIPSState *mipsState); - - void RunLoopUntil(u64 globalticks) override; - - void ClearCache() override; - void InvalidateCacheAt(u32 em_address, int length = 4) override; - - bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - bool CodeInRange(const u8 *ptr) const override; - bool IsAtDispatchFetch(const u8 *ptr) const override; - const u8 *GetDispatcher() const override; - const u8 *GetCrashHandler() const override; - - void UpdateFCR31() override; - - JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override; - -protected: - void Init(IRNativeBackend &backend); - bool CompileTargetBlock(IRBlock *block, int block_num, bool preload) override; - void FinalizeTargetBlock(IRBlock *block, int block_num) override; - - IRNativeBackend *backend_ = nullptr; - IRNativeHooks hooks_; - IRNativeBlockCacheDebugInterface debugInterface_; -}; - -} // namespace MIPSComp diff --git a/Core/MIPS/IR/IRPassSimplify.cpp b/Core/MIPS/IR/IRPassSimplify.cpp index 2d368d019..572545484 100644 --- a/Core/MIPS/IR/IRPassSimplify.cpp +++ b/Core/MIPS/IR/IRPassSimplify.cpp @@ -6,8 +6,6 @@ #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Log.h" #include "Core/Config.h" -#include "Core/MIPS/MIPSVFPUUtils.h" -#include "Core/MIPS/IR/IRAnalysis.h" #include "Core/MIPS/IR/IRInterpreter.h" #include "Core/MIPS/IR/IRPassSimplify.h" #include "Core/MIPS/IR/IRRegCache.h" @@ -87,8 +85,6 @@ IROp ShiftToShiftImm(IROp op) { } bool IRApplyPasses(const IRPassFunc *passes, size_t c, const IRWriter &in, IRWriter &out, const IROptions &opts) { - out.Reserve(in.GetInstructions().size()); - if (c == 1) { return passes[0](in, out, opts); } @@ -98,7 +94,6 @@ bool IRApplyPasses(const IRPassFunc *passes, size_t c, const IRWriter &in, IRWri IRWriter temp[2]; const IRWriter *nextIn = ∈ IRWriter *nextOut = &temp[1]; - temp[1].Reserve(nextIn->GetInstructions().size()); for (size_t i = 0; i < c - 1; ++i) { if (passes[i](*nextIn, *nextOut, opts)) { logBlocks = true; @@ -106,12 +101,8 @@ bool IRApplyPasses(const IRPassFunc *passes, size_t c, const IRWriter &in, IRWri temp[0] = std::move(temp[1]); nextIn = &temp[0]; - - temp[1].Clear(); - temp[1].Reserve(nextIn->GetInstructions().size()); } - out.Reserve(nextIn->GetInstructions().size()); if (passes[c - 1](*nextIn, out, opts)) { logBlocks = true; } @@ -137,9 +128,7 @@ bool OptimizeFPMoves(const IRWriter &in, IRWriter &out, const IROptions &opts) { if (prev.op == IROp::FMovToGPR && prev.dest == inst.src1) { inst.op = IROp::FMov; inst.src1 = prev.src1; - // Skip it entirely if it's just a copy to and back. - if (inst.dest != inst.src1) - out.Write(inst); + out.Write(inst); } else { out.Write(inst); } @@ -239,7 +228,7 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions }; auto combineOpposite = [&](IROp matchOp, int matchOff, IROp replaceOp, int replaceOff) { - if (i + 1 >= n) + if (!opts.unalignedLoadStore || i + 1 >= n) return false; const IRInst &next = nextOp(); if (next.op != matchOp || next.dest != inst.dest || next.src1 != inst.src1) @@ -247,40 +236,8 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions if (inst.constant + matchOff != next.constant) return false; - if (opts.unalignedLoadStore) { - // Write out one unaligned op. - out.Write(replaceOp, inst.dest, inst.src1, out.AddConstant(inst.constant + replaceOff)); - } else if (replaceOp == IROp::Load32) { - // We can still combine to a simpler set of two loads. - // We start by isolating the address and shift amount. - - // IRTEMP_LR_ADDR = rs + imm - out.Write(IROp::AddConst, IRTEMP_LR_ADDR, inst.src1, out.AddConstant(inst.constant + replaceOff)); - // IRTEMP_LR_SHIFT = (addr & 3) * 8 - out.Write(IROp::AndConst, IRTEMP_LR_SHIFT, IRTEMP_LR_ADDR, out.AddConstant(3)); - out.Write(IROp::ShlImm, IRTEMP_LR_SHIFT, IRTEMP_LR_SHIFT, 3); - // IRTEMP_LR_ADDR = addr & 0xfffffffc - out.Write(IROp::AndConst, IRTEMP_LR_ADDR, IRTEMP_LR_ADDR, out.AddConstant(0xFFFFFFFC)); - // IRTEMP_LR_VALUE = low_word, dest = high_word - out.Write(IROp::Load32, inst.dest, IRTEMP_LR_ADDR, out.AddConstant(0)); - out.Write(IROp::Load32, IRTEMP_LR_VALUE, IRTEMP_LR_ADDR, out.AddConstant(4)); - - // Now we just need to adjust and combine dest and IRTEMP_LR_VALUE. - // inst.dest >>= shift (putting its bits in the right spot.) - out.Write(IROp::Shr, inst.dest, inst.dest, IRTEMP_LR_SHIFT); - // We can't shift by 32, so we compromise by shifting twice. - out.Write(IROp::ShlImm, IRTEMP_LR_VALUE, IRTEMP_LR_VALUE, 8); - // IRTEMP_LR_SHIFT = 24 - shift - out.Write(IROp::Neg, IRTEMP_LR_SHIFT, IRTEMP_LR_SHIFT); - out.Write(IROp::AddConst, IRTEMP_LR_SHIFT, IRTEMP_LR_SHIFT, out.AddConstant(24)); - // IRTEMP_LR_VALUE <<= (24 - shift) - out.Write(IROp::Shl, IRTEMP_LR_VALUE, IRTEMP_LR_VALUE, IRTEMP_LR_SHIFT); - - // At this point the values are aligned, and we just merge. - out.Write(IROp::Or, inst.dest, inst.dest, IRTEMP_LR_VALUE); - } else { - return false; - } + // Write out one unaligned op. + out.Write(replaceOp, inst.dest, inst.src1, out.AddConstant(inst.constant + replaceOff)); // Skip the next one, replaced. i++; return true; @@ -426,10 +383,9 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts) { CONDITIONAL_DISABLE; - IRImmRegCache gpr(&out); + IRRegCache gpr(&out); bool logBlocks = false; - bool skipNextExitToConst = false; for (int i = 0; i < (int)in.GetInstructions().size(); i++) { IRInst inst = in.GetInstructions()[i]; bool symmetric = true; @@ -441,25 +397,9 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts goto doDefault; case IROp::Sub: - if (gpr.IsImm(inst.src1) && gpr.GetImm(inst.src1) == 0 && !gpr.IsImm(inst.src2)) { - // Morph into a Neg. - gpr.MapDirtyIn(inst.dest, inst.src2); - out.Write(IROp::Neg, inst.dest, inst.src2); - break; - } else if (inst.src1 == inst.src2) { - // Seen sometimes, yet another way of producing zero. - gpr.SetImm(inst.dest, 0); - break; - } -#if __cplusplus >= 201703 || _MSC_VER > 1910 - [[fallthrough]]; -#endif case IROp::Slt: case IROp::SltU: - symmetric = false; -#if __cplusplus >= 201703 || _MSC_VER > 1910 - [[fallthrough]]; -#endif + symmetric = false; // fallthrough case IROp::Add: case IROp::And: case IROp::Or: @@ -632,7 +572,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts case IROp::Store32: case IROp::Store32Left: case IROp::Store32Right: - case IROp::Store32Conditional: if (gpr.IsImm(inst.src1) && inst.src1 != inst.dest) { gpr.MapIn(inst.dest); out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + inst.constant)); @@ -656,7 +595,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts case IROp::Load16: case IROp::Load16Ext: case IROp::Load32: - case IROp::Load32Linked: if (gpr.IsImm(inst.src1) && inst.src1 != inst.dest) { gpr.MapDirty(inst.dest); out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + inst.constant)); @@ -729,8 +667,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts case IROp::FCeil: case IROp::FFloor: case IROp::FCvtSW: - case IROp::FCvtScaledWS: - case IROp::FCvtScaledSW: case IROp::FSin: case IROp::FCos: case IROp::FSqrt: @@ -741,20 +677,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts break; case IROp::SetCtrlVFPU: - gpr.MapDirty(IRREG_VFPU_CTRL_BASE + inst.dest); - goto doDefault; - - case IROp::SetCtrlVFPUReg: - if (gpr.IsImm(inst.src1)) { - out.Write(IROp::SetCtrlVFPU, inst.dest, out.AddConstant(gpr.GetImm(inst.src1))); - } else { - gpr.MapDirtyIn(IRREG_VFPU_CTRL_BASE + inst.dest, inst.src1); - out.Write(inst); - } - break; - - case IROp::SetCtrlVFPUFReg: - gpr.MapDirty(IRREG_VFPU_CTRL_BASE + inst.dest); goto doDefault; case IROp::FCvtWS: @@ -764,10 +686,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts out.Write(inst); break; - case IROp::FpCondFromReg: - gpr.MapDirtyIn(IRREG_FPCOND, inst.src1); - out.Write(inst); - break; case IROp::FpCondToReg: if (gpr.IsImm(IRREG_FPCOND)) { gpr.SetImm(inst.dest, gpr.GetImm(IRREG_FPCOND)); @@ -776,13 +694,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts out.Write(inst); } break; - case IROp::FpCtrlFromReg: - gpr.MapDirtyIn(IRREG_FCR31, inst.src1); - gpr.MapDirty(IRREG_FPCOND); - goto doDefault; - case IROp::FpCtrlToReg: - gpr.MapDirtyInIn(inst.dest, IRREG_FPCOND, IRREG_FCR31); - goto doDefault; case IROp::Vec4Init: case IROp::Vec4Mov: @@ -793,7 +704,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts case IROp::Vec4Dot: case IROp::Vec4Scale: case IROp::Vec4Shuffle: - case IROp::Vec4Blend: case IROp::Vec4Neg: case IROp::Vec4Abs: case IROp::Vec4Pack31To8: @@ -807,6 +717,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts out.Write(inst); break; + case IROp::ZeroFpCond: case IROp::FCmp: gpr.MapDirty(IRREG_FPCOND); goto doDefault; @@ -820,90 +731,20 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts gpr.MapDirtyIn(inst.dest, IRREG_VFPU_CTRL_BASE + inst.src1); goto doDefault; - case IROp::FCmpVfpuBit: - gpr.MapDirty(IRREG_VFPU_CC); - goto doDefault; - - case IROp::FCmovVfpuCC: - gpr.MapIn(IRREG_VFPU_CC); - goto doDefault; - - case IROp::FCmpVfpuAggregate: - gpr.MapDirtyIn(IRREG_VFPU_CC, IRREG_VFPU_CC); - goto doDefault; - - case IROp::ExitToConstIfEq: - case IROp::ExitToConstIfNeq: - if (gpr.IsImm(inst.src1) && gpr.IsImm(inst.src2)) { - bool passed = false; - switch (inst.op) { - case IROp::ExitToConstIfEq: passed = gpr.GetImm(inst.src1) == gpr.GetImm(inst.src2); break; - case IROp::ExitToConstIfNeq: passed = gpr.GetImm(inst.src1) != gpr.GetImm(inst.src2); break; - default: _assert_(false); break; - } - - // This is a bit common for the first cycle of loops. - // Reduce bloat by skipping on fail, and const exit on pass. - if (passed) { - gpr.FlushAll(); - out.Write(IROp::ExitToConst, out.AddConstant(inst.constant)); - skipNextExitToConst = true; - } - break; - } - gpr.FlushAll(); - goto doDefault; - - case IROp::ExitToConstIfGtZ: - case IROp::ExitToConstIfGeZ: - case IROp::ExitToConstIfLtZ: - case IROp::ExitToConstIfLeZ: - if (gpr.IsImm(inst.src1)) { - bool passed = false; - switch (inst.op) { - case IROp::ExitToConstIfGtZ: passed = (s32)gpr.GetImm(inst.src1) > 0; break; - case IROp::ExitToConstIfGeZ: passed = (s32)gpr.GetImm(inst.src1) >= 0; break; - case IROp::ExitToConstIfLtZ: passed = (s32)gpr.GetImm(inst.src1) < 0; break; - case IROp::ExitToConstIfLeZ: passed = (s32)gpr.GetImm(inst.src1) <= 0; break; - default: _assert_(false); break; - } - - if (passed) { - gpr.FlushAll(); - out.Write(IROp::ExitToConst, out.AddConstant(inst.constant)); - skipNextExitToConst = true; - } - break; - } - gpr.FlushAll(); - goto doDefault; - - case IROp::ExitToConst: - if (skipNextExitToConst) { - skipNextExitToConst = false; - break; - } - gpr.FlushAll(); - goto doDefault; - - case IROp::ExitToReg: - if (gpr.IsImm(inst.src1)) { - // This happens sometimes near loops. - // Prefer ExitToConst to allow block linking. - u32 dest = gpr.GetImm(inst.src1); - gpr.FlushAll(); - out.Write(IROp::ExitToConst, out.AddConstant(dest)); - break; - } - gpr.FlushAll(); - goto doDefault; - case IROp::CallReplacement: case IROp::Break: case IROp::Syscall: case IROp::Interpret: + case IROp::ExitToConst: + case IROp::ExitToReg: + case IROp::ExitToConstIfEq: + case IROp::ExitToConstIfNeq: case IROp::ExitToConstIfFpFalse: case IROp::ExitToConstIfFpTrue: + case IROp::ExitToConstIfGeZ: + case IROp::ExitToConstIfGtZ: + case IROp::ExitToConstIfLeZ: + case IROp::ExitToConstIfLtZ: case IROp::Breakpoint: case IROp::MemoryCheck: default: @@ -919,37 +760,70 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts return logBlocks; } -IRInstMeta IRReplaceSrcGPR(const IRInstMeta &inst, int fromReg, int toReg) { - IRInstMeta newInst = inst; +bool IRReadsFromGPR(const IRInst &inst, int reg, bool directly = false) { + const IRMeta *m = GetIRMeta(inst.op); - if (inst.m.types[1] == 'G' && inst.src1 == fromReg) { + if (m->types[1] == 'G' && inst.src1 == reg) { + return true; + } + if (m->types[2] == 'G' && inst.src2 == reg) { + return true; + } + if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == 'G' && inst.src3 == reg) { + return true; + } + if (!directly) { + if (inst.op == IROp::Interpret || inst.op == IROp::CallReplacement || inst.op == IROp::Syscall || inst.op == IROp::Break) + return true; + if (inst.op == IROp::Breakpoint || inst.op == IROp::MemoryCheck) + return true; + } + return false; +} + +IRInst IRReplaceSrcGPR(const IRInst &inst, int fromReg, int toReg) { + IRInst newInst = inst; + const IRMeta *m = GetIRMeta(inst.op); + + if (m->types[1] == 'G' && inst.src1 == fromReg) { newInst.src1 = toReg; } - if (inst.m.types[2] == 'G' && inst.src2 == fromReg) { + if (m->types[2] == 'G' && inst.src2 == fromReg) { newInst.src2 = toReg; } - if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && inst.m.types[0] == 'G' && inst.src3 == fromReg) { + if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == 'G' && inst.src3 == fromReg) { newInst.src3 = toReg; } return newInst; } -IRInstMeta IRReplaceDestGPR(const IRInstMeta &inst, int fromReg, int toReg) { - IRInstMeta newInst = inst; +int IRDestGPR(const IRInst &inst) { + const IRMeta *m = GetIRMeta(inst.op); - if ((inst.m.flags & IRFLAG_SRC3) == 0 && inst.m.types[0] == 'G' && inst.dest == fromReg) { + if ((m->flags & IRFLAG_SRC3) == 0 && m->types[0] == 'G') { + return inst.dest; + } + return -1; +} + +IRInst IRReplaceDestGPR(const IRInst &inst, int fromReg, int toReg) { + IRInst newInst = inst; + const IRMeta *m = GetIRMeta(inst.op); + + if ((m->flags & IRFLAG_SRC3) == 0 && m->types[0] == 'G' && inst.dest == fromReg) { newInst.dest = toReg; } return newInst; } -bool IRMutatesDestGPR(const IRInstMeta &inst, int reg) { - return (inst.m.flags & IRFLAG_SRC3DST) != 0 && inst.m.types[0] == 'G' && inst.src3 == reg; +bool IRMutatesDestGPR(const IRInst &inst, int reg) { + const IRMeta *m = GetIRMeta(inst.op); + return (m->flags & IRFLAG_SRC3DST) != 0 && m->types[0] == 'G' && inst.src3 == reg; } bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { CONDITIONAL_DISABLE; - std::vector insts; + std::vector insts; insts.reserve(in.GetInstructions().size()); // We track writes both to rename regs and to purge dead stores. @@ -965,67 +839,32 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { int index; // Whether the dest reg is read by any Exit. bool readByExit; - int8_t fplen = 0; }; std::vector checks; - checks.reserve(insts.size() / 2); - // This tracks the last index at which each reg was modified. int lastWrittenTo[256]; - int lastReadFrom[256]; memset(lastWrittenTo, -1, sizeof(lastWrittenTo)); - memset(lastReadFrom, -1, sizeof(lastReadFrom)); - - auto readsFromFPRCheck = [](IRInstMeta &inst, Check &check, bool *directly) { - if (check.reg < 32) - return false; - - bool result = false; - *directly = true; - for (int i = 0; i < 4; ++i) { - bool laneDirectly; - if (check.fplen >= i + 1 && IRReadsFromFPR(inst, check.reg - 32 + i, &laneDirectly)) { - result = true; - if (!laneDirectly) { - *directly = false; - break; - } - } - } - return result; - }; bool logBlocks = false; - size_t firstCheck = 0; for (int i = 0, n = (int)in.GetInstructions().size(); i < n; i++) { - IRInstMeta inst = GetIRMeta(in.GetInstructions()[i]); - - // It helps to skip through rechecking ones we already discarded. - for (size_t ch = firstCheck; ch < checks.size(); ++ch) { - Check &check = checks[ch]; - if (check.reg != 0) { - firstCheck = ch; - break; - } - } + IRInst inst = in.GetInstructions()[i]; + const IRMeta *m = GetIRMeta(inst.op); // Check if we can optimize by running through all the writes we've previously found. - for (size_t ch = firstCheck; ch < checks.size(); ++ch) { - Check &check = checks[ch]; + for (Check &check : checks) { if (check.reg == 0) { // This means we already optimized this or a later inst depends on it. continue; } - bool readsDirectly; - if (IRReadsFromGPR(inst, check.reg, &readsDirectly)) { + if (IRReadsFromGPR(inst, check.reg)) { // If this reads from the reg, we either depend on it or we can fold or swap. // That's determined below. // If this reads and writes the reg (e.g. MovZ, Load32Left), we can't just swap. bool mutatesReg = IRMutatesDestGPR(inst, check.reg); // If this doesn't directly read (i.e. Interpret), we can't swap. - bool cannotReplace = !readsDirectly; + bool cannotReplace = !IRReadsFromGPR(inst, check.reg, true); if (!mutatesReg && !cannotReplace && check.srcReg >= 0 && lastWrittenTo[check.srcReg] < check.index) { // Replace with the srcReg instead. This happens with non-nice delay slots. // We're changing "Mov A, B; Add C, C, A" to "Mov A, B; Add C, C, B" here. @@ -1055,87 +894,9 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { std::swap(inst.dest, inst.src1); } else { // Legitimately read from, so we can't optimize out. - // Unless this is an exit and a temp not read directly by the exit. - if ((inst.m.flags & IRFLAG_EXIT) == 0 || check.readByExit || readsDirectly) - check.reg = 0; + check.reg = 0; } - } else if (check.fplen >= 1 && readsFromFPRCheck(inst, check, &readsDirectly)) { - // If one or the other is a Vec, they must match. - bool lenMismatch = false; - - auto checkMismatch = [&check, &lenMismatch](IRReg src, char type) { - int srclen = 1; - if (type == 'V') - srclen = 4; - else if (type == '2') - srclen = 2; - else if (type != 'F') - return; - - if (src + 32 + srclen > check.reg && src + 32 < check.reg + check.fplen) { - if (src + 32 != check.reg || srclen != check.fplen) - lenMismatch = true; - } - }; - - checkMismatch(inst.src1, inst.m.types[1]); - checkMismatch(inst.src2, inst.m.types[2]); - if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) - checkMismatch(inst.src3, inst.m.types[3]); - - bool cannotReplace = !readsDirectly || lenMismatch; - if (!cannotReplace && check.srcReg >= 32 && lastWrittenTo[check.srcReg] < check.index) { - // This is probably not worth doing unless we can get rid of a temp. - if (!check.readByExit) { - if (insts[check.index].dest == inst.src1) - inst.src1 = check.srcReg - 32; - else if (insts[check.index].dest == inst.src2) - inst.src2 = check.srcReg - 32; - else - _assert_msg_(false, "Unexpected src3 read of FPR"); - - // Check if we've clobbered it entirely. - if (inst.dest == check.reg) { - check.reg = 0; - insts[check.index].op = IROp::Mov; - insts[check.index].dest = 0; - insts[check.index].src1 = 0; - } - } else { - // Let's not bother. - check.reg = 0; - } - } else if ((inst.op == IROp::FMov || inst.op == IROp::Vec4Mov) && !lenMismatch) { - // A swap could be profitable if this is a temp, and maybe in other cases. - // These can happen a lot from mask regs, etc. - // But make sure no other changes happened between. - bool destNotChanged = true; - for (int j = 0; j < check.fplen; ++j) - destNotChanged = destNotChanged && lastWrittenTo[inst.dest + 32 + j] < check.index; - - bool destNotRead = true; - for (int j = 0; j < check.fplen; ++j) - destNotRead = destNotRead && lastReadFrom[inst.dest + 32 + j] <= check.index; - - if (!check.readByExit && destNotChanged && destNotRead) { - _dbg_assert_(insts[check.index].dest == inst.src1); - insts[check.index].dest = inst.dest; - for (int j = 0; j < check.fplen; ++j) - lastWrittenTo[inst.dest + 32 + j] = check.index; - // If it's being read from (by inst now), we can't optimize out. - check.reg = 0; - // Swap the dest and src1 so we can optimize this out later, maybe. - std::swap(inst.dest, inst.src1); - } else { - // Doesn't look like a good candidate. - check.reg = 0; - } - } else { - // Legitimately read from, so we can't optimize out. - if ((inst.m.flags & IRFLAG_EXIT) == 0 || check.readByExit || readsDirectly) - check.reg = 0; - } - } else if (check.readByExit && (inst.m.flags & IRFLAG_EXIT) != 0) { + } else if (check.readByExit && (m->flags & IRFLAG_EXIT) != 0) { // This is an exit, and the reg is read by any exit. Clear it. check.reg = 0; } else if (IRDestGPR(inst) == check.reg) { @@ -1145,21 +906,6 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { insts[check.index].dest = 0; insts[check.index].src1 = 0; check.reg = 0; - } else if (IRWritesToFPR(inst, check.reg - 32) && check.fplen >= 1) { - IRReg destFPRs[4]; - int numFPRs = IRDestFPRs(inst, destFPRs); - - if (numFPRs == check.fplen && inst.dest + 32 == check.reg) { - // This means we've clobbered it, and with full overlap. - // Sometimes this happens for non-temps, i.e. vmmov + vinit last row. - insts[check.index].op = IROp::Mov; - insts[check.index].dest = 0; - insts[check.index].src1 = 0; - check.reg = 0; - } else { - // Since there's an overlap, we simply cannot optimize. - check.reg = 0; - } } } @@ -1203,46 +949,7 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { break; } - IRReg regs[16]; - int readGPRs = IRReadsFromGPRs(inst, regs); - if (readGPRs == -1) { - for (int j = 0; j < 256; ++j) - lastReadFrom[j] = i; - } else { - for (int j = 0; j < readGPRs; ++j) - lastReadFrom[regs[j]] = i; - } - - int readFPRs = IRReadsFromFPRs(inst, regs); - if (readFPRs == -1) { - for (int j = 0; j < 256; ++j) - lastReadFrom[j] = i; - } else { - for (int j = 0; j < readFPRs; ++j) - lastReadFrom[regs[j] + 32] = i; - } - - int destFPRs = IRDestFPRs(inst, regs); - for (int j = 0; j < destFPRs; ++j) - lastWrittenTo[regs[j] + 32] = i; - - dest = destFPRs > 0 ? regs[0] + 32 : -1; - if (dest >= 32 && dest < IRTEMP_0) { - // Standard FPU or VFPU reg. - Check check(dest, i, true); - check.fplen = (int8_t)destFPRs; - checks.push_back(check); - } else if (dest >= IRVTEMP_PFX_S + 32 && dest < IRVTEMP_PFX_S + 32 + 16) { - // These are temporary regs and not read by exits. - Check check(dest, i, false); - check.fplen = (int8_t)destFPRs; - if (inst.op == IROp::FMov || inst.op == IROp::Vec4Mov) { - check.srcReg = inst.src1 + 32; - } - checks.push_back(check); - } else if (dest != -1) { - _assert_msg_(false, "Unexpected FPR output %d", dest); - } + // TODO: VFPU temps? Especially for masked dregs. insts.push_back(inst); } @@ -1256,10 +963,10 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { } } - for (const IRInstMeta &inst : insts) { + for (const IRInst &inst : insts) { // Simply skip any Mov 0, 0 instructions, since that's how we nuke one. if (inst.op != IROp::Mov || inst.dest != 0 || inst.src1 != 0) { - out.Write(inst.i); + out.Write(inst); } } @@ -1277,11 +984,12 @@ bool ReduceLoads(const IRWriter &in, IRWriter &out, const IROptions &opts) { IRInst inst = in.GetInstructions()[i]; if (inst.op == IROp::Load32 || inst.op == IROp::Load16 || inst.op == IROp::Load16Ext) { - int dest = IRDestGPR(GetIRMeta(inst)); + int dest = IRDestGPR(inst); for (int j = i + 1; j < n; j++) { - const IRInstMeta laterInst = GetIRMeta(in.GetInstructions()[j]); + const IRInst &laterInst = in.GetInstructions()[j]; + const IRMeta *m = GetIRMeta(laterInst.op); - if ((laterInst.m.flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0) { + if ((m->flags & IRFLAG_EXIT) != 0) { // Exit, so we can't do the optimization. break; } @@ -1573,7 +1281,6 @@ bool ReorderLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts) case IROp::MtHi: case IROp::MtLo: - case IROp::FpCondFromReg: if (inst.src1 && otherRegs[inst.src1] != RegState::CHANGED) otherRegs[inst.src1] = RegState::READ; otherQueue.push_back(inst); @@ -1582,6 +1289,7 @@ bool ReorderLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts) case IROp::Nop: case IROp::Downcount: + case IROp::ZeroFpCond: if (queuing) { // These are freebies. Sometimes helps with delay slots. otherQueue.push_back(inst); @@ -1734,130 +1442,53 @@ bool MergeLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts) { return logBlocks; } -struct IRMemoryOpInfo { - int size; - bool isWrite; - bool isWordLR; -}; - -static IRMemoryOpInfo IROpMemoryAccessSize(IROp op) { - // Assumes all take src1 + constant. - switch (op) { - case IROp::Load8: - case IROp::Load8Ext: - case IROp::Store8: - return { 1, op == IROp::Store8 }; - - case IROp::Load16: - case IROp::Load16Ext: - case IROp::Store16: - return { 2, op == IROp::Store16 }; - - case IROp::Load32: - case IROp::Load32Linked: - case IROp::LoadFloat: - case IROp::Store32: - case IROp::Store32Conditional: - case IROp::StoreFloat: - return { 4, op == IROp::Store32 || op == IROp::Store32Conditional || op == IROp::StoreFloat }; - - case IROp::LoadVec4: - case IROp::StoreVec4: - return { 16, op == IROp::StoreVec4 }; - - case IROp::Load32Left: - case IROp::Load32Right: - case IROp::Store32Left: - case IROp::Store32Right: - // This explicitly does not require alignment, so validate as an 8-bit operation. - return { 1, op == IROp::Store32Left || op == IROp::Store32Right, true }; - - default: - return { 0 }; - } -} - bool ApplyMemoryValidation(const IRWriter &in, IRWriter &out, const IROptions &opts) { CONDITIONAL_DISABLE; if (g_Config.bFastMemory) DISABLE; - int spLower = 0; - int spUpper = -1; - bool spWrite = false; - bool spModified = false; - for (IRInst inst : in.GetInstructions()) { - IRMemoryOpInfo info = IROpMemoryAccessSize(inst.op); - // Note: we only combine word aligned accesses. - if (info.size != 0 && inst.src1 == MIPS_REG_SP && info.size == 4) { - if (spModified) { - // No good, it was modified and then we did more accesses. Can't combine. - spUpper = -1; - break; - } - if ((int)inst.constant < 0 || (int)inst.constant >= 0x4000) { - // Let's assume this might cross boundaries or something. Uncommon. - spUpper = -1; - break; - } - - spLower = std::min(spLower, (int)inst.constant); - spUpper = std::max(spUpper, (int)inst.constant + info.size); - spWrite = spWrite || info.isWrite; - } - - const IRMeta *m = GetIRMeta(inst.op); - if (m->types[0] == 'G' && (m->flags & IRFLAG_SRC3) == 0 && inst.dest == MIPS_REG_SP) { - // We only care if it changes after we start combining. - spModified = spUpper != -1; - } - } - - bool skipSP = spUpper != -1; - bool flushedSP = false; - - std::map checks; - const auto addValidate = [&](IROp validate, uint8_t sz, const IRInst &inst, bool isStore) { - if (inst.src1 == MIPS_REG_SP && skipSP && validate == IROp::ValidateAddress32) { - if (!flushedSP) { - out.Write(IROp::ValidateAddress32, 0, MIPS_REG_SP, spWrite ? 1U : 0U, spLower); - if (spUpper > spLower + 4) - out.Write(IROp::ValidateAddress32, 0, MIPS_REG_SP, spWrite ? 1U : 0U, spUpper - 4); - flushedSP = true; - } - return; - } - - uint64_t key = ((uint64_t)inst.src1 << 32) | inst.constant; - auto it = checks.find(key); - if (it == checks.end() || it->second < sz) { - out.Write(validate, 0, inst.src1, isStore ? 1U : 0U, inst.constant); - checks[key] = sz; - } + const auto addValidate = [&out](IROp validate, const IRInst &inst, bool isStore) { + out.Write({ validate, { 0 }, inst.src1, isStore ? (u8)1 : (u8)0, inst.constant }); }; + // TODO: Could be smart about not double-validating an address that has a load / store, etc. bool logBlocks = false; for (IRInst inst : in.GetInstructions()) { - IRMemoryOpInfo info = IROpMemoryAccessSize(inst.op); - IROp validateOp = IROp::Nop; - switch (info.size) { - case 1: validateOp = IROp::ValidateAddress8; break; - case 2: validateOp = IROp::ValidateAddress16; break; - case 4: validateOp = IROp::ValidateAddress32; break; - case 16: validateOp = IROp::ValidateAddress128; break; - case 0: break; - default: _assert_msg_(false, "Unexpected memory access size"); - } + switch (inst.op) { + case IROp::Load8: + case IROp::Load8Ext: + case IROp::Store8: + addValidate(IROp::ValidateAddress8, inst, inst.op == IROp::Store8); + break; - if (validateOp != IROp::Nop) { - addValidate(validateOp, info.size, inst, info.isWrite); - } + case IROp::Load16: + case IROp::Load16Ext: + case IROp::Store16: + addValidate(IROp::ValidateAddress16, inst, inst.op == IROp::Store16); + break; - const IRMeta *m = GetIRMeta(inst.op); - if (m->types[0] == 'G' && (m->flags & IRFLAG_SRC3) == 0) { - uint64_t key = (uint64_t)inst.dest << 32; - // Wipe out all the already done checks since this was modified. - checks.erase(checks.lower_bound(key), checks.upper_bound(key | 0xFFFFFFFFULL)); + case IROp::Load32: + case IROp::LoadFloat: + case IROp::Store32: + case IROp::StoreFloat: + addValidate(IROp::ValidateAddress32, inst, inst.op == IROp::Store32 || inst.op == IROp::StoreFloat); + break; + + case IROp::LoadVec4: + case IROp::StoreVec4: + addValidate(IROp::ValidateAddress128, inst, inst.op == IROp::StoreVec4); + break; + + case IROp::Load32Left: + case IROp::Load32Right: + case IROp::Store32Left: + case IROp::Store32Right: + // This explicitly does not require alignment, so validate as an 8-bit operation. + addValidate(IROp::ValidateAddress8, inst, inst.op == IROp::Store32Left || inst.op == IROp::Store32Right); + break; + + default: + break; } // Always write out the original. We're only adding. @@ -1865,282 +1496,3 @@ bool ApplyMemoryValidation(const IRWriter &in, IRWriter &out, const IROptions &o } return logBlocks; } - -bool ReduceVec4Flush(const IRWriter &in, IRWriter &out, const IROptions &opts) { - CONDITIONAL_DISABLE; - // Only do this when using a SIMD backend. - if (!opts.preferVec4) { - DISABLE; - } - - bool isVec4[256]{}; - bool isUsed[256]{}; - bool isVec4Dirty[256]{}; - auto updateVec4 = [&](char type, IRReg r) { - bool downgraded = false; - switch (type) { - case 'F': - downgraded = isVec4[r & ~3]; - isVec4[r & ~3] = false; - isUsed[r] = true; - break; - - case 'V': - _dbg_assert_((r & 3) == 0); - isVec4[r] = true; - for (int i = 0; i < 4; ++i) - isUsed[r + i] = true; - break; - - case '2': - downgraded = isVec4[r & ~3]; - isVec4[r & ~3] = false; - for (int i = 0; i < 2; ++i) - isUsed[r + i] = true; - break; - - default: - break; - } - - return downgraded; - }; - auto updateVec4Dest = [&](char type, IRReg r, uint32_t flags) { - if ((flags & IRFLAG_SRC3) == 0) { - switch (type) { - case 'F': - isVec4Dirty[r & ~3] = false; - break; - - case 'V': - _dbg_assert_((r & 3) == 0); - isVec4Dirty[r] = true; - break; - - case '2': - isVec4Dirty[r & ~3] = false; - break; - - default: - break; - } - } - return updateVec4(type, r); - }; - - // Checks overlap from r1 to other params. - auto overlapped = [](IRReg r1, int l1, IRReg r2, int l2, IRReg r3 = IRREG_INVALID, int l3 = 0) { - if (r1 < r2 + l2 && r1 + l1 > r2) - return true; - if (r1 < r3 + l3 && r1 + l1 > r3) - return true; - return false; - }; - - bool logBlocks = false; - int inCount = (int)in.GetInstructions().size(); - for (int i = 0; i < inCount; ++i) { - IRInst inst = in.GetInstructions()[i]; - const IRMeta *m = GetIRMeta(inst.op); - - if ((m->flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0) { - memset(isVec4, 0, sizeof(isVec4)); - out.Write(inst); - continue; - } - - IRReg temp = IRREG_INVALID; - auto findAvailTempVec4 = [&]() { - // If it's not used yet in this block, we can use it. - // Note: even if the instruction uses it to write, that should be fine. - for (IRReg r = IRVTEMP_PFX_S; r < IRVTEMP_0 + 4; r += 4) { - if (isUsed[r]) - continue; - - bool usable = true; - for (int j = 1; j < 4; ++j) - usable = usable && !isUsed[r + j]; - - if (usable) { - temp = r; - // We don't update isUsed because our temporary doesn't need to last. - return true; - } - } - - return false; - }; - - auto usedLaterAsVec4 = [&](IRReg r) { - for (int j = i + 1; j < inCount; ++j) { - IRInst inst = in.GetInstructions()[j]; - const IRMeta *m = GetIRMeta(inst.op); - if (m->types[0] == 'V' && inst.dest == r) - return true; - if (m->types[1] == 'V' && inst.src1 == r) - return true; - if (m->types[2] == 'V' && inst.src2 == r) - return true; - } - return false; - }; - - bool skip = false; - switch (inst.op) { - case IROp::SetConstF: - if (isVec4[inst.dest & ~3] && findAvailTempVec4()) { - // Check if we're setting multiple in a row, this is a bit common. - u8 blendMask = 1 << (inst.dest & 3); - while (i + 1 < inCount) { - IRInst next = in.GetInstructions()[i + 1]; - if (next.op != IROp::SetConstF || (next.dest & ~3) != (inst.dest & ~3)) - break; - if (next.constant != inst.constant) - break; - - blendMask |= 1 << (next.dest & 3); - i++; - } - - if (inst.constant == 0) { - out.Write(IROp::Vec4Init, temp, (int)Vec4Init::AllZERO); - } else if (inst.constant == 0x3F800000) { - out.Write(IROp::Vec4Init, temp, (int)Vec4Init::AllONE); - } else if (inst.constant == 0xBF800000) { - out.Write(IROp::Vec4Init, temp, (int)Vec4Init::AllMinusONE); - } else { - out.Write(IROp::SetConstF, temp, out.AddConstant(inst.constant)); - out.Write(IROp::Vec4Shuffle, temp, temp, 0); - } - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, temp, blendMask); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } - break; - - case IROp::FMovFromGPR: - if (isVec4[inst.dest & ~3] && findAvailTempVec4()) { - u8 blendMask = 1 << (inst.dest & 3); - out.Write(IROp::FMovFromGPR, temp, inst.src1); - out.Write(IROp::Vec4Shuffle, temp, temp, 0); - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, temp, blendMask); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } - break; - - case IROp::LoadFloat: - if (isVec4[inst.dest & ~3] && isVec4Dirty[inst.dest & ~3] && usedLaterAsVec4(inst.dest & ~3) && findAvailTempVec4()) { - u8 blendMask = 1 << (inst.dest & 3); - out.Write(inst.op, temp, inst.src1, inst.src2, inst.constant); - out.Write(IROp::Vec4Shuffle, temp, temp, 0); - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, temp, blendMask); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } - break; - - case IROp::StoreFloat: - if (isVec4[inst.src3 & ~3] && isVec4Dirty[inst.src3 & ~3] && usedLaterAsVec4(inst.src3 & ~3) && findAvailTempVec4()) { - out.Write(IROp::FMov, temp, inst.src3, 0); - out.Write(inst.op, temp, inst.src1, inst.src2, inst.constant); - continue; - } - break; - - case IROp::FMov: - if (isVec4[inst.dest & ~3] && (inst.dest & ~3) == (inst.src1 & ~3)) { - // Oh, actually a shuffle? - uint8_t shuffle = (uint8_t)VFPU_SWIZZLE(0, 1, 2, 3); - uint8_t destShift = (inst.dest & 3) * 2; - shuffle = (shuffle & ~(3 << destShift)) | ((inst.src1 & 3) << destShift); - out.Write(IROp::Vec4Shuffle, inst.dest & ~3, inst.dest & ~3, shuffle); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } else if (isVec4[inst.dest & ~3] && (inst.dest & 3) == (inst.src1 & 3)) { - // We can turn this directly into a blend, since it's the same lane. - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, inst.src1 & ~3, 1 << (inst.dest & 3)); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } else if (isVec4[inst.dest & ~3] && isVec4[inst.src1 & ~3] && findAvailTempVec4()) { - // For this, we'll need a temporary to move to the right lane. - int lane = inst.src1 & 3; - uint8_t shuffle = (uint8_t)VFPU_SWIZZLE(lane, lane, lane, lane); - out.Write(IROp::Vec4Shuffle, temp, inst.src1 & ~3, shuffle); - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, temp, 1 << (inst.dest & 3)); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } - break; - - case IROp::FAdd: - case IROp::FSub: - case IROp::FMul: - case IROp::FDiv: - if (isVec4[inst.dest & ~3] && isVec4Dirty[inst.dest & ~3] && usedLaterAsVec4(inst.dest & ~3)) { - if (!overlapped(inst.dest & ~3, 4, inst.src1, 1, inst.src2, 1) && findAvailTempVec4()) { - u8 blendMask = 1 << (inst.dest & 3); - out.Write(inst.op, temp, inst.src1, inst.src2); - out.Write(IROp::Vec4Shuffle, temp, temp, 0); - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, temp, blendMask); - updateVec4('F', inst.src1); - updateVec4('F', inst.src2); - isVec4Dirty[inst.dest & ~3] = true; - continue; - } - } - break; - - case IROp::Vec4Dot: - if (overlapped(inst.dest, 1, inst.src1, 4, inst.src2, 4) && findAvailTempVec4()) { - out.Write(inst.op, temp, inst.src1, inst.src2, inst.constant); - if (usedLaterAsVec4(inst.dest & ~3)) { - // Broadcast to other lanes if needed. - if ((inst.dest & 3) != 0) - out.Write(IROp::Vec4Shuffle, temp, temp, 0); - out.Write(IROp::Vec4Blend, inst.dest & ~3, inst.dest & ~3, temp, 1 << (inst.dest & 3)); - // It's overlapped, so it'll get marked as Vec4 and used anyway. - isVec4Dirty[inst.dest & ~3] = true; - inst.dest = IRREG_INVALID; - } else { - out.Write(IROp::FMov, inst.dest, temp); - } - skip = true; - } - break; - - case IROp::Vec4Scale: - if (overlapped(inst.src2, 1, inst.src1, 4, inst.dest, 4) && findAvailTempVec4()) { - out.Write(IROp::FMov, temp, inst.src2); - out.Write(inst.op, inst.dest, inst.src1, temp, inst.constant); - skip = true; - inst.src2 = IRREG_INVALID; - } else if (isVec4[inst.src2 & 3] && usedLaterAsVec4(inst.src2 & ~3) && findAvailTempVec4()) { - out.Write(IROp::FMov, temp, inst.src2); - out.Write(inst.op, inst.dest, inst.src1, temp, inst.constant); - skip = true; - inst.src2 = IRREG_INVALID; - } - break; - - default: - break; - } - - bool downgrade = false; - if (inst.src1 != IRREG_INVALID && updateVec4(m->types[1], inst.src1)) - downgrade = true; - if (inst.src2 != IRREG_INVALID && updateVec4(m->types[2], inst.src2)) - downgrade = true; - if (inst.dest != IRREG_INVALID && updateVec4Dest(m->types[0], inst.dest, m->flags)) - downgrade = true; - - if (downgrade) { - //WARN_LOG(JIT, "Vec4 downgrade by: %s", m->name); - } - - if (!skip) - out.Write(inst); - } - return logBlocks; -} diff --git a/Core/MIPS/IR/IRPassSimplify.h b/Core/MIPS/IR/IRPassSimplify.h index c7c644351..7fdc5d1c7 100644 --- a/Core/MIPS/IR/IRPassSimplify.h +++ b/Core/MIPS/IR/IRPassSimplify.h @@ -15,4 +15,3 @@ bool OptimizeFPMoves(const IRWriter &in, IRWriter &out, const IROptions &opts); bool ReorderLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts); bool MergeLoadStore(const IRWriter &in, IRWriter &out, const IROptions &opts); bool ApplyMemoryValidation(const IRWriter &in, IRWriter &out, const IROptions &opts); -bool ReduceVec4Flush(const IRWriter &in, IRWriter &out, const IROptions &opts); diff --git a/Core/MIPS/IR/IRRegCache.cpp b/Core/MIPS/IR/IRRegCache.cpp index 01eed63fa..ca54392be 100644 --- a/Core/MIPS/IR/IRRegCache.cpp +++ b/Core/MIPS/IR/IRRegCache.cpp @@ -1,100 +1,63 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#ifndef offsetof -#include -#endif - #include -#include "Common/Log.h" -#include "Common/LogReporting.h" -#include "Core/MemMap.h" -#include "Core/MIPS/IR/IRAnalysis.h" #include "Core/MIPS/IR/IRRegCache.h" #include "Core/MIPS/IR/IRInst.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/JitCommon/JitState.h" -void IRImmRegCache::Flush(IRReg rd) { - if (isImm_[rd]) { - if (rd == 0) { - return; - } - _assert_((rd > 0 && rd < 32) || (rd >= IRTEMP_0 && rd < IRREG_VFPU_CTRL_BASE)); - ir_->WriteSetConstant(rd, immVal_[rd]); - isImm_[rd] = false; - } -} - -void IRImmRegCache::Discard(IRReg rd) { +void IRRegCache::Flush(int rd) { if (rd == 0) { return; } - isImm_[rd] = false; -} - -IRImmRegCache::IRImmRegCache(IRWriter *ir) : ir_(ir) { - memset(&isImm_, 0, sizeof(isImm_)); - memset(&immVal_, 0, sizeof(immVal_)); - isImm_[0] = true; - ir_ = ir; -} - -void IRImmRegCache::FlushAll() { - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS; ) { - if (isImm_[i]) { - Flush(i); - } - - // Most of the time, lots are not. This speeds it up a lot. - bool *next = (bool *)memchr(&isImm_[i], 1, TOTAL_MAPPABLE_IRREGS - i); - if (!next) - break; - i = (int)(next - &isImm_[0]); + if (reg_[rd].isImm) { + ir_->WriteSetConstant(rd, reg_[rd].immVal); + reg_[rd].isImm = false; } } -void IRImmRegCache::MapIn(IRReg rd) { +void IRRegCache::Discard(int rd) { + if (rd == 0) { + return; + } + reg_[rd].isImm = false; +} + +IRRegCache::IRRegCache(IRWriter *ir) : ir_(ir) { + memset(®_, 0, sizeof(reg_)); + reg_[0].isImm = true; + ir_ = ir; +} + +void IRRegCache::FlushAll() { + for (int i = 0; i < TOTAL_MAPPABLE_MIPSREGS; i++) { + Flush(i); + } +} + +void IRRegCache::MapIn(int rd) { Flush(rd); } -void IRImmRegCache::MapDirty(IRReg rd) { +void IRRegCache::MapDirty(int rd) { Discard(rd); } -void IRImmRegCache::MapInIn(IRReg rs, IRReg rt) { +void IRRegCache::MapInIn(int rs, int rt) { Flush(rs); Flush(rt); } -void IRImmRegCache::MapInInIn(IRReg rd, IRReg rs, IRReg rt) { +void IRRegCache::MapInInIn(int rd, int rs, int rt) { Flush(rd); Flush(rs); Flush(rt); } -void IRImmRegCache::MapDirtyIn(IRReg rd, IRReg rs) { +void IRRegCache::MapDirtyIn(int rd, int rs) { if (rs != rd) { Discard(rd); } Flush(rs); } -void IRImmRegCache::MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt) { +void IRRegCache::MapDirtyInIn(int rd, int rs, int rt) { if (rs != rd && rt != rd) { Discard(rd); } @@ -102,1167 +65,3 @@ void IRImmRegCache::MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt) { Flush(rt); } -IRNativeRegCacheBase::IRNativeRegCacheBase(MIPSComp::JitOptions *jo) - : jo_(jo) {} - -void IRNativeRegCacheBase::Start(MIPSComp::IRBlock *irBlock) { - if (!initialReady_) { - SetupInitialRegs(); - initialReady_ = true; - } - - memcpy(nr, nrInitial_, sizeof(nr[0]) * config_.totalNativeRegs); - memcpy(mr, mrInitial_, sizeof(mr)); - - int numStatics; - const StaticAllocation *statics = GetStaticAllocations(numStatics); - for (int i = 0; i < numStatics; i++) { - nr[statics[i].nr].mipsReg = statics[i].mr; - nr[statics[i].nr].pointerified = statics[i].pointerified && jo_->enablePointerify; - nr[statics[i].nr].normalized32 = statics[i].normalized32; - mr[statics[i].mr].loc = statics[i].loc; - mr[statics[i].mr].nReg = statics[i].nr; - mr[statics[i].mr].isStatic = true; - // Lock it until the very end. - mr[statics[i].mr].spillLockIRIndex = irBlock->GetNumInstructions(); - } - - irBlock_ = irBlock; - irIndex_ = 0; -} - -void IRNativeRegCacheBase::SetupInitialRegs() { - _assert_msg_(config_.totalNativeRegs > 0, "totalNativeRegs was never set by backend"); - - // Everything else is initialized in the struct. - mrInitial_[MIPS_REG_ZERO].loc = MIPSLoc::IMM; - mrInitial_[MIPS_REG_ZERO].imm = 0; -} - -bool IRNativeRegCacheBase::IsGPRInRAM(IRReg gpr) { - _dbg_assert_(IsValidGPR(gpr)); - return mr[gpr].loc == MIPSLoc::MEM; -} - -bool IRNativeRegCacheBase::IsFPRInRAM(IRReg fpr) { - _dbg_assert_(IsValidFPR(fpr)); - return mr[fpr + 32].loc == MIPSLoc::MEM; -} - -bool IRNativeRegCacheBase::IsGPRMapped(IRReg gpr) { - _dbg_assert_(IsValidGPR(gpr)); - return mr[gpr].loc == MIPSLoc::REG || mr[gpr].loc == MIPSLoc::REG_IMM; -} - -bool IRNativeRegCacheBase::IsFPRMapped(IRReg fpr) { - _dbg_assert_(IsValidFPR(fpr)); - return mr[fpr + 32].loc == MIPSLoc::FREG || mr[fpr + 32].loc == MIPSLoc::VREG; -} - -int IRNativeRegCacheBase::GetFPRLaneCount(IRReg fpr) { - if (!IsFPRMapped(fpr)) - return 0; - if (mr[fpr + 32].lane == -1) - return 1; - - IRReg base = fpr + 32 - mr[fpr + 32].lane; - int c = 1; - for (int i = 1; i < 4; ++i) { - if (mr[base + i].nReg != mr[base].nReg || mr[base + i].loc != mr[base].loc) - return c; - if (mr[base + i].lane != i) - return c; - - c++; - } - - return c; -} - -int IRNativeRegCacheBase::GetFPRLane(IRReg fpr) { - _dbg_assert_(IsValidFPR(fpr)); - if (mr[fpr + 32].loc == MIPSLoc::FREG || mr[fpr + 32].loc == MIPSLoc::VREG) { - int l = mr[fpr + 32].lane; - return l == -1 ? 0 : l; - } - return -1; -} - -bool IRNativeRegCacheBase::IsGPRMappedAsPointer(IRReg gpr) { - _dbg_assert_(IsValidGPR(gpr)); - if (mr[gpr].loc == MIPSLoc::REG) { - return nr[mr[gpr].nReg].pointerified; - } else if (mr[gpr].loc == MIPSLoc::REG_IMM) { - _assert_msg_(!nr[mr[gpr].nReg].pointerified, "Really shouldn't be pointerified here"); - } else if (mr[gpr].loc == MIPSLoc::REG_AS_PTR) { - return true; - } - return false; -} - -bool IRNativeRegCacheBase::IsGPRMappedAsStaticPointer(IRReg gpr) { - if (IsGPRMappedAsPointer(gpr)) { - return mr[gpr].isStatic; - } - return false; -} - -bool IRNativeRegCacheBase::IsGPRImm(IRReg gpr) { - _dbg_assert_(IsValidGPR(gpr)); - if (gpr == MIPS_REG_ZERO) - return true; - return mr[gpr].loc == MIPSLoc::IMM || mr[gpr].loc == MIPSLoc::REG_IMM; -} - -bool IRNativeRegCacheBase::IsGPR2Imm(IRReg base) { - return IsGPRImm(base) && IsGPRImm(base + 1); -} - -uint32_t IRNativeRegCacheBase::GetGPRImm(IRReg gpr) { - _dbg_assert_(IsValidGPR(gpr)); - if (gpr == MIPS_REG_ZERO) - return 0; - if (mr[gpr].loc != MIPSLoc::IMM && mr[gpr].loc != MIPSLoc::REG_IMM) { - _assert_msg_(mr[gpr].loc == MIPSLoc::IMM || mr[gpr].loc == MIPSLoc::REG_IMM, "GPR %d not in an imm", gpr); - } - return mr[gpr].imm; -} - -uint64_t IRNativeRegCacheBase::GetGPR2Imm(IRReg base) { - return (uint64_t)GetGPRImm(base) | ((uint64_t)GetGPRImm(base + 1) << 32); -} - -void IRNativeRegCacheBase::SetGPRImm(IRReg gpr, uint32_t immVal) { - _dbg_assert_(IsValidGPR(gpr)); - if (gpr == MIPS_REG_ZERO && immVal != 0) { - ERROR_LOG_REPORT(JIT, "Trying to set immediate %08x to r0", immVal); - return; - } - - if (mr[gpr].loc == MIPSLoc::REG_IMM && mr[gpr].imm == immVal) { - // Already have that value, let's keep it in the reg. - return; - } - - if (mr[gpr].nReg != -1) { - // Zap existing value if cached in a reg. - _assert_msg_(mr[gpr].lane == -1, "Should not be a multilane reg"); - DiscardNativeReg(mr[gpr].nReg); - } - - mr[gpr].loc = MIPSLoc::IMM; - mr[gpr].imm = immVal; -} - -void IRNativeRegCacheBase::SetGPR2Imm(IRReg base, uint64_t immVal) { - _dbg_assert_(IsValidGPRNoZero(base)); - uint32_t imm0 = (uint32_t)(immVal & 0xFFFFFFFF); - uint32_t imm1 = (uint32_t)(immVal >> 32); - - if (IsGPRImm(base) && IsGPRImm(base + 1) && GetGPRImm(base) == imm0 && GetGPRImm(base + 1) == imm1) { - // Already set to this, don't bother. - return; - } - - if (mr[base].nReg != -1) { - // Zap existing value if cached in a reg. - DiscardNativeReg(mr[base].nReg); - if (mr[base + 1].nReg != -1) - DiscardNativeReg(mr[base + 1].nReg); - } - - mr[base].loc = MIPSLoc::IMM; - mr[base].imm = imm0; - mr[base + 1].loc = MIPSLoc::IMM; - mr[base + 1].imm = imm1; -} - -void IRNativeRegCacheBase::SpillLockGPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidGPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidGPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidGPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidGPR(r4)); - SetSpillLockIRIndex(r1, r2, r3, r4, 0, irIndex_); -} - -void IRNativeRegCacheBase::SpillLockFPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidFPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidFPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidFPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidFPR(r4)); - SetSpillLockIRIndex(r1, r2, r3, r4, 32, irIndex_); -} - -void IRNativeRegCacheBase::ReleaseSpillLockGPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidGPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidGPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidGPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidGPR(r4)); - SetSpillLockIRIndex(r1, r2, r3, r4, 0, -1); -} - -void IRNativeRegCacheBase::ReleaseSpillLockFPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidFPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidFPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidFPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidFPR(r4)); - SetSpillLockIRIndex(r1, r2, r3, r4, 32, -1); -} - -void IRNativeRegCacheBase::SetSpillLockIRIndex(IRReg r1, IRReg r2, IRReg r3, IRReg r4, int offset, int index) { - if (!mr[r1 + offset].isStatic) - mr[r1 + offset].spillLockIRIndex = index; - if (r2 != IRREG_INVALID && !mr[r2 + offset].isStatic) - mr[r2 + offset].spillLockIRIndex = index; - if (r3 != IRREG_INVALID && !mr[r3 + offset].isStatic) - mr[r3 + offset].spillLockIRIndex = index; - if (r4 != IRREG_INVALID && !mr[r4 + offset].isStatic) - mr[r4 + offset].spillLockIRIndex = index; -} - -void IRNativeRegCacheBase::SetSpillLockIRIndex(IRReg r1, int index) { - if (!mr[r1].isStatic) - mr[r1].spillLockIRIndex = index; -} - -void IRNativeRegCacheBase::MarkGPRDirty(IRReg gpr, bool andNormalized32) { - _assert_(IsGPRMapped(gpr)); - if (!IsGPRMapped(gpr)) - return; - - IRNativeReg nreg = mr[gpr].nReg; - nr[nreg].isDirty = true; - nr[nreg].normalized32 = andNormalized32; - // If reg is written to, pointerification is assumed lost. - nr[nreg].pointerified = false; - if (mr[gpr].loc == MIPSLoc::REG_AS_PTR || mr[gpr].loc == MIPSLoc::REG_IMM) { - mr[gpr].loc = MIPSLoc::REG; - mr[gpr].imm = -1; - } - _dbg_assert_(mr[gpr].loc == MIPSLoc::REG); -} - -void IRNativeRegCacheBase::MarkGPRAsPointerDirty(IRReg gpr) { - _assert_(IsGPRMappedAsPointer(gpr)); - if (!IsGPRMappedAsPointer(gpr)) - return; - -#ifdef MASKED_PSP_MEMORY - if (mr[gpr].loc == MIPSLoc::REG_AS_PTR) { - _assert_msg_(false, "MarkGPRAsPointerDirty is not possible when using MASKED_PSP_MEMORY"); - } -#endif - - IRNativeReg nreg = mr[gpr].nReg; - _dbg_assert_(!nr[nreg].normalized32); - nr[nreg].isDirty = true; - // Stays pointerified or REG_AS_PTR. -} - -IRNativeReg IRNativeRegCacheBase::AllocateReg(MIPSLoc type, MIPSMap flags) { - _dbg_assert_(type == MIPSLoc::REG || type == MIPSLoc::FREG || type == MIPSLoc::VREG); - - IRNativeReg nreg = FindFreeReg(type, flags); - if (nreg != -1) - return nreg; - - // Still nothing. Let's spill a reg and goto 10. - bool clobbered; - IRNativeReg bestToSpill = FindBestToSpill(type, flags, true, &clobbered); - if (bestToSpill == -1) { - bestToSpill = FindBestToSpill(type, flags, false, &clobbered); - } - - if (bestToSpill != -1) { - if (clobbered) { - DiscardNativeReg(bestToSpill); - } else { - FlushNativeReg(bestToSpill); - } - // Now one must be free. - return FindFreeReg(type, flags); - } - - // Uh oh, we have all of them spilllocked.... - ERROR_LOG_REPORT(JIT, "Out of spillable registers in block PC %08x, index %d", irBlock_->GetOriginalStart(), irIndex_); - _assert_(bestToSpill != -1); - return -1; -} - -IRNativeReg IRNativeRegCacheBase::FindFreeReg(MIPSLoc type, MIPSMap flags) const { - int allocCount = 0, base = 0; - const int *allocOrder = GetAllocationOrder(type, flags, allocCount, base); - - for (int i = 0; i < allocCount; i++) { - IRNativeReg nreg = IRNativeReg(allocOrder[i] - base); - - if (nr[nreg].mipsReg == IRREG_INVALID && nr[nreg].tempLockIRIndex < irIndex_) { - return nreg; - } - } - - return -1; -} - -bool IRNativeRegCacheBase::IsGPRClobbered(IRReg gpr) const { - _dbg_assert_(IsValidGPR(gpr)); - return IsRegClobbered(MIPSLoc::REG, gpr); -} - -bool IRNativeRegCacheBase::IsFPRClobbered(IRReg fpr) const { - _dbg_assert_(IsValidFPR(fpr)); - return IsRegClobbered(MIPSLoc::FREG, fpr + 32); -} - -IRUsage IRNativeRegCacheBase::GetNextRegUsage(const IRSituation &info, MIPSLoc type, IRReg r) const { - if (type == MIPSLoc::REG) - return IRNextGPRUsage(r, info); - else if (type == MIPSLoc::FREG || type == MIPSLoc::VREG) - return IRNextFPRUsage(r - 32, info); - _assert_msg_(false, "Unknown spill allocation type"); - return IRUsage::UNKNOWN; -} - -bool IRNativeRegCacheBase::IsRegClobbered(MIPSLoc type, IRReg r) const { - static const int UNUSED_LOOKAHEAD_OPS = 30; - - IRSituation info; - info.lookaheadCount = UNUSED_LOOKAHEAD_OPS; - // We look starting one ahead, unlike spilling. We want to know if it clobbers later. - info.currentIndex = irIndex_ + 1; - info.instructions = irBlock_->GetInstructions(); - info.numInstructions = irBlock_->GetNumInstructions(); - - // Make sure we're on the first one if this is multi-lane. - IRReg first = r; - if (mr[r].lane != -1) - first -= mr[r].lane; - - IRUsage usage = GetNextRegUsage(info, type, first); - if (usage == IRUsage::CLOBBERED) { - // If multiple mips regs use this native reg (i.e. vector, HI/LO), check each. - bool canClobber = true; - for (IRReg m = first + 1; mr[m].nReg == mr[first].nReg && m < IRREG_INVALID && canClobber; ++m) - canClobber = GetNextRegUsage(info, type, m) == IRUsage::CLOBBERED; - - return canClobber; - } - return false; -} - -bool IRNativeRegCacheBase::IsRegRead(MIPSLoc type, IRReg first) const { - static const int UNUSED_LOOKAHEAD_OPS = 30; - - IRSituation info; - info.lookaheadCount = UNUSED_LOOKAHEAD_OPS; - // We look starting one ahead, unlike spilling. - info.currentIndex = irIndex_ + 1; - info.instructions = irBlock_->GetInstructions(); - info.numInstructions = irBlock_->GetNumInstructions(); - - // Note: this intentionally doesn't look at the full reg, only the lane. - IRUsage usage = GetNextRegUsage(info, type, first); - return usage == IRUsage::READ; -} - -IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, bool unusedOnly, bool *clobbered) const { - int allocCount = 0, base = 0; - const int *allocOrder = GetAllocationOrder(type, flags, allocCount, base); - - static const int UNUSED_LOOKAHEAD_OPS = 30; - - IRSituation info; - info.lookaheadCount = UNUSED_LOOKAHEAD_OPS; - info.currentIndex = irIndex_; - info.instructions = irBlock_->GetInstructions(); - info.numInstructions = irBlock_->GetNumInstructions(); - - *clobbered = false; - for (int i = 0; i < allocCount; i++) { - IRNativeReg nreg = IRNativeReg(allocOrder[i] - base); - if (nr[nreg].mipsReg != IRREG_INVALID && mr[nr[nreg].mipsReg].spillLockIRIndex >= irIndex_) - continue; - if (nr[nreg].tempLockIRIndex >= irIndex_) - continue; - - // As it's in alloc-order, we know it's not static so we don't need to check for that. - IRReg mipsReg = nr[nreg].mipsReg; - IRUsage usage = GetNextRegUsage(info, type, mipsReg); - - // Awesome, a clobbered reg. Let's use it? - if (usage == IRUsage::CLOBBERED) { - // If multiple mips regs use this native reg (i.e. vector, HI/LO), check each. - // Note: mipsReg points to the lowest numbered IRReg. - bool canClobber = true; - for (IRReg m = mipsReg + 1; mr[m].nReg == nreg && m < IRREG_INVALID && canClobber; ++m) - canClobber = GetNextRegUsage(info, type, m) == IRUsage::CLOBBERED; - - // Okay, if all can be clobbered, we're good to go. - if (canClobber) { - *clobbered = true; - return nreg; - } - } - - // Not awesome. A used reg. Let's try to avoid spilling. - if (!unusedOnly || usage == IRUsage::UNUSED) { - // TODO: Use age or something to choose which register to spill? - // TODO: Spill dirty regs first? or opposite? - *clobbered = mipsReg == MIPS_REG_ZERO; - return nreg; - } - } - - return -1; -} - -bool IRNativeRegCacheBase::IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes) { - int allocCount = 0, base = 0; - const int *allocOrder = GetAllocationOrder(type, flags, allocCount, base); - - for (int i = 0; i < allocCount; i++) { - IRNativeReg allocReg = IRNativeReg(allocOrder[i] - base); - if (allocReg == nreg) - return true; - } - - return false; -} - -bool IRNativeRegCacheBase::TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) { - // To be overridden if the backend supports transfers. - return false; -} - -void IRNativeRegCacheBase::DiscardNativeReg(IRNativeReg nreg) { - _assert_msg_(nreg >= 0 && nreg < config_.totalNativeRegs, "DiscardNativeReg on invalid register %d", nreg); - if (nr[nreg].mipsReg != IRREG_INVALID) { - int8_t lanes = 0; - for (IRReg m = nr[nreg].mipsReg; mr[m].nReg == nreg && m < IRREG_INVALID; ++m) - lanes++; - - if (mr[nr[nreg].mipsReg].isStatic) { - _assert_(nr[nreg].mipsReg != MIPS_REG_ZERO); - - int numStatics; - const StaticAllocation *statics = GetStaticAllocations(numStatics); - - // If it's not currently marked as in a reg, throw it away. - for (IRReg m = nr[nreg].mipsReg; m < nr[nreg].mipsReg + lanes; ++m) { - _assert_msg_(mr[m].isStatic, "Reg in lane %d mismatched static status", m - nr[nreg].mipsReg); - for (int i = 0; i < numStatics; i++) { - if (m == statics[i].mr) - mr[m].loc = statics[i].loc; - } - } - } else { - for (IRReg m = nr[nreg].mipsReg; m < nr[nreg].mipsReg + lanes; ++m) { - mr[m].loc = MIPSLoc::MEM; - mr[m].nReg = -1; - mr[m].imm = 0; - mr[m].lane = -1; - _assert_msg_(!mr[m].isStatic, "Reg in lane %d mismatched static status", m - nr[nreg].mipsReg); - } - - nr[nreg].mipsReg = IRREG_INVALID; - } - } - - // Even for a static reg, we assume this means it's not pointerified anymore. - nr[nreg].pointerified = false; - nr[nreg].isDirty = false; - nr[nreg].normalized32 = false; -} - -void IRNativeRegCacheBase::FlushNativeReg(IRNativeReg nreg) { - _assert_msg_(nreg >= 0 && nreg < config_.totalNativeRegs, "FlushNativeReg on invalid register %d", nreg); - if (nr[nreg].mipsReg == IRREG_INVALID || nr[nreg].mipsReg == MIPS_REG_ZERO) { - // Nothing to do, reg not mapped or mapped to fixed zero. - _dbg_assert_(!nr[nreg].isDirty); - return; - } - _dbg_assert_(!mr[nr[nreg].mipsReg].isStatic); - if (mr[nr[nreg].mipsReg].isStatic) { - ERROR_LOG(JIT, "Cannot FlushNativeReg a statically mapped register"); - return; - } - - // Multiple mipsRegs may match this if a vector or HI/LO, etc. - bool isDirty = nr[nreg].isDirty; - int8_t lanes = 0; - for (IRReg m = nr[nreg].mipsReg; mr[m].nReg == nreg && m < IRREG_INVALID; ++m) { - _assert_(!mr[m].isStatic); - // If we're flushing a native reg, better not be partially in mem or an imm. - _assert_(mr[m].loc != MIPSLoc::MEM && mr[m].loc != MIPSLoc::IMM); - lanes++; - } - - if (isDirty) { - IRReg first = nr[nreg].mipsReg; - if (mr[first].loc == MIPSLoc::REG_AS_PTR) { - // We assume this can't be multiple lanes. Maybe some gather craziness? - _assert_(lanes == 1); - AdjustNativeRegAsPtr(nreg, false); - mr[first].loc = MIPSLoc::REG; - } - StoreNativeReg(nreg, first, lanes); - } - - for (int8_t i = 0; i < lanes; ++i) { - auto &mreg = mr[nr[nreg].mipsReg + i]; - mreg.nReg = -1; - // Note that it loses its imm status, because imms are always dirty. - mreg.loc = MIPSLoc::MEM; - mreg.imm = 0; - mreg.lane = -1; - } - - nr[nreg].mipsReg = IRREG_INVALID; - nr[nreg].isDirty = false; - nr[nreg].pointerified = false; - nr[nreg].normalized32 = false; -} - -void IRNativeRegCacheBase::DiscardReg(IRReg mreg) { - if (mr[mreg].isStatic) { - DiscardNativeReg(mr[mreg].nReg); - return; - } - switch (mr[mreg].loc) { - case MIPSLoc::IMM: - if (mreg != MIPS_REG_ZERO) { - mr[mreg].loc = MIPSLoc::MEM; - mr[mreg].imm = 0; - } - break; - - case MIPSLoc::REG: - case MIPSLoc::REG_AS_PTR: - case MIPSLoc::REG_IMM: - case MIPSLoc::FREG: - case MIPSLoc::VREG: - DiscardNativeReg(mr[mreg].nReg); - break; - - case MIPSLoc::MEM: - // Already discarded. - break; - } - mr[mreg].spillLockIRIndex = -1; -} - -void IRNativeRegCacheBase::FlushReg(IRReg mreg) { - _assert_msg_(!mr[mreg].isStatic, "Cannot flush static reg %d", mreg); - - switch (mr[mreg].loc) { - case MIPSLoc::IMM: - // IMM is always "dirty". - StoreRegValue(mreg, mr[mreg].imm); - mr[mreg].loc = MIPSLoc::MEM; - mr[mreg].nReg = -1; - mr[mreg].imm = 0; - break; - - case MIPSLoc::REG: - case MIPSLoc::REG_IMM: - case MIPSLoc::REG_AS_PTR: - case MIPSLoc::FREG: - case MIPSLoc::VREG: - // Might be in a native reg with multiple IR regs, flush together. - FlushNativeReg(mr[mreg].nReg); - break; - - case MIPSLoc::MEM: - // Already there, nothing to do. - break; - } -} - -void IRNativeRegCacheBase::FlushAll(bool gprs, bool fprs) { - // Note: make sure not to change the registers when flushing. - // Branching code may expect the native reg to retain its value. - - if (!mr[MIPS_REG_ZERO].isStatic && mr[MIPS_REG_ZERO].nReg != -1) - DiscardNativeReg(mr[MIPS_REG_ZERO].nReg); - - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS; i++) { - IRReg mipsReg = (IRReg)i; - if (!fprs && i >= 32 && IsValidFPR(mipsReg - 32)) - continue; - if (!gprs && IsValidGPR(mipsReg)) - continue; - - if (mr[i].isStatic) { - IRNativeReg nreg = mr[i].nReg; - // Cannot leave any IMMs in registers, not even MIPSLoc::REG_IMM. - // Can confuse the regalloc later if this flush is mid-block - // due to an interpreter fallback that changes the register. - if (mr[i].loc == MIPSLoc::IMM) { - SetNativeRegValue(mr[i].nReg, mr[i].imm); - _assert_(IsValidGPR(mipsReg)); - mr[i].loc = MIPSLoc::REG; - nr[nreg].pointerified = false; - } else if (mr[i].loc == MIPSLoc::REG_IMM) { - // The register already contains the immediate. - if (nr[nreg].pointerified) { - ERROR_LOG(JIT, "RVREG_IMM but pointerified. Wrong."); - nr[nreg].pointerified = false; - } - mr[i].loc = MIPSLoc::REG; - } else if (mr[i].loc == MIPSLoc::REG_AS_PTR) { - AdjustNativeRegAsPtr(mr[i].nReg, false); - mr[i].loc = MIPSLoc::REG; - } - _assert_(mr[i].nReg != -1); - } else if (mr[i].loc != MIPSLoc::MEM) { - FlushReg(mipsReg); - } - } - - int count = 0; - const StaticAllocation *allocs = GetStaticAllocations(count); - for (int i = 0; i < count; i++) { - if (!fprs && allocs[i].loc != MIPSLoc::FREG && allocs[i].loc != MIPSLoc::VREG) - continue; - if (!gprs && allocs[i].loc != MIPSLoc::REG) - continue; - if (allocs[i].pointerified && !nr[allocs[i].nr].pointerified && jo_->enablePointerify) { - // Re-pointerify - if (mr[allocs[i].mr].loc == MIPSLoc::REG_IMM) - mr[allocs[i].mr].loc = MIPSLoc::REG; - _dbg_assert_(mr[allocs[i].mr].loc == MIPSLoc::REG); - AdjustNativeRegAsPtr(allocs[i].nr, true); - nr[allocs[i].nr].pointerified = true; - } else if (!allocs[i].pointerified) { - // If this register got pointerified on the way, mark it as not. - // This is so that after save/reload (like in an interpreter fallback), - // it won't be regarded as such, as it may no longer be. - nr[allocs[i].nr].pointerified = false; - } - } - // Sanity check - for (int i = 0; i < config_.totalNativeRegs; i++) { - if (nr[i].mipsReg != IRREG_INVALID && !mr[nr[i].mipsReg].isStatic) { - ERROR_LOG_REPORT(JIT, "Flush fail: nr[%i].mipsReg=%i", i, nr[i].mipsReg); - } - } -} - -void IRNativeRegCacheBase::Map(const IRInst &inst) { - Mapping mapping[3]; - MappingFromInst(inst, mapping); - - ApplyMapping(mapping, 3); - CleanupMapping(mapping, 3); -} - -void IRNativeRegCacheBase::MapWithExtra(const IRInst &inst, std::vector extra) { - extra.resize(extra.size() + 3); - MappingFromInst(inst, &extra[extra.size() - 3]); - - ApplyMapping(extra.data(), (int)extra.size()); - CleanupMapping(extra.data(), (int)extra.size()); -} - -IRNativeReg IRNativeRegCacheBase::MapWithTemp(const IRInst &inst, MIPSLoc type) { - Mapping mapping[3]; - MappingFromInst(inst, mapping); - - ApplyMapping(mapping, 3); - // Grab a temp while things are spill locked. - IRNativeReg temp = AllocateReg(type, MIPSMap::INIT); - CleanupMapping(mapping, 3); - return temp; -} - -void IRNativeRegCacheBase::ApplyMapping(const Mapping *mapping, int count) { - for (int i = 0; i < count; ++i) { - SetSpillLockIRIndex(mapping[i].reg, irIndex_); - if (!config_.mapFPUSIMD && mapping[i].type != 'G') { - for (int j = 1; j < mapping[i].lanes; ++j) - SetSpillLockIRIndex(mapping[i].reg + j, irIndex_); - } - } - - auto isNoinit = [](MIPSMap f) { - return (f & MIPSMap::NOINIT) == MIPSMap::NOINIT; - }; - - auto mapRegs = [&](int i) { - MIPSLoc type = MIPSLoc::MEM; - switch (mapping[i].type) { - case 'G': type = MIPSLoc::REG; break; - case 'F': type = MIPSLoc::FREG; break; - case 'V': type = MIPSLoc::VREG; break; - - case '_': - // Ignored intentionally. - return; - - default: - _assert_msg_(false, "Unexpected type: %c", mapping[i].type); - return; - } - - bool mapSIMD = config_.mapFPUSIMD || mapping[i].type == 'G'; - MIPSMap flags = mapping[i].flags; - for (int j = 0; j < count; ++j) { - if (mapping[j].type == mapping[i].type && mapping[j].reg == mapping[i].reg && i != j) { - _assert_msg_(!mapSIMD || mapping[j].lanes == mapping[i].lanes, "Lane aliasing not supported yet"); - - if (!isNoinit(mapping[j].flags) && isNoinit(flags)) { - flags = (flags & MIPSMap::BACKEND_MASK) | MIPSMap::DIRTY; - } - } - } - - if (mapSIMD) { - MapNativeReg(type, mapping[i].reg, mapping[i].lanes, flags); - return; - } - - for (int j = 0; j < mapping[i].lanes; ++j) - MapNativeReg(type, mapping[i].reg + j, 1, flags); - }; - auto mapFilteredRegs = [&](auto pred) { - for (int i = 0; i < count; ++i) { - if (pred(mapping[i].flags)) - mapRegs(i); - } - }; - - // Do two passes: with backend special flags, and without. - mapFilteredRegs([](MIPSMap flags) { - return (flags & MIPSMap::BACKEND_MASK) != MIPSMap::INIT; - }); - mapFilteredRegs([](MIPSMap flags) { - return (flags & MIPSMap::BACKEND_MASK) == MIPSMap::INIT; - }); -} - -void IRNativeRegCacheBase::CleanupMapping(const Mapping *mapping, int count) { - for (int i = 0; i < count; ++i) { - SetSpillLockIRIndex(mapping[i].reg, -1); - if (!config_.mapFPUSIMD && mapping[i].type != 'G') { - for (int j = 1; j < mapping[i].lanes; ++j) - SetSpillLockIRIndex(mapping[i].reg + j, -1); - } - } - - // Sanity check. If these don't pass, we may have Vec overlap issues or etc. - for (int i = 0; i < count; ++i) { - if (mapping[i].reg != IRREG_INVALID) { - auto &mreg = mr[mapping[i].reg]; - _dbg_assert_(mreg.nReg != -1); - if (mapping[i].type == 'G') { - _dbg_assert_(mreg.loc == MIPSLoc::REG || mreg.loc == MIPSLoc::REG_AS_PTR || mreg.loc == MIPSLoc::REG_IMM); - } else if (mapping[i].type == 'F') { - _dbg_assert_(mreg.loc == MIPSLoc::FREG); - } else if (mapping[i].type == 'V') { - _dbg_assert_(mreg.loc == MIPSLoc::VREG); - } - if (mapping[i].lanes != 1 && (config_.mapFPUSIMD || mapping[i].type == 'G')) { - _dbg_assert_(mreg.lane == 0); - _dbg_assert_(mr[mapping[i].reg + mapping[i].lanes - 1].lane == mapping[i].lanes - 1); - _dbg_assert_(mreg.nReg == mr[mapping[i].reg + mapping[i].lanes - 1].nReg); - } else { - _dbg_assert_(mreg.lane == -1); - } - } - } -} - -void IRNativeRegCacheBase::MappingFromInst(const IRInst &inst, Mapping mapping[3]) { - mapping[0].reg = inst.dest; - mapping[1].reg = inst.src1; - mapping[2].reg = inst.src2; - - const IRMeta *m = GetIRMeta(inst.op); - for (int i = 0; i < 3; ++i) { - switch (m->types[i]) { - case 'G': - mapping[i].type = 'G'; - _assert_msg_(IsValidGPR(mapping[i].reg), "G was not valid GPR?"); - break; - - case 'F': - mapping[i].reg += 32; - mapping[i].type = 'F'; - _assert_msg_(IsValidFPR(mapping[i].reg - 32), "F was not valid FPR?"); - break; - - case 'V': - case '2': - mapping[i].reg += 32; - mapping[i].type = config_.mapUseVRegs ? 'V' : 'F'; - mapping[i].lanes = m->types[i] == 'V' ? 4 : (m->types[i] == '2' ? 2 : 1); - _assert_msg_(IsValidFPR(mapping[i].reg - 32), "%c was not valid FPR?", m->types[i]); - break; - - case 'T': - mapping[i].type = 'G'; - _assert_msg_(mapping[i].reg < VFPU_CTRL_MAX, "T was not valid VFPU CTRL?"); - mapping[i].reg += IRREG_VFPU_CTRL_BASE; - break; - - case '\0': - case '_': - case 'C': - case 'I': - case 'v': - case 's': - case 'm': - mapping[i].type = '_'; - mapping[i].reg = IRREG_INVALID; - mapping[i].lanes = 0; - break; - - default: - _assert_msg_(mapping[i].reg == IRREG_INVALID, "Unexpected register type %c", m->types[i]); - break; - } - } - - if (mapping[0].type != '_') { - if ((m->flags & IRFLAG_SRC3DST) != 0) - mapping[0].flags = MIPSMap::DIRTY; - else if ((m->flags & IRFLAG_SRC3) != 0) - mapping[0].flags = MIPSMap::INIT; - else - mapping[0].flags = MIPSMap::NOINIT; - } -} - -IRNativeReg IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRReg first, int lanes, MIPSMap flags) { - _assert_msg_(first != IRREG_INVALID, "Cannot map invalid register"); - _assert_msg_(lanes >= 1 && lanes <= 4, "Cannot map %d lanes", lanes); - if (first == IRREG_INVALID || lanes < 0) - return -1; - - // Let's see if it's already mapped or we need a new reg. - IRNativeReg nreg = mr[first].nReg; - if (mr[first].isStatic) { - _assert_msg_(nreg != -1, "MapIRReg on static without an nReg?"); - } else { - switch (mr[first].loc) { - case MIPSLoc::REG_IMM: - case MIPSLoc::REG_AS_PTR: - case MIPSLoc::REG: - if (type != MIPSLoc::REG) { - nreg = AllocateReg(type, flags); - } else if (!IsNativeRegCompatible(nreg, type, flags, lanes)) { - // If it's not compatible, we'll need to reallocate. - if (TransferNativeReg(nreg, -1, type, first, lanes, flags)) { - nreg = mr[first].nReg; - } else { - FlushNativeReg(nreg); - nreg = AllocateReg(type, flags); - } - } - break; - - case MIPSLoc::FREG: - case MIPSLoc::VREG: - if (type != mr[first].loc) { - nreg = AllocateReg(type, flags); - } else if (!IsNativeRegCompatible(nreg, type, flags, lanes)) { - if (TransferNativeReg(nreg, -1, type, first, lanes, flags)) { - nreg = mr[first].nReg; - } else { - FlushNativeReg(nreg); - nreg = AllocateReg(type, flags); - } - } - break; - - case MIPSLoc::IMM: - case MIPSLoc::MEM: - nreg = AllocateReg(type, flags); - break; - } - } - - if (nreg != -1) { - // This will handle already mapped and new mappings. - MapNativeReg(type, nreg, first, lanes, flags); - } - - return nreg; -} - -void IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRNativeReg nreg, IRReg first, int lanes, MIPSMap flags) { - // First, try to clean up any lane mismatches. - // It must either be in the same nreg and lane count, or not in an nreg. - for (int i = 0; i < lanes; ++i) { - auto &mreg = mr[first + i]; - if (mreg.nReg != -1) { - // How many lanes is it currently in? - int oldlanes = 0; - for (IRReg m = nr[mreg.nReg].mipsReg; mr[m].nReg == mreg.nReg && m < IRREG_INVALID; ++m) - oldlanes++; - - // We may need to flush if it goes outside or we're initing. - int oldlane = mreg.lane == -1 ? 0 : mreg.lane; - bool mismatch = oldlanes != lanes || oldlane != i; - if (mismatch) { - _assert_msg_(!mreg.isStatic, "Cannot MapNativeReg a static reg mismatch"); - if ((flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) { - // If we need init, we have to flush mismatches. - if (!TransferNativeReg(mreg.nReg, nreg, type, first, lanes, flags)) { - // TODO: We may also be motivated to have multiple read-only "views" or an IRReg. - // For example Vec4Scale v0..v3, v0..v3, v3 - FlushNativeReg(mreg.nReg); - } - // The mismatch has been "resolved" now. - mismatch = false; - } else if (oldlanes != 1) { - // Even if we don't care about the current contents, we can't discard outside. - bool extendsBefore = oldlane > i; - bool extendsAfter = i + oldlanes - oldlane > lanes; - if (extendsBefore || extendsAfter) { - // Usually, this is 4->1. Check for clobber. - bool clobbered = false; - if (lanes == 1) { - IRSituation info; - info.lookaheadCount = 16; - info.currentIndex = irIndex_; - info.instructions = irBlock_->GetInstructions(); - info.numInstructions = irBlock_->GetNumInstructions(); - - IRReg basefpr = first - oldlane - 32; - clobbered = true; - for (int l = 0; l < oldlanes; ++l) { - // Ignore the one we're modifying. - if (l == oldlane) - continue; - - if (IRNextFPRUsage(basefpr + l, info) != IRUsage::CLOBBERED) { - clobbered = false; - break; - } - } - } - - if (clobbered) - DiscardNativeReg(mreg.nReg); - else - FlushNativeReg(mreg.nReg); - - // That took care of the mismatch, either by clobber or flush. - mismatch = false; - } - } - } - - // If it's still in a different reg, either discard or possibly transfer. - if (mreg.nReg != -1 && (mreg.nReg != nreg || mismatch)) { - _assert_msg_(!mreg.isStatic, "Cannot MapNativeReg a static reg to a new reg"); - if ((flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) { - // We better not be trying to map to a different nreg if it's in one now. - // This might happen on some sort of transfer... - if (!TransferNativeReg(mreg.nReg, nreg, type, first, lanes, flags)) - FlushNativeReg(mreg.nReg); - } else { - DiscardNativeReg(mreg.nReg); - } - } - } - - // If somehow this is an imm and mapping to a multilane native reg (HI/LO?), we store it. - // TODO: Could check the others are imm and be smarter, but seems an unlikely case. - if (mreg.loc == MIPSLoc::IMM && lanes > 1) { - if ((flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) - StoreRegValue(first + i, mreg.imm); - mreg.loc = MIPSLoc::MEM; - if (!mreg.isStatic) - mreg.nReg = -1; - mreg.imm = 0; - } - } - - // Double check: everything should be in the same loc for multilane now. - for (int i = 1; i < lanes; ++i) { - _assert_(mr[first + i].loc == mr[first].loc); - } - - bool markDirty = (flags & MIPSMap::DIRTY) == MIPSMap::DIRTY; - if (mr[first].nReg != nreg) { - nr[nreg].isDirty = markDirty; - nr[nreg].pointerified = false; - nr[nreg].normalized32 = false; - } - - // Alright, now to actually map. - if ((flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) { - if (first == MIPS_REG_ZERO) { - _assert_msg_(lanes == 1, "Cannot use MIPS_REG_ZERO in multilane"); - SetNativeRegValue(nreg, 0); - mr[first].loc = MIPSLoc::REG_IMM; - mr[first].imm = 0; - } else { - // Note: we checked above, everything is in the same loc if multilane. - switch (mr[first].loc) { - case MIPSLoc::IMM: - _assert_msg_(lanes == 1, "Not handling multilane imm here"); - SetNativeRegValue(nreg, mr[first].imm); - // IMM is always dirty unless static. - if (!mr[first].isStatic) - nr[nreg].isDirty = true; - - // If we are mapping dirty, it means we're gonna overwrite. - // So the imm value is no longer valid. - if ((flags & MIPSMap::DIRTY) == MIPSMap::DIRTY) - mr[first].loc = MIPSLoc::REG; - else - mr[first].loc = MIPSLoc::REG_IMM; - break; - - case MIPSLoc::REG_IMM: - // If it's not dirty, we can keep it. - _assert_msg_(type == MIPSLoc::REG, "Should have flushed this reg already"); - if ((flags & MIPSMap::DIRTY) == MIPSMap::DIRTY || lanes != 1) - mr[first].loc = MIPSLoc::REG; - for (int i = 1; i < lanes; ++i) - mr[first + i].loc = type; - break; - - case MIPSLoc::REG_AS_PTR: - _assert_msg_(lanes == 1, "Should have flushed before getting here"); - _assert_msg_(type == MIPSLoc::REG, "Should have flushed this reg already"); -#ifndef MASKED_PSP_MEMORY - AdjustNativeRegAsPtr(nreg, false); -#endif - for (int i = 0; i < lanes; ++i) - mr[first + i].loc = type; -#ifdef MASKED_PSP_MEMORY - LoadNativeReg(nreg, first, lanes); -#endif - break; - - case MIPSLoc::REG: - case MIPSLoc::FREG: - case MIPSLoc::VREG: - // Might be flipping from FREG -> VREG or something. - _assert_msg_(type == mr[first].loc, "Should have flushed this reg already"); - for (int i = 0; i < lanes; ++i) - mr[first + i].loc = type; - break; - - case MIPSLoc::MEM: - for (int i = 0; i < lanes; ++i) - mr[first + i].loc = type; - LoadNativeReg(nreg, first, lanes); - break; - } - } - } else { - for (int i = 0; i < lanes; ++i) - mr[first + i].loc = type; - } - - for (int i = 0; i < lanes; ++i) { - mr[first + i].nReg = nreg; - mr[first + i].lane = lanes == 1 ? -1 : i; - } - - nr[nreg].mipsReg = first; - - if (markDirty) { - nr[nreg].isDirty = true; - nr[nreg].pointerified = false; - nr[nreg].normalized32 = false; - _assert_(first != MIPS_REG_ZERO); - } -} - -IRNativeReg IRNativeRegCacheBase::MapNativeRegAsPointer(IRReg gpr) { - _dbg_assert_(IsValidGPRNoZero(gpr)); - - // Already mapped. - if (mr[gpr].loc == MIPSLoc::REG_AS_PTR) { - return mr[gpr].nReg; - } - - // Cannot use if somehow multilane. - if (mr[gpr].nReg != -1 && mr[gpr].lane != -1) { - FlushNativeReg(mr[gpr].nReg); - } - - IRNativeReg nreg = mr[gpr].nReg; - if (mr[gpr].loc != MIPSLoc::REG && mr[gpr].loc != MIPSLoc::REG_IMM) { - nreg = MapNativeReg(MIPSLoc::REG, gpr, 1, MIPSMap::INIT); - } - - if (mr[gpr].loc == MIPSLoc::REG || mr[gpr].loc == MIPSLoc::REG_IMM) { - // If there was an imm attached, discard it. - mr[gpr].loc = MIPSLoc::REG; - mr[gpr].imm = 0; - -#ifdef MASKED_PSP_MEMORY - if (nr[mr[gpr].nReg].isDirty) { - StoreNativeReg(mr[gpr].nReg, gpr, 1); - nr[mr[gpr].nReg].isDirty = false; - } -#endif - - if (!jo_->enablePointerify) { - AdjustNativeRegAsPtr(nreg, true); - mr[gpr].loc = MIPSLoc::REG_AS_PTR; - } else if (!nr[nreg].pointerified) { - AdjustNativeRegAsPtr(nreg, true); - nr[nreg].pointerified = true; - } - } else { - ERROR_LOG(JIT, "MapNativeRegAsPointer: MapNativeReg failed to allocate a register?"); - } - return nreg; -} - -void IRNativeRegCacheBase::AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) { - // This isn't necessary to implement if REG_AS_PTR is unsupported entirely. - _assert_msg_(false, "AdjustNativeRegAsPtr unimplemented"); -} - -int IRNativeRegCacheBase::GetMipsRegOffset(IRReg r) { - _dbg_assert_(IsValidGPR(r) || (r >= 32 && IsValidFPR(r - 32))); - return r * 4; -} - -bool IRNativeRegCacheBase::IsValidGPR(IRReg r) const { - // See MIPSState for these offsets. - - // Don't allow FPU regs, VFPU regs, or VFPU temps here. - if (r >= 32 && IsValidFPR(r - 32)) - return false; - // Don't allow nextPC, etc. since it's probably a mistake. - if (r > IRREG_FPCOND && r != IRREG_LLBIT) - return false; - // Don't allow PC either. - if (r == 241) - return false; - - return true; -} - -bool IRNativeRegCacheBase::IsValidGPRNoZero(IRReg r) const { - return IsValidGPR(r) && r != MIPS_REG_ZERO; -} - -bool IRNativeRegCacheBase::IsValidFPR(IRReg r) const { - // FPR parameters are off by 32 within the MIPSState object. - if (r >= TOTAL_MAPPABLE_IRREGS - 32) - return false; - - // See MIPSState for these offsets. - int index = r + 32; - - // Allow FPU or VFPU regs here. - if (index >= 32 && index < 32 + 32 + 128) - return true; - // Also allow VFPU temps. - if (index >= 224 && index < 224 + 16) - return true; - - // Nothing else is allowed for the FPU side. - return false; -} diff --git a/Core/MIPS/IR/IRRegCache.h b/Core/MIPS/IR/IRRegCache.h index 4301886b4..9fcdab8b1 100644 --- a/Core/MIPS/IR/IRRegCache.h +++ b/Core/MIPS/IR/IRRegCache.h @@ -1,266 +1,47 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - #pragma once -// IRImmRegCache is only to perform pre-constant folding. This is worth it to get cleaner +// IRRegCache is only to perform pre-constant folding. This is worth it to get cleaner // IR. #include "Common/CommonTypes.h" #include "Core/MIPS/MIPS.h" -#include "Core/MIPS/IR/IRAnalysis.h" -#include "Core/MIPS/IR/IRInst.h" +enum { + TOTAL_MAPPABLE_MIPSREGS = 256, +}; -// Have to account for all of them due to temps, etc. -constexpr int TOTAL_MAPPABLE_IRREGS = 256; -// Arbitrary - increase if your backend has more. -constexpr int TOTAL_POSSIBLE_NATIVEREGS = 128; - -typedef int8_t IRNativeReg; - -constexpr IRReg IRREG_INVALID = 255; +struct RegIR { + bool isImm; + u32 immVal; +}; class IRWriter; -class MIPSState; - -namespace MIPSComp { -class IRBlock; -struct JitOptions; -} // Transient -class IRImmRegCache { +class IRRegCache { public: - IRImmRegCache(IRWriter *ir); + IRRegCache(IRWriter *ir); - void SetImm(IRReg r, u32 immVal) { - isImm_[r] = true; - immVal_[r] = immVal; + void SetImm(int r, u32 immVal) { + reg_[r].isImm = true; + reg_[r].immVal = immVal; } - bool IsImm(IRReg r) const { return isImm_[r]; } - u32 GetImm(IRReg r) const { return immVal_[r]; } + bool IsImm(int r) const { return reg_[r].isImm; } + u32 GetImm(int r) const { return reg_[r].immVal; } void FlushAll(); - void MapDirty(IRReg rd); - void MapIn(IRReg rd); - void MapInIn(IRReg rs, IRReg rt); - void MapInInIn(IRReg rd, IRReg rs, IRReg rt); - void MapDirtyIn(IRReg rd, IRReg rs); - void MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt); + void MapDirty(int rd); + void MapIn(int rd); + void MapInIn(int rs, int rt); + void MapInInIn(int rd, int rs, int rt); + void MapDirtyIn(int rd, int rs); + void MapDirtyInIn(int rd, int rs, int rt); private: - void Flush(IRReg rd); - void Discard(IRReg rd); - - bool isImm_[TOTAL_MAPPABLE_IRREGS]; - uint32_t immVal_[TOTAL_MAPPABLE_IRREGS]; + void Flush(int rd); + void Discard(int rd); + RegIR reg_[TOTAL_MAPPABLE_MIPSREGS]; IRWriter *ir_; }; - -// Initing is the default so the flag is reversed. -// 8 bits - upper 4 are reserved for backend purposes. -enum class MIPSMap : uint8_t { - INIT = 0, - DIRTY = 1, - NOINIT = 2 | DIRTY, - - BACKEND_MASK = 0xF0, -}; -static inline MIPSMap operator |(const MIPSMap &lhs, const MIPSMap &rhs) { - return MIPSMap((uint8_t)lhs | (uint8_t)rhs); -} -static inline MIPSMap operator &(const MIPSMap &lhs, const MIPSMap &rhs) { - return MIPSMap((uint8_t)lhs & (uint8_t)rhs); -} - -class IRNativeRegCacheBase { -protected: - enum class MIPSLoc { - // Known immediate value (only in regcache.) - IMM, - // In a general reg. - REG, - // In a general reg, but an adjusted pointer (not pointerified - unaligned.) - REG_AS_PTR, - // In a general reg, but also has a known immediate value. - REG_IMM, - // In a native floating-point reg. - FREG, - // In a native vector reg. Note: if FREGs and VREGS overlap, just use FREG. - VREG, - // Away in memory (in the mips context struct.) - MEM, - }; - - struct RegStatusMIPS { - // Where is this IR/MIPS register? Note: base reg if vector. - MIPSLoc loc = MIPSLoc::MEM; - // If in a register, what index (into nr array)? - IRNativeReg nReg = -1; - // If a known immediate value, what value? - uint32_t imm = 0; - // Locked from spilling (i.e. used by current instruction) as of what IR instruction? - int spillLockIRIndex = -1; - // If in a multipart reg (vector or HI/LO), which lane? - int lane = -1; - // Whether this reg is statically allocated. - bool isStatic = false; - }; - struct RegStatusNative { - // Which IR/MIPS reg is this currently holding? - IRReg mipsReg = IRREG_INVALID; - // Locked either as temp or direct reg as of what IR instruction? - int tempLockIRIndex = -1; - // Should the register be written back? - bool isDirty = false; - // Upper part of the register is used for "pointerification". - // Depending on backend, this may not be used or some/all operations may work on the lower 32 bits. - bool pointerified = false; - // Upper part of the register has a normalized form (i.e. zero or sign extend.) - // Which this means or if it matters depends on the backend. - bool normalized32 = false; - }; - - struct StaticAllocation { - IRReg mr; - IRNativeReg nr; - // Register type. - MIPSLoc loc; - // Whether the reg should be marked pointerified by default. - bool pointerified = false; - // Whether the reg should be considered always normalized at the start of a block. - bool normalized32 = false; - }; - -public: - IRNativeRegCacheBase(MIPSComp::JitOptions *jo); - virtual ~IRNativeRegCacheBase() {} - - virtual void Start(MIPSComp::IRBlock *irBlock); - void SetIRIndex(int index) { - irIndex_ = index; - } - - bool IsGPRInRAM(IRReg gpr); - bool IsFPRInRAM(IRReg fpr); - bool IsGPRMapped(IRReg gpr); - bool IsFPRMapped(IRReg fpr); - bool IsGPRMappedAsPointer(IRReg gpr); - bool IsGPRMappedAsStaticPointer(IRReg gpr); - int GetFPRLane(IRReg fpr); - int GetFPRLaneCount(IRReg fpr); - - bool IsGPRImm(IRReg gpr); - bool IsGPR2Imm(IRReg base); - uint32_t GetGPRImm(IRReg gpr); - uint64_t GetGPR2Imm(IRReg first); - void SetGPRImm(IRReg gpr, uint32_t immval); - void SetGPR2Imm(IRReg first, uint64_t immval); - - // Protect the native registers containing register froms spilling, to ensure that - // it's being kept allocated. - void SpillLockGPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - void SpillLockFPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - void ReleaseSpillLockGPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - void ReleaseSpillLockFPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - - void MarkGPRDirty(IRReg gpr, bool andNormalized32 = false); - void MarkGPRAsPointerDirty(IRReg gpr); - - bool IsGPRClobbered(IRReg gpr) const; - bool IsFPRClobbered(IRReg gpr) const; - - struct Mapping { - char type = '?'; - IRReg reg = IRREG_INVALID; - uint8_t lanes = 1; - MIPSMap flags = MIPSMap::INIT; - }; - - void Map(const IRInst &inst); - void MapWithExtra(const IRInst &inst, std::vector extra); - virtual void FlushAll(bool gprs = true, bool fprs = true); - -protected: - virtual void SetupInitialRegs(); - virtual const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const = 0; - virtual const StaticAllocation *GetStaticAllocations(int &count) const { - count = 0; - return nullptr; - } - - IRNativeReg AllocateReg(MIPSLoc type, MIPSMap flags); - IRNativeReg FindFreeReg(MIPSLoc type, MIPSMap flags) const; - IRNativeReg FindBestToSpill(MIPSLoc type, MIPSMap flags, bool unusedOnly, bool *clobbered) const; - virtual bool IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes); - virtual void DiscardNativeReg(IRNativeReg nreg); - virtual void FlushNativeReg(IRNativeReg nreg); - virtual void DiscardReg(IRReg mreg); - virtual void FlushReg(IRReg mreg); - virtual void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state); - virtual void MapNativeReg(MIPSLoc type, IRNativeReg nreg, IRReg first, int lanes, MIPSMap flags); - virtual bool TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags); - virtual IRNativeReg MapNativeReg(MIPSLoc type, IRReg first, int lanes, MIPSMap flags); - IRNativeReg MapNativeRegAsPointer(IRReg gpr); - - IRNativeReg MapWithTemp(const IRInst &inst, MIPSLoc type); - - void MappingFromInst(const IRInst &inst, Mapping mapping[3]); - void ApplyMapping(const Mapping *mapping, int count); - void CleanupMapping(const Mapping *mapping, int count); - - // Load data from memory (possibly multiple lanes) into a native reg. - virtual void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) = 0; - // Store data in a native reg back into memory. - virtual void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) = 0; - // Set a native reg to a specific integer value. - virtual void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) = 0; - // Store the imm value for a reg to memory (not currently in a native reg.) - virtual void StoreRegValue(IRReg mreg, uint32_t imm) = 0; - - void SetSpillLockIRIndex(IRReg reg, IRReg reg2, IRReg reg3, IRReg reg4, int offset, int index); - void SetSpillLockIRIndex(IRReg reg, int index); - int GetMipsRegOffset(IRReg r); - - bool IsRegClobbered(MIPSLoc type, IRReg r) const; - bool IsRegRead(MIPSLoc type, IRReg r) const; - IRUsage GetNextRegUsage(const IRSituation &info, MIPSLoc type, IRReg r) const; - - bool IsValidGPR(IRReg r) const; - bool IsValidGPRNoZero(IRReg r) const; - bool IsValidFPR(IRReg r) const; - - MIPSComp::JitOptions *jo_; - const MIPSComp::IRBlock *irBlock_ = nullptr; - int irIndex_ = 0; - - struct { - int totalNativeRegs = 0; - bool mapFPUSIMD = false; - bool mapUseVRegs = false; - } config_; - - RegStatusNative nr[TOTAL_POSSIBLE_NATIVEREGS]; - RegStatusMIPS mr[TOTAL_MAPPABLE_IRREGS]; - RegStatusNative nrInitial_[TOTAL_POSSIBLE_NATIVEREGS]; - RegStatusMIPS mrInitial_[TOTAL_MAPPABLE_IRREGS]; - - bool initialReady_ = false; -}; diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index f8ba2436c..1f0e2e0e2 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -31,7 +31,6 @@ #include "Core/MemMap.h" #include "Core/CoreTiming.h" #include "Core/Reporting.h" -#include "Core/Config.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSTables.h" @@ -84,7 +83,7 @@ JitBlockCache::~JitBlockCache() { Shutdown(); } -bool JitBlock::ContainsAddress(u32 em_address) const { +bool JitBlock::ContainsAddress(u32 em_address) { // WARNING - THIS DOES NOT WORK WITH JIT INLINING ENABLED. // However, that doesn't exist yet so meh. return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize); @@ -247,7 +246,6 @@ static void ExpandRange(std::pair &range, u32 newStart, u32 newEnd) { void JitBlockCache::FinalizeBlock(int block_num, bool block_link) { JitBlock &b = blocks_[block_num]; - _assert_msg_(Memory::IsValidAddress(b.originalAddress), "FinalizeBlock: Bad originalAddress %08x in block %d (b.num: %d) proxy: %s sz: %d", b.originalAddress, block_num, b.blockNum, b.proxyFor ? "y" : "n", b.codeSize); b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); MIPSOpcode opcode = GetEmuHackOpForBlock(block_num); @@ -462,11 +460,6 @@ void JitBlockCache::UnlinkBlock(int i) { if (ppp.first == ppp.second) return; for (auto iter = ppp.first; iter != ppp.second; ++iter) { - if ((size_t)iter->second >= num_blocks_) { - // Something probably went very wrong. Try to stumble along nevertheless. - ERROR_LOG(JIT, "UnlinkBlock: Invalid block number %d", iter->second); - continue; - } JitBlock &sourceBlock = blocks_[iter->second]; for (int e = 0; e < MAX_JIT_BLOCK_EXITS; e++) { if (sourceBlock.exitAddress[e] == b.originalAddress) @@ -695,7 +688,7 @@ JitBlockDebugInfo JitBlockCache::GetBlockDebugInfo(int blockNum) const { debugInfo.originalAddress = block->originalAddress; for (u32 addr = block->originalAddress; addr <= block->originalAddress + block->originalSize * 4; addr += 4) { char temp[256]; - MIPSDisAsm(Memory::Read_Instruction(addr), addr, temp, sizeof(temp), true); + MIPSDisAsm(Memory::Read_Instruction(addr), addr, temp, true); std::string mipsDis = temp; debugInfo.origDisasm.push_back(mipsDis); } diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index 09eae3cc2..71b7df966 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -29,7 +29,7 @@ #include "Core/MIPS/MIPS.h" #if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) -const int MAX_JIT_BLOCK_EXITS = 4; +const int MAX_JIT_BLOCK_EXITS = 2; #else const int MAX_JIT_BLOCK_EXITS = 8; #endif @@ -59,7 +59,7 @@ enum class DestroyType { // We should be careful not to access these block structures during runtime as they are large. // Fine to mess with them at block compile time though. struct JitBlock { - bool ContainsAddress(u32 em_address) const; + bool ContainsAddress(u32 em_address); const u8 *checkedEntry; // const, we have to translate to writable. const u8 *normalEntry; diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index 259b500f0..20a8fb6e7 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -41,14 +41,10 @@ #include "../ARM/ArmJit.h" #elif PPSSPP_ARCH(ARM64) #include "../ARM64/Arm64Jit.h" -#include "../ARM64/Arm64IRJit.h" #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #include "../x86/Jit.h" -#include "../x86/X64IRJit.h" #elif PPSSPP_ARCH(MIPS) #include "../MIPS/MipsJit.h" -#elif PPSSPP_ARCH(RISCV64) -#include "../RiscV/RiscVJit.h" #else #include "../fake/FakeJit.h" #endif @@ -103,21 +99,15 @@ namespace MIPSComp { return notTakenTarget; } - JitInterface *CreateNativeJit(MIPSState *mipsState, bool useIR) { + JitInterface *CreateNativeJit(MIPSState *mipsState) { #if PPSSPP_ARCH(ARM) return new MIPSComp::ArmJit(mipsState); #elif PPSSPP_ARCH(ARM64) - if (useIR) - return new MIPSComp::Arm64IRJit(mipsState); return new MIPSComp::Arm64Jit(mipsState); #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - if (useIR) - return new MIPSComp::X64IRJit(mipsState); return new MIPSComp::Jit(mipsState); #elif PPSSPP_ARCH(MIPS) return new MIPSComp::MipsJit(mipsState); -#elif PPSSPP_ARCH(RISCV64) - return new MIPSComp::RiscVJit(mipsState); #else return new MIPSComp::FakeJit(mipsState); #endif @@ -341,12 +331,12 @@ std::vector DisassembleRV64(const u8 *data, int size) { // Force align in case we're somehow unaligned. len = 2 - ((uintptr_t)data & 1); invalid_count += (int)len; - i += (int)len; + i +=(int) len; continue; } invalid_flush(); - riscv_disasm_inst(temp, sizeof(temp), rv64, (uintptr_t)data + i, inst); + riscv_disasm_inst(temp, sizeof(temp), rv64, i * 4, inst); lines.push_back(ReplaceAll(temp, "\t", " ")); i += (int)len; diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index 2698e026e..b5944c3db 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -54,7 +54,6 @@ namespace MIPSComp { virtual void Comp_RunBlock(MIPSOpcode op) = 0; virtual void Comp_ReplacementFunc(MIPSOpcode op) = 0; virtual void Comp_ITypeMem(MIPSOpcode op) = 0; - virtual void Comp_StoreSync(MIPSOpcode op) = 0; virtual void Comp_Cache(MIPSOpcode op) = 0; virtual void Comp_RelBranch(MIPSOpcode op) = 0; virtual void Comp_RelBranchRI(MIPSOpcode op) = 0; @@ -177,5 +176,5 @@ namespace MIPSComp { void DoDummyJitState(PointerWrap &p); - JitInterface *CreateNativeJit(MIPSState *mipsState, bool useIR); + JitInterface *CreateNativeJit(MIPSState *mipsState); } diff --git a/Core/MIPS/JitCommon/JitState.cpp b/Core/MIPS/JitCommon/JitState.cpp index 9144513cc..00e87913a 100644 --- a/Core/MIPS/JitCommon/JitState.cpp +++ b/Core/MIPS/JitCommon/JitState.cpp @@ -64,10 +64,6 @@ namespace MIPSComp { useStaticAlloc = !Disabled(JitDisable::STATIC_ALLOC); // iOS/etc. may disable at runtime if Memory::base is not nicely aligned. enablePointerify = !Disabled(JitDisable::POINTERIFY); -#endif -#if PPSSPP_ARCH(RISCV64) - // Seems to perform slightly better than a checked entry at the start. - useBackJump = true; #endif } diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index 37acde3b6..48d8f7540 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -77,7 +77,6 @@ namespace MIPSComp { // VFPU prefix magic bool startDefaultPrefix = true; - bool blockWrotePrefixes = false; u32 prefixS; u32 prefixT; u32 prefixD; @@ -234,7 +233,6 @@ namespace MIPSComp { bool downcountInRegister; // ARM64 only bool useASIMDVFPU; - // ARM64 and RV64 bool useStaticAlloc; bool enablePointerify; diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 91223bd63..9efe9fbd1 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -122,7 +122,7 @@ MIPSState::MIPSState() { // * 4x4 Matrices are contiguous in RAM, making them, too, fast-loadable in NEON // Disadvantages: - // * Extra indirection, can be confusing and slower (interpreter only, however we can often skip the table by rerranging formulas) + // * Extra indirection, can be confusing and slower (interpreter only) // * Flushing and reloading row registers is now slower int i = 0; @@ -209,11 +209,13 @@ void MIPSState::Init() { llBit = 0; nextPC = 0; downcount = 0; + // Initialize the VFPU random number generator with .. something? + rng.Init(0x1337); std::lock_guard guard(MIPSComp::jitLock); - if (PSP_CoreParameter().cpuCore == CPUCore::JIT || PSP_CoreParameter().cpuCore == CPUCore::JIT_IR) { - MIPSComp::jit = MIPSComp::CreateNativeJit(this, PSP_CoreParameter().cpuCore == CPUCore::JIT_IR); - } else if (PSP_CoreParameter().cpuCore == CPUCore::IR_INTERPRETER) { + if (PSP_CoreParameter().cpuCore == CPUCore::JIT) { + MIPSComp::jit = MIPSComp::CreateNativeJit(this); + } else if (PSP_CoreParameter().cpuCore == CPUCore::IR_JIT) { MIPSComp::jit = new MIPSComp::IRJit(this); } else { MIPSComp::jit = nullptr; @@ -235,18 +237,17 @@ void MIPSState::UpdateCore(CPUCore desired) { switch (PSP_CoreParameter().cpuCore) { case CPUCore::JIT: - case CPUCore::JIT_IR: - INFO_LOG(CPU, "Switching to JIT%s", PSP_CoreParameter().cpuCore == CPUCore::JIT_IR ? " IR" : ""); + INFO_LOG(CPU, "Switching to JIT"); if (oldjit) { std::lock_guard guard(MIPSComp::jitLock); MIPSComp::jit = nullptr; delete oldjit; } - newjit = MIPSComp::CreateNativeJit(this, PSP_CoreParameter().cpuCore == CPUCore::JIT_IR); + newjit = MIPSComp::CreateNativeJit(this); break; - case CPUCore::IR_INTERPRETER: - INFO_LOG(CPU, "Switching to IR interpreter"); + case CPUCore::IR_JIT: + INFO_LOG(CPU, "Switching to IRJIT"); if (oldjit) { std::lock_guard guard(MIPSComp::jitLock); MIPSComp::jit = nullptr; @@ -270,7 +271,7 @@ void MIPSState::UpdateCore(CPUCore desired) { } void MIPSState::DoState(PointerWrap &p) { - auto s = p.Section("MIPSState", 1, 4); + auto s = p.Section("MIPSState", 1, 3); if (!s) return; @@ -307,12 +308,8 @@ void MIPSState::DoState(PointerWrap &p) { Do(p, fcr0_unused); } Do(p, fcr31); - if (s <= 3) { - uint32_t dummy; - Do(p, dummy); // rng.m_w - Do(p, dummy); // rng.m_z - } - + Do(p, rng.m_w); + Do(p, rng.m_z); Do(p, inDelaySlot); Do(p, llBit); Do(p, debugCount); @@ -333,8 +330,7 @@ void MIPSState::SingleStep() { int MIPSState::RunLoopUntil(u64 globalTicks) { switch (PSP_CoreParameter().cpuCore) { case CPUCore::JIT: - case CPUCore::JIT_IR: - case CPUCore::IR_INTERPRETER: + case CPUCore::IR_JIT: while (inDelaySlot) { // We must get out of the delay slot before going into jit. SingleStep(); diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index dad324609..62dc15020 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -21,6 +21,7 @@ #include +#include "Common/Data/Random/Rng.h" #include "Common/CommonTypes.h" #include "Core/Opcode.h" @@ -228,6 +229,8 @@ public: // Temporary used around delay slots and similar. u64 saved_flags; + GMRng rng; // VFPU hardware random number generator. Probably not the right type. + // Debug stuff u32 debugCount; // can be used to count basic blocks before crashes, etc. diff --git a/Core/MIPS/MIPS/MipsJit.h b/Core/MIPS/MIPS/MipsJit.h index 9026ac185..195579b37 100644 --- a/Core/MIPS/MIPS/MipsJit.h +++ b/Core/MIPS/MIPS/MipsJit.h @@ -62,7 +62,6 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override {} - void Comp_StoreSync(MIPSOpcode op) override {} void Comp_Cache(MIPSOpcode op) override {} void Comp_RelBranch(MIPSOpcode op) override {} diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 1cdeeb00b..c7837e25f 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -16,7 +16,6 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "ppsspp_config.h" -#include #include #include #include @@ -28,7 +27,6 @@ #include "Common/File/FileUtil.h" #include "Common/Log.h" -#include "Common/StringUtils.h" #include "Common/TimeUtil.h" #include "Core/Config.h" #include "Core/MemMap.h" @@ -813,7 +811,7 @@ namespace MIPSAnalyst { break; } - if (reg >= 32) { + if (reg > 32) { return USAGE_UNKNOWN; } @@ -942,10 +940,6 @@ skip: return true; } - // Un named stubs, just in case. - if (!strncmp(name, "[UNK:", strlen("[UNK:"))) - return true; - // Assume any z_un, not just the address, is a default func. return !strncmp(name, "z_un_", strlen("z_un_")) || !strncmp(name, "u_un_", strlen("u_un_")); } @@ -1195,12 +1189,6 @@ skip: } } - bool SkipFuncHash(const std::string &name) { - std::vector funcs; - SplitString(g_Config.sSkipFuncHashMap, ',', funcs); - return std::find(funcs.begin(), funcs.end(), name) != funcs.end(); - } - void RegisterFunction(u32 startAddr, u32 size, const char *name) { std::lock_guard guard(functions_lock); @@ -1208,7 +1196,7 @@ skip: for (auto iter = functions.begin(); iter != functions.end(); iter++) { if (iter->start == startAddr) { // Let's just add it to the hashmap. - if (iter->hasHash && size > 16 && SkipFuncHash(name)) { + if (iter->hasHash && size > 16) { HashMapFunc hfun; hfun.hash = iter->hash; strncpy(hfun.name, name, 64); @@ -1290,7 +1278,7 @@ skip: } // Functions with default names aren't very interesting either. const std::string name = g_symbolMap->GetLabelString(f.start); - if (IsDefaultFunction(name) || SkipFuncHash(name)) { + if (IsDefaultFunction(name)) { continue; } diff --git a/Core/MIPS/MIPSDebugInterface.cpp b/Core/MIPS/MIPSDebugInterface.cpp index 747a9a508..69b3c8e97 100644 --- a/Core/MIPS/MIPSDebugInterface.cpp +++ b/Core/MIPS/MIPSDebugInterface.cpp @@ -22,12 +22,11 @@ #include #endif -#include "Common/StringUtils.h" #include "Core/Debugger/Breakpoints.h" #include "Core/Debugger/SymbolMap.h" #include "Core/Debugger/DebugInterface.h" #include "Core/MIPS/MIPSDebugInterface.h" -#include "Core/MIPS/MIPSVFPUUtils.h" + #include "Core/HLE/sceKernelThread.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPSTables.h" @@ -61,12 +60,12 @@ public: char reg[8]; snprintf(reg, sizeof(reg), "r%d", i); - if (strcasecmp(str, reg) == 0 || strcasecmp(str, cpu->GetRegName(0, i).c_str()) == 0) + if (strcasecmp(str, reg) == 0 || strcasecmp(str, cpu->GetRegName(0, i)) == 0) { referenceIndex = i; return true; } - else if (strcasecmp(str, cpu->GetRegName(1, i).c_str()) == 0) + else if (strcasecmp(str, cpu->GetRegName(1, i)) == 0) { referenceIndex = REF_INDEX_FPU | i; return true; @@ -82,7 +81,7 @@ public: for (int i = 0; i < 128; i++) { - if (strcasecmp(str, cpu->GetRegName(2, i).c_str()) == 0) + if (strcasecmp(str, cpu->GetRegName(2, i)) == 0) { referenceIndex = REF_INDEX_VFPU | i; return true; @@ -160,7 +159,7 @@ public: return EXPR_TYPE_UINT; } - bool getMemoryValue(uint32_t address, int size, uint32_t& dest, std::string *error) override { + bool getMemoryValue(uint32_t address, int size, uint32_t& dest, char* error, size_t errorBufSize) override { // We allow, but ignore, bad access. // If we didn't, log/condition statements that reference registers couldn't be configured. uint32_t valid = Memory::ValidSize(address, size); @@ -180,7 +179,7 @@ public: return true; } - *error = StringFromFormat("Unexpected memory access size %d", size); + snprintf(error, errorBufSize, "Unexpected memory access size %d", size); return false; } @@ -190,11 +189,14 @@ private: -void MIPSDebugInterface::DisAsm(u32 pc, char *out, size_t outSize) { - if (Memory::IsValidAddress(pc)) - MIPSDisAsm(Memory::Read_Opcode_JIT(pc), pc, out, outSize); +const char *MIPSDebugInterface::disasm(unsigned int address, unsigned int align) +{ + static char mojs[256]; + if (Memory::IsValidAddress(address)) + MIPSDisAsm(Memory::Read_Opcode_JIT(address), address, mojs); else - truncate_cpy(out, outSize, "-"); + strcpy(mojs, "-"); + return mojs; } unsigned int MIPSDebugInterface::readMemory(unsigned int address) { @@ -262,7 +264,9 @@ const char *MIPSDebugInterface::GetName() return ("R4"); } -std::string MIPSDebugInterface::GetRegName(int cat, int index) { +// NOT threadsafe. +const char *MIPSDebugInterface::GetRegName(int cat, int index) +{ static const char *regName[32] = { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", @@ -273,20 +277,23 @@ std::string MIPSDebugInterface::GetRegName(int cat, int index) { "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" }; - static const char *fpRegName[32] = { - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", - "f16", "f16", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", - }; - if (cat == 0 && (unsigned)index < sizeof(regName)) { + // really nasty hack so that this function can be called several times on one line of c++. + static int access = 0; + access++; + access &= 3; + static char temp[4][16]; + + if (cat == 0) { return regName[index]; - } else if (cat == 1 && (unsigned)index < sizeof(fpRegName)) { - return fpRegName[index]; + } else if (cat == 1) { + snprintf(temp[access], sizeof(temp[access]), "f%d", index); + return temp[access]; } else if (cat == 2) { - return GetVectorNotation(index, V_Single); + snprintf(temp[access], sizeof(temp[access]), "v%03x", index); + return temp[access]; + } else { + return "???"; } - return "???"; } diff --git a/Core/MIPS/MIPSDebugInterface.h b/Core/MIPS/MIPSDebugInterface.h index 6d5cec88a..36651c2f1 100644 --- a/Core/MIPS/MIPSDebugInterface.h +++ b/Core/MIPS/MIPSDebugInterface.h @@ -28,6 +28,7 @@ class MIPSDebugInterface : public DebugInterface MIPSState *cpu; public: MIPSDebugInterface(MIPSState *_cpu) { cpu = _cpu; } + const char *disasm(unsigned int address, unsigned int align) override; int getInstructionSize(int instruction) override { return 4; } bool isAlive() override; bool isBreakpoint(unsigned int address) override; @@ -50,7 +51,6 @@ public: u32 GetGPR32Value(int reg) override { return cpu->r[reg]; } u32 GetPC() override { return cpu->pc; } u32 GetLR() override { return cpu->r[MIPS_REG_RA]; } - void DisAsm(u32 pc, char *out, size_t outSize) override; void SetPC(u32 _pc) override { cpu->pc = _pc; } const char *GetCategoryName(int cat) override { @@ -62,7 +62,7 @@ public: static int r[3] = { 32, 32, 128 }; return r[cat]; } - std::string GetRegName(int cat, int index) override; + const char *GetRegName(int cat, int index) override; void PrintRegValue(int cat, int index, char *out, size_t outSize) override { switch (cat) { diff --git a/Core/MIPS/MIPSDis.cpp b/Core/MIPS/MIPSDis.cpp index a9784635d..81eac961f 100644 --- a/Core/MIPS/MIPSDis.cpp +++ b/Core/MIPS/MIPSDis.cpp @@ -16,7 +16,6 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include -#include "Common/StringUtils.h" #include "Core/HLE/HLE.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" @@ -34,14 +33,18 @@ #define _POS ((op>>6 ) & 0x1F) #define _SIZE ((op>>11) & 0x1F) -#define RN(i) (currentDebugMIPS->GetRegName(0, i).c_str()) -#define FN(i) (currentDebugMIPS->GetRegName(1, i).c_str()) -//#define VN(i) (currentDebugMIPS->GetRegName(2, i).c_str()) +#define RN(i) currentDebugMIPS->GetRegName(0,i) +#define FN(i) currentDebugMIPS->GetRegName(1,i) +//#define VN(i) currentMIPS->GetRegName(2,i) + +u32 disPC; namespace MIPSDis { - std::string SignedHex(int i) { - char temp[32]; + // One shot, not re-entrant. + const char *SignedHex(int i) + { + static char temp[32]; int offset = 0; if (i < 0) { @@ -50,96 +53,108 @@ namespace MIPSDis i = -i; } - snprintf(&temp[offset], sizeof(temp) - offset, "0x%X", i); + sprintf(&temp[offset], "0x%X", i); return temp; } - void Dis_Generic(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - snprintf(out, outSize, "%s\t --- unknown ---", MIPSGetName(op)); + void Dis_Generic(MIPSOpcode op, char *out) + { + sprintf(out, "%s\t --- unknown ---", MIPSGetName(op)); } - void Dis_Cache(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Cache(MIPSOpcode op, char *out) + { int imm = SignExtend16ToS32(op & 0xFFFF); int rs = _RS; int func = (op >> 16) & 0x1F; - snprintf(out, outSize, "%s\tfunc=%i, %s(%s)", MIPSGetName(op), func, RN(rs), SignedHex(imm).c_str()); + sprintf(out, "%s\tfunc=%i, %s(%s)", MIPSGetName(op), func, RN(rs), SignedHex(imm)); } - void Dis_mxc1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_mxc1(MIPSOpcode op, char *out) + { int fs = _FS; int rt = _RT; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, RN(rt), FN(fs)); + sprintf(out, "%s\t%s, %s",name,RN(rt),FN(fs)); } - void Dis_FPU3op(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_FPU3op(MIPSOpcode op, char *out) + { int ft = _FT; int fs = _FS; int fd = _FD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s, %s", name, FN(fd), FN(fs), FN(ft)); + sprintf(out, "%s\t%s, %s, %s",name,FN(fd),FN(fs),FN(ft)); } - void Dis_FPU2op(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_FPU2op(MIPSOpcode op, char *out) + { int fs = _FS; int fd = _FD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, FN(fd), FN(fs)); + sprintf(out, "%s\t%s, %s",name,FN(fd),FN(fs)); } - void Dis_FPULS(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_FPULS(MIPSOpcode op, char *out) + { int offset = SignExtend16ToS32(op & 0xFFFF); int ft = _FT; int rs = _RS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s(%s)", name, FN(ft), SignedHex(offset).c_str(), RN(rs)); + sprintf(out, "%s\t%s, %s(%s)",name,FN(ft),SignedHex(offset),RN(rs)); } - - void Dis_FPUComp(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_FPUComp(MIPSOpcode op, char *out) + { int fs = _FS; int ft = _FT; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, FN(fs), FN(ft)); + sprintf(out, "%s\t%s, %s",name,FN(fs),FN(ft)); } - void Dis_FPUBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - u32 off = pc; + void Dis_FPUBranch(MIPSOpcode op, char *out) + { + u32 off = disPC; int imm = SignExtend16ToS32(op & 0xFFFF) << 2; off += imm + 4; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t->$%08x", name, off); + sprintf(out, "%s\t->$%08x",name,off); } - void Dis_RelBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - u32 off = pc; + void Dis_RelBranch(MIPSOpcode op, char *out) + { + u32 off = disPC; int imm = SignExtend16ToS32(op & 0xFFFF) << 2; int rs = _RS; off += imm + 4; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, ->$%08x", name, RN(rs), off); + sprintf(out, "%s\t%s, ->$%08x", name, RN(rs), off); } - void Dis_Syscall(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Syscall(MIPSOpcode op, char *out) + { u32 callno = (op>>6) & 0xFFFFF; //20 bits int funcnum = callno & 0xFFF; int modulenum = (callno & 0xFF000) >> 12; - snprintf(out, outSize, "syscall\t %s", GetFuncName(modulenum, funcnum)); + sprintf(out, "syscall\t %s",/*PSPHLE::GetModuleName(modulenum),*/GetFuncName(modulenum, funcnum)); } - void Dis_ToHiloTransfer(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_ToHiloTransfer(MIPSOpcode op, char *out) + { int rs = _RS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s", name, RN(rs)); + sprintf(out, "%s\t%s",name,RN(rs)); } - void Dis_FromHiloTransfer(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_FromHiloTransfer(MIPSOpcode op, char *out) + { int rd = _RD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s", name, RN(rd)); + sprintf(out, "%s\t%s",name,RN(rd)); } - void Dis_RelBranch2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - u32 off = pc; + void Dis_RelBranch2(MIPSOpcode op, char *out) + { + u32 off = disPC; int imm = SignExtend16ToS32(op & 0xFFFF) << 2; int rt = _RT; int rs = _RS; @@ -148,14 +163,15 @@ namespace MIPSDis const char *name = MIPSGetName(op); int o = op>>26; if (o==4 && rs == rt)//beq - snprintf(out, outSize, "b\t->$%08x", off); + sprintf(out, "b\t->$%08x", off); else if (o==20 && rs == rt)//beql - snprintf(out, outSize, "bl\t->$%08x", off); + sprintf(out, "bl\t->$%08x", off); else - snprintf(out, outSize, "%s\t%s, %s, ->$%08x", name, RN(rs), RN(rt), off); + sprintf(out, "%s\t%s, %s, ->$%08x", name, RN(rs), RN(rt), off); } - void Dis_IType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_IType(MIPSOpcode op, char *out) + { u32 uimm = op & 0xFFFF; u32 suimm = SignExtend16ToU32(op); s32 simm = SignExtend16ToS32(op); @@ -168,114 +184,127 @@ namespace MIPSDis case 8: //addi case 9: //addiu case 10: //slti - snprintf(out, outSize, "%s\t%s, %s, %s", name, RN(rt), RN(rs), SignedHex(simm).c_str()); + sprintf(out, "%s\t%s, %s, %s",name,RN(rt),RN(rs),SignedHex(simm)); break; case 11: //sltiu - snprintf(out, outSize, "%s\t%s, %s, 0x%X", name, RN(rt), RN(rs), suimm); + sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),suimm); break; default: - snprintf(out, outSize, "%s\t%s, %s, 0x%X", name, RN(rt), RN(rs), uimm); + sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),uimm); break; } } - void Dis_ori(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_ori(MIPSOpcode op, char *out) + { u32 uimm = op & 0xFFFF; int rt = _RT; int rs = _RS; const char *name = MIPSGetName(op); if (rs == 0) - snprintf(out, outSize, "li\t%s, 0x%X", RN(rt), uimm); + sprintf(out, "li\t%s, 0x%X",RN(rt),uimm); else - snprintf(out, outSize, "%s\t%s, %s, 0x%X", name, RN(rt), RN(rs), uimm); + sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),uimm); } - void Dis_IType1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_IType1(MIPSOpcode op, char *out) + { u32 uimm = op & 0xFFFF; int rt = _RT; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, 0x%X", name, RN(rt), uimm); + sprintf(out, "%s\t%s, 0x%X",name,RN(rt),uimm); } - void Dis_addi(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_addi(MIPSOpcode op, char *out) + { int imm = SignExtend16ToS32(op & 0xFFFF); int rt = _RT; int rs = _RS; if (rs == 0) - snprintf(out, outSize, "li\t%s, %s", RN(rt), SignedHex(imm).c_str()); + sprintf(out, "li\t%s, %s",RN(rt),SignedHex(imm)); else - Dis_IType(op, pc, out, outSize); + Dis_IType(op,out); } - void Dis_ITypeMem(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_ITypeMem(MIPSOpcode op, char *out) + { int imm = SignExtend16ToS32(op & 0xFFFF); int rt = _RT; int rs = _RS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s(%s)", name, RN(rt), SignedHex(imm).c_str(), RN(rs)); + sprintf(out, "%s\t%s, %s(%s)",name,RN(rt),SignedHex(imm),RN(rs)); } - void Dis_RType2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_RType2(MIPSOpcode op, char *out) + { int rs = _RS; int rd = _RD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, RN(rd), RN(rs)); + sprintf(out, "%s\t%s, %s",name,RN(rd),RN(rs)); } - void Dis_RType3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_RType3(MIPSOpcode op, char *out) + { int rt = _RT; int rs = _RS; int rd = _RD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s, %s", name, RN(rd), RN(rs), RN(rt)); + sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rs),RN(rt)); } - void Dis_addu(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_addu(MIPSOpcode op, char *out) + { int rt = _RT; int rs = _RS; int rd = _RD; const char *name = MIPSGetName(op); if (rs==0 && rt==0) - snprintf(out, outSize, "li\t%s, 0", RN(rd)); + sprintf(out,"li\t%s, 0",RN(rd)); else if (rs == 0) - snprintf(out, outSize, "move\t%s, %s", RN(rd), RN(rt)); + sprintf(out,"move\t%s, %s",RN(rd),RN(rt)); else if (rt == 0) - snprintf(out, outSize, "move\t%s, %s", RN(rd), RN(rs)); + sprintf(out,"move\t%s, %s",RN(rd),RN(rs)); else - snprintf(out, outSize, "%s\t%s, %s, %s", name, RN(rd), RN(rs), RN(rt)); + sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rs),RN(rt)); } - void Dis_ShiftType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_ShiftType(MIPSOpcode op, char *out) + { int rt = _RT; int rs = _RS; int rd = _RD; - int sa = (op>>6) & 0x1F; + int sa = (op>>6) & 0x1F; const char *name = MIPSGetName(op); if (((op & 0x3f) == 2) && rs == 1) name = "rotr"; if (((op & 0x3f) == 6) && sa == 1) name = "rotrv"; - snprintf(out, outSize, "%s\t%s, %s, 0x%X", name, RN(rd), RN(rt), sa); + sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rd),RN(rt),sa); } - void Dis_VarShiftType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VarShiftType(MIPSOpcode op, char *out) + { int rt = _RT; int rs = _RS; int rd = _RD; - int sa = (op>>6) & 0x1F; + int sa = (op>>6) & 0x1F; const char *name = MIPSGetName(op); if (((op & 0x3f) == 6) && sa == 1) name = "rotrv"; - snprintf(out, outSize, "%s\t%s, %s, %s", name, RN(rd), RN(rt), RN(rs)); + sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rt),RN(rs)); } - void Dis_MulDivType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + + void Dis_MulDivType(MIPSOpcode op, char *out) + { int rt = _RT; int rs = _RS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, RN(rs), RN(rt)); + sprintf(out, "%s\t%s, %s",name,RN(rs),RN(rt)); } - void Dis_Special3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + + void Dis_Special3(MIPSOpcode op, char *out) + { int rs = _RS; int Rt = _RT; int pos = _POS; @@ -286,67 +315,77 @@ namespace MIPSDis case 0x0: //ext { int size = _SIZE + 1; - snprintf(out, outSize, "%s\t%s, %s, 0x%X, 0x%X", name, RN(Rt), RN(rs), pos, size); + sprintf(out,"%s\t%s, %s, 0x%X, 0x%X",name,RN(Rt),RN(rs),pos,size); } break; case 0x4: // ins { int size = (_SIZE + 1) - pos; - snprintf(out, outSize, "%s\t%s, %s, 0x%X, 0x%X", name, RN(Rt), RN(rs), pos, size); + sprintf(out,"%s\t%s, %s, 0x%X, 0x%X",name,RN(Rt),RN(rs),pos,size); } break; } } - void Dis_JumpType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_JumpType(MIPSOpcode op, char *out) + { u32 off = ((op & 0x03FFFFFF) << 2); - u32 addr = (pc & 0xF0000000) | off; + u32 addr = (disPC & 0xF0000000) | off; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t->$%08x", name, addr); + sprintf(out, "%s\t->$%08x",name,addr); } - void Dis_JumpRegType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_JumpRegType(MIPSOpcode op, char *out) + { int rs = _RS; int rd = _RD; const char *name = MIPSGetName(op); if ((op & 0x3f) == 9 && rd != MIPS_REG_RA) - snprintf(out, outSize, "%s\t%s,->%s", name, RN(rd), RN(rs)); + sprintf(out, "%s\t%s,->%s", name, RN(rd), RN(rs)); else - snprintf(out, outSize, "%s\t->%s", name, RN(rs)); + sprintf(out, "%s\t->%s", name, RN(rs)); } - void Dis_Allegrex(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Allegrex(MIPSOpcode op, char *out) + { int rt = _RT; int rd = _RD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s,%s", name, RN(rd), RN(rt)); + sprintf(out,"%s\t%s,%s",name,RN(rd),RN(rt)); } - void Dis_Allegrex2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Allegrex2(MIPSOpcode op, char *out) + { int rt = _RT; int rd = _RD; const char *name = MIPSGetName(op); - snprintf(out, outSize,"%s\t%s,%s", name, RN(rd), RN(rt)); + sprintf(out,"%s\t%s,%s",name,RN(rd),RN(rt)); } - void Dis_Emuhack(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - auto resolved = Memory::Read_Instruction(pc, true); - char disasm[256]; + void Dis_Emuhack(MIPSOpcode op, char *out) + { + auto resolved = Memory::Read_Instruction(disPC, true); + union { + char disasm[256]; + char truncated[241]; + }; if (MIPS_IS_EMUHACK(resolved)) { - truncate_cpy(disasm, sizeof(disasm), "(invalid emuhack)"); + strcpy(disasm, "(invalid emuhack)"); } else { - MIPSDisAsm(resolved, pc, disasm, sizeof(disasm), true); + MIPSDisAsm(resolved, disPC, disasm, true); } + // Truncate in case it was too long, just to avoid warnings. + truncated[240] = '\0'; switch (op.encoding >> 24) { case 0x68: - snprintf(out, outSize, "* jitblock: %s", disasm); + snprintf(out, 256, "* jitblock: %s", truncated); break; case 0x6a: - snprintf(out, outSize, "* replacement: %s", disasm); + snprintf(out, 256, "* replacement: %s", truncated); break; default: - snprintf(out, outSize, "* (invalid): %s", disasm); + snprintf(out, 256, "* (invalid): %s", truncated); break; } } diff --git a/Core/MIPS/MIPSDis.h b/Core/MIPS/MIPSDis.h index 464ec6d87..8ac177fcb 100644 --- a/Core/MIPS/MIPSDis.h +++ b/Core/MIPS/MIPSDis.h @@ -20,42 +20,44 @@ #include "Common/CommonTypes.h" #include "Core/MIPS/MIPS.h" +extern u32 disPC; + namespace MIPSDis { - void Dis_Unknown(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Unimpl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Syscall(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_Unknown(MIPSOpcode op, char *out); + void Dis_Unimpl(MIPSOpcode op, char *out); + void Dis_Syscall(MIPSOpcode op, char *out); - void Dis_mxc1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_addi(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_addu(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_RelBranch2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_RelBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Generic(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Cache(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_IType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_IType1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_ITypeMem(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_RType2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_RType3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_MulDivType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_ShiftType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VarShiftType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_FPU3op(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_FPU2op(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_FPULS(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_FPUComp(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_FPUBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_ori(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Special3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_mxc1(MIPSOpcode op, char *out); + void Dis_addi(MIPSOpcode op, char *out); + void Dis_addu(MIPSOpcode op, char *out); + void Dis_RelBranch2(MIPSOpcode op, char *out); + void Dis_RelBranch(MIPSOpcode op, char *out); + void Dis_Generic(MIPSOpcode op, char *out); + void Dis_Cache(MIPSOpcode op, char *out); + void Dis_IType(MIPSOpcode op, char *out); + void Dis_IType1(MIPSOpcode op, char *out); + void Dis_ITypeMem(MIPSOpcode op, char *out); + void Dis_RType2(MIPSOpcode op, char *out); + void Dis_RType3(MIPSOpcode op, char *out); + void Dis_MulDivType(MIPSOpcode op, char *out); + void Dis_ShiftType(MIPSOpcode op, char *out); + void Dis_VarShiftType(MIPSOpcode op, char *out); + void Dis_FPU3op(MIPSOpcode op, char *out); + void Dis_FPU2op(MIPSOpcode op, char *out); + void Dis_FPULS(MIPSOpcode op, char *out); + void Dis_FPUComp(MIPSOpcode op, char *out); + void Dis_FPUBranch(MIPSOpcode op, char *out); + void Dis_ori(MIPSOpcode op, char *out); + void Dis_Special3(MIPSOpcode op, char *out); - void Dis_ToHiloTransfer(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_FromHiloTransfer(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_JumpType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_JumpRegType(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_ToHiloTransfer(MIPSOpcode op, char *out); + void Dis_FromHiloTransfer(MIPSOpcode op, char *out); + void Dis_JumpType(MIPSOpcode op, char *out); + void Dis_JumpRegType(MIPSOpcode op, char *out); - void Dis_Allegrex(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Allegrex2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_Allegrex(MIPSOpcode op, char *out); + void Dis_Allegrex2(MIPSOpcode op, char *out); - void Dis_Emuhack(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_Emuhack(MIPSOpcode op, char *out); } diff --git a/Core/MIPS/MIPSDisVFPU.cpp b/Core/MIPS/MIPSDisVFPU.cpp index b3116a8b4..a39bd4e20 100644 --- a/Core/MIPS/MIPSDisVFPU.cpp +++ b/Core/MIPS/MIPSDisVFPU.cpp @@ -17,7 +17,6 @@ #include #include "Common/Data/Convert/SmallDataConvert.h" -#include "Common/StringUtils.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSDis.h" #include "Core/MIPS/MIPSTables.h" @@ -34,9 +33,9 @@ #define _SIZE ((op>>11) & 0x1F) -#define RN(i) (currentDebugMIPS->GetRegName(0, i).c_str()) -#define FN(i) (currentDebugMIPS->GetRegName(1, i).c_str()) -//#define VN(i) (currentDebugMIPS->GetRegName(2, i).c_str()) +#define RN(i) currentDebugMIPS->GetRegName(0,i) +#define FN(i) currentDebugMIPS->GetRegName(1,i) +//#define VN(i) currentDebugMIPS->GetRegName(2,i) #define S_not(a,b,c) (a<<2)|(b)|(c<<5) @@ -48,7 +47,8 @@ #define VertOff 1 #define MtxOff 4 -inline std::string VNStr(int v, VectorSize size) { +inline const char *VN(int v, VectorSize size) +{ static const char *vfpuCtrlNames[VFPU_CTRL_MAX] = { "SPFX", "TPFX", @@ -76,13 +76,11 @@ inline std::string VNStr(int v, VectorSize size) { return GetVectorNotation(v, size); } -inline std::string MNStr(int v, MatrixSize size) { +inline const char *MN(int v, MatrixSize size) +{ return GetMatrixNotation(v, size); } -#define VN(v, s) (VNStr(v, s).c_str()) -#define MN(v, s) (MNStr(v, s).c_str()) - inline const char *VSuff(MIPSOpcode op) { int a = (op>>7)&1; @@ -100,62 +98,67 @@ inline const char *VSuff(MIPSOpcode op) namespace MIPSDis { - std::string SignedHex(int i); + const char *SignedHex(int i); - void Dis_SV(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_SV(MIPSOpcode op, char *out) + { int offset = SignExtend16ToS32(op & 0xFFFC); int vt = ((op>>16)&0x1f)|((op&3)<<5); int rs = (op>>21) & 0x1f; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s(%s)", name, VN(vt, V_Single), SignedHex(offset).c_str(), RN(rs)); + sprintf(out, "%s\t%s, %s(%s)", name, VN(vt, V_Single), SignedHex(offset), RN(rs)); } - void Dis_SVQ(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_SVQ(MIPSOpcode op, char *out) + { int offset = SignExtend16ToS32(op & 0xFFFC); int vt = (((op>>16)&0x1f))|((op&1)<<5); int rs = (op>>21) & 0x1f; const char *name = MIPSGetName(op); - size_t outpos = 0; - outpos += snprintf(out, outSize, "%s\t%s, %s(%s)", name, VN(vt, V_Quad), SignedHex(offset).c_str(), RN(rs)); - if ((op & 2) && outpos < outSize) - truncate_cpy(out + outpos, outSize - outpos, ", wb"); + sprintf(out, "%s\t%s, %s(%s)", name, VN(vt, V_Quad), SignedHex(offset), RN(rs)); + if (op & 2) + strcat(out, ", wb"); } - void Dis_SVLRQ(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_SVLRQ(MIPSOpcode op, char *out) + { int offset = SignExtend16ToS32(op & 0xFFFC); int vt = (((op>>16)&0x1f))|((op&1)<<5); int rs = (op>>21) & 0x1f; int lr = (op>>1)&1; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s.q\t%s, %s(%s)", name, lr ? "r" : "l", VN(vt, V_Quad), SignedHex(offset).c_str(), RN(rs)); + sprintf(out, "%s%s.q\t%s, %s(%s)", name, lr ? "r" : "l", VN(vt, V_Quad), SignedHex(offset), RN(rs)); } - void Dis_Mftv(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Mftv(MIPSOpcode op, char *out) + { int vr = op & 0xFF; int rt = _RT; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, vr > 127 ? "c" : "", RN(rt), VN(vr, V_Single)); + sprintf(out, "%s%s\t%s, %s",name,vr>127?"c":"", RN(rt), VN(vr, V_Single)); } - void Dis_Vmfvc(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vmfvc(MIPSOpcode op, char *out) + { int vd = _VD; int vr = (op >> 8) & 0x7F; const char* name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, VN(vd, V_Single), VN(vr + 128, V_Single)); + sprintf(out, "%s\t%s, %s", name, VN(vd, V_Single), VN(vr + 128, V_Single)); } - void Dis_Vmtvc(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vmtvc(MIPSOpcode op, char *out) + { int vr = op & 0x7F; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t%s, %s", name, VN(vs, V_Single), VN(vr + 128, V_Single)); + sprintf(out, "%s\t%s, %s", name, VN(vs, V_Single), VN(vr + 128, V_Single)); } - void Dis_VPFXST(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VPFXST(MIPSOpcode op, char *out) + { int data = op & 0xFFFFF; const char *name = MIPSGetName(op); - size_t outpos = snprintf(out, outSize, "%s\t[", name); - + sprintf(out, "%s\t[",name); static const char *regnam[4] = {"X","Y","Z","W"}; static const char *constan[8] = {"0","1","2","1/2","3","1/3","1/4","1/6"}; for (int i=0; i<4; i++) @@ -164,70 +167,71 @@ namespace MIPSDis int abs = (data>>(8+i)) & 1; int negate = (data>>(16+i)) & 1; int constants = (data>>(12+i)) & 1; - if (negate && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, "-"); - if (abs && !constants && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, "|"); - if (!constants) { - if (outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, regnam[regnum]); - } else { + if (negate) + strcat(out, "-"); + if (abs && !constants) + strcat(out, "|"); + if (!constants) + { + strcat(out, regnam[regnum]); + } + else + { if (abs) regnum+=4; - if (outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, constan[regnum]); + strcat(out, constan[regnum]); } - if (abs && !constants && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, "|"); - if (i != 3 && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, ","); + if (abs && !constants) + strcat(out, "|"); + if (i != 3) + strcat(out, ","); } - if (outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, "]"); + strcat(out, "]"); } - void Dis_VPFXD(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VPFXD(MIPSOpcode op, char *out) + { int data = op & 0xFFFFF; const char *name = MIPSGetName(op); - size_t outpos = snprintf(out, outSize, "%s\t[", name); - + sprintf(out, "%s\t[", name); static const char *satNames[4] = {"", "0:1", "X", "-1:1"}; for (int i=0; i<4; i++) { int sat = (data>>i*2)&3; int mask = (data>>(8+i))&1; - if (sat && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, satNames[sat]); - if (mask && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, "M"); - if (i < 4 - 1 && outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, ","); + if (sat) + strcat(out, satNames[sat]); + if (mask) + strcat(out, "M"); + if (i < 4 - 1) + strcat(out, ","); } - if (outpos < outSize) - outpos += truncate_cpy(out + outpos, outSize - outpos, "]"); + strcat(out, "]"); } - void Dis_Viim(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Viim(MIPSOpcode op, char *out) + { int vt = _VT; int imm = SignExtend16ToS32(op & 0xFFFF); const char *name = MIPSGetName(op); int type = (op >> 23) & 7; if (type == 6) - snprintf(out, outSize, "%s\t%s, %i", name, VN(vt, V_Single), imm); + sprintf(out, "%s\t%s, %i", name, VN(vt, V_Single), imm); else if (type == 7) - snprintf(out, outSize, "%s\t%s, %f", name, VN(vt, V_Single), Float16ToFloat32((u16)imm)); + sprintf(out, "%s\t%s, %f", name, VN(vt, V_Single), Float16ToFloat32((u16)imm)); else - snprintf(out, outSize, "%s\tARGH", name); + sprintf(out, "%s\tARGH", name); } - void Dis_Vcst(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vcst(MIPSOpcode op, char *out) + { int conNum = (op>>16) & 0x1f; int vd = _VD; - VectorSize sz = GetVecSize(op); + VectorSize sz = GetVecSizeSafe(op); static const char *constants[32] = { "(undef)", @@ -254,171 +258,188 @@ namespace MIPSDis const char *name = MIPSGetName(op); const char *c = constants[conNum]; if (c==0) c = constants[0]; - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd,sz), c); + sprintf(out,"%s%s\t%s, %s",name,VSuff(op),VN(vd,sz), c); } - void Dis_MatrixSet1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_MatrixSet1(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; - MatrixSize sz = GetMtxSize(op); - snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), MN(vd, sz)); + MatrixSize sz = GetMtxSizeSafe(op); + sprintf(out, "%s%s\t%s",name,VSuff(op),MN(vd, sz)); } - void Dis_MatrixSet2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_MatrixSet2(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; - MatrixSize sz = GetMtxSize(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), MN(vd, sz), MN(vs,sz)); + MatrixSize sz = GetMtxSizeSafe(op); + sprintf(out, "%s%s\t%s, %s",name,VSuff(op),MN(vd, sz),MN(vs,sz)); } - void Dis_MatrixSet3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_MatrixSet3(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; int vt = _VT; - MatrixSize sz = GetMtxSize(op); - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(vs,sz), MN(vt,sz)); + MatrixSize sz = GetMtxSizeSafe(op); + sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),MN(vd, sz),MN(vs,sz),MN(vt,sz)); } - void Dis_MatrixMult(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_MatrixMult(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; int vt = _VT; - MatrixSize sz = GetMtxSize(op); + MatrixSize sz = GetMtxSizeSafe(op); // TODO: Xpose? - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(Xpose(vs),sz), MN(vt,sz)); + sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),MN(vd, sz),MN(Xpose(vs),sz),MN(vt,sz)); } - void Dis_Vmscl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vmscl(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; int vt = _VT; - MatrixSize sz = GetMtxSize(op); - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(vs, sz), VN(vt, V_Single)); + MatrixSize sz = GetMtxSizeSafe(op); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(vs, sz), VN(vt, V_Single)); } - void Dis_VectorDot(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VectorDot(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; int vt = _VT; - VectorSize sz = GetVecSize(op); - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz), VN(vt, sz)); + VectorSize sz = GetVecSizeSafe(op); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz), VN(vt, sz)); } - void Dis_Vtfm(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vtfm(MIPSOpcode op, char *out) + { int vd = _VD; int vs = _VS; int vt = _VT; int ins = (op>>23) & 7; - VectorSize sz = GetVecSize(op); - MatrixSize msz = GetMtxSize(op); + VectorSize sz = GetVecSizeSafe(op); + MatrixSize msz = GetMtxSizeSafe(op); int n = GetNumVectorElements(sz); if (n == ins) { //homogenous - snprintf(out, outSize, "vhtfm%i%s\t%s, %s, %s", n, VSuff(op), VN(vd, sz), MN(vs, msz), VN(vt, sz)); + sprintf(out, "vhtfm%i%s\t%s, %s, %s", n, VSuff(op), VN(vd, sz), MN(vs, msz), VN(vt, sz)); } else if (n == ins+1) { - snprintf(out, outSize, "vtfm%i%s\t%s, %s, %s", n, VSuff(op), VN(vd, sz), MN(vs, msz), VN(vt, sz)); + sprintf(out, "vtfm%i%s\t%s, %s, %s", n, VSuff(op), VN(vd, sz), MN(vs, msz), VN(vt, sz)); } else { - truncate_cpy(out, outSize, "BADVTFM"); + sprintf(out,"BADVTFM"); } } - void Dis_Vflush(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - truncate_cpy(out, outSize, "vflush"); + void Dis_Vflush(MIPSOpcode op, char *out) + { + sprintf(out,"vflush"); } - void Dis_Vcrs(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vcrs(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vt = _VT; int vs = _VS; int vd = _VD; - VectorSize sz = GetVecSize(op); + VectorSize sz = GetVecSizeSafe(op); if (sz != V_Triple) { - truncate_cpy(out, outSize, "vcrs\tERROR"); + sprintf(out, "vcrs\tERROR"); } else - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz), VN(vt,sz)); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz), VN(vt,sz)); } - void Dis_Vcmp(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vcmp(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vt = _VT; int vs = _VS; int cond = op&15; - VectorSize sz = GetVecSize(op); + VectorSize sz = GetVecSizeSafe(op); const char *condNames[16] = {"FL","EQ","LT","LE","TR","NE","GE","GT","EZ","EN","EI","ES","NZ","NN","NI","NS"}; - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), condNames[cond], VN(vs, sz), VN(vt,sz)); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), condNames[cond], VN(vs, sz), VN(vt,sz)); } - void Dis_Vcmov(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vcmov(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); - VectorSize sz = GetVecSize(op); + VectorSize sz = GetVecSizeSafe(op); int vd = _VD; int vs = _VS; int tf = (op >> 19)&3; int imm3 = (op>>16)&7; if (tf > 1) { - snprintf(out, outSize, "%s\tARGH%i", name, tf); + sprintf(out, "%s\tARGH%i", name, tf); return; } if (imm3<6) - snprintf(out, outSize, "%s%s%s\t%s, %s, CC[%i]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz), imm3); + sprintf(out, "%s%s%s\t%s, %s, CC[%i]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz), imm3); else if (imm3 == 6) - snprintf(out, outSize, "%s%s%s\t%s, %s, CC[...]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz)); + sprintf(out, "%s%s%s\t%s, %s, CC[...]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz)); } - void Dis_Vfad(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vfad(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; - VectorSize sz = GetVecSize(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz)); + VectorSize sz = GetVecSizeSafe(op); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz)); } - void Dis_VScl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VScl(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; int vt = _VT; - VectorSize sz = GetVecSize(op); - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, V_Single)); + VectorSize sz = GetVecSizeSafe(op); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, V_Single)); } - void Dis_VectorSet1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VectorSet1(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; - VectorSize sz = GetVecSize(op); - snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), VN(vd, sz)); + VectorSize sz = GetVecSizeSafe(op); + sprintf(out, "%s%s\t%s",name,VSuff(op),VN(vd, sz)); } - void Dis_VectorSet2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VectorSet2(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; - VectorSize sz = GetVecSize(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz)); + VectorSize sz = GetVecSizeSafe(op); + sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, sz),VN(vs, sz)); } - void Dis_VectorSet3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VectorSet3(MIPSOpcode op, char *out) + { const char *name = MIPSGetName(op); int vd = _VD; int vs = _VS; int vt = _VT; - VectorSize sz = GetVecSize(op); - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz)); + VectorSize sz = GetVecSizeSafe(op); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz)); } - void Dis_VRot(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_VRot(MIPSOpcode op, char *out) + { int vd = _VD; int vs = _VS; int imm = (op>>16) & 0x1f; @@ -432,7 +453,7 @@ namespace MIPSDis } c[(imm>>2) & 3] = 'S'; c[imm&3] = 'C'; - VectorSize sz = GetVecSize(op); + VectorSize sz = GetVecSizeSafe(op); int numElems = GetNumVectorElements(sz); int pos = 0; temp[pos++] = '['; @@ -447,11 +468,12 @@ namespace MIPSDis temp[pos++] = ']'; temp[pos]=0; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs, V_Single),temp); + sprintf(out, "%s%s\t%s, %s, %s",name,VSuff(op),VN(vd, sz),VN(vs, V_Single),temp); } - void Dis_CrossQuat(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_CrossQuat(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); const char *name; switch (sz) { @@ -471,36 +493,40 @@ namespace MIPSDis int vd = _VD; int vs = _VS; int vt = _VT; - snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz)); + sprintf(out, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz)); } - void Dis_Vbfy(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vbfy(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); int vd = _VD; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz)); + sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, sz),VN(vs, sz)); } - void Dis_Vf2i(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vf2i(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); int vd = _VD; int vs = _VS; int imm = (op>>16)&0x1f; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s, %i", name, VSuff(op), VN(vd, sz), VN(vs, sz), imm); + sprintf(out, "%s%s\t%s, %s, %i",name,VSuff(op),VN(vd, sz),VN(vs, sz),imm); } - void Dis_Vs2i(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vs2i(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); int vd = _VD; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz)); + sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, sz),VN(vs, sz)); } - void Dis_Vi2x(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vi2x(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); VectorSize dsz = GetHalfVectorSizeSafe(sz); if (((op>>16)&3)==0) dsz = V_Single; @@ -508,21 +534,23 @@ namespace MIPSDis int vd = _VD; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + sprintf(out, "%s%s\t%s, %s",name,VSuff(op),VN(vd, dsz),VN(vs, sz)); } - void Dis_Vwbn(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vwbn(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); int vd = _VD; int vs = _VS; int imm = (int)((op >> 16) & 0xFF); const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s, %d", name, VSuff(op), VN(vd, sz), VN(vs, sz), imm); + sprintf(out, "%s%s\t%s, %s, %d", name, VSuff(op), VN(vd, sz), VN(vs, sz), imm); } - void Dis_Vf2h(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vf2h(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); VectorSize dsz = GetHalfVectorSizeSafe(sz); if (((op>>16)&3)==0) dsz = V_Single; @@ -530,50 +558,55 @@ namespace MIPSDis int vd = _VD; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); } - void Dis_Vh2f(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_Vh2f(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); VectorSize dsz = GetDoubleVectorSizeSafe(sz); int vd = _VD; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); } - void Dis_ColorConv(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_ColorConv(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); VectorSize dsz = GetHalfVectorSizeSafe(sz); int vd = _VD; int vs = _VS; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); + sprintf(out, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz)); } - void Dis_Vrnds(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { + void Dis_Vrnds(MIPSOpcode op, char *out) + { int vd = _VD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), VN(vd, V_Single)); + sprintf(out, "%s%s\t%s", name, VSuff(op), VN(vd, V_Single)); } - void Dis_VrndX(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - VectorSize sz = GetVecSize(op); + void Dis_VrndX(MIPSOpcode op, char *out) + { + VectorSize sz = GetVecSizeSafe(op); int vd = _VD; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), VN(vd, sz)); + sprintf(out, "%s%s\t%s", name, VSuff(op), VN(vd, sz)); } - void Dis_VBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) { - u32 off = pc; + void Dis_VBranch(MIPSOpcode op, char *out) + { + u32 off = disPC; int imm = SignExtend16ToS32(op&0xFFFF) << 2; int imm3 = (op>>18)&7; off += imm + 4; const char *name = MIPSGetName(op); - snprintf(out, outSize, "%s\t->$%08x (CC[%i])", name, off, imm3); + sprintf(out, "%s\t->$%08x (CC[%i])",name,off,imm3); } } diff --git a/Core/MIPS/MIPSDisVFPU.h b/Core/MIPS/MIPSDisVFPU.h index d03f2ff99..8890ed29b 100644 --- a/Core/MIPS/MIPSDisVFPU.h +++ b/Core/MIPS/MIPSDisVFPU.h @@ -19,50 +19,52 @@ #include "Common/CommonTypes.h" +extern u32 disPC; + namespace MIPSDis { - void Dis_Mftv(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vmfvc(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vmtvc(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_Mftv(MIPSOpcode op, char *out); + void Dis_Vmfvc(MIPSOpcode op, char *out); + void Dis_Vmtvc(MIPSOpcode op, char *out); - void Dis_SV(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_SVQ(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_SVLRQ(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_SV(MIPSOpcode op, char *out); + void Dis_SVQ(MIPSOpcode op, char *out); + void Dis_SVLRQ(MIPSOpcode op, char *out); - void Dis_MatrixSet1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_MatrixSet2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_MatrixSet3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_MatrixMult(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vmscl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_MatrixSet1(MIPSOpcode op, char *out); + void Dis_MatrixSet2(MIPSOpcode op, char *out); + void Dis_MatrixSet3(MIPSOpcode op, char *out); + void Dis_MatrixMult(MIPSOpcode op, char *out); + void Dis_Vmscl(MIPSOpcode op, char *out); - void Dis_VectorDot(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vfad(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VectorSet1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VectorSet2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VectorSet3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VRot(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VScl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_VectorDot(MIPSOpcode op, char *out); + void Dis_Vfad(MIPSOpcode op, char *out); + void Dis_VectorSet1(MIPSOpcode op, char *out); + void Dis_VectorSet2(MIPSOpcode op, char *out); + void Dis_VectorSet3(MIPSOpcode op, char *out); + void Dis_VRot(MIPSOpcode op, char *out); + void Dis_VScl(MIPSOpcode op, char *out); - void Dis_VPFXST(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VPFXD(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vcrs(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Viim(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vcst(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_CrossQuat(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vtfm(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vcmp(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vcmov(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vflush(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vbfy(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vf2i(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vi2x(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vs2i(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vwbn(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vf2h(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vh2f(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_Vrnds(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_VrndX(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); - void Dis_ColorConv(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_VPFXST(MIPSOpcode op, char *out); + void Dis_VPFXD(MIPSOpcode op, char *out); + void Dis_Vcrs(MIPSOpcode op, char *out); + void Dis_Viim(MIPSOpcode op, char *out); + void Dis_Vcst(MIPSOpcode op, char *out); + void Dis_CrossQuat(MIPSOpcode op, char *out); + void Dis_Vtfm(MIPSOpcode op, char *out); + void Dis_Vcmp(MIPSOpcode op, char *out); + void Dis_Vcmov(MIPSOpcode op, char *out); + void Dis_Vflush(MIPSOpcode op, char *out); + void Dis_Vbfy(MIPSOpcode op, char *out); + void Dis_Vf2i(MIPSOpcode op, char *out); + void Dis_Vi2x(MIPSOpcode op, char *out); + void Dis_Vs2i(MIPSOpcode op, char *out); + void Dis_Vwbn(MIPSOpcode op, char *out); + void Dis_Vf2h(MIPSOpcode op, char *out); + void Dis_Vh2f(MIPSOpcode op, char *out); + void Dis_Vrnds(MIPSOpcode op, char *out); + void Dis_VrndX(MIPSOpcode op, char *out); + void Dis_ColorConv(MIPSOpcode op, char *out); - void Dis_VBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize); + void Dis_VBranch(MIPSOpcode op, char *out); } diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 9fcc40941..9009b9169 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -101,8 +101,9 @@ inline float nanclamp(float f, float lower, float upper) return nanmin(nanmax(f, lower), upper); } -static void ApplyPrefixST(float *r, u32 data, VectorSize size, float invalid = 0.0f) { - // Check for no prefix. + +void ApplyPrefixST(float *r, u32 data, VectorSize size, float invalid = 0.0f) { + // Possible optimization shortcut: if (data == 0xe4) return; @@ -123,7 +124,7 @@ static void ApplyPrefixST(float *r, u32 data, VectorSize size, float invalid = 0 if (!constants) { if (regnum >= n) { // We mostly handle this now, but still worth reporting. - ERROR_LOG_REPORT(CPU, "Invalid VFPU swizzle: %08x: %i / %d at PC = %08x (%s)", data, regnum, n, currentMIPS->pc, MIPSDisasmAt(currentMIPS->pc).c_str()); + ERROR_LOG_REPORT(CPU, "Invalid VFPU swizzle: %08x: %i / %d at PC = %08x (%s)", data, regnum, n, currentMIPS->pc, MIPSDisasmAt(currentMIPS->pc)); } r[i] = origV[regnum]; if (abs) @@ -170,7 +171,6 @@ static void RetainInvalidSwizzleST(float *d, VectorSize sz) { int tPrefix = currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX]; int n = GetNumVectorElements(sz); - // TODO: We can probably do some faster check of sPrefix and tPrefix to skip over this loop. for (int i = 0; i < n; i++) { int swizzleS = (sPrefix >> (i + i)) & 3; int swizzleT = (tPrefix >> (i + i)) & 3; @@ -926,8 +926,10 @@ namespace MIPSInt switch ((op >> 16) & 3) { case 0: // vuc2i // Quad is the only option. - // This converts 8-bit unsigned to 31-bit signed, swizzling to saturate. - // Similar to 5-bit to 8-bit color swizzling, but clamping to INT_MAX. + // This operation is weird. This particular way of working matches hw but does not + // seem quite sane. + // I guess it's used for fixed-point math, and fills more bits to facilitate + // conversion between 8-bit and 16-bit values. But then why not do it in vc2i? { u32 value = s[0]; for (int i = 0; i < 4; i++) { @@ -940,8 +942,6 @@ namespace MIPSInt case 1: // vc2i // Quad is the only option - // Unlike vuc2i, the source and destination are signed so there is no shift. - // It lacks the swizzle because of negative values. { u32 value = s[0]; d[0] = (value & 0xFF) << 24; @@ -953,7 +953,6 @@ namespace MIPSInt break; case 2: // vus2i - // Note: for some reason, this skips swizzle such that 0xFFFF -> 0x7FFF8000 unlike vuc2i. oz = V_Pair; switch (sz) { case V_Quad: @@ -1016,9 +1015,9 @@ namespace MIPSInt void Int_Vi2x(MIPSOpcode op) { int s[4]{}; u32 d[2]{}; - const int vd = _VD; - const int vs = _VS; - const VectorSize sz = GetVecSize(op); + int vd = _VD; + int vs = _VS; + VectorSize sz = GetVecSize(op); VectorSize oz; ReadVector(reinterpret_cast(s), sz, vs); // Negate, const, etc. apply as expected. @@ -1045,9 +1044,7 @@ namespace MIPSInt break; case 2: //vi2us - { - int elems = (GetNumVectorElements(sz) + 1) / 2; - for (int i = 0; i < elems; i++) { + for (int i = 0; i < (GetNumVectorElements(sz) + 1) / 2; i++) { int low = s[i * 2]; int high = s[i * 2 + 1]; if (low < 0) low = 0; @@ -1067,11 +1064,8 @@ namespace MIPSInt break; } break; - } case 3: //vi2s - { - int elems = (GetNumVectorElements(sz) + 1) / 2; - for (int i = 0; i < elems; i++) { + for (int i = 0; i < (GetNumVectorElements(sz) + 1) / 2; i++) { u32 low = s[i * 2]; u32 high = s[i * 2 + 1]; low >>= 16; @@ -1084,12 +1078,11 @@ namespace MIPSInt case V_Pair: oz = V_Single; break; case V_Single: oz = V_Single; break; default: - _dbg_assert_msg_(0, "Trying to interpret instruction that can't be interpreted"); + _dbg_assert_msg_( 0, "Trying to interpret instruction that can't be interpreted"); oz = V_Single; break; } break; - } default: _dbg_assert_msg_( 0, "Trying to interpret instruction that can't be interpreted"); oz = V_Single; @@ -1126,7 +1119,7 @@ namespace MIPSInt int b = ((in >> 16) & 0xFF) >> 4; int g = ((in >> 8) & 0xFF) >> 4; int r = ((in) & 0xFF) >> 4; - col = (a << 12) | (b << 8) | (g << 4) | (r); + col = (a << 12) | (b << 8) | (g << 4 ) | (r); break; } case 2: // 5551 @@ -1446,7 +1439,7 @@ namespace MIPSInt d[0] += s[2] * t[2] + s[3] * t[3]; } - ApplyPrefixD(d, V_Single); + ApplyPrefixD(d, sz); WriteVector(d, V_Single, vd); PC += 4; EatPrefixes(); @@ -1550,7 +1543,7 @@ namespace MIPSInt int seed = VI(vd); // Swizzles apply a constant value, constants/abs/neg work to vary the seed. ApplySwizzleS(reinterpret_cast(&seed), V_Single); - vrnd_init(uint32_t(seed), currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0); + currentMIPS->rng.Init(seed); PC += 4; EatPrefixes(); } @@ -1560,12 +1553,12 @@ namespace MIPSInt int vd = _VD; VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); - // Values are written in backwards order. - for (int i = n - 1; i >= 0; i--) { + for (int i = 0; i < n; i++) { + // TODO: Make more accurate, use and update RCX regs? switch ((op >> 16) & 0x1f) { - case 1: d.u[i] = vrnd_generate(currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0); break; // vrndi - case 2: d.u[i] = 0x3F800000 | (vrnd_generate(currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0) & 0x007FFFFF); break; // vrndf1 (>= 1, < 2) - case 3: d.u[i] = 0x40000000 | (vrnd_generate(currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0) & 0x007FFFFF); break; // vrndf2 (>= 2, < 4) + case 1: d.u[i] = currentMIPS->rng.R32(); break; // vrndi + case 2: d.u[i] = 0x3F800000 | (currentMIPS->rng.R32() & 0x007FFFFF); break; // vrndf1 (>= 1, < 2) + case 3: d.u[i] = 0x40000000 | (currentMIPS->rng.R32() & 0x007FFFFF); break; // vrndf2 (>= 2, < 4) default: _dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted"); } } diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 825c2d24d..f5b4af34c 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -150,7 +150,7 @@ static const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ........ INSTR("swr", JITFUNC(Comp_ITypeMem), Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM|MEMTYPE_WORD), INSTR("cache", JITFUNC(Comp_Cache), Dis_Cache, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR), //48 - INSTR("ll", JITFUNC(Comp_StoreSync), Dis_ITypeMem, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD), + INSTR("ll", JITFUNC(Comp_Generic), Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD), INSTR("lwc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_FT|MEMTYPE_FLOAT|IS_FPU), INSTR("lv.s", JITFUNC(Comp_SV), Dis_SV, Int_SV, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_FLOAT), INVALID, @@ -159,7 +159,7 @@ static const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ........ INSTR("lv.q", JITFUNC(Comp_SVQ), Dis_SVQ, Int_SVQ, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_VQUAD), //copU ENCODING(VFPU5), //56 - INSTR("sc", JITFUNC(Comp_StoreSync), Dis_ITypeMem, Int_StoreSync, IN_IMM16|IN_RS_ADDR|IN_OTHER|IN_RT|OUT_RT|OUT_MEM|MEMTYPE_WORD), + INSTR("sc", JITFUNC(Comp_Generic), Dis_Generic, Int_StoreSync, IN_IMM16|IN_RS_ADDR|IN_OTHER|IN_RT|OUT_RT|OUT_MEM|MEMTYPE_WORD), INSTR("swc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_IMM16|IN_RS_ADDR|IN_FT|OUT_MEM|MEMTYPE_FLOAT|IS_FPU), //copU INSTR("sv.s", JITFUNC(Comp_SV), Dis_SV, Int_SV, IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_MEM|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_FLOAT), INVALID, @@ -340,7 +340,7 @@ static const MIPSInstruction tableCop2[32] = // 010010 xxxxx ..... ............. INSTR("mtc2", JITFUNC(Comp_Generic), Dis_Generic, 0, IN_RT), INVALID, INSTR("ctc2", JITFUNC(Comp_Generic), Dis_Generic, 0, 0), - INSTR("mtv", JITFUNC(Comp_Mftv), Dis_Mftv, Int_Mftv, IN_RT|OUT_VFPU_CC|OUT_OTHER|IS_VFPU|OUT_VFPU_PREFIX), + INSTR("mtv", JITFUNC(Comp_Mftv), Dis_Mftv, Int_Mftv, IN_RT|OUT_VFPU_CC|OUT_OTHER|IS_VFPU), //8 ENCODING(Cop2BC2), INSTR("??", JITFUNC(Comp_Generic), Dis_Generic, 0, 0), @@ -749,7 +749,7 @@ static const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . //16 INSTR("vmfvc", JITFUNC(Comp_Vmfvc), Dis_Vmfvc, Int_Vmfvc, IN_OTHER|IN_VFPU_CC|OUT_OTHER|IS_VFPU), - INSTR("vmtvc", JITFUNC(Comp_Vmtvc), Dis_Vmtvc, Int_Vmtvc, IN_OTHER|OUT_VFPU_CC|OUT_OTHER|IS_VFPU|OUT_VFPU_PREFIX), + INSTR("vmtvc", JITFUNC(Comp_Vmtvc), Dis_Vmtvc, Int_Vmtvc, IN_OTHER|OUT_VFPU_CC|OUT_OTHER|IS_VFPU), INVALID, INVALID, @@ -918,13 +918,14 @@ void MIPSCompileOp(MIPSOpcode op, MIPSComp::MIPSFrontendInterface *jit) { } } -void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, size_t outSize, bool tabsToSpaces) { +void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, bool tabsToSpaces) { if (op == 0) { - truncate_cpy(out, outSize, "nop"); + strcpy(out, "nop"); } else { + disPC = pc; const MIPSInstruction *instr = MIPSGetInstruction(op); if (instr && instr->disasm) { - instr->disasm(op, pc, out, outSize); + instr->disasm(op, out); if (tabsToSpaces) { while (*out) { if (*out == '\t') @@ -933,7 +934,7 @@ void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, size_t outSize, bool tabsToSpa } } } else { - truncate_cpy(out, outSize, "no instruction :("); + strcpy(out, "no instruction :("); } } } @@ -945,7 +946,7 @@ static inline void Interpret(const MIPSInstruction *instr, MIPSOpcode op) { ERROR_LOG_REPORT(CPU, "Unknown instruction %08x at %08x", op.encoding, currentMIPS->pc); // Try to disassemble it char disasm[256]; - MIPSDisAsm(op, currentMIPS->pc, disasm, sizeof(disasm)); + MIPSDisAsm(op, currentMIPS->pc, disasm); _dbg_assert_msg_(0, "%s", disasm); currentMIPS->pc += 4; } @@ -1119,8 +1120,8 @@ int MIPSGetMemoryAccessSize(MIPSOpcode op) { return 0; } -std::string MIPSDisasmAt(u32 compilerPC) { - char temp[512]; - MIPSDisAsm(Memory::Read_Instruction(compilerPC), 0, temp, sizeof(temp)); +const char *MIPSDisasmAt(u32 compilerPC) { + static char temp[256]; + MIPSDisAsm(Memory::Read_Instruction(compilerPC), 0, temp); return temp; } diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 9c53a07ea..484eab35e 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -17,8 +17,6 @@ #pragma once -#include -#include #include "Common/CommonTypes.h" #include "Core/MIPS/MIPS.h" @@ -72,9 +70,8 @@ #define OUT_EAT_PREFIX 0x08000000ULL #define VFPU_NO_PREFIX 0x10000000ULL -#define OUT_VFPU_PREFIX 0x20000000ULL -#define IS_VFPU 0x40000000ULL -#define IS_FPU 0x80000000ULL +#define IS_VFPU 0x20000000ULL +#define IS_FPU 0x40000000ULL #define IN_FS 0x000100000000ULL #define IN_FT 0x000200000000ULL @@ -118,7 +115,7 @@ struct MIPSInfo { u64 cycles : 16; }; -typedef void (CDECL *MIPSDisFunc)(MIPSOpcode opcode, uint32_t pc, char *out, size_t outSize); +typedef void (CDECL *MIPSDisFunc)(MIPSOpcode opcode, char *out); typedef void (CDECL *MIPSInterpretFunc)(MIPSOpcode opcode); namespace MIPSComp { @@ -126,7 +123,7 @@ namespace MIPSComp { } void MIPSCompileOp(MIPSOpcode op, MIPSComp::MIPSFrontendInterface *jit); -void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, size_t outSize, bool tabsToSpaces = false); +void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, bool tabsToSpaces = false); MIPSInfo MIPSGetInfo(MIPSOpcode op); void MIPSInterpret(MIPSOpcode op); //only for those rare ones int MIPSInterpret_RunUntil(u64 globalTicks); @@ -135,4 +132,4 @@ MIPSInterpretFunc MIPSGetInterpretFunc(MIPSOpcode op); int MIPSGetInstructionCycleEstimate(MIPSOpcode op); int MIPSGetMemoryAccessSize(MIPSOpcode op); const char *MIPSGetName(MIPSOpcode op); -std::string MIPSDisasmAt(u32 compilerPC); +const char *MIPSDisasmAt(u32 compilerPC); diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index d8196999e..e80bb77ac 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -23,7 +23,6 @@ #include "Common/BitScan.h" #include "Common/CommonFuncs.h" #include "Common/File/VFS/VFS.h" -#include "Common/StringUtils.h" #include "Core/Reporting.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSVFPUUtils.h" @@ -33,6 +32,9 @@ #pragma warning(disable: 4146) #endif +#define V(i) (currentMIPS->v[voffset[i]]) +#define VI(i) (currentMIPS->vi[voffset[i]]) + union float2int { uint32_t i; float f; @@ -162,68 +164,73 @@ void GetMatrixRows(int matrixReg, MatrixSize msize, u8 vecs[4]) { } void ReadVector(float *rd, VectorSize size, int reg) { - int row; - int length; + int row = 0; + int length = 0; + switch (size) { - case V_Single: rd[0] = currentMIPS->v[voffset[reg]]; return; // transpose = 0; row=(reg>>5)&3; length = 1; break; + case V_Single: rd[0] = V(reg); return; // transpose = 0; row=(reg>>5)&3; length = 1; break; case V_Pair: row=(reg>>5)&2; length = 2; break; case V_Triple: row=(reg>>6)&1; length = 3; break; case V_Quad: row=(reg>>5)&2; length = 4; break; - default: length = 0; break; + default: _assert_msg_(false, "%s: Bad vector size", __FUNCTION__); } - int transpose = (reg >> 5) & 1; - const int mtx = ((reg << 2) & 0x70); + int transpose = (reg>>5) & 1; + const int mtx = (reg >> 2) & 7; const int col = reg & 3; - // NOTE: We now skip the voffset lookups. + if (transpose) { - const int base = mtx + col; + const int base = mtx * 4 + col * 32; for (int i = 0; i < length; i++) - rd[i] = currentMIPS->v[base + ((row + i) & 3) * 4]; + rd[i] = V(base + ((row+i)&3)); } else { - const int base = mtx + col * 4; + const int base = mtx * 4 + col; for (int i = 0; i < length; i++) - rd[i] = currentMIPS->v[base + ((row + i) & 3)]; + rd[i] = V(base + ((row+i)&3)*32); } } void WriteVector(const float *rd, VectorSize size, int reg) { - int row; - int length; + if (size == V_Single) { + // Optimize the common case. + if (!currentMIPS->VfpuWriteMask(0)) { + V(reg) = rd[0]; + } + return; + } + + const int mtx = (reg>>2)&7; + const int col = reg & 3; + int transpose = (reg>>5)&1; + int row = 0; + int length = 0; switch (size) { - case V_Single: if (!currentMIPS->VfpuWriteMask(0)) currentMIPS->v[voffset[reg]] = rd[0]; return; // transpose = 0; row=(reg>>5)&3; length = 1; break; + case V_Single: _dbg_assert_(false); return; // transpose = 0; row=(reg>>5)&3; length = 1; break; case V_Pair: row=(reg>>5)&2; length = 2; break; case V_Triple: row=(reg>>6)&1; length = 3; break; case V_Quad: row=(reg>>5)&2; length = 4; break; - default: length = 0; break; + default: _assert_msg_(false, "%s: Bad vector size", __FUNCTION__); } - const int mtx = ((reg << 2) & 0x70); - const int col = reg & 3; - bool transpose = (reg >> 5) & 1; - // NOTE: We now skip the voffset lookups. - if (transpose) { - const int base = mtx + col; - if (currentMIPS->VfpuWriteMask() == 0) { + if (currentMIPS->VfpuWriteMask() == 0) { + if (transpose) { + const int base = mtx * 4 + col * 32; for (int i = 0; i < length; i++) - currentMIPS->v[base + ((row+i) & 3) * 4] = rd[i]; + V(base + ((row+i)&3)) = rd[i]; } else { - for (int i = 0; i < length; i++) { - if (!currentMIPS->VfpuWriteMask(i)) { - currentMIPS->v[base + ((row+i) & 3) * 4] = rd[i]; - } - } + const int base = mtx * 4 + col; + for (int i = 0; i < length; i++) + V(base + ((row+i)&3)*32) = rd[i]; } } else { - const int base = mtx + col * 4; - if (currentMIPS->VfpuWriteMask() == 0) { - for (int i = 0; i < length; i++) - currentMIPS->v[base + ((row + i) & 3)] = rd[i]; - } else { - for (int i = 0; i < length; i++) { - if (!currentMIPS->VfpuWriteMask(i)) { - currentMIPS->v[base + ((row + i) & 3)] = rd[i]; - } + for (int i = 0; i < length; i++) { + if (!currentMIPS->VfpuWriteMask(i)) { + int index = mtx * 4; + if (transpose) + index += ((row+i)&3) + col*32; + else + index += col + ((row+i)&3)*32; + V(index) = rd[i]; } } } @@ -235,6 +242,9 @@ u32 VFPURewritePrefix(int ctrl, u32 remove, u32 add) { } void ReadMatrix(float *rd, MatrixSize size, int reg) { + int mtx = (reg >> 2) & 7; + int col = reg & 3; + int row = 0; int side = 0; int transpose = (reg >> 5) & 1; @@ -244,12 +254,9 @@ void ReadMatrix(float *rd, MatrixSize size, int reg) { case M_2x2: row = (reg >> 5) & 2; side = 2; break; case M_3x3: row = (reg >> 6) & 1; side = 3; break; case M_4x4: row = (reg >> 5) & 2; side = 4; break; - default: side = 0; break; + default: _assert_msg_(false, "%s: Bad matrix size", __FUNCTION__); } - int mtx = (reg >> 2) & 7; - int col = reg & 3; - // The voffset ordering is now integrated in these formulas, // eliminating a table lookup. const float *v = currentMIPS->v + (size_t)mtx * 16; @@ -288,8 +295,8 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) { int mtx = (reg>>2)&7; int col = reg&3; - int row; - int side; + int row = 0; + int side = 0; int transpose = (reg >> 5) & 1; switch (size) { @@ -297,7 +304,7 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) { case M_2x2: row = (reg >> 5) & 2; side = 2; break; case M_3x3: row = (reg >> 6) & 1; side = 3; break; case M_4x4: row = (reg >> 5) & 2; side = 4; break; - default: side = 0; + default: _assert_msg_(false, "%s: Bad matrix size", __FUNCTION__); } if (currentMIPS->VfpuWriteMask() != 0) { @@ -362,6 +369,16 @@ int GetVectorOverlap(int vec1, VectorSize size1, int vec2, VectorSize size2) { return count; } +int GetNumVectorElements(VectorSize sz) { + switch (sz) { + case V_Single: return 1; + case V_Pair: return 2; + case V_Triple: return 3; + case V_Quad: return 4; + default: return 0; + } +} + VectorSize GetHalfVectorSizeSafe(VectorSize sz) { switch (sz) { case V_Pair: return V_Single; @@ -390,6 +407,25 @@ VectorSize GetDoubleVectorSize(VectorSize sz) { return res; } +VectorSize GetVecSizeSafe(MIPSOpcode op) { + int a = (op >> 7) & 1; + int b = (op >> 15) & 1; + a += (b << 1); + switch (a) { + case 0: return V_Single; + case 1: return V_Pair; + case 2: return V_Triple; + case 3: return V_Quad; + default: return V_Invalid; + } +} + +VectorSize GetVecSize(MIPSOpcode op) { + VectorSize res = GetVecSizeSafe(op); + _assert_msg_(res != V_Invalid, "%s: Bad vector size", __FUNCTION__); + return res; +} + VectorSize GetVectorSizeSafe(MatrixSize sz) { switch (sz) { case M_1x1: return V_Single; @@ -422,6 +458,25 @@ MatrixSize GetMatrixSize(VectorSize sz) { return res; } +MatrixSize GetMtxSizeSafe(MIPSOpcode op) { + int a = (op >> 7) & 1; + int b = (op >> 15) & 1; + a += (b << 1); + switch (a) { + case 0: return M_1x1; // This happens in disassembly of junk, but has predictable behavior. + case 1: return M_2x2; + case 2: return M_3x3; + case 3: return M_4x4; + default: return M_Invalid; + } +} + +MatrixSize GetMtxSize(MIPSOpcode op) { + MatrixSize res = GetMtxSizeSafe(op); + _assert_msg_(res != M_Invalid, "%s: Bad matrix size", __FUNCTION__); + return res; +} + VectorSize MatrixVectorSizeSafe(MatrixSize sz) { switch (sz) { case M_1x1: return V_Single; @@ -483,7 +538,11 @@ MatrixOverlapType GetMatrixOverlap(int mtx1, int mtx2, MatrixSize msize) { return OVERLAP_NONE; } -std::string GetVectorNotation(int reg, VectorSize size) { +const char *GetVectorNotation(int reg, VectorSize size) +{ + static char temp[4][16]; + static int yo = 0; yo++; yo &= 3; + int mtx = (reg>>2)&7; int col = reg&3; int row = 0; @@ -498,27 +557,34 @@ std::string GetVectorNotation(int reg, VectorSize size) { } if (transpose && c == 'C') c='R'; if (transpose) - return StringFromFormat("%c%i%i%i", c, mtx, row, col); - return StringFromFormat("%c%i%i%i", c, mtx, col, row); + snprintf(temp[yo], sizeof(temp[yo]), "%c%i%i%i",c,mtx,row,col); + else + snprintf(temp[yo], sizeof(temp[yo]), "%c%i%i%i",c,mtx,col,row); + return temp[yo]; } -std::string GetMatrixNotation(int reg, MatrixSize size) { - int mtx = (reg>>2)&7; - int col = reg&3; - int row = 0; - int transpose = (reg>>5)&1; - char c; - switch (size) - { - case M_2x2: c='M'; row=(reg>>5)&2; break; - case M_3x3: c='M'; row=(reg>>6)&1; break; - case M_4x4: c='M'; row=(reg>>5)&2; break; - default: c='?'; break; - } - if (transpose && c=='M') c='E'; - if (transpose) - return StringFromFormat("%c%i%i%i", c, mtx, row, col); - return StringFromFormat("%c%i%i%i", c, mtx, col, row); +const char *GetMatrixNotation(int reg, MatrixSize size) +{ + static char temp[4][16]; + static int yo=0;yo++;yo&=3; + int mtx = (reg>>2)&7; + int col = reg&3; + int row = 0; + int transpose = (reg>>5)&1; + char c; + switch (size) + { + case M_2x2: c='M'; row=(reg>>5)&2; break; + case M_3x3: c='M'; row=(reg>>6)&1; break; + case M_4x4: c='M'; row=(reg>>5)&2; break; + default: c='?'; break; + } + if (transpose && c=='M') c='E'; + if (transpose) + snprintf(temp[yo], sizeof(temp[yo]), "%c%i%i%i",c,mtx,row,col); + else + snprintf(temp[yo], sizeof(temp[yo]), "%c%i%i%i",c,mtx,col,row); + return temp[yo]; } bool GetVFPUCtrlMask(int reg, u32 *mask) { @@ -600,8 +666,7 @@ float Float16ToFloat32(unsigned short l) return f; } -// Reference C++ version. -static float vfpu_dot_cpp(const float a[4], const float b[4]) { +float vfpu_dot(const float a[4], const float b[4]) { static const int EXTRA_BITS = 2; float2int result; float2int src[2]; @@ -714,249 +779,6 @@ static float vfpu_dot_cpp(const float a[4], const float b[4]) { return result.f; } -#if defined(__SSE2__) - -#include - -static inline __m128i mulhi32x4(__m128i a, __m128i b) { - __m128i m02 = _mm_mul_epu32(a, b); - __m128i m13 = _mm_mul_epu32( - _mm_shuffle_epi32(a, _MM_SHUFFLE(3, 3, 1, 1)), - _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1))); - __m128i m=_mm_unpacklo_epi32( - _mm_shuffle_epi32(m02, _MM_SHUFFLE(3, 2, 3, 1)), - _mm_shuffle_epi32(m13, _MM_SHUFFLE(3, 2, 3, 1))); - return m; -} - -// Values of rounding_mode: -// -1 - detect at runtime -// 0 - assume round-to-nearest-ties-to-even -// 1 - round yourself in integer math -template -static float vfpu_dot_sse2(const float a[4], const float b[4]) -{ - static const int EXTRA_BITS = 2; - - bool is_default_rounding_mode = (rounding_mode == 0); - if(rounding_mode == -1) - { - volatile float test05 = 5.9604644775390625e-08f; // 0.5*2^-23 - volatile float test15 = 1.78813934326171875e-07f; // 1.5*2^-23 - const float res15 = 1.0000002384185791015625f; // 1+2^-22 - test05 += 1.0f; - test15 += 1.0f; - is_default_rounding_mode = (test05 == 1.0f && test15 == res15); - } - __m128 A = _mm_loadu_ps(a); - __m128 B = _mm_loadu_ps(b); - // Extract exponents. - __m128 exp_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000)); - __m128 eA = _mm_and_ps(A, exp_mask); - __m128 eB = _mm_and_ps(B, exp_mask); - __m128i exps = _mm_srli_epi32(_mm_add_epi32( - _mm_castps_si128(eA), - _mm_castps_si128(eB)),23); - // Find maximum exponent, stored as float32 in [1;2), - // so we can use _mm_max_ps() with normal arguments. - __m128 t = _mm_or_ps(_mm_castsi128_ps(exps), _mm_set1_ps(1.0f)); - t = _mm_max_ps(t, _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(t), _MM_SHUFFLE(2, 3, 0, 1)))); - t = _mm_max_ps(t, _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(t), _MM_SHUFFLE(1, 0, 3, 2)))); - t = _mm_max_ps(t, _mm_castsi128_ps(_mm_set1_epi32(0x3F80007F))); - int32_t mexp = _mm_cvtsi128_si32(_mm_castps_si128(t)) & 511; - // NOTE: mexp is doubly-biased, same for exps. - int32_t max_exp = mexp - 127; - // Fall back on anything weird. - __m128 finiteA = _mm_sub_ps(A, A); - __m128 finiteB = _mm_sub_ps(B, B); - finiteA = _mm_cmpeq_ps(finiteA, finiteA); - finiteB = _mm_cmpeq_ps(finiteB, finiteB); - if(max_exp >= 255 || _mm_movemask_ps(_mm_and_ps(finiteA, finiteB)) != 15) return vfpu_dot_cpp(a, b); - // Extract significands. - __m128i mA = _mm_or_si128(_mm_and_si128(_mm_castps_si128(A),_mm_set1_epi32(0x007FFFFF)),_mm_set1_epi32(0x00800000)); - __m128i mB = _mm_or_si128(_mm_and_si128(_mm_castps_si128(B),_mm_set1_epi32(0x007FFFFF)),_mm_set1_epi32(0x00800000)); - // Multiply. - // NOTE: vfpu_dot does multiplication as - // ((x<>(23+EXTRA_BITS), - // here we do (x*y)>>(23-EXTRA_BITS-1), - // which produces twice the result (neither expression - // overflows in our case). We need that because our - // variable-shift scheme (below) must shift by at least 1 bit. - static const int s = 32-(23 - EXTRA_BITS - 1), s0 = s / 2,s1 = s - s0; - // We compute ((x*y)>>shift) as - // (((x*y)<<(32-shift))>>32), which we express as - // (((x<>32) (neither shift overflows). - __m128i m = mulhi32x4(_mm_slli_epi32(mA, s0), _mm_slli_epi32(mB, s1)); - // Shift according to max_exp. Since SSE2 doesn't have - // variable per-lane shifts, we multiply *again*, - // specifically, x>>y turns into (x<<(1<<(32-y)))>>32. - // We compute 1<<(32-y) using floating-point casts. - // NOTE: the cast for 1<<31 produces the correct value, - // since the _mm_cvttps_epi32 error code just happens - // to be 0x80000000. - // So (since we pre-multiplied m by 2), we need - // (m>>1)>>(mexp-exps), - // i.e. m>>(mexp+1-exps), - // i.e. (m<<(32-(mexp+1-exps)))>>32, - // i.e. (m<<(exps-(mexp-31)))>>32. - __m128i amounts = _mm_sub_epi32(exps, _mm_set1_epi32(mexp - 31)); - // Clamp by 0. Both zero and negative amounts produce zero, - // since they correspond to right-shifting by 32 or more bits. - amounts = _mm_and_si128(amounts, _mm_cmpgt_epi32(amounts, _mm_set1_epi32(0))); - // Set up multipliers. - __m128i bits = _mm_add_epi32(_mm_set1_epi32(0x3F800000), _mm_slli_epi32(amounts, 23)); - __m128i muls = _mm_cvttps_epi32(_mm_castsi128_ps(bits)); - m = mulhi32x4(m, muls); - // Extract signs. - __m128i signs = _mm_cmpgt_epi32( - _mm_set1_epi32(0), - _mm_xor_si128(_mm_castps_si128(A), _mm_castps_si128(B))); - // Apply signs to m. - m = _mm_sub_epi32(_mm_xor_si128(m, signs), signs); - // Horizontal sum. - // See https://stackoverflow.com/questions/6996764/fastest-way-to-do-horizontal-sse-vector-sum-or-other-reduction - __m128i h64 = _mm_shuffle_epi32(m, _MM_SHUFFLE(1, 0, 3, 2)); - __m128i s64 = _mm_add_epi32(h64, m); - __m128i h32 = _mm_shufflelo_epi16(s64, _MM_SHUFFLE(1, 0, 3, 2)); - __m128i s32 = _mm_add_epi32(s64, h32); - int32_t mant_sum = _mm_cvtsi128_si32(s32); - - // The rest is scalar. - uint32_t sign_sum = 0; - if (mant_sum < 0) { - sign_sum = 0x80000000; - mant_sum = -mant_sum; - } - - // Truncate off the extra bits now. We want to zero them for rounding purposes. - mant_sum >>= EXTRA_BITS; - - if (mant_sum == 0 || max_exp <= 0) { - return 0.0f; - } - - if(is_default_rounding_mode) - { - float2int r; - r.f = (float)mant_sum; - mant_sum = (r.i & 0x007FFFFF) | 0x00800000; - max_exp += (r.i >> 23) - 0x96; - } - else - { - int8_t shift = (int8_t)clz32_nonzero(mant_sum) - 8; - if (shift < 0) { - // Round to even if we'd shift away a 0.5. - const uint32_t round_bit = 1 << (-shift - 1); - if ((mant_sum & round_bit) && (mant_sum & (round_bit << 1))) { - mant_sum += round_bit; - shift = (int8_t)clz32_nonzero(mant_sum) - 8; - } else if ((mant_sum & round_bit) && (mant_sum & (round_bit - 1))) { - mant_sum += round_bit; - shift = (int8_t)clz32_nonzero(mant_sum) - 8; - } - mant_sum >>= -shift; - max_exp += -shift; - } else { - mant_sum <<= shift; - max_exp -= shift; - } - _dbg_assert_msg_((mant_sum & 0x00800000) != 0, "Mantissa wrong: %08x", mant_sum); - } - - if (max_exp >= 255) { - max_exp = 255; - mant_sum = 0; - } else if (max_exp <= 0) { - return 0.0f; - } - - float2int result; - result.i = sign_sum | (max_exp << 23) | (mant_sum & 0x007FFFFF); - return result.f; -} - -#endif // defined(__SSE2__) - -float vfpu_dot(const float a[4], const float b[4]) { -#if defined(__SSE2__) - return vfpu_dot_sse2(a, b); -#else - return vfpu_dot_cpp(a, b); -#endif -} - -//============================================================================== -// The code below attempts to exactly match behaviour of -// PSP's vrnd instructions. See investigation starting around -// https://github.com/hrydgard/ppsspp/issues/16946#issuecomment-1467261209 -// for details. - -// Redundant currently, since MIPSState::Init() already -// does this on its own, but left as-is to be self-contained. -void vrnd_init_default(uint32_t *rcx) { - rcx[0] = 0x00000001; - rcx[1] = 0x00000002; - rcx[2] = 0x00000004; - rcx[3] = 0x00000008; - rcx[4] = 0x00000000; - rcx[5] = 0x00000000; - rcx[6] = 0x00000000; - rcx[7] = 0x00000000; -} - -void vrnd_init(uint32_t seed, uint32_t *rcx) { - for(int i = 0; i < 8; ++i) rcx[i] = - 0x3F800000u | // 1.0f mask. - ((seed >> ((i / 4) * 16)) & 0xFFFFu) | // lower or upper half of the seed. - (((seed >> (4 * i)) & 0xF) << 16); // remaining nibble. - -} - -uint32_t vrnd_generate(uint32_t *rcx) { - // The actual RNG state appears to be 5 parts - // (32-bit each) stored into the registers as follows: - uint32_t A = (rcx[0] & 0xFFFFu) | (rcx[4] << 16); - uint32_t B = (rcx[1] & 0xFFFFu) | (rcx[5] << 16); - uint32_t C = (rcx[2] & 0xFFFFu) | (rcx[6] << 16); - uint32_t D = (rcx[3] & 0xFFFFu) | (rcx[7] << 16); - uint32_t E = (((rcx[0] >> 16) & 0xF) << 0) | - (((rcx[1] >> 16) & 0xF) << 4) | - (((rcx[2] >> 16) & 0xF) << 8) | - (((rcx[3] >> 16) & 0xF) << 12) | - (((rcx[4] >> 16) & 0xF) << 16) | - (((rcx[5] >> 16) & 0xF) << 20) | - (((rcx[6] >> 16) & 0xF) << 24) | - (((rcx[7] >> 16) & 0xF) << 28); - // Update. - // LCG with classic parameters. - A = 69069u * A + 1u; // NOTE: decimal constants. - // Xorshift, with classic parameters. Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs". - B ^= B << 13; - B ^= B >> 17; - B ^= B << 5; - // Sequence similar to Pell numbers ( https://en.wikipedia.org/wiki/Pell_number ), - // except with different starting values, and an occasional increment (E). - uint32_t t= 2u * D + C + E; - // NOTE: the details of how E-part is set are somewhat of a guess - // at the moment. The expression below looks weird, but does match - // the available test data. - E = uint32_t((uint64_t(C) + uint64_t(D >> 1) + uint64_t(E)) >> 32); - C = D; - D = t; - // Store. - rcx[0] = 0x3F800000u | (((E >> 0) & 0xF) << 16) | (A & 0xFFFFu); - rcx[1] = 0x3F800000u | (((E >> 4) & 0xF) << 16) | (B & 0xFFFFu); - rcx[2] = 0x3F800000u | (((E >> 8) & 0xF) << 16) | (C & 0xFFFFu); - rcx[3] = 0x3F800000u | (((E >> 12) & 0xF) << 16) | (D & 0xFFFFu); - rcx[4] = 0x3F800000u | (((E >> 16) & 0xF) << 16) | (A >> 16); - rcx[5] = 0x3F800000u | (((E >> 20) & 0xF) << 16) | (B >> 16); - rcx[6] = 0x3F800000u | (((E >> 24) & 0xF) << 16) | (C >> 16); - rcx[7] = 0x3F800000u | (((E >> 28) & 0xF) << 16) | (D >> 16); - // Return value. - return A + B + D; -} - //============================================================================== // The code below attempts to exactly match the output of // several PSP's VFPU functions. For the sake of diff --git a/Core/MIPS/MIPSVFPUUtils.h b/Core/MIPS/MIPSVFPUUtils.h index b0beb850c..f26340f35 100644 --- a/Core/MIPS/MIPSVFPUUtils.h +++ b/Core/MIPS/MIPSVFPUUtils.h @@ -16,9 +16,8 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once - #include -#include + #include "Common/CommonTypes.h" #include "Core/MIPS/MIPS.h" @@ -68,10 +67,6 @@ extern float vfpu_rexp2(float); extern float vfpu_log2(float); extern float vfpu_rcp(float); -extern void vrnd_init_default(uint32_t *rcx); -extern void vrnd_init(uint32_t seed, uint32_t *rcx); -extern uint32_t vrnd_generate(uint32_t *rcx); - inline uint32_t get_uexp(uint32_t x) { return (x >> 23) & 0xFF; } @@ -202,51 +197,34 @@ enum MatrixOverlapType { MatrixOverlapType GetMatrixOverlap(int m1, int m2, MatrixSize msize); + // Returns a number from 0-7, good for checking overlap for 4x4 matrices. -static inline int GetMtx(int matrixReg) { +inline int GetMtx(int matrixReg) { return (matrixReg >> 2) & 7; } -static inline VectorSize GetVecSize(MIPSOpcode op) { - int a = (op >> 7) & 1; - int b = (op >> 14) & 2; - return (VectorSize)(a + b + 1); // Safe, there are no other possibilities -} - -static inline MatrixSize GetMtxSize(MIPSOpcode op) { - int a = (op >> 7) & 1; - int b = (op >> 14) & 2; - return (MatrixSize)(a + b + 1); // Safe, there are no other possibilities -} - +VectorSize GetVecSizeSafe(MIPSOpcode op); +VectorSize GetVecSize(MIPSOpcode op); +MatrixSize GetMtxSizeSafe(MIPSOpcode op); +MatrixSize GetMtxSize(MIPSOpcode op); VectorSize GetHalfVectorSizeSafe(VectorSize sz); VectorSize GetHalfVectorSize(VectorSize sz); VectorSize GetDoubleVectorSizeSafe(VectorSize sz); VectorSize GetDoubleVectorSize(VectorSize sz); VectorSize MatrixVectorSizeSafe(MatrixSize sz); VectorSize MatrixVectorSize(MatrixSize sz); - -static inline int GetNumVectorElements(VectorSize sz) { - switch (sz) { - case V_Single: return 1; - case V_Pair: return 2; - case V_Triple: return 3; - case V_Quad: return 4; - default: return 0; - } -} - +int GetNumVectorElements(VectorSize sz); int GetMatrixSideSafe(MatrixSize sz); int GetMatrixSide(MatrixSize sz); -std::string GetVectorNotation(int reg, VectorSize size); -std::string GetMatrixNotation(int reg, MatrixSize size); -static inline bool IsMatrixTransposed(int matrixReg) { +const char *GetVectorNotation(int reg, VectorSize size); +const char *GetMatrixNotation(int reg, MatrixSize size); +inline bool IsMatrixTransposed(int matrixReg) { return (matrixReg >> 5) & 1; } -static inline bool IsVectorColumn(int vectorReg) { +inline bool IsVectorColumn(int vectorReg) { return !((vectorReg >> 5) & 1); } -static inline int TransposeMatrixReg(int matrixReg) { +inline int TransposeMatrixReg(int matrixReg) { return matrixReg ^ 0x20; } int GetVectorOverlap(int reg1, VectorSize size1, int reg2, VectorSize size2); diff --git a/Core/MIPS/RiscV/RiscVAsm.cpp b/Core/MIPS/RiscV/RiscVAsm.cpp deleted file mode 100644 index 730a6d9dc..000000000 --- a/Core/MIPS/RiscV/RiscVAsm.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Common/Log.h" -#include "Core/CoreTiming.h" -#include "Core/MemMap.h" -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/System.h" - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -static const bool enableDebug = false; -static const bool enableDisasm = false; - -static void ShowPC(u32 downcount, void *membase, void *jitbase) { - static int count = 0; - if (currentMIPS) { - ERROR_LOG(JIT, "[%08x] ShowPC Downcount : %08x %d %p %p", currentMIPS->pc, downcount, count, membase, jitbase); - } else { - ERROR_LOG(JIT, "Universe corrupt?"); - } - //if (count > 2000) - // exit(0); - count++; -} - -void RiscVJitBackend::GenerateFixedCode(MIPSState *mipsState) { - // This will be used as a writable scratch area, always 32-bit accessible. - const u8 *start = AlignCodePage(); - if (DebugProfilerEnabled()) { - ProtectMemoryPages(start, GetMemoryProtectPageSize(), MEM_PROT_READ | MEM_PROT_WRITE); - hooks_.profilerPC = (uint32_t *)GetWritableCodePtr(); - *hooks_.profilerPC = 0; - hooks_.profilerStatus = (IRProfilerStatus *)GetWritableCodePtr() + 1; - *hooks_.profilerStatus = IRProfilerStatus::NOT_RUNNING; - SetCodePointer(GetCodePtr() + sizeof(uint32_t) * 2, GetWritableCodePtr() + sizeof(uint32_t) * 2); - } - - const u8 *disasmStart = AlignCodePage(); - BeginWrite(GetMemoryProtectPageSize()); - - if (jo.useStaticAlloc) { - saveStaticRegisters_ = AlignCode16(); - SW(DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - regs_.EmitSaveStaticRegisters(); - RET(); - - loadStaticRegisters_ = AlignCode16(); - regs_.EmitLoadStaticRegisters(); - LW(DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - RET(); - } else { - saveStaticRegisters_ = nullptr; - loadStaticRegisters_ = nullptr; - } - - applyRoundingMode_ = AlignCode16(); - { - // Not sure if RISC-V has any flush to zero capability? Leaving it off for now... - LWU(SCRATCH2, CTXREG, offsetof(MIPSState, fcr31)); - - // We can skip if the rounding mode is nearest (0) and flush is not set. - // (as restoreRoundingMode cleared it out anyway) - FixupBranch skip = BEQ(SCRATCH2, R_ZERO); - - // MIPS Rounding Mode: RISC-V - // 0: Round nearest 0 - // 1: Round to zero 1 - // 2: Round up (ceil) 3 - // 3: Round down (floor) 2 - if (cpu_info.RiscV_Zbs) { - BEXTI(SCRATCH1, SCRATCH2, 1); - } else { - ANDI(SCRATCH1, SCRATCH2, 2); - SRLI(SCRATCH1, SCRATCH1, 1); - } - // Swap the lowest bit by the second bit. - XOR(SCRATCH2, SCRATCH2, SCRATCH1); - - FSRM(SCRATCH2); - - SetJumpTarget(skip); - RET(); - } - - hooks_.enterDispatcher = (IRNativeFuncNoArg)AlignCode16(); - - // Start by saving some regs on the stack. There are 12 GPs and 12 FPs we want. - // Note: we leave R_SP as, well, SP, so it doesn't need to be saved. - _assert_msg_(cpu_info.Mode64bit, "RiscVAsm currently assumes RV64, not RV32 or RV128"); - static constexpr RiscVReg regs_to_save[]{ R_RA, X8, X9, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27 }; - // TODO: Maybe we shouldn't regalloc all of these? Is it worth it? - static constexpr RiscVReg regs_to_save_fp[]{ F8, F9, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27 }; - int saveSize = (XLEN / 8) * (int)(ARRAY_SIZE(regs_to_save) + ARRAY_SIZE(regs_to_save_fp)); - if (saveSize & 0xF) - saveSize += 8; - _assert_msg_((saveSize & 0xF) == 0, "Stack must be kept aligned"); - int saveOffset = 0; - ADDI(R_SP, R_SP, -saveSize); - for (RiscVReg r : regs_to_save) { - SD(r, R_SP, saveOffset); - saveOffset += XLEN / 8; - } - for (RiscVReg r : regs_to_save_fp) { - FS(64, r, R_SP, saveOffset); - saveOffset += XLEN / 8; - } - _assert_(saveOffset <= saveSize); - - // Fixed registers, these are always kept when in Jit context. - LI(MEMBASEREG, Memory::base, SCRATCH1); - LI(CTXREG, mipsState, SCRATCH1); - LI(JITBASEREG, GetBasePtr() - MIPS_EMUHACK_OPCODE, SCRATCH1); - - LoadStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - MovFromPC(SCRATCH1); - WriteDebugPC(SCRATCH1); - outerLoopPCInSCRATCH1_ = GetCodePtr(); - MovToPC(SCRATCH1); - outerLoop_ = GetCodePtr(); - // Advance can change the downcount (or thread), so must save/restore around it. - SaveStaticRegisters(); - RestoreRoundingMode(true); - WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE); - QuickCallFunction(&CoreTiming::Advance, X7); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - ApplyRoundingMode(true); - LoadStaticRegisters(); - - dispatcherCheckCoreState_ = GetCodePtr(); - LI(SCRATCH1, &coreState, SCRATCH2); - LW(SCRATCH1, SCRATCH1, 0); - FixupBranch badCoreState = BNE(SCRATCH1, R_ZERO); - - // We just checked coreState, so go to advance if downcount is negative. - BLT(DOWNCOUNTREG, R_ZERO, outerLoop_); - FixupBranch skipToRealDispatch = J(); - - dispatcherPCInSCRATCH1_ = GetCodePtr(); - MovToPC(SCRATCH1); - - hooks_.dispatcher = GetCodePtr(); - FixupBranch bail = BLT(DOWNCOUNTREG, R_ZERO); - SetJumpTarget(skipToRealDispatch); - - dispatcherNoCheck_ = GetCodePtr(); - - // Debug - if (enableDebug) { - MV(X10, DOWNCOUNTREG); - MV(X11, MEMBASEREG); - MV(X12, JITBASEREG); - QuickCallFunction(&ShowPC, X7); - } - - LWU(SCRATCH1, CTXREG, offsetof(MIPSState, pc)); - WriteDebugPC(SCRATCH1); -#ifdef MASKED_PSP_MEMORY - LI(SCRATCH2, 0x3FFFFFFF); - AND(SCRATCH1, SCRATCH1, SCRATCH2); -#endif - ADD(SCRATCH1, SCRATCH1, MEMBASEREG); - hooks_.dispatchFetch = GetCodePtr(); - LWU(SCRATCH1, SCRATCH1, 0); - SRLI(SCRATCH2, SCRATCH1, 24); - // We're in other words comparing to the top 8 bits of MIPS_EMUHACK_OPCODE by subtracting. - ADDI(SCRATCH2, SCRATCH2, -(MIPS_EMUHACK_OPCODE >> 24)); - FixupBranch needsCompile = BNE(SCRATCH2, R_ZERO); - // No need to mask, JITBASEREG has already accounted for the upper bits. - ADD(SCRATCH1, JITBASEREG, SCRATCH1); - JR(SCRATCH1); - SetJumpTarget(needsCompile); - - // No block found, let's jit. We don't need to save static regs, they're all callee saved. - RestoreRoundingMode(true); - WriteDebugProfilerStatus(IRProfilerStatus::COMPILING); - QuickCallFunction(&MIPSComp::JitAt, X7); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - ApplyRoundingMode(true); - - // Try again, the block index should be set now. - J(dispatcherNoCheck_); - - SetJumpTarget(bail); - - LI(SCRATCH1, &coreState, SCRATCH2); - LW(SCRATCH1, SCRATCH1, 0); - BEQ(SCRATCH1, R_ZERO, outerLoop_); - - const uint8_t *quitLoop = GetCodePtr(); - SetJumpTarget(badCoreState); - - WriteDebugProfilerStatus(IRProfilerStatus::NOT_RUNNING); - SaveStaticRegisters(); - RestoreRoundingMode(true); - - _assert_msg_(cpu_info.Mode64bit, "RiscVAsm currently assumes RV64, not RV32 or RV128"); - saveOffset = 0; - for (RiscVReg r : regs_to_save) { - LD(r, R_SP, saveOffset); - saveOffset += XLEN / 8; - } - for (RiscVReg r : regs_to_save_fp) { - FL(64, r, R_SP, saveOffset); - saveOffset += XLEN / 8; - } - ADDI(R_SP, R_SP, saveSize); - - RET(); - - hooks_.crashHandler = GetCodePtr(); - LI(SCRATCH1, &coreState, SCRATCH2); - LI(SCRATCH2, CORE_RUNTIME_ERROR); - SW(SCRATCH2, SCRATCH1, 0); - J(quitLoop); - - // Leave this at the end, add more stuff above. - if (enableDisasm) { -#if PPSSPP_ARCH(RISCV64) - std::vector lines = DisassembleRV64(start, GetCodePtr() - start); - for (auto s : lines) { - INFO_LOG(JIT, "%s", s.c_str()); - } -#endif - } - - // Let's spare the pre-generated code from unprotect-reprotect. - AlignCodePage(); - jitStartOffset_ = (int)(GetCodePtr() - start); - // Don't forget to zap the instruction cache! This must stay at the end of this function. - FlushIcache(); - EndWrite(); -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVCompALU.cpp b/Core/MIPS/RiscV/RiscVCompALU.cpp deleted file mode 100644 index 52a13f3fd..000000000 --- a/Core/MIPS/RiscV/RiscVCompALU.cpp +++ /dev/null @@ -1,762 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Common/CPUDetect.h" -#include "Core/MemMap.h" -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -// This file contains compilation for integer / arithmetic / logic related instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -void RiscVJitBackend::CompIR_Arith(IRInst inst) { - CONDITIONAL_DISABLE; - - bool allowPtrMath = true; -#ifdef MASKED_PSP_MEMORY - // Since we modify it, we can't safely. - allowPtrMath = false; -#endif - - // RISC-V only adds signed immediates, so rewrite a small enough subtract to an add. - // We use -2047 and 2048 here because the range swaps. - if (inst.op == IROp::SubConst && (int32_t)inst.constant >= -2047 && (int32_t)inst.constant <= 2048) { - inst.op = IROp::AddConst; - inst.constant = (uint32_t)-(int32_t)inst.constant; - } - - switch (inst.op) { - case IROp::Add: - regs_.Map(inst); - ADDW(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::Sub: - regs_.Map(inst); - SUBW(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::AddConst: - if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { - // Typical of stack pointer updates. - if (regs_.IsGPRMappedAsPointer(inst.dest) && inst.dest == inst.src1 && allowPtrMath) { - regs_.MarkGPRAsPointerDirty(inst.dest); - ADDI(regs_.RPtr(inst.dest), regs_.RPtr(inst.dest), inst.constant); - } else { - regs_.Map(inst); - ADDIW(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant); - regs_.MarkGPRDirty(inst.dest, true); - } - } else { - regs_.Map(inst); - LI(SCRATCH1, (int32_t)inst.constant); - ADDW(regs_.R(inst.dest), regs_.R(inst.src1), SCRATCH1); - regs_.MarkGPRDirty(inst.dest, true); - } - break; - - case IROp::SubConst: - regs_.Map(inst); - LI(SCRATCH1, (int32_t)inst.constant); - SUBW(regs_.R(inst.dest), regs_.R(inst.src1), SCRATCH1); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::Neg: - regs_.Map(inst); - SUBW(regs_.R(inst.dest), R_ZERO, regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Logic(IRInst inst) { - CONDITIONAL_DISABLE; - - bool resultNormalized = false; - switch (inst.op) { - case IROp::And: - if (inst.src1 != inst.src2) { - regs_.Map(inst); - AND(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - } else if (inst.src1 != inst.dest) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - break; - - case IROp::Or: - if (inst.src1 != inst.src2) { - // If both were normalized before, the result is normalized. - resultNormalized = regs_.IsNormalized32(inst.src1) && regs_.IsNormalized32(inst.src2); - regs_.Map(inst); - OR(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, resultNormalized); - } else if (inst.src1 != inst.dest) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - break; - - case IROp::Xor: - if (inst.src1 == inst.src2) { - regs_.SetGPRImm(inst.dest, 0); - } else { - regs_.Map(inst); - XOR(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - } - break; - - case IROp::AndConst: - resultNormalized = regs_.IsNormalized32(inst.src1); - regs_.Map(inst); - if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { - ANDI(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant); - } else { - LI(SCRATCH1, (int32_t)inst.constant); - AND(regs_.R(inst.dest), regs_.R(inst.src1), SCRATCH1); - } - // If the sign bits aren't cleared, and it was normalized before - it still is. - if ((inst.constant & 0x80000000) != 0 && resultNormalized) - regs_.MarkGPRDirty(inst.dest, true); - // Otherwise, if we cleared the sign bits, it's naturally normalized. - else if ((inst.constant & 0x80000000) == 0) - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::OrConst: - resultNormalized = regs_.IsNormalized32(inst.src1); - regs_.Map(inst); - if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { - ORI(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant); - } else { - LI(SCRATCH1, (int32_t)inst.constant); - OR(regs_.R(inst.dest), regs_.R(inst.src1), SCRATCH1); - } - // Since our constant is normalized, oring its bits in won't hurt normalization. - regs_.MarkGPRDirty(inst.dest, resultNormalized); - break; - - case IROp::XorConst: - regs_.Map(inst); - if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { - XORI(regs_.R(inst.dest), regs_.R(inst.src1), inst.constant); - } else { - LI(SCRATCH1, (int32_t)inst.constant); - XOR(regs_.R(inst.dest), regs_.R(inst.src1), SCRATCH1); - } - break; - - case IROp::Not: - regs_.Map(inst); - NOT(regs_.R(inst.dest), regs_.R(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Assign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Mov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - break; - - case IROp::Ext8to32: - regs_.Map(inst); - if (cpu_info.RiscV_Zbb) { - SEXT_B(regs_.R(inst.dest), regs_.R(inst.src1)); - } else { - SLLI(regs_.R(inst.dest), regs_.R(inst.src1), 24); - SRAIW(regs_.R(inst.dest), regs_.R(inst.dest), 24); - } - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::Ext16to32: - regs_.Map(inst); - if (cpu_info.RiscV_Zbb) { - SEXT_H(regs_.R(inst.dest), regs_.R(inst.src1)); - } else { - SLLI(regs_.R(inst.dest), regs_.R(inst.src1), 16); - SRAIW(regs_.R(inst.dest), regs_.R(inst.dest), 16); - } - regs_.MarkGPRDirty(inst.dest, true); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Bits(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::ReverseBits: - if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - // Start by reversing bytes (note: this puts in upper 32 of XLEN.) - REV8(regs_.R(inst.dest), regs_.R(inst.src1)); - - // Swap nibbles. - LI(SCRATCH1, (s32)0xF0F0F0F0); - SRLI(SCRATCH2, regs_.R(inst.dest), XLEN - 32 - 4); - AND(SCRATCH2, SCRATCH2, SCRATCH1); - if (XLEN >= 64) - SRLI(regs_.R(inst.dest), regs_.R(inst.dest), XLEN - 28); - else - SLLI(regs_.R(inst.dest), regs_.R(inst.dest), 4); - SRLIW(SCRATCH1, SCRATCH1, 4); - AND(regs_.R(inst.dest), regs_.R(inst.dest), SCRATCH1); - OR(regs_.R(inst.dest), regs_.R(inst.dest), SCRATCH2); - - // Now the consecutive pairs. - LI(SCRATCH1, (s32)0x33333333); - SRLI(SCRATCH2, regs_.R(inst.dest), 2); - AND(SCRATCH2, SCRATCH2, SCRATCH1); - AND(regs_.R(inst.dest), regs_.R(inst.dest), SCRATCH1); - SLLIW(regs_.R(inst.dest), regs_.R(inst.dest), 2); - OR(regs_.R(inst.dest), regs_.R(inst.dest), SCRATCH2); - - // And finally the even and odd bits. - LI(SCRATCH1, (s32)0x55555555); - SRLI(SCRATCH2, regs_.R(inst.dest), 1); - AND(SCRATCH2, SCRATCH2, SCRATCH1); - AND(regs_.R(inst.dest), regs_.R(inst.dest), SCRATCH1); - SLLIW(regs_.R(inst.dest), regs_.R(inst.dest), 1); - OR(regs_.R(inst.dest), regs_.R(inst.dest), SCRATCH2); - } else { - CompIR_Generic(inst); - } - break; - - case IROp::BSwap16: - CompIR_Generic(inst); - break; - - case IROp::BSwap32: - if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - REV8(regs_.R(inst.dest), regs_.R(inst.src1)); - if (XLEN >= 64) { - // REV8 swaps the entire register, so get the 32 highest bits. - SRAI(regs_.R(inst.dest), regs_.R(inst.dest), XLEN - 32); - regs_.MarkGPRDirty(inst.dest, true); - } - } else { - CompIR_Generic(inst); - } - break; - - case IROp::Clz: - if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - // This even sets to 32 when zero, perfect. - CLZW(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, true); - } else { - CompIR_Generic(inst); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Shift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Shl: - regs_.Map(inst); - SLLW(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::Shr: - regs_.Map(inst); - SRLW(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::Sar: - regs_.Map(inst); - SRAW(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::Ror: - if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - RORW(regs_.R(inst.dest), regs_.R(inst.src1), regs_.R(inst.src2)); - regs_.MarkGPRDirty(inst.dest, true); - } else { - CompIR_Generic(inst); - } - break; - - case IROp::ShlImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - } else { - regs_.Map(inst); - SLLIW(regs_.R(inst.dest), regs_.R(inst.src1), inst.src2); - regs_.MarkGPRDirty(inst.dest, true); - } - break; - - case IROp::ShrImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - } else { - regs_.Map(inst); - SRLIW(regs_.R(inst.dest), regs_.R(inst.src1), inst.src2); - regs_.MarkGPRDirty(inst.dest, true); - } - break; - - case IROp::SarImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.Map(inst); - SRAIW(regs_.R(inst.dest), regs_.R(inst.src1), 31); - regs_.MarkGPRDirty(inst.dest, true); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - } else { - regs_.Map(inst); - SRAIW(regs_.R(inst.dest), regs_.R(inst.src1), inst.src2); - regs_.MarkGPRDirty(inst.dest, true); - } - break; - - case IROp::RorImm: - if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - } else if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - RORIW(regs_.R(inst.dest), regs_.R(inst.src1), inst.src2 & 31); - regs_.MarkGPRDirty(inst.dest, true); - } else { - CompIR_Generic(inst); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Compare(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg lhs = INVALID_REG; - RiscVReg rhs = INVALID_REG; - switch (inst.op) { - case IROp::Slt: - regs_.Map(inst); - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - - SLT(regs_.R(inst.dest), lhs, rhs); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::SltConst: - if (inst.constant == 0) { - // Basically, getting the sign bit. Let's shift instead. - regs_.Map(inst); - SRLIW(regs_.R(inst.dest), regs_.R(inst.src1), 31); - regs_.MarkGPRDirty(inst.dest, true); - } else { - regs_.Map(inst); - NormalizeSrc1(inst, &lhs, SCRATCH1, false); - - if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { - SLTI(regs_.R(inst.dest), lhs, (int32_t)inst.constant); - } else { - LI(SCRATCH2, (int32_t)inst.constant); - SLT(regs_.R(inst.dest), lhs, SCRATCH2); - } - regs_.MarkGPRDirty(inst.dest, true); - } - break; - - case IROp::SltU: - regs_.Map(inst); - // It's still fine to sign extend, the biggest just get even bigger. - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - - SLTU(regs_.R(inst.dest), lhs, rhs); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::SltUConst: - if (inst.constant == 0) { - regs_.SetGPRImm(inst.dest, 0); - } else { - regs_.Map(inst); - NormalizeSrc1(inst, &lhs, SCRATCH1, false); - - // We sign extend because we're comparing against something normalized. - // It's also the most efficient to set. - if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { - SLTIU(regs_.R(inst.dest), lhs, (int32_t)inst.constant); - } else { - LI(SCRATCH2, (int32_t)inst.constant); - SLTU(regs_.R(inst.dest), lhs, SCRATCH2); - } - regs_.MarkGPRDirty(inst.dest, true); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_CondAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg lhs = INVALID_REG; - RiscVReg rhs = INVALID_REG; - FixupBranch fixup; - switch (inst.op) { - case IROp::MovZ: - case IROp::MovNZ: - if (inst.dest == inst.src2) - return; - - // We could have a "zero" with wrong upper due to XOR, so we have to normalize. - regs_.Map(inst); - NormalizeSrc1(inst, &lhs, SCRATCH1, true); - - switch (inst.op) { - case IROp::MovZ: - fixup = BNE(lhs, R_ZERO); - break; - case IROp::MovNZ: - fixup = BEQ(lhs, R_ZERO); - break; - default: - INVALIDOP; - break; - } - - MV(regs_.R(inst.dest), regs_.R(inst.src2)); - SetJumpTarget(fixup); - break; - - case IROp::Max: - if (inst.src1 != inst.src2) { - if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - MAX(regs_.R(inst.dest), lhs, rhs); - // Because we had to normalize the inputs, the output is normalized. - regs_.MarkGPRDirty(inst.dest, true); - } else { - CompIR_Generic(inst); - } - } else if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - break; - - case IROp::Min: - if (inst.src1 != inst.src2) { - if (cpu_info.RiscV_Zbb) { - regs_.Map(inst); - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - MIN(regs_.R(inst.dest), lhs, rhs); - // Because we had to normalize the inputs, the output is normalized. - regs_.MarkGPRDirty(inst.dest, true); - } else { - CompIR_Generic(inst); - } - } else if (inst.dest != inst.src1) { - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(inst.src1)); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_HiLo(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::MtLo: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // First, clear the bits we're replacing. - SRLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - SLLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - // And now, insert the low 32 bits of src1. - if (cpu_info.RiscV_Zba) { - ADD_UW(regs_.R(IRREG_LO), regs_.R(inst.src1), regs_.R(IRREG_LO)); - } else { - SLLI(SCRATCH1, regs_.R(inst.src1), XLEN - 32); - SRLI(SCRATCH1, SCRATCH1, XLEN - 32); - ADD(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - } - break; - - case IROp::MtHi: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - SLLI(SCRATCH1, regs_.R(inst.src1), XLEN - 32); - if (cpu_info.RiscV_Zba) { - ADD_UW(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - } else { - SLLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - SRLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - ADD(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - } - break; - - case IROp::MfLo: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::INIT } }); - // It won't be normalized, but that's fine... - MV(regs_.R(inst.dest), regs_.R(IRREG_LO)); - break; - - case IROp::MfHi: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::INIT } }); - SRAI(regs_.R(inst.dest), regs_.R(IRREG_LO), 32); - if (XLEN == 64) - regs_.MarkGPRDirty(inst.dest, true); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Mult(IRInst inst) { - CONDITIONAL_DISABLE; - - auto makeArgsUnsigned = [&](RiscVReg *lhs, RiscVReg *rhs) { - if (cpu_info.RiscV_Zba) { - ZEXT_W(SCRATCH1, regs_.R(inst.src1)); - ZEXT_W(SCRATCH2, regs_.R(inst.src2)); - } else { - SLLI(SCRATCH1, regs_.R(inst.src1), XLEN - 32); - SRLI(SCRATCH1, SCRATCH1, XLEN - 32); - SLLI(SCRATCH2, regs_.R(inst.src2), XLEN - 32); - SRLI(SCRATCH2, SCRATCH2, XLEN - 32); - } - *lhs = SCRATCH1; - *rhs = SCRATCH2; - }; - - RiscVReg lhs = INVALID_REG; - RiscVReg rhs = INVALID_REG; - switch (inst.op) { - case IROp::Mult: - // TODO: Maybe IR could simplify when HI is not needed or clobbered? - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - MUL(regs_.R(IRREG_LO), lhs, rhs); - break; - - case IROp::MultU: - // This is an "anti-norm32" case. Let's just zero always. - // TODO: If we could know that LO was only needed, we could use MULW. - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - makeArgsUnsigned(&lhs, &rhs); - MUL(regs_.R(IRREG_LO), lhs, rhs); - break; - - case IROp::Madd: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - MUL(SCRATCH1, lhs, rhs); - ADD(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - break; - - case IROp::MaddU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - makeArgsUnsigned(&lhs, &rhs); - MUL(SCRATCH1, lhs, rhs); - ADD(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - break; - - case IROp::Msub: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); - MUL(SCRATCH1, lhs, rhs); - SUB(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - break; - - case IROp::MsubU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - makeArgsUnsigned(&lhs, &rhs); - MUL(SCRATCH1, lhs, rhs); - SUB(regs_.R(IRREG_LO), regs_.R(IRREG_LO), SCRATCH1); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Div(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg numReg, denomReg; - switch (inst.op) { - case IROp::Div: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - // We have to do this because of the divide by zero and overflow checks below. - NormalizeSrc12(inst, &numReg, &denomReg, SCRATCH1, SCRATCH2, true); - DIVW(regs_.R(IRREG_LO), numReg, denomReg); - REMW(R_RA, numReg, denomReg); - // Now to combine them. We'll do more with them below... - SLLI(R_RA, R_RA, 32); - if (cpu_info.RiscV_Zba) { - ADD_UW(regs_.R(IRREG_LO), regs_.R(IRREG_LO), R_RA); - } else { - SLLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - SRLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - ADD(regs_.R(IRREG_LO), regs_.R(IRREG_LO), R_RA); - } - - // Now some tweaks for divide by zero and overflow. - { - // Start with divide by zero, remainder is fine. - FixupBranch skipNonZero = BNE(denomReg, R_ZERO); - FixupBranch keepNegOne = BGE(numReg, R_ZERO); - // Clear the -1 and replace it with 1. - SRLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), 32); - SLLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), 32); - ADDI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), 1); - SetJumpTarget(keepNegOne); - SetJumpTarget(skipNonZero); - - // For overflow, RISC-V sets LO right, but remainder to zero. - // Cheating a bit by using R_RA as a temp... - LI(R_RA, (int32_t)0x80000000); - FixupBranch notMostNegative = BNE(numReg, R_RA); - LI(R_RA, -1); - FixupBranch notNegativeOne = BNE(denomReg, R_RA); - // Take our R_RA and put it in the high bits. - SLLI(R_RA, R_RA, 32); - OR(regs_.R(IRREG_LO), regs_.R(IRREG_LO), R_RA); - SetJumpTarget(notNegativeOne); - SetJumpTarget(notMostNegative); - } - break; - - case IROp::DivU: - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - // We have to do this because of the divide by zero check below. - NormalizeSrc12(inst, &numReg, &denomReg, SCRATCH1, SCRATCH2, true); - DIVUW(regs_.R(IRREG_LO), numReg, denomReg); - REMUW(R_RA, numReg, denomReg); - - // On divide by zero, everything is correct already except the 0xFFFF case. - { - FixupBranch skipNonZero = BNE(denomReg, R_ZERO); - // Luckily, we don't need SCRATCH2/denomReg anymore. - LI(SCRATCH2, 0xFFFF); - FixupBranch keepNegOne = BLTU(SCRATCH2, numReg); - MV(regs_.R(IRREG_LO), SCRATCH2); - SetJumpTarget(keepNegOne); - SetJumpTarget(skipNonZero); - } - - // Now combine the remainder in. - SLLI(R_RA, R_RA, 32); - if (cpu_info.RiscV_Zba) { - ADD_UW(regs_.R(IRREG_LO), regs_.R(IRREG_LO), R_RA); - } else { - SLLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - SRLI(regs_.R(IRREG_LO), regs_.R(IRREG_LO), XLEN - 32); - ADD(regs_.R(IRREG_LO), regs_.R(IRREG_LO), R_RA); - } - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVCompBranch.cpp b/Core/MIPS/RiscV/RiscVCompBranch.cpp deleted file mode 100644 index f8663a82c..000000000 --- a/Core/MIPS/RiscV/RiscVCompBranch.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -// This file contains compilation for exits. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -void RiscVJitBackend::CompIR_Exit(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg exitReg = INVALID_REG; - switch (inst.op) { - case IROp::ExitToConst: - FlushAll(); - WriteConstExit(inst.constant); - break; - - case IROp::ExitToReg: - exitReg = regs_.MapGPR(inst.src1); - FlushAll(); - // TODO: If ever we don't read this back in dispatcherPCInSCRATCH1_, we should zero upper. - MV(SCRATCH1, exitReg); - QuickJ(R_RA, dispatcherPCInSCRATCH1_); - break; - - case IROp::ExitToPC: - FlushAll(); - QuickJ(R_RA, dispatcherCheckCoreState_); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_ExitIf(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg lhs = INVALID_REG; - RiscVReg rhs = INVALID_REG; - FixupBranch fixup; - switch (inst.op) { - case IROp::ExitToConstIfEq: - case IROp::ExitToConstIfNeq: - regs_.Map(inst); - // We can't use SCRATCH1, which is destroyed by FlushAll()... but cheat and use R_RA. - NormalizeSrc12(inst, &lhs, &rhs, R_RA, SCRATCH2, true); - FlushAll(); - - switch (inst.op) { - case IROp::ExitToConstIfEq: - fixup = BNE(lhs, rhs); - break; - - case IROp::ExitToConstIfNeq: - fixup = BEQ(lhs, rhs); - break; - - default: - INVALIDOP; - break; - } - - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfGtZ: - case IROp::ExitToConstIfGeZ: - case IROp::ExitToConstIfLtZ: - case IROp::ExitToConstIfLeZ: - regs_.Map(inst); - NormalizeSrc1(inst, &lhs, SCRATCH2, true); - FlushAll(); - - switch (inst.op) { - case IROp::ExitToConstIfGtZ: - fixup = BGE(R_ZERO, lhs); - break; - - case IROp::ExitToConstIfGeZ: - fixup = BLT(lhs, R_ZERO); - break; - - case IROp::ExitToConstIfLtZ: - fixup = BGE(lhs, R_ZERO); - break; - - case IROp::ExitToConstIfLeZ: - fixup = BLT(R_ZERO, lhs); - break; - - default: - INVALIDOP; - break; - } - - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfFpTrue: - case IROp::ExitToConstIfFpFalse: - // Note: not used. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVCompFPU.cpp b/Core/MIPS/RiscV/RiscVCompFPU.cpp deleted file mode 100644 index 132ef8e58..000000000 --- a/Core/MIPS/RiscV/RiscVCompFPU.cpp +++ /dev/null @@ -1,654 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -// This file contains compilation for floating point related instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -void RiscVJitBackend::CompIR_FArith(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FAdd: - regs_.Map(inst); - FADD(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FSub: - regs_.Map(inst); - FSUB(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FMul: - regs_.Map(inst); - // We'll assume everyone will make it such that 0 * infinity = NAN properly. - // See blame on this comment if that proves untrue. - FMUL(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FDiv: - regs_.Map(inst); - FDIV(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - break; - - case IROp::FSqrt: - regs_.Map(inst); - FSQRT(32, regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FNeg: - regs_.Map(inst); - FNEG(32, regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FCondAssign(IRInst inst) { - CONDITIONAL_DISABLE; - if (inst.op != IROp::FMin && inst.op != IROp::FMax) - INVALIDOP; - bool maxCondition = inst.op == IROp::FMax; - - // FMin and FMax are used by VFPU and handle NAN/INF as just a larger exponent. - regs_.Map(inst); - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - FCLASS(32, SCRATCH2, regs_.F(inst.src2)); - - // If either side is a NAN, it needs to participate in the comparison. - OR(SCRATCH1, SCRATCH1, SCRATCH2); - // NAN is either 0x100 or 0x200. - ANDI(SCRATCH1, SCRATCH1, 0x300); - FixupBranch useNormalCond = BEQ(SCRATCH1, R_ZERO); - - // Time to use bits... classify won't help because it ignores -NAN. - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1)); - FMV(FMv::X, FMv::W, SCRATCH2, regs_.F(inst.src2)); - - // If both are negative, we flip the comparison (not two's compliment.) - // We cheat and use RA... - AND(R_RA, SCRATCH1, SCRATCH2); - SRLIW(R_RA, R_RA, 31); - - if (cpu_info.RiscV_Zbb) { - FixupBranch swapCompare = BNE(R_RA, R_ZERO); - if (maxCondition) - MAX(SCRATCH1, SCRATCH1, SCRATCH2); - else - MIN(SCRATCH1, SCRATCH1, SCRATCH2); - FixupBranch skipSwapCompare = J(); - SetJumpTarget(swapCompare); - if (maxCondition) - MIN(SCRATCH1, SCRATCH1, SCRATCH2); - else - MAX(SCRATCH1, SCRATCH1, SCRATCH2); - SetJumpTarget(skipSwapCompare); - } else { - RiscVReg isSrc1LowerReg = regs_.GetAndLockTempGPR(); - SLT(isSrc1LowerReg, SCRATCH1, SCRATCH2); - // Flip the flag (to reverse the min/max) based on if both were negative. - XOR(isSrc1LowerReg, isSrc1LowerReg, R_RA); - FixupBranch useSrc1; - if (maxCondition) - useSrc1 = BEQ(isSrc1LowerReg, R_ZERO); - else - useSrc1 = BNE(isSrc1LowerReg, R_ZERO); - MV(SCRATCH1, SCRATCH2); - SetJumpTarget(useSrc1); - } - - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - FixupBranch finish = J(); - - SetJumpTarget(useNormalCond); - if (maxCondition) - FMAX(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - else - FMIN(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - SetJumpTarget(finish); -} - -void RiscVJitBackend::CompIR_FAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FMov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - FMV(32, regs_.F(inst.dest), regs_.F(inst.src1)); - } - break; - - case IROp::FAbs: - regs_.Map(inst); - FABS(32, regs_.F(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FSign: - { - regs_.Map(inst); - // Check if it's negative zero, either 0x10/0x08 is zero. - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - ANDI(SCRATCH1, SCRATCH1, 0x18); - SEQZ(SCRATCH1, SCRATCH1); - // Okay, it's zero if zero, 1 otherwise. Convert 1 to a constant 1.0. - // Probably non-zero is the common case, so we make that the straight line. - FixupBranch skipOne = BEQ(SCRATCH1, R_ZERO); - LI(SCRATCH1, 1.0f); - - // Now we just need the sign from it. - FMV(FMv::X, FMv::W, SCRATCH2, regs_.F(inst.src1)); - // Use a wall to isolate the sign, and combine. - SRAIW(SCRATCH2, SCRATCH2, 31); - SLLIW(SCRATCH2, SCRATCH2, 31); - OR(SCRATCH1, SCRATCH1, SCRATCH2); - - SetJumpTarget(skipOne); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - break; - } - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FRound(IRInst inst) { - CONDITIONAL_DISABLE; - - // TODO: If this is followed by a GPR transfer, might want to combine. - regs_.Map(inst); - - switch (inst.op) { - case IROp::FRound: - FCVT(FConv::W, FConv::S, SCRATCH1, regs_.F(inst.src1), Round::NEAREST_EVEN); - break; - - case IROp::FTrunc: - FCVT(FConv::W, FConv::S, SCRATCH1, regs_.F(inst.src1), Round::TOZERO); - break; - - case IROp::FCeil: - FCVT(FConv::W, FConv::S, SCRATCH1, regs_.F(inst.src1), Round::UP); - break; - - case IROp::FFloor: - FCVT(FConv::W, FConv::S, SCRATCH1, regs_.F(inst.src1), Round::DOWN); - break; - - default: - INVALIDOP; - break; - } - - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); -} - -void RiscVJitBackend::CompIR_FCvt(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg tempReg = INVALID_REG; - switch (inst.op) { - case IROp::FCvtWS: - CompIR_Generic(inst); - break; - - case IROp::FCvtSW: - // TODO: This is probably proceeded by a GPR transfer, might be ideal to combine. - regs_.Map(inst); - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1)); - FCVT(FConv::S, FConv::W, regs_.F(inst.dest), SCRATCH1); - break; - - case IROp::FCvtScaledWS: - { - Round rm = Round::NEAREST_EVEN; - switch (inst.src2 >> 6) { - case 0: rm = Round::NEAREST_EVEN; break; - case 1: rm = Round::TOZERO; break; - case 2: rm = Round::UP; break; - case 3: rm = Round::DOWN; break; - default: - _assert_msg_(false, "Invalid rounding mode for FCvtScaledWS"); - } - - tempReg = regs_.MapWithFPRTemp(inst); - // Prepare the multiplier. - LI(SCRATCH1, 1UL << (inst.src2 & 0x1F)); - FCVT(FConv::S, FConv::WU, tempReg, SCRATCH1, rm); - - FMUL(32, regs_.F(inst.dest), regs_.F(inst.src1), tempReg, rm); - // NAN and clamping should all be correct. - FCVT(FConv::W, FConv::S, SCRATCH1, regs_.F(inst.dest), rm); - // TODO: Could combine with a transfer, often is one... - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - break; - } - - case IROp::FCvtScaledSW: - // TODO: This is probably proceeded by a GPR transfer, might be ideal to combine. - tempReg = regs_.MapWithFPRTemp(inst); - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1)); - FCVT(FConv::S, FConv::W, regs_.F(inst.dest), SCRATCH1); - - // Pre-divide so we can avoid any actual divide. - LI(SCRATCH1, 1.0f / (1UL << (inst.src2 & 0x1F))); - FMV(FMv::W, FMv::X, tempReg, SCRATCH1); - FMUL(32, regs_.F(inst.dest), regs_.F(inst.dest), tempReg); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FSat(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg tempReg = INVALID_REG; - FixupBranch skipLower; - FixupBranch finishLower; - FixupBranch skipHigher; - switch (inst.op) { - case IROp::FSat0_1: - tempReg = regs_.MapWithFPRTemp(inst); - if (inst.dest != inst.src1) - FMV(32, regs_.F(inst.dest), regs_.F(inst.src1)); - - // First, set SCRATCH1 = clamp to zero, SCRATCH2 = clamp to one. - FCVT(FConv::S, FConv::W, tempReg, R_ZERO); - // FLE here is intentional to convert -0.0 to +0.0. - FLE(32, SCRATCH1, regs_.F(inst.src1), tempReg); - LI(SCRATCH2, 1.0f); - FMV(FMv::W, FMv::X, tempReg, SCRATCH2); - FLT(32, SCRATCH2, tempReg, regs_.F(inst.src1)); - - skipLower = BEQ(SCRATCH1, R_ZERO); - FCVT(FConv::S, FConv::W, regs_.F(inst.dest), R_ZERO); - finishLower = J(); - - SetJumpTarget(skipLower); - skipHigher = BEQ(SCRATCH2, R_ZERO); - // Still has 1.0 in it. - FMV(32, regs_.F(inst.dest), tempReg); - - SetJumpTarget(finishLower); - SetJumpTarget(skipHigher); - break; - - case IROp::FSatMinus1_1: - tempReg = regs_.MapWithFPRTemp(inst); - if (inst.dest != inst.src1) - FMV(32, regs_.F(inst.dest), regs_.F(inst.src1)); - - // First, set SCRATCH1 = clamp to negative, SCRATCH2 = clamp to positive. - LI(SCRATCH2, -1.0f); - FMV(FMv::W, FMv::X, tempReg, SCRATCH2); - FLT(32, SCRATCH1, regs_.F(inst.src1), tempReg); - FNEG(32, tempReg, tempReg); - FLT(32, SCRATCH2, tempReg, regs_.F(inst.src1)); - - // But we can actually do one branch, using sign-injection to keep the original sign. - OR(SCRATCH1, SCRATCH1, SCRATCH2); - - skipLower = BEQ(SCRATCH1, R_ZERO); - FSGNJ(32, regs_.F(inst.dest), tempReg, regs_.F(inst.dest)); - SetJumpTarget(skipLower); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FCompare(IRInst inst) { - CONDITIONAL_DISABLE; - - constexpr IRReg IRREG_VFPU_CC = IRREG_VFPU_CTRL_BASE + VFPU_CTRL_CC; - - switch (inst.op) { - case IROp::FCmp: - switch (inst.dest) { - case IRFpCompareMode::False: - regs_.SetGPRImm(IRREG_FPCOND, 0); - break; - - case IRFpCompareMode::EitherUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - FCLASS(32, SCRATCH2, regs_.F(inst.src2)); - OR(SCRATCH1, SCRATCH1, SCRATCH2); - // NAN is 0x100 or 0x200. - ANDI(SCRATCH1, SCRATCH1, 0x300); - SNEZ(regs_.R(IRREG_FPCOND), SCRATCH1); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IRFpCompareMode::EqualOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FEQ(32, regs_.R(IRREG_FPCOND), regs_.F(inst.src1), regs_.F(inst.src2)); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IRFpCompareMode::EqualUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FEQ(32, regs_.R(IRREG_FPCOND), regs_.F(inst.src1), regs_.F(inst.src2)); - - // Now let's just OR in the unordered check. - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - FCLASS(32, SCRATCH2, regs_.F(inst.src2)); - OR(SCRATCH1, SCRATCH1, SCRATCH2); - // NAN is 0x100 or 0x200. - ANDI(SCRATCH1, SCRATCH1, 0x300); - SNEZ(SCRATCH1, SCRATCH1); - OR(regs_.R(IRREG_FPCOND), regs_.R(IRREG_FPCOND), SCRATCH1); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IRFpCompareMode::LessEqualOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FLE(32, regs_.R(IRREG_FPCOND), regs_.F(inst.src1), regs_.F(inst.src2)); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IRFpCompareMode::LessEqualUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FLT(32, regs_.R(IRREG_FPCOND), regs_.F(inst.src2), regs_.F(inst.src1)); - SEQZ(regs_.R(IRREG_FPCOND), regs_.R(IRREG_FPCOND)); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IRFpCompareMode::LessOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FLT(32, regs_.R(IRREG_FPCOND), regs_.F(inst.src1), regs_.F(inst.src2)); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IRFpCompareMode::LessUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - FLE(32, regs_.R(IRREG_FPCOND), regs_.F(inst.src2), regs_.F(inst.src1)); - SEQZ(regs_.R(IRREG_FPCOND), regs_.R(IRREG_FPCOND)); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - default: - _assert_msg_(false, "Unexpected IRFpCompareMode %d", inst.dest); - } - break; - - case IROp::FCmovVfpuCC: - regs_.MapWithExtra(inst, { { 'G', IRREG_VFPU_CC, 1, MIPSMap::INIT } }); - if ((inst.src2 & 0xF) == 0) { - ANDI(SCRATCH1, regs_.R(IRREG_VFPU_CC), 1); - } else if (cpu_info.RiscV_Zbs) { - BEXTI(SCRATCH1, regs_.R(IRREG_VFPU_CC), inst.src2 & 0xF); - } else { - SRLI(SCRATCH1, regs_.R(IRREG_VFPU_CC), inst.src2 & 0xF); - ANDI(SCRATCH1, SCRATCH1, 1); - } - if ((inst.src2 >> 7) & 1) { - FixupBranch skip = BEQ(SCRATCH1, R_ZERO); - FMV(32, regs_.F(inst.dest), regs_.F(inst.src1)); - SetJumpTarget(skip); - } else { - FixupBranch skip = BNE(SCRATCH1, R_ZERO); - FMV(32, regs_.F(inst.dest), regs_.F(inst.src1)); - SetJumpTarget(skip); - } - break; - - case IROp::FCmpVfpuBit: - regs_.MapGPR(IRREG_VFPU_CC, MIPSMap::DIRTY); - - switch (VCondition(inst.dest & 0xF)) { - case VC_EQ: - regs_.Map(inst); - FEQ(32, SCRATCH1, regs_.F(inst.src1), regs_.F(inst.src2)); - break; - case VC_NE: - regs_.Map(inst); - FEQ(32, SCRATCH1, regs_.F(inst.src1), regs_.F(inst.src2)); - SEQZ(SCRATCH1, SCRATCH1); - break; - case VC_LT: - regs_.Map(inst); - FLT(32, SCRATCH1, regs_.F(inst.src1), regs_.F(inst.src2)); - break; - case VC_LE: - regs_.Map(inst); - FLE(32, SCRATCH1, regs_.F(inst.src1), regs_.F(inst.src2)); - break; - case VC_GT: - regs_.Map(inst); - FLT(32, SCRATCH1, regs_.F(inst.src2), regs_.F(inst.src1)); - break; - case VC_GE: - regs_.Map(inst); - FLE(32, SCRATCH1, regs_.F(inst.src2), regs_.F(inst.src1)); - break; - case VC_EZ: - case VC_NZ: - regs_.MapFPR(inst.src1); - // Zero is either 0x10 or 0x08. - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - ANDI(SCRATCH1, SCRATCH1, 0x18); - if ((inst.dest & 4) == 0) - SNEZ(SCRATCH1, SCRATCH1); - else - SEQZ(SCRATCH1, SCRATCH1); - break; - case VC_EN: - case VC_NN: - regs_.MapFPR(inst.src1); - // NAN is either 0x100 or 0x200. - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - ANDI(SCRATCH1, SCRATCH1, 0x300); - if ((inst.dest & 4) == 0) - SNEZ(SCRATCH1, SCRATCH1); - else - SEQZ(SCRATCH1, SCRATCH1); - break; - case VC_EI: - case VC_NI: - regs_.MapFPR(inst.src1); - // Infinity is either 0x80 or 0x01. - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - ANDI(SCRATCH1, SCRATCH1, 0x81); - if ((inst.dest & 4) == 0) - SNEZ(SCRATCH1, SCRATCH1); - else - SEQZ(SCRATCH1, SCRATCH1); - break; - case VC_ES: - case VC_NS: - regs_.MapFPR(inst.src1); - // Infinity is either 0x80 or 0x01, NAN is either 0x100 or 0x200. - FCLASS(32, SCRATCH1, regs_.F(inst.src1)); - ANDI(SCRATCH1, SCRATCH1, 0x381); - if ((inst.dest & 4) == 0) - SNEZ(SCRATCH1, SCRATCH1); - else - SEQZ(SCRATCH1, SCRATCH1); - break; - case VC_TR: - LI(SCRATCH1, 1); - break; - case VC_FL: - LI(SCRATCH1, 0); - break; - } - - ANDI(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), ~(1 << (inst.dest >> 4))); - if ((inst.dest >> 4) != 0) - SLLI(SCRATCH1, SCRATCH1, inst.dest >> 4); - OR(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), SCRATCH1); - break; - - case IROp::FCmpVfpuAggregate: - regs_.MapGPR(IRREG_VFPU_CC, MIPSMap::DIRTY); - if (inst.dest == 1) { - ANDI(SCRATCH1, regs_.R(IRREG_VFPU_CC), inst.dest); - // Negate so 1 becomes all bits set and zero stays zero, then mask to 0x30. - NEG(SCRATCH1, SCRATCH1); - ANDI(SCRATCH1, SCRATCH1, 0x30); - - // Reject the old any/all bits and replace them with our own. - ANDI(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), ~0x30); - OR(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), SCRATCH1); - } else { - ANDI(SCRATCH1, regs_.R(IRREG_VFPU_CC), inst.dest); - FixupBranch skipZero = BEQ(SCRATCH1, R_ZERO); - - // To compare to inst.dest for "all", let's simply subtract it and compare to zero. - ADDI(SCRATCH1, SCRATCH1, -inst.dest); - SEQZ(SCRATCH1, SCRATCH1); - // Now we combine with the "any" bit. - SLLI(SCRATCH1, SCRATCH1, 5); - ORI(SCRATCH1, SCRATCH1, 0x10); - - SetJumpTarget(skipZero); - - // Reject the old any/all bits and replace them with our own. - ANDI(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), ~0x30); - OR(regs_.R(IRREG_VFPU_CC), regs_.R(IRREG_VFPU_CC), SCRATCH1); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_RoundingMode(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::RestoreRoundingMode: - RestoreRoundingMode(); - break; - - case IROp::ApplyRoundingMode: - ApplyRoundingMode(); - break; - - case IROp::UpdateRoundingMode: - // We don't need to do anything, instructions allow a "dynamic" rounding mode. - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FSpecial(IRInst inst) { - CONDITIONAL_DISABLE; - -#ifdef __riscv_float_abi_soft -#error Currently hard float is required. -#endif - - auto callFuncF_F = [&](float (*func)(float)) { - regs_.FlushBeforeCall(); - WriteDebugProfilerStatus(IRProfilerStatus::MATH_HELPER); - - // It might be in a non-volatile register. - // TODO: May have to handle a transfer if SIMD here. - if (regs_.IsFPRMapped(inst.src1)) { - FMV(32, F10, regs_.F(inst.src1)); - } else { - int offset = offsetof(MIPSState, f) + inst.src1 * 4; - FL(32, F10, CTXREG, offset); - } - QuickCallFunction(func, SCRATCH1); - - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - // If it's already F10, we're done - MapReg doesn't actually overwrite the reg in that case. - if (regs_.F(inst.dest) != F10) { - FMV(32, regs_.F(inst.dest), F10); - } - - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - }; - - RiscVReg tempReg = INVALID_REG; - switch (inst.op) { - case IROp::FSin: - callFuncF_F(&vfpu_sin); - break; - - case IROp::FCos: - callFuncF_F(&vfpu_cos); - break; - - case IROp::FRSqrt: - tempReg = regs_.MapWithFPRTemp(inst); - FSQRT(32, regs_.F(inst.dest), regs_.F(inst.src1)); - - // Ugh, we can't really avoid a temp here. Probably not worth a permanent one. - LI(SCRATCH1, 1.0f); - FMV(FMv::W, FMv::X, tempReg, SCRATCH1); - FDIV(32, regs_.F(inst.dest), tempReg, regs_.F(inst.dest)); - break; - - case IROp::FRecip: - if (inst.dest != inst.src1) { - // This is the easy case. - regs_.Map(inst); - LI(SCRATCH1, 1.0f); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - FDIV(32, regs_.F(inst.dest), regs_.F(inst.dest), regs_.F(inst.src1)); - } else { - tempReg = regs_.MapWithFPRTemp(inst); - LI(SCRATCH1, 1.0f); - FMV(FMv::W, FMv::X, tempReg, SCRATCH1); - FDIV(32, regs_.F(inst.dest), tempReg, regs_.F(inst.src1)); - } - break; - - case IROp::FAsin: - callFuncF_F(&vfpu_asin); - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp deleted file mode 100644 index 9db1ebb65..000000000 --- a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Core/MemMap.h" -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -// This file contains compilation for load/store instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -void RiscVJitBackend::SetScratch1ToSrc1Address(IRReg src1) { - regs_.MapGPR(src1); -#ifdef MASKED_PSP_MEMORY - SLLIW(SCRATCH1, regs_.R(src1), 2); - SRLIW(SCRATCH1, SCRATCH1, 2); - ADD(SCRATCH1, SCRATCH1, MEMBASEREG); -#else - // Clear the top bits to be safe. - if (cpu_info.RiscV_Zba) { - ADD_UW(SCRATCH1, regs_.R(src1), MEMBASEREG); - } else { - _assert_(XLEN == 64); - SLLI(SCRATCH1, regs_.R(src1), 32); - SRLI(SCRATCH1, SCRATCH1, 32); - ADD(SCRATCH1, SCRATCH1, MEMBASEREG); - } -#endif -} - -int32_t RiscVJitBackend::AdjustForAddressOffset(RiscVGen::RiscVReg *reg, int32_t constant, int32_t range) { - if (constant < -2048 || constant + range > 2047) { -#ifdef MASKED_PSP_MEMORY - if (constant > 0) - constant &= Memory::MEMVIEW32_MASK; -#endif - // It can't be this negative, must be a constant with top bit set. - if ((constant & 0xC0000000) == 0x80000000) { - if (cpu_info.RiscV_Zba) { - LI(SCRATCH2, constant); - ADD_UW(SCRATCH1, SCRATCH2, *reg); - } else { - LI(SCRATCH2, (uint32_t)constant); - ADD(SCRATCH1, *reg, SCRATCH2); - } - } else { - LI(SCRATCH2, constant); - ADD(SCRATCH1, *reg, SCRATCH2); - } - *reg = SCRATCH1; - return 0; - } - return constant; -} - -void RiscVJitBackend::CompIR_Load(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.SpillLockGPR(inst.dest, inst.src1); - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - // With NOINIT, MapReg won't subtract MEMBASEREG even if dest == src1. - regs_.MapGPR(inst.dest, MIPSMap::NOINIT); - regs_.MarkGPRDirty(inst.dest, true); - - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::Load8: - LBU(regs_.R(inst.dest), addrReg, imm); - break; - - case IROp::Load8Ext: - LB(regs_.R(inst.dest), addrReg, imm); - break; - - case IROp::Load16: - LHU(regs_.R(inst.dest), addrReg, imm); - break; - - case IROp::Load16Ext: - LH(regs_.R(inst.dest), addrReg, imm); - break; - - case IROp::Load32: - LW(regs_.R(inst.dest), addrReg, imm); - break; - - case IROp::Load32Linked: - if (inst.dest != MIPS_REG_ZERO) - LW(regs_.R(inst.dest), addrReg, imm); - regs_.SetGPRImm(IRREG_LLBIT, 1); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_LoadShift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Load32Left: - case IROp::Load32Right: - // Should not happen if the pass to split is active. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FLoad(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::LoadFloat: - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - FL(32, regs_.F(inst.dest), addrReg, imm); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_VecLoad(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - - // We need to be able to address the whole 16 bytes, so offset of 12. - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant, 12); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::LoadVec4: - for (int i = 0; i < 4; ++i) { - // Spilling is okay. - regs_.MapFPR(inst.dest + i, MIPSMap::NOINIT); - FL(32, regs_.F(inst.dest + i), addrReg, imm + 4 * i); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Store(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.SpillLockGPR(inst.src3, inst.src1); - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if ((jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - RiscVReg valueReg = regs_.TryMapTempImm(inst.src3); - if (valueReg == INVALID_REG) - valueReg = regs_.MapGPR(inst.src3); - - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::Store8: - SB(valueReg, addrReg, imm); - break; - - case IROp::Store16: - SH(valueReg, addrReg, imm); - break; - - case IROp::Store32: - SW(valueReg, addrReg, imm); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_CondStore(IRInst inst) { - CONDITIONAL_DISABLE; - if (inst.op != IROp::Store32Conditional) - INVALIDOP; - - regs_.SpillLockGPR(IRREG_LLBIT, inst.src3, inst.src1); - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if ((jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - regs_.MapGPR(inst.src3, inst.dest == MIPS_REG_ZERO ? MIPSMap::INIT : MIPSMap::DIRTY); - regs_.MapGPR(IRREG_LLBIT); - - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - FixupBranch condFailed = BEQ(regs_.R(IRREG_LLBIT), R_ZERO); - SW(regs_.R(inst.src3), addrReg, imm); - - if (inst.dest != MIPS_REG_ZERO) { - LI(regs_.R(inst.dest), 1); - FixupBranch finish = J(); - - SetJumpTarget(condFailed); - LI(regs_.R(inst.dest), 0); - SetJumpTarget(finish); - } else { - SetJumpTarget(condFailed); - } -} - -void RiscVJitBackend::CompIR_StoreShift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Store32Left: - case IROp::Store32Right: - // Should not happen if the pass to split is active. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_FStore(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::StoreFloat: - regs_.MapFPR(inst.src3); - FS(32, regs_.F(inst.src3), addrReg, imm); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_VecStore(IRInst inst) { - CONDITIONAL_DISABLE; - - RiscVReg addrReg = INVALID_REG; - if (inst.src1 == MIPS_REG_ZERO) { - // This will get changed by AdjustForAddressOffset. - addrReg = MEMBASEREG; -#ifdef MASKED_PSP_MEMORY - inst.constant &= Memory::MEMVIEW32_MASK; -#endif - } else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) { - addrReg = regs_.MapGPRAsPointer(inst.src1); - } else { - SetScratch1ToSrc1Address(inst.src1); - addrReg = SCRATCH1; - } - - // We need to be able to address the whole 16 bytes, so offset of 12. - s32 imm = AdjustForAddressOffset(&addrReg, inst.constant, 12); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::StoreVec4: - for (int i = 0; i < 4; ++i) { - // Spilling is okay, though not ideal. - regs_.MapFPR(inst.src3 + i); - FS(32, regs_.F(inst.src3 + i), addrReg, imm + 4 * i); - } - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVCompSystem.cpp b/Core/MIPS/RiscV/RiscVCompSystem.cpp deleted file mode 100644 index 4605648ed..000000000 --- a/Core/MIPS/RiscV/RiscVCompSystem.cpp +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "Common/Profiler/Profiler.h" -#include "Core/Core.h" -#include "Core/HLE/HLE.h" -#include "Core/HLE/ReplaceTables.h" -#include "Core/MemMap.h" -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -// This file contains compilation for basic PC/downcount accounting, syscalls, debug funcs, etc. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -void RiscVJitBackend::CompIR_Basic(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::SetConst: - // Sign extend all constants. We get 0xFFFFFFFF sometimes, and it's more work to truncate. - // The register only holds 32 bits in the end anyway. - regs_.SetGPRImm(inst.dest, (int32_t)inst.constant); - break; - - case IROp::SetConstF: - regs_.Map(inst); - if (inst.constant == 0) { - FCVT(FConv::S, FConv::W, regs_.F(inst.dest), R_ZERO); - } else { - // TODO: In the future, could use FLI if it's approved. - // Also, is FCVT faster? - LI(SCRATCH1, (int32_t)inst.constant); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - } - break; - - case IROp::Downcount: - if (inst.constant <= 2048) { - ADDI(DOWNCOUNTREG, DOWNCOUNTREG, -(s32)inst.constant); - } else { - LI(SCRATCH1, inst.constant, SCRATCH2); - SUB(DOWNCOUNTREG, DOWNCOUNTREG, SCRATCH1); - } - break; - - case IROp::SetPC: - regs_.Map(inst); - MovToPC(regs_.R(inst.src1)); - break; - - case IROp::SetPCConst: - LI(SCRATCH1, inst.constant, SCRATCH2); - MovToPC(SCRATCH1); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Transfer(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::SetCtrlVFPU: - regs_.SetGPRImm(IRREG_VFPU_CTRL_BASE + inst.dest, inst.constant); - break; - - case IROp::SetCtrlVFPUReg: - regs_.Map(inst); - MV(regs_.R(IRREG_VFPU_CTRL_BASE + inst.dest), regs_.R(inst.src1)); - regs_.MarkGPRDirty(IRREG_VFPU_CTRL_BASE + inst.dest, regs_.IsNormalized32(inst.src1)); - break; - - case IROp::SetCtrlVFPUFReg: - regs_.Map(inst); - FMV(FMv::X, FMv::W, regs_.R(IRREG_VFPU_CTRL_BASE + inst.dest), regs_.F(inst.src1)); - regs_.MarkGPRDirty(IRREG_VFPU_CTRL_BASE + inst.dest, true); - break; - - case IROp::FpCondFromReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - MV(regs_.R(IRREG_FPCOND), regs_.R(inst.src1)); - break; - - case IROp::FpCondToReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::INIT } }); - MV(regs_.R(inst.dest), regs_.R(IRREG_FPCOND)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(IRREG_FPCOND)); - break; - - case IROp::FpCtrlFromReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - LI(SCRATCH1, 0x0181FFFF); - AND(SCRATCH1, regs_.R(inst.src1), SCRATCH1); - // Extract the new fpcond value. - if (cpu_info.RiscV_Zbs) { - BEXTI(regs_.R(IRREG_FPCOND), SCRATCH1, 23); - } else { - SRLI(regs_.R(IRREG_FPCOND), SCRATCH1, 23); - ANDI(regs_.R(IRREG_FPCOND), regs_.R(IRREG_FPCOND), 1); - } - SW(SCRATCH1, CTXREG, IRREG_FCR31 * 4); - regs_.MarkGPRDirty(IRREG_FPCOND, true); - break; - - case IROp::FpCtrlToReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::INIT } }); - // Load fcr31 and clear the fpcond bit. - LW(SCRATCH1, CTXREG, IRREG_FCR31 * 4); - if (cpu_info.RiscV_Zbs) { - BCLRI(SCRATCH1, SCRATCH1, 23); - } else { - LI(SCRATCH2, ~(1 << 23)); - AND(SCRATCH1, SCRATCH1, SCRATCH2); - } - - // Now get the correct fpcond bit. - ANDI(SCRATCH2, regs_.R(IRREG_FPCOND), 1); - SLLI(SCRATCH2, SCRATCH2, 23); - OR(regs_.R(inst.dest), SCRATCH1, SCRATCH2); - - // Also update mips->fcr31 while we're here. - SW(regs_.R(inst.dest), CTXREG, IRREG_FCR31 * 4); - regs_.MarkGPRDirty(inst.dest, true); - break; - - case IROp::VfpuCtrlToReg: - regs_.Map(inst); - MV(regs_.R(inst.dest), regs_.R(IRREG_VFPU_CTRL_BASE + inst.src1)); - regs_.MarkGPRDirty(inst.dest, regs_.IsNormalized32(IRREG_VFPU_CTRL_BASE + inst.src1)); - break; - - case IROp::FMovFromGPR: - if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) { - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - FCVT(FConv::S, FConv::W, regs_.F(inst.dest), R_ZERO); - } else { - regs_.Map(inst); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::FMovToGPR: - regs_.Map(inst); - FMV(FMv::X, FMv::W, regs_.R(inst.dest), regs_.F(inst.src1)); - regs_.MarkGPRDirty(inst.dest, true); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_System(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Syscall: - FlushAll(); - SaveStaticRegisters(); - - WriteDebugProfilerStatus(IRProfilerStatus::SYSCALL); -#ifdef USE_PROFILER - // When profiling, we can't skip CallSyscall, since it times syscalls. - LI(X10, (int32_t)inst.constant); - QuickCallFunction(&CallSyscall, SCRATCH2); -#else - // Skip the CallSyscall where possible. - { - MIPSOpcode op(inst.constant); - void *quickFunc = GetQuickSyscallFunc(op); - if (quickFunc) { - LI(X10, (uintptr_t)GetSyscallFuncPointer(op)); - QuickCallFunction((const u8 *)quickFunc, SCRATCH2); - } else { - LI(X10, (int32_t)inst.constant); - QuickCallFunction(&CallSyscall, SCRATCH2); - } - } -#endif - - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - // This is always followed by an ExitToPC, where we check coreState. - break; - - case IROp::CallReplacement: - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::REPLACEMENT); - QuickCallFunction(GetReplacementFunc(inst.constant)->replaceFunc, SCRATCH2); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - SUB(DOWNCOUNTREG, DOWNCOUNTREG, X10); - break; - - case IROp::Break: - FlushAll(); - // This doesn't naturally have restore/apply around it. - RestoreRoundingMode(true); - SaveStaticRegisters(); - MovFromPC(X10); - QuickCallFunction(&Core_Break, SCRATCH2); - LoadStaticRegisters(); - ApplyRoundingMode(true); - MovFromPC(SCRATCH1); - ADDI(SCRATCH1, SCRATCH1, 4); - QuickJ(R_RA, dispatcherPCInSCRATCH1_); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_Breakpoint(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Breakpoint: - case IROp::MemoryCheck: - CompIR_Generic(inst); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_ValidateAddress(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::ValidateAddress8: - case IROp::ValidateAddress16: - case IROp::ValidateAddress32: - case IROp::ValidateAddress128: - CompIR_Generic(inst); - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVCompVec.cpp b/Core/MIPS/RiscV/RiscVCompVec.cpp deleted file mode 100644 index b220d0ce8..000000000 --- a/Core/MIPS/RiscV/RiscVCompVec.cpp +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include -#include "Core/MemMap.h" -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -// This file contains compilation for vector instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -static bool Overlap(IRReg r1, int l1, IRReg r2, int l2) { - return r1 < r2 + l2 && r1 + l1 > r2; -} - -void RiscVJitBackend::CompIR_VecAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Init: - regs_.Map(inst); - - // TODO: Check if FCVT/FMV/FL is better. - switch ((Vec4Init)inst.src1) { - case Vec4Init::AllZERO: - for (int i = 0; i < 4; ++i) - FCVT(FConv::S, FConv::W, regs_.F(inst.dest + i), R_ZERO); - break; - - case Vec4Init::AllONE: - LI(SCRATCH1, 1.0f); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - for (int i = 1; i < 4; ++i) - FMV(32, regs_.F(inst.dest + i), regs_.F(inst.dest)); - break; - - case Vec4Init::AllMinusONE: - LI(SCRATCH1, -1.0f); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - for (int i = 1; i < 4; ++i) - FMV(32, regs_.F(inst.dest + i), regs_.F(inst.dest)); - break; - - case Vec4Init::Set_1000: - LI(SCRATCH1, 1.0f); - for (int i = 0; i < 4; ++i) { - if (i == 0) - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - else - FCVT(FConv::S, FConv::W, regs_.F(inst.dest + i), R_ZERO); - } - break; - - case Vec4Init::Set_0100: - LI(SCRATCH1, 1.0f); - for (int i = 0; i < 4; ++i) { - if (i == 1) - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - else - FCVT(FConv::S, FConv::W, regs_.F(inst.dest + i), R_ZERO); - } - break; - - case Vec4Init::Set_0010: - LI(SCRATCH1, 1.0f); - for (int i = 0; i < 4; ++i) { - if (i == 2) - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - else - FCVT(FConv::S, FConv::W, regs_.F(inst.dest + i), R_ZERO); - } - break; - - case Vec4Init::Set_0001: - LI(SCRATCH1, 1.0f); - for (int i = 0; i < 4; ++i) { - if (i == 3) - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - else - FCVT(FConv::S, FConv::W, regs_.F(inst.dest + i), R_ZERO); - } - break; - } - break; - - case IROp::Vec4Shuffle: - if (inst.dest == inst.src1) { - RiscVReg tempReg = regs_.MapWithFPRTemp(inst); - - // Try to find the least swaps needed to move in place, never worse than 6 FMVs. - // Would be better with a vmerge and vector regs. - int state[4]{ 0, 1, 2, 3 }; - int goal[4]{ (inst.src2 >> 0) & 3, (inst.src2 >> 2) & 3, (inst.src2 >> 4) & 3, (inst.src2 >> 6) & 3 }; - - static constexpr int NOT_FOUND = 4; - auto findIndex = [](int *arr, int val, int start = 0) { - return (int)(std::find(arr + start, arr + 4, val) - arr); - }; - auto moveChained = [&](const std::vector &lanes, bool rotate) { - int firstState = state[lanes.front()]; - if (rotate) - FMV(32, tempReg, regs_.F(inst.dest + lanes.front())); - for (size_t i = 1; i < lanes.size(); ++i) { - FMV(32, regs_.F(inst.dest + lanes[i - 1]), regs_.F(inst.dest + lanes[i])); - state[lanes[i - 1]] = state[lanes[i]]; - } - if (rotate) { - FMV(32, regs_.F(inst.dest + lanes.back()), tempReg); - state[lanes.back()] = firstState; - } - }; - - for (int i = 0; i < 4; ++i) { - // Overlap, so if they match, nothing to do. - if (goal[i] == state[i]) - continue; - - int neededBy = findIndex(goal, state[i], i + 1); - int foundIn = findIndex(state, goal[i], 0); - _assert_(foundIn != NOT_FOUND); - - if (neededBy == NOT_FOUND || neededBy == foundIn) { - moveChained({ i, foundIn }, neededBy == foundIn); - continue; - } - - // Maybe we can avoid a swap and move the next thing into place. - int neededByDepth2 = findIndex(goal, state[neededBy], i + 1); - if (neededByDepth2 == NOT_FOUND || neededByDepth2 == foundIn) { - moveChained({ neededBy, i, foundIn }, neededByDepth2 == foundIn); - continue; - } - - // Since we only have 4 items, this is as deep as the chain could go. - int neededByDepth3 = findIndex(goal, state[neededByDepth2], i + 1); - moveChained({ neededByDepth2, neededBy, i, foundIn }, neededByDepth3 == foundIn); - } - } else { - regs_.Map(inst); - for (int i = 0; i < 4; ++i) { - int lane = (inst.src2 >> (i * 2)) & 3; - FMV(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + lane)); - } - } - break; - - case IROp::Vec4Blend: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) { - int which = (inst.constant >> i) & 1; - IRReg srcReg = which ? inst.src2 : inst.src1; - if (inst.dest != srcReg) - FMV(32, regs_.F(inst.dest + i), regs_.F(srcReg + i)); - } - break; - - case IROp::Vec4Mov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FMV(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i)); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_VecArith(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Add: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FADD(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i)); - break; - - case IROp::Vec4Sub: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FSUB(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i)); - break; - - case IROp::Vec4Mul: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FMUL(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i)); - break; - - case IROp::Vec4Div: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FDIV(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i)); - break; - - case IROp::Vec4Scale: - regs_.Map(inst); - if (Overlap(inst.src2, 1, inst.dest, 3)) { - // We have to handle overlap, doing dest == src2 last. - for (int i = 0; i < 4; ++i) { - if (inst.src2 != inst.dest + i) - FMUL(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2)); - } - for (int i = 0; i < 4; ++i) { - if (inst.src2 == inst.dest + i) - FMUL(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2)); - } - } else { - for (int i = 0; i < 4; ++i) - FMUL(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i), regs_.F(inst.src2)); - } - break; - - case IROp::Vec4Neg: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FNEG(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i)); - break; - - case IROp::Vec4Abs: - regs_.Map(inst); - for (int i = 0; i < 4; ++i) - FABS(32, regs_.F(inst.dest + i), regs_.F(inst.src1 + i)); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_VecHoriz(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Dot: - regs_.Map(inst); - if (Overlap(inst.dest, 1, inst.src1, 4) || Overlap(inst.dest, 1, inst.src2, 4)) { - // This means inst.dest overlaps one of src1 or src2. We have to do that one first. - // Technically this may impact -0.0 and such, but dots accurately need to be aligned anyway. - for (int i = 0; i < 4; ++i) { - if (inst.dest == inst.src1 + i || inst.dest == inst.src2 + i) - FMUL(32, regs_.F(inst.dest), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i)); - } - for (int i = 0; i < 4; ++i) { - if (inst.dest != inst.src1 + i && inst.dest != inst.src2 + i) - FMADD(32, regs_.F(inst.dest), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i), regs_.F(inst.dest)); - } - } else { - FMUL(32, regs_.F(inst.dest), regs_.F(inst.src1), regs_.F(inst.src2)); - for (int i = 1; i < 4; ++i) - FMADD(32, regs_.F(inst.dest), regs_.F(inst.src1 + i), regs_.F(inst.src2 + i), regs_.F(inst.dest)); - } - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_VecPack(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec2Unpack16To31: - case IROp::Vec4Pack32To8: - case IROp::Vec2Pack31To16: - CompIR_Generic(inst); - break; - - case IROp::Vec4Unpack8To32: - // TODO: This works for now, but may need to handle aliasing for vectors. - regs_.Map(inst); - FMV(FMv::X, FMv::W, SCRATCH2, regs_.F(inst.src1)); - for (int i = 0; i < 4; ++i) { - // Mask using walls. - if (i != 0) { - SRLI(SCRATCH1, SCRATCH2, i * 8); - SLLI(SCRATCH1, SCRATCH1, 24); - } else { - SLLI(SCRATCH1, SCRATCH2, 24); - } - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - } - break; - - case IROp::Vec2Unpack16To32: - // TODO: This works for now, but may need to handle aliasing for vectors. - regs_.Map(inst); - FMV(FMv::X, FMv::W, SCRATCH2, regs_.F(inst.src1)); - SLLI(SCRATCH1, SCRATCH2, 16); - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - SRLI(SCRATCH1, SCRATCH2, 16); - SLLI(SCRATCH1, SCRATCH1, 16); - FMV(FMv::W, FMv::X, regs_.F(inst.dest + 1), SCRATCH1); - break; - - case IROp::Vec4DuplicateUpperBitsAndShift1: - regs_.Map(inst); - for (int i = 0; i < 4; i++) { - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1 + i)); - SRLIW(SCRATCH2, SCRATCH1, 8); - OR(SCRATCH1, SCRATCH1, SCRATCH2); - SRLIW(SCRATCH2, SCRATCH1, 16); - OR(SCRATCH1, SCRATCH1, SCRATCH2); - SRLIW(SCRATCH1, SCRATCH1, 1); - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - } - break; - - case IROp::Vec4Pack31To8: - // TODO: This works for now, but may need to handle aliasing for vectors. - regs_.Map(inst); - for (int i = 0; i < 4; ++i) { - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1 + i)); - SRLI(SCRATCH1, SCRATCH1, 23); - if (i == 0) { - ANDI(SCRATCH2, SCRATCH1, 0xFF); - } else { - ANDI(SCRATCH1, SCRATCH1, 0xFF); - SLLI(SCRATCH1, SCRATCH1, 8 * i); - OR(SCRATCH2, SCRATCH2, SCRATCH1); - } - } - - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH2); - break; - - case IROp::Vec2Pack32To16: - // TODO: This works for now, but may need to handle aliasing for vectors. - regs_.Map(inst); - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1)); - FMV(FMv::X, FMv::W, SCRATCH2, regs_.F(inst.src1 + 1)); - // Keep in mind, this was sign-extended, so we have to zero the upper. - SLLI(SCRATCH1, SCRATCH1, XLEN - 32); - // Now we just set (SCRATCH2 & 0xFFFF0000) | SCRATCH1. - SRLI(SCRATCH1, SCRATCH1, XLEN - 16); - // Use a wall to mask. We can ignore the upper 32 here. - SRLI(SCRATCH2, SCRATCH2, 16); - SLLI(SCRATCH2, SCRATCH2, 16); - OR(SCRATCH1, SCRATCH1, SCRATCH2); - // Okay, to the floating point register. - FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1); - break; - - default: - INVALIDOP; - break; - } -} - -void RiscVJitBackend::CompIR_VecClamp(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4ClampToZero: - regs_.Map(inst); - for (int i = 0; i < 4; i++) { - FMV(FMv::X, FMv::W, SCRATCH1, regs_.F(inst.src1 + i)); - SRAIW(SCRATCH2, SCRATCH1, 31); - if (cpu_info.RiscV_Zbb) { - ANDN(SCRATCH1, SCRATCH1, SCRATCH2); - } else { - NOT(SCRATCH2, SCRATCH2); - AND(SCRATCH1, SCRATCH1, SCRATCH2); - } - FMV(FMv::W, FMv::X, regs_.F(inst.dest + i), SCRATCH1); - } - break; - - case IROp::Vec2ClampToZero: - CompIR_Generic(inst); - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp deleted file mode 100644 index 60d5c5f92..000000000 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include -#include "Core/MemMap.h" -#include "Core/MIPS/MIPSTables.h" -#include "Core/MIPS/RiscV/RiscVJit.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -#include -// for std::min - -namespace MIPSComp { - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -// Needs space for a LI and J which might both be 32-bit offsets. -static constexpr int MIN_BLOCK_NORMAL_LEN = 16; -static constexpr int MIN_BLOCK_EXIT_LEN = 8; - -RiscVJitBackend::RiscVJitBackend(JitOptions &jitopt, IRBlockCache &blocks) - : IRNativeBackend(blocks), jo(jitopt), regs_(&jo) { - // Automatically disable incompatible options. - if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { - jo.enablePointerify = false; - } - - // Since we store the offset, this is as big as it can be. - // We could shift off one bit to double it, would need to change RiscVAsm. - AllocCodeSpace(1024 * 1024 * 16); - SetAutoCompress(true); - - regs_.Init(this); -} - -RiscVJitBackend::~RiscVJitBackend() { -} - -static void NoBlockExits() { - _assert_msg_(false, "Never exited block, invalid IR?"); -} - -bool RiscVJitBackend::CompileBlock(IRBlock *block, int block_num, bool preload) { - if (GetSpaceLeft() < 0x800) - return false; - - BeginWrite(std::min(GetSpaceLeft(), (size_t)block->GetNumInstructions() * 32)); - - u32 startPC = block->GetOriginalStart(); - bool wroteCheckedOffset = false; - if (jo.enableBlocklink && !jo.useBackJump) { - SetBlockCheckedOffset(block_num, (int)GetOffset(GetCodePointer())); - wroteCheckedOffset = true; - - WriteDebugPC(startPC); - - FixupBranch normalEntry = BGE(DOWNCOUNTREG, R_ZERO); - LI(SCRATCH1, startPC); - QuickJ(R_RA, outerLoopPCInSCRATCH1_); - SetJumpTarget(normalEntry); - } - - // Don't worry, the codespace isn't large enough to overflow offsets. - const u8 *blockStart = GetCodePointer(); - block->SetTargetOffset((int)GetOffset(blockStart)); - compilingBlockNum_ = block_num; - - regs_.Start(block); - - std::vector addresses; - for (int i = 0; i < block->GetNumInstructions(); ++i) { - const IRInst &inst = block->GetInstructions()[i]; - regs_.SetIRIndex(i); - addresses.push_back(GetCodePtr()); - - CompileIRInst(inst); - - if (jo.Disabled(JitDisable::REGALLOC_GPR) || jo.Disabled(JitDisable::REGALLOC_FPR)) - regs_.FlushAll(jo.Disabled(JitDisable::REGALLOC_GPR), jo.Disabled(JitDisable::REGALLOC_FPR)); - - // Safety check, in case we get a bunch of really large jit ops without a lot of branching. - if (GetSpaceLeft() < 0x800) { - compilingBlockNum_ = -1; - return false; - } - } - - // We should've written an exit above. If we didn't, bad things will happen. - // Only check if debug stats are enabled - needlessly wastes jit space. - if (DebugStatsEnabled()) { - QuickCallFunction(&NoBlockExits, SCRATCH2); - QuickJ(R_RA, hooks_.crashHandler); - } - - int len = (int)GetOffset(GetCodePointer()) - block->GetTargetOffset(); - if (len < MIN_BLOCK_NORMAL_LEN) { - // We need at least 16 bytes to invalidate blocks with, but larger doesn't need to align. - ReserveCodeSpace(MIN_BLOCK_NORMAL_LEN - len); - } - - if (!wroteCheckedOffset) { - // Always record this, even if block link disabled - it's used for size calc. - SetBlockCheckedOffset(block_num, (int)GetOffset(GetCodePointer())); - } - - if (jo.enableBlocklink && jo.useBackJump) { - WriteDebugPC(startPC); - - // Most blocks shouldn't be >= 4KB, so usually we can just BGE. - if (BInRange(blockStart)) { - BGE(DOWNCOUNTREG, R_ZERO, blockStart); - } else { - FixupBranch skip = BLT(DOWNCOUNTREG, R_ZERO); - J(blockStart); - SetJumpTarget(skip); - } - LI(SCRATCH1, startPC); - QuickJ(R_RA, outerLoopPCInSCRATCH1_); - } - - if (logBlocks_ > 0) { - --logBlocks_; - - std::map addressesLookup; - for (int i = 0; i < (int)addresses.size(); ++i) - addressesLookup[addresses[i]] = i; - - INFO_LOG(JIT, "=============== RISCV (%08x, %d bytes) ===============", startPC, len); - for (const u8 *p = blockStart; p < GetCodePointer(); ) { - auto it = addressesLookup.find(p); - if (it != addressesLookup.end()) { - const IRInst &inst = block->GetInstructions()[it->second]; - - char temp[512]; - DisassembleIR(temp, sizeof(temp), inst); - INFO_LOG(JIT, "IR: #%d %s", it->second, temp); - } - - auto next = std::next(it); - const u8 *nextp = next == addressesLookup.end() ? GetCodePointer() : next->first; - -#if PPSSPP_ARCH(RISCV64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__)) - auto lines = DisassembleRV64(p, (int)(nextp - p)); - for (const auto &line : lines) - INFO_LOG(JIT, "RV: %s", line.c_str()); -#endif - p = nextp; - } - } - - EndWrite(); - FlushIcache(); - compilingBlockNum_ = -1; - - return true; -} - -void RiscVJitBackend::WriteConstExit(uint32_t pc) { - int block_num = blocks_.GetBlockNumberFromStartAddress(pc); - const IRNativeBlock *nativeBlock = GetNativeBlock(block_num); - - int exitStart = (int)GetOffset(GetCodePointer()); - if (block_num >= 0 && jo.enableBlocklink && nativeBlock && nativeBlock->checkedOffset != 0) { - QuickJ(SCRATCH1, GetBasePtr() + nativeBlock->checkedOffset); - } else { - LI(SCRATCH1, pc); - QuickJ(R_RA, dispatcherPCInSCRATCH1_); - } - - if (jo.enableBlocklink) { - // In case of compression or early link, make sure it's large enough. - int len = (int)GetOffset(GetCodePointer()) - exitStart; - if (len < MIN_BLOCK_EXIT_LEN) { - ReserveCodeSpace(MIN_BLOCK_EXIT_LEN - len); - len = MIN_BLOCK_EXIT_LEN; - } - - AddLinkableExit(compilingBlockNum_, pc, exitStart, len); - } -} - -void RiscVJitBackend::OverwriteExit(int srcOffset, int len, int block_num) { - _dbg_assert_(len >= MIN_BLOCK_EXIT_LEN); - - const IRNativeBlock *nativeBlock = GetNativeBlock(block_num); - if (nativeBlock) { - u8 *writable = GetWritablePtrFromCodePtr(GetBasePtr()) + srcOffset; - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, len, MEM_PROT_READ | MEM_PROT_WRITE); - } - - RiscVEmitter emitter(GetBasePtr() + srcOffset, writable); - emitter.QuickJ(SCRATCH1, GetBasePtr() + nativeBlock->checkedOffset); - int bytesWritten = (int)(emitter.GetWritableCodePtr() - writable); - if (bytesWritten < len) - emitter.ReserveCodeSpace(len - bytesWritten); - emitter.FlushIcache(); - - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, 16, MEM_PROT_READ | MEM_PROT_EXEC); - } - } -} - -void RiscVJitBackend::CompIR_Generic(IRInst inst) { - // If we got here, we're going the slow way. - uint64_t value; - memcpy(&value, &inst, sizeof(inst)); - - FlushAll(); - LI(X10, value, SCRATCH2); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::IR_INTERPRET); - QuickCallFunction(&DoIRInst, SCRATCH2); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - - // We only need to check the return value if it's a potential exit. - if ((GetIRMeta(inst.op)->flags & IRFLAG_EXIT) != 0) { - // Result in X10 aka SCRATCH1. - _assert_(X10 == SCRATCH1); - if (BInRange(dispatcherPCInSCRATCH1_)) { - BNE(X10, R_ZERO, dispatcherPCInSCRATCH1_); - } else { - FixupBranch skip = BEQ(X10, R_ZERO); - QuickJ(R_RA, dispatcherPCInSCRATCH1_); - SetJumpTarget(skip); - } - } -} - -void RiscVJitBackend::CompIR_Interpret(IRInst inst) { - MIPSOpcode op(inst.constant); - - // IR protects us against this being a branching instruction (well, hopefully.) - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::INTERPRET); - if (DebugStatsEnabled()) { - LI(X10, MIPSGetName(op)); - QuickCallFunction(&NotifyMIPSInterpret, SCRATCH2); - } - LI(X10, (int32_t)inst.constant); - QuickCallFunction((const u8 *)MIPSGetInterpretFunc(op), SCRATCH2); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); -} - -void RiscVJitBackend::FlushAll() { - regs_.FlushAll(); -} - -bool RiscVJitBackend::DescribeCodePtr(const u8 *ptr, std::string &name) const { - // Used in disassembly viewer. - // Don't use spaces; profilers get confused or truncate them. - if (ptr == dispatcherPCInSCRATCH1_) { - name = "dispatcherPCInSCRATCH1"; - } else if (ptr == outerLoopPCInSCRATCH1_) { - name = "outerLoopPCInSCRATCH1"; - } else if (ptr == dispatcherNoCheck_) { - name = "dispatcherNoCheck"; - } else if (ptr == saveStaticRegisters_) { - name = "saveStaticRegisters"; - } else if (ptr == loadStaticRegisters_) { - name = "loadStaticRegisters"; - } else if (ptr == applyRoundingMode_) { - name = "applyRoundingMode"; - } else if (ptr >= GetBasePtr() && ptr < GetBasePtr() + jitStartOffset_) { - name = "fixedCode"; - } else { - return IRNativeBackend::DescribeCodePtr(ptr, name); - } - return true; -} - -void RiscVJitBackend::ClearAllBlocks() { - ClearCodeSpace(jitStartOffset_); - FlushIcacheSection(region + jitStartOffset_, region + region_size - jitStartOffset_); - EraseAllLinks(-1); -} - -void RiscVJitBackend::InvalidateBlock(IRBlock *block, int block_num) { - int offset = block->GetTargetOffset(); - u8 *writable = GetWritablePtrFromCodePtr(GetBasePtr()) + offset; - - // Overwrite the block with a jump to compile it again. - u32 pc = block->GetOriginalStart(); - if (pc != 0) { - // Hopefully we always have at least 16 bytes, which should be all we need. - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, MIN_BLOCK_NORMAL_LEN, MEM_PROT_READ | MEM_PROT_WRITE); - } - - RiscVEmitter emitter(GetBasePtr() + offset, writable); - // We sign extend to ensure it will fit in 32-bit and 8 bytes LI. - // TODO: May need to change if dispatcher doesn't reload PC. - emitter.LI(SCRATCH1, (int32_t)pc); - emitter.QuickJ(R_RA, dispatcherPCInSCRATCH1_); - int bytesWritten = (int)(emitter.GetWritableCodePtr() - writable); - if (bytesWritten < MIN_BLOCK_NORMAL_LEN) - emitter.ReserveCodeSpace(MIN_BLOCK_NORMAL_LEN - bytesWritten); - emitter.FlushIcache(); - - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, MIN_BLOCK_NORMAL_LEN, MEM_PROT_READ | MEM_PROT_EXEC); - } - } - - EraseAllLinks(block_num); -} - -void RiscVJitBackend::RestoreRoundingMode(bool force) { - FSRMI(Round::NEAREST_EVEN); -} - -void RiscVJitBackend::ApplyRoundingMode(bool force) { - QuickCallFunction(applyRoundingMode_); -} - -void RiscVJitBackend::MovFromPC(RiscVReg r) { - LWU(r, CTXREG, offsetof(MIPSState, pc)); -} - -void RiscVJitBackend::MovToPC(RiscVReg r) { - SW(r, CTXREG, offsetof(MIPSState, pc)); -} - -void RiscVJitBackend::WriteDebugPC(uint32_t pc) { - if (hooks_.profilerPC) { - int offset = (const u8 *)hooks_.profilerPC - GetBasePtr(); - LI(SCRATCH2, hooks_.profilerPC); - LI(R_RA, (int32_t)pc); - SW(R_RA, SCRATCH2, 0); - } -} - -void RiscVJitBackend::WriteDebugPC(RiscVReg r) { - if (hooks_.profilerPC) { - int offset = (const u8 *)hooks_.profilerPC - GetBasePtr(); - LI(SCRATCH2, hooks_.profilerPC); - SW(r, SCRATCH2, 0); - } -} - -void RiscVJitBackend::WriteDebugProfilerStatus(IRProfilerStatus status) { - if (hooks_.profilerPC) { - int offset = (const u8 *)hooks_.profilerStatus - GetBasePtr(); - LI(SCRATCH2, hooks_.profilerStatus); - LI(R_RA, (int)status); - SW(R_RA, SCRATCH2, 0); - } -} - -void RiscVJitBackend::SaveStaticRegisters() { - if (jo.useStaticAlloc) { - QuickCallFunction(saveStaticRegisters_); - } else { - // Inline the single operation - SW(DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - } -} - -void RiscVJitBackend::LoadStaticRegisters() { - if (jo.useStaticAlloc) { - QuickCallFunction(loadStaticRegisters_); - } else { - LW(DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount)); - } -} - -void RiscVJitBackend::NormalizeSrc1(IRInst inst, RiscVReg *reg, RiscVReg tempReg, bool allowOverlap) { - *reg = NormalizeR(inst.src1, allowOverlap ? 0 : inst.dest, tempReg); -} - -void RiscVJitBackend::NormalizeSrc12(IRInst inst, RiscVReg *lhs, RiscVReg *rhs, RiscVReg lhsTempReg, RiscVReg rhsTempReg, bool allowOverlap) { - *lhs = NormalizeR(inst.src1, allowOverlap ? 0 : inst.dest, lhsTempReg); - *rhs = NormalizeR(inst.src2, allowOverlap ? 0 : inst.dest, rhsTempReg); -} - -RiscVReg RiscVJitBackend::NormalizeR(IRReg rs, IRReg rd, RiscVReg tempReg) { - // For proper compare, we must sign extend so they both match or don't match. - // But don't change pointers, in case one is SP (happens in LittleBigPlanet.) - if (regs_.IsGPRImm(rs) && regs_.GetGPRImm(rs) == 0) { - return R_ZERO; - } else if (regs_.IsGPRMappedAsPointer(rs) || rs == rd) { - return regs_.Normalize32(rs, tempReg); - } else { - return regs_.Normalize32(rs); - } -} - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVJit.h b/Core/MIPS/RiscV/RiscVJit.h deleted file mode 100644 index 7ccbcce90..000000000 --- a/Core/MIPS/RiscV/RiscVJit.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include -#include -#include "Common/RiscVEmitter.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRNativeCommon.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" - -namespace MIPSComp { - -class RiscVJitBackend : public RiscVGen::RiscVCodeBlock, public IRNativeBackend { -public: - RiscVJitBackend(JitOptions &jo, IRBlockCache &blocks); - ~RiscVJitBackend(); - - bool DescribeCodePtr(const u8 *ptr, std::string &name) const override; - - void GenerateFixedCode(MIPSState *mipsState) override; - bool CompileBlock(IRBlock *block, int block_num, bool preload) override; - void ClearAllBlocks() override; - void InvalidateBlock(IRBlock *block, int block_num) override; - -protected: - const CodeBlockCommon &CodeBlock() const override { - return *this; - } - -private: - void RestoreRoundingMode(bool force = false); - void ApplyRoundingMode(bool force = false); - void MovFromPC(RiscVGen::RiscVReg r); - void MovToPC(RiscVGen::RiscVReg r); - void WriteDebugPC(uint32_t pc); - void WriteDebugPC(RiscVGen::RiscVReg r); - void WriteDebugProfilerStatus(IRProfilerStatus status); - - void SaveStaticRegisters(); - void LoadStaticRegisters(); - - // Note: destroys SCRATCH1. - void FlushAll(); - - void WriteConstExit(uint32_t pc); - void OverwriteExit(int srcOffset, int len, int block_num) override; - - void CompIR_Arith(IRInst inst) override; - void CompIR_Assign(IRInst inst) override; - void CompIR_Basic(IRInst inst) override; - void CompIR_Bits(IRInst inst) override; - void CompIR_Breakpoint(IRInst inst) override; - void CompIR_Compare(IRInst inst) override; - void CompIR_CondAssign(IRInst inst) override; - void CompIR_CondStore(IRInst inst) override; - void CompIR_Div(IRInst inst) override; - void CompIR_Exit(IRInst inst) override; - void CompIR_ExitIf(IRInst inst) override; - void CompIR_FArith(IRInst inst) override; - void CompIR_FAssign(IRInst inst) override; - void CompIR_FCompare(IRInst inst) override; - void CompIR_FCondAssign(IRInst inst) override; - void CompIR_FCvt(IRInst inst) override; - void CompIR_FLoad(IRInst inst) override; - void CompIR_FRound(IRInst inst) override; - void CompIR_FSat(IRInst inst) override; - void CompIR_FSpecial(IRInst inst) override; - void CompIR_FStore(IRInst inst) override; - void CompIR_Generic(IRInst inst) override; - void CompIR_HiLo(IRInst inst) override; - void CompIR_Interpret(IRInst inst) override; - void CompIR_Load(IRInst inst) override; - void CompIR_LoadShift(IRInst inst) override; - void CompIR_Logic(IRInst inst) override; - void CompIR_Mult(IRInst inst) override; - void CompIR_RoundingMode(IRInst inst) override; - void CompIR_Shift(IRInst inst) override; - void CompIR_Store(IRInst inst) override; - void CompIR_StoreShift(IRInst inst) override; - void CompIR_System(IRInst inst) override; - void CompIR_Transfer(IRInst inst) override; - void CompIR_VecArith(IRInst inst) override; - void CompIR_VecAssign(IRInst inst) override; - void CompIR_VecClamp(IRInst inst) override; - void CompIR_VecHoriz(IRInst inst) override; - void CompIR_VecLoad(IRInst inst) override; - void CompIR_VecPack(IRInst inst) override; - void CompIR_VecStore(IRInst inst) override; - void CompIR_ValidateAddress(IRInst inst) override; - - void SetScratch1ToSrc1Address(IRReg src1); - // Modifies SCRATCH regs. - int32_t AdjustForAddressOffset(RiscVGen::RiscVReg *reg, int32_t constant, int32_t range = 0); - void NormalizeSrc1(IRInst inst, RiscVGen::RiscVReg *reg, RiscVGen::RiscVReg tempReg, bool allowOverlap); - void NormalizeSrc12(IRInst inst, RiscVGen::RiscVReg *lhs, RiscVGen::RiscVReg *rhs, RiscVGen::RiscVReg lhsTempReg, RiscVGen::RiscVReg rhsTempReg, bool allowOverlap); - RiscVGen::RiscVReg NormalizeR(IRReg rs, IRReg rd, RiscVGen::RiscVReg tempReg); - - JitOptions &jo; - RiscVRegCache regs_; - - const u8 *outerLoop_ = nullptr; - const u8 *outerLoopPCInSCRATCH1_ = nullptr; - const u8 *dispatcherCheckCoreState_ = nullptr; - const u8 *dispatcherPCInSCRATCH1_ = nullptr; - const u8 *dispatcherNoCheck_ = nullptr; - const u8 *applyRoundingMode_ = nullptr; - - const u8 *saveStaticRegisters_ = nullptr; - const u8 *loadStaticRegisters_ = nullptr; - - int jitStartOffset_ = 0; - int compilingBlockNum_ = -1; - int logBlocks_ = 0; -}; - -class RiscVJit : public IRNativeJit { -public: - RiscVJit(MIPSState *mipsState) - : IRNativeJit(mipsState), rvBackend_(jo, blocks_) { - Init(rvBackend_); - } - -private: - RiscVJitBackend rvBackend_; -}; - -} // namespace MIPSComp diff --git a/Core/MIPS/RiscV/RiscVRegCache.cpp b/Core/MIPS/RiscV/RiscVRegCache.cpp deleted file mode 100644 index 25528aa3a..000000000 --- a/Core/MIPS/RiscV/RiscVRegCache.cpp +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#ifndef offsetof -#include -#endif - -#include "Common/CPUDetect.h" -#include "Core/MIPS/IR/IRInst.h" -#include "Core/MIPS/IR/IRAnalysis.h" -#include "Core/MIPS/RiscV/RiscVRegCache.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/Reporting.h" - -using namespace RiscVGen; -using namespace RiscVJitConstants; - -RiscVRegCache::RiscVRegCache(MIPSComp::JitOptions *jo) - : IRNativeRegCacheBase(jo) { - // TODO: Update these when using RISC-V V. - config_.totalNativeRegs = NUM_RVGPR + NUM_RVFPR; - config_.mapUseVRegs = false; - config_.mapFPUSIMD = false; -} - -void RiscVRegCache::Init(RiscVEmitter *emitter) { - emit_ = emitter; -} - -void RiscVRegCache::SetupInitialRegs() { - IRNativeRegCacheBase::SetupInitialRegs(); - - // Treat R_ZERO a bit specially, but it's basically static alloc too. - nrInitial_[R_ZERO].mipsReg = MIPS_REG_ZERO; - nrInitial_[R_ZERO].normalized32 = true; - - // Since we also have a fixed zero, mark it as a static allocation. - mrInitial_[MIPS_REG_ZERO].loc = MIPSLoc::REG_IMM; - mrInitial_[MIPS_REG_ZERO].nReg = R_ZERO; - mrInitial_[MIPS_REG_ZERO].imm = 0; - mrInitial_[MIPS_REG_ZERO].isStatic = true; -} - -const int *RiscVRegCache::GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const { - base = X0; - - if (type == MIPSLoc::REG) { - // X8 and X9 are the most ideal for static alloc because they can be used with compression. - // Otherwise we stick to saved regs - might not be necessary. - static const int allocationOrder[] = { - X8, X9, X12, X13, X14, X15, X5, X6, X7, X16, X17, X18, X19, X20, X21, X22, X23, X28, X29, X30, X31, - }; - static const int allocationOrderStaticAlloc[] = { - X12, X13, X14, X15, X5, X6, X7, X16, X17, X21, X22, X23, X28, X29, X30, X31, - }; - - if (jo_->useStaticAlloc) { - count = ARRAY_SIZE(allocationOrderStaticAlloc); - return allocationOrderStaticAlloc; - } else { - count = ARRAY_SIZE(allocationOrder); - return allocationOrder; - } - } else if (type == MIPSLoc::FREG) { - // F8 through F15 are used for compression, so they are great. - static const int allocationOrder[] = { - F8, F9, F10, F11, F12, F13, F14, F15, - F0, F1, F2, F3, F4, F5, F6, F7, - F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31, - }; - - count = ARRAY_SIZE(allocationOrder); - return allocationOrder; - } else { - _assert_msg_(false, "Allocation order not yet implemented"); - count = 0; - return nullptr; - } -} - -const RiscVRegCache::StaticAllocation *RiscVRegCache::GetStaticAllocations(int &count) const { - static const StaticAllocation allocs[] = { - { MIPS_REG_SP, X8, MIPSLoc::REG, true }, - { MIPS_REG_V0, X9, MIPSLoc::REG }, - { MIPS_REG_V1, X18, MIPSLoc::REG }, - { MIPS_REG_A0, X19, MIPSLoc::REG }, - { MIPS_REG_RA, X20, MIPSLoc::REG }, - }; - - if (jo_->useStaticAlloc) { - count = ARRAY_SIZE(allocs); - return allocs; - } - return IRNativeRegCacheBase::GetStaticAllocations(count); -} - -void RiscVRegCache::EmitLoadStaticRegisters() { - int count; - const StaticAllocation *allocs = GetStaticAllocations(count); - for (int i = 0; i < count; i++) { - int offset = GetMipsRegOffset(allocs[i].mr); - if (allocs[i].pointerified && jo_->enablePointerify) { - emit_->LWU((RiscVReg)allocs[i].nr, CTXREG, offset); - emit_->ADD((RiscVReg)allocs[i].nr, (RiscVReg)allocs[i].nr, MEMBASEREG); - } else { - emit_->LW((RiscVReg)allocs[i].nr, CTXREG, offset); - } - } -} - -void RiscVRegCache::EmitSaveStaticRegisters() { - int count; - const StaticAllocation *allocs = GetStaticAllocations(count); - // This only needs to run once (by Asm) so checks don't need to be fast. - for (int i = 0; i < count; i++) { - int offset = GetMipsRegOffset(allocs[i].mr); - emit_->SW((RiscVReg)allocs[i].nr, CTXREG, offset); - } -} - -void RiscVRegCache::FlushBeforeCall() { - // These registers are not preserved by function calls. - // They match between X0 and F0, conveniently. - for (int i = 5; i <= 7; ++i) { - FlushNativeReg(X0 + i); - FlushNativeReg(F0 + i); - } - for (int i = 10; i <= 17; ++i) { - FlushNativeReg(X0 + i); - FlushNativeReg(F0 + i); - } - for (int i = 28; i <= 31; ++i) { - FlushNativeReg(X0 + i); - FlushNativeReg(F0 + i); - } -} - -bool RiscVRegCache::IsNormalized32(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - if (XLEN == 32) - return true; - if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - return nr[mr[mipsReg].nReg].normalized32; - } - return false; -} - -RiscVGen::RiscVReg RiscVRegCache::Normalize32(IRReg mipsReg, RiscVGen::RiscVReg destReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(destReg == INVALID_REG || (destReg > X0 && destReg <= X31)); - - RiscVReg reg = (RiscVReg)mr[mipsReg].nReg; - if (XLEN == 32) - return reg; - - switch (mr[mipsReg].loc) { - case MIPSLoc::IMM: - case MIPSLoc::MEM: - _assert_msg_(false, "Cannot normalize an imm or mem"); - return INVALID_REG; - - case MIPSLoc::REG: - case MIPSLoc::REG_IMM: - if (!nr[mr[mipsReg].nReg].normalized32) { - if (destReg == INVALID_REG) { - emit_->SEXT_W((RiscVReg)mr[mipsReg].nReg, (RiscVReg)mr[mipsReg].nReg); - nr[mr[mipsReg].nReg].normalized32 = true; - nr[mr[mipsReg].nReg].pointerified = false; - } else { - emit_->SEXT_W(destReg, (RiscVReg)mr[mipsReg].nReg); - } - } else if (destReg != INVALID_REG) { - emit_->SEXT_W(destReg, (RiscVReg)mr[mipsReg].nReg); - } - break; - - case MIPSLoc::REG_AS_PTR: - _dbg_assert_(nr[mr[mipsReg].nReg].normalized32 == false); - if (destReg == INVALID_REG) { - // If we can pointerify, SEXT_W will be enough. - if (!jo_->enablePointerify) - AdjustNativeRegAsPtr(mr[mipsReg].nReg, false); - emit_->SEXT_W((RiscVReg)mr[mipsReg].nReg, (RiscVReg)mr[mipsReg].nReg); - mr[mipsReg].loc = MIPSLoc::REG; - nr[mr[mipsReg].nReg].normalized32 = true; - nr[mr[mipsReg].nReg].pointerified = false; - } else if (!jo_->enablePointerify) { - emit_->SUB(destReg, (RiscVReg)mr[mipsReg].nReg, MEMBASEREG); - emit_->SEXT_W(destReg, destReg); - } else { - emit_->SEXT_W(destReg, (RiscVReg)mr[mipsReg].nReg); - } - break; - - default: - _assert_msg_(false, "Should not normalize32 floats"); - break; - } - - return destReg == INVALID_REG ? reg : destReg; -} - -RiscVReg RiscVRegCache::TryMapTempImm(IRReg r) { - _dbg_assert_(IsValidGPR(r)); - // If already mapped, no need for a temporary. - if (IsGPRMapped(r)) { - return R(r); - } - - if (mr[r].loc == MIPSLoc::IMM) { - if (mr[r].imm == 0) { - return R_ZERO; - } - - // Try our luck - check for an exact match in another rvreg. - for (int i = 0; i < TOTAL_MAPPABLE_IRREGS; ++i) { - if (mr[i].loc == MIPSLoc::REG_IMM && mr[i].imm == mr[r].imm) { - // Awesome, let's just use this reg. - return (RiscVReg)mr[i].nReg; - } - } - } - - return INVALID_REG; -} - -RiscVReg RiscVRegCache::GetAndLockTempGPR() { - RiscVReg reg = (RiscVReg)AllocateReg(MIPSLoc::REG, MIPSMap::INIT); - if (reg != INVALID_REG) { - nr[reg].tempLockIRIndex = irIndex_; - } - return reg; -} - -RiscVReg RiscVRegCache::MapWithFPRTemp(const IRInst &inst) { - return (RiscVReg)MapWithTemp(inst, MIPSLoc::FREG); -} - -RiscVReg RiscVRegCache::MapGPR(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidGPR(mipsReg)); - - // Okay, not mapped, so we need to allocate an RV register. - IRNativeReg nreg = MapNativeReg(MIPSLoc::REG, mipsReg, 1, mapFlags); - return (RiscVReg)nreg; -} - -RiscVReg RiscVRegCache::MapGPRAsPointer(IRReg reg) { - return (RiscVReg)MapNativeRegAsPointer(reg); -} - -RiscVReg RiscVRegCache::MapFPR(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidFPR(mipsReg)); - _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::MEM || mr[mipsReg + 32].loc == MIPSLoc::FREG); - - IRNativeReg nreg = MapNativeReg(MIPSLoc::FREG, mipsReg + 32, 1, mapFlags); - if (nreg != -1) - return (RiscVReg)nreg; - return INVALID_REG; -} - -void RiscVRegCache::AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) { - RiscVReg r = (RiscVReg)(X0 + nreg); - _assert_(r >= X0 && r <= X31); - if (state) { -#ifdef MASKED_PSP_MEMORY - // This destroys the value... - _dbg_assert_(!nr[nreg].isDirty); - emit_->SLLIW(r, r, 2); - emit_->SRLIW(r, r, 2); - emit_->ADD(r, r, MEMBASEREG); -#else - // Clear the top bits to be safe. - if (cpu_info.RiscV_Zba) { - emit_->ADD_UW(r, r, MEMBASEREG); - } else { - _assert_(XLEN == 64); - emit_->SLLI(r, r, 32); - emit_->SRLI(r, r, 32); - emit_->ADD(r, r, MEMBASEREG); - } -#endif - nr[nreg].normalized32 = false; - } else { -#ifdef MASKED_PSP_MEMORY - _dbg_assert_(!nr[nreg].isDirty); -#endif - emit_->SUB(r, r, MEMBASEREG); - nr[nreg].normalized32 = false; - } -} - -bool RiscVRegCache::IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes) { - // No special flags except VREG, skip the check for a little speed. - if (type != MIPSLoc::VREG) - return true; - return IRNativeRegCacheBase::IsNativeRegCompatible(nreg, type, flags, lanes); -} - -void RiscVRegCache::LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) { - RiscVReg r = (RiscVReg)(X0 + nreg); - _dbg_assert_(r > X0); - _dbg_assert_(first != MIPS_REG_ZERO); - if (r <= X31) { - _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); - if (lanes == 1) - emit_->LW(r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 2) - emit_->LD(r, CTXREG, GetMipsRegOffset(first)); - else - _assert_(false); - nr[nreg].normalized32 = true; - } else { - _dbg_assert_(r >= F0 && r <= F31); - // Multilane not yet supported. - _assert_(lanes == 1); - if (mr[first].loc == MIPSLoc::FREG) { - emit_->FL(32, r, CTXREG, GetMipsRegOffset(first)); - } else { - _assert_msg_(mr[first].loc == MIPSLoc::FREG, "Cannot store this type: %d", (int)mr[first].loc); - } - } -} - -void RiscVRegCache::StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) { - RiscVReg r = (RiscVReg)(X0 + nreg); - _dbg_assert_(r > X0); - _dbg_assert_(first != MIPS_REG_ZERO); - if (r <= X31) { - // Multilane not yet supported. - _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); - _assert_(mr[first].loc == MIPSLoc::REG || mr[first].loc == MIPSLoc::REG_IMM); - if (lanes == 1) - emit_->SW(r, CTXREG, GetMipsRegOffset(first)); - else if (lanes == 2) - emit_->SD(r, CTXREG, GetMipsRegOffset(first)); - else - _assert_(false); - } else { - _dbg_assert_(r >= F0 && r <= F31); - // Multilane not yet supported. - _assert_(lanes == 1); - if (mr[first].loc == MIPSLoc::FREG) { - emit_->FS(32, r, CTXREG, GetMipsRegOffset(first)); - } else { - _assert_msg_(mr[first].loc == MIPSLoc::FREG, "Cannot store this type: %d", (int)mr[first].loc); - } - } -} - -void RiscVRegCache::SetNativeRegValue(IRNativeReg nreg, uint32_t imm) { - RiscVReg r = (RiscVReg)(X0 + nreg); - if (r == R_ZERO && imm == 0) - return; - _dbg_assert_(r > X0 && r <= X31); - emit_->LI(r, (int32_t)imm); - - // We always use 32-bit immediates, so this is normalized now. - nr[nreg].normalized32 = true; -} - -void RiscVRegCache::StoreRegValue(IRReg mreg, uint32_t imm) { - _assert_(IsValidGPRNoZero(mreg)); - // Try to optimize using a different reg. - RiscVReg storeReg = INVALID_REG; - - // Zero is super easy. - if (imm == 0) { - storeReg = R_ZERO; - } else { - // Could we get lucky? Check for an exact match in another rvreg. - for (int i = 0; i < TOTAL_MAPPABLE_IRREGS; ++i) { - if (mr[i].loc == MIPSLoc::REG_IMM && mr[i].imm == imm) { - // Awesome, let's just store this reg. - storeReg = (RiscVReg)mr[i].nReg; - break; - } - } - - if (storeReg == INVALID_REG) { - emit_->LI(SCRATCH1, imm); - storeReg = SCRATCH1; - } - } - - emit_->SW(storeReg, CTXREG, GetMipsRegOffset(mreg)); -} - -RiscVReg RiscVRegCache::R(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM); - if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - return (RiscVReg)mr[mipsReg].nReg; - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in riscv reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -RiscVReg RiscVRegCache::RPtr(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM || mr[mipsReg].loc == MIPSLoc::REG_AS_PTR); - if (mr[mipsReg].loc == MIPSLoc::REG_AS_PTR) { - return (RiscVReg)mr[mipsReg].nReg; - } else if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - int rv = mr[mipsReg].nReg; - _dbg_assert_(nr[rv].pointerified); - if (nr[rv].pointerified) { - return (RiscVReg)mr[mipsReg].nReg; - } else { - ERROR_LOG(JIT, "Tried to use a non-pointer register as a pointer"); - return INVALID_REG; - } - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in riscv reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -RiscVReg RiscVRegCache::F(IRReg mipsReg) { - _dbg_assert_(IsValidFPR(mipsReg)); - _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::FREG); - if (mr[mipsReg + 32].loc == MIPSLoc::FREG) { - return (RiscVReg)mr[mipsReg + 32].nReg; - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in riscv reg", mipsReg); - return INVALID_REG; // BAAAD - } -} diff --git a/Core/MIPS/RiscV/RiscVRegCache.h b/Core/MIPS/RiscV/RiscVRegCache.h deleted file mode 100644 index e0075f2c6..000000000 --- a/Core/MIPS/RiscV/RiscVRegCache.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "Common/RiscVEmitter.h" -#include "Core/MIPS/MIPS.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRRegCache.h" - -namespace RiscVJitConstants { - -// Note: we don't support 32-bit or 128-bit CPUs currently. -constexpr int XLEN = 64; - -const RiscVGen::RiscVReg DOWNCOUNTREG = RiscVGen::X24; -const RiscVGen::RiscVReg JITBASEREG = RiscVGen::X25; -const RiscVGen::RiscVReg CTXREG = RiscVGen::X26; -const RiscVGen::RiscVReg MEMBASEREG = RiscVGen::X27; -// TODO: Experiment. X7-X13 are compressed regs. X8/X9 are saved so nice for static alloc, though. -const RiscVGen::RiscVReg SCRATCH1 = RiscVGen::X10; -const RiscVGen::RiscVReg SCRATCH2 = RiscVGen::X11; - -} // namespace RiscVJitConstants - -class RiscVRegCache : public IRNativeRegCacheBase { -public: - RiscVRegCache(MIPSComp::JitOptions *jo); - - void Init(RiscVGen::RiscVEmitter *emitter); - - // May fail and return INVALID_REG if it needs flushing. - RiscVGen::RiscVReg TryMapTempImm(IRReg reg); - - // Returns an RV register containing the requested MIPS register. - RiscVGen::RiscVReg MapGPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - RiscVGen::RiscVReg MapGPRAsPointer(IRReg reg); - RiscVGen::RiscVReg MapFPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - - RiscVGen::RiscVReg MapWithFPRTemp(const IRInst &inst); - - bool IsNormalized32(IRReg reg); - - // Copies to another reg if specified, otherwise same reg. - RiscVGen::RiscVReg Normalize32(IRReg reg, RiscVGen::RiscVReg destReg = RiscVGen::INVALID_REG); - - void FlushBeforeCall(); - - RiscVGen::RiscVReg GetAndLockTempGPR(); - - RiscVGen::RiscVReg R(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer - RiscVGen::RiscVReg RPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer - RiscVGen::RiscVReg F(IRReg preg); - - // These are called once on startup to generate functions, that you should then call. - void EmitLoadStaticRegisters(); - void EmitSaveStaticRegisters(); - -protected: - void SetupInitialRegs() override; - const StaticAllocation *GetStaticAllocations(int &count) const override; - const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const override; - void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) override; - - bool IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes) override; - void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; - void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; - void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) override; - void StoreRegValue(IRReg mreg, uint32_t imm) override; - -private: - RiscVGen::RiscVEmitter *emit_ = nullptr; - - enum { - NUM_RVGPR = 32, - NUM_RVFPR = 32, - NUM_RVVPR = 32, - }; -}; diff --git a/Core/MIPS/fake/FakeJit.cpp b/Core/MIPS/fake/FakeJit.cpp index 3e696814c..f833526a6 100644 --- a/Core/MIPS/fake/FakeJit.cpp +++ b/Core/MIPS/fake/FakeJit.cpp @@ -153,6 +153,10 @@ void FakeJit::Comp_RunBlock(MIPSOpcode op) ERROR_LOG(JIT, "Comp_RunBlock should never be reached!"); } +bool FakeJit::ReplaceJalTo(u32 dest) { + return true; +} + void FakeJit::Comp_ReplacementFunc(MIPSOpcode op) { } diff --git a/Core/MIPS/fake/FakeJit.h b/Core/MIPS/fake/FakeJit.h index bce7fe92d..44cfefec0 100644 --- a/Core/MIPS/fake/FakeJit.h +++ b/Core/MIPS/fake/FakeJit.h @@ -60,7 +60,6 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override {} - void Comp_StoreSync(MIPSOpcode op) override {} void Comp_Cache(MIPSOpcode op) override {} void Comp_RelBranch(MIPSOpcode op) override {} @@ -163,6 +162,8 @@ private: void MovFromPC(FakeReg r); void MovToPC(FakeReg r); + bool ReplaceJalTo(u32 dest); + void SaveDowncount(); void RestoreDowncount(); diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 52655319c..474936cde 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -107,7 +107,7 @@ static void JitBranchLog(MIPSOpcode op, u32 pc) { static void JitBranchLogMismatch(MIPSOpcode op, u32 pc) { char temp[256]; - MIPSDisAsm(op, pc, temp, sizeof(temp), true); + MIPSDisAsm(op, pc, temp, true); ERROR_LOG(JIT, "Bad jump: %s - int:%08x jit:%08x", temp, currentMIPS->intBranchExit, currentMIPS->jitBranchExit); Core_EnableStepping(true, "jit.branchdebug", pc); } diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 9509f63d6..feb627d3e 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -44,7 +44,6 @@ // #define CONDITIONAL_DISABLE(flag) { Comp_Generic(op); return; } #define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; } #define DISABLE { Comp_Generic(op); return; } -#define INVALIDOP { Comp_Generic(op); return; } namespace MIPSComp { using namespace Gen; @@ -80,7 +79,7 @@ namespace MIPSComp { return in; } - void Jit::CompITypeMemWrite(MIPSOpcode op, u32 bits, const void *safeFunc, bool makeRTWritable) + void Jit::CompITypeMemWrite(MIPSOpcode op, u32 bits, const void *safeFunc) { CONDITIONAL_DISABLE(LSU); int offset = _IMM16; @@ -90,9 +89,6 @@ namespace MIPSComp { gpr.Lock(rt, rs); if (rt == MIPS_REG_ZERO || gpr.R(rt).IsImm()) { - if (makeRTWritable) { - gpr.MapReg(rt, true, true); - } // NOTICE_LOG(JIT, "%d-bit Imm at %08x : %08x", bits, js.blockStart, (u32)gpr.R(rt).GetImmValue()); } else { gpr.MapReg(rt, true, false); @@ -409,48 +405,6 @@ namespace MIPSComp { } - void Jit::Comp_StoreSync(MIPSOpcode op) { - CONDITIONAL_DISABLE(LSU); - - int offset = _IMM16; - MIPSGPReg rt = _RT; - MIPSGPReg rs = _RS; - // Note: still does something even if loading to zero. - - CheckMemoryBreakpoint(0, rs, offset); - - FixupBranch skipStore; - FixupBranch finish; - switch (op >> 26) { - case 48: // ll - CompITypeMemRead(op, 32, &XEmitter::MOVZX, safeMemFuncs.readU32); - MOV(8, MDisp(X64JitConstants::CTXREG, -128 + offsetof(MIPSState, llBit)), Imm8(1)); - break; - - case 56: // sc - // Map before the jump in case any regs spill. Unlock happens inside CompITypeMemWrite(). - // This is not a very common op, but it's in jit so memory breakpoints can trip. - gpr.Lock(rt, rs); - gpr.MapReg(rt, true, true); - gpr.MapReg(rs, true, false); - - CMP(8, MDisp(X64JitConstants::CTXREG, -128 + offsetof(MIPSState, llBit)), Imm8(1)); - skipStore = J_CC(CC_NE); - - CompITypeMemWrite(op, 32, safeMemFuncs.writeU32, true); - MOV(32, gpr.R(rt), Imm32(1)); - finish = J(); - - SetJumpTarget(skipStore); - MOV(32, gpr.R(rt), Imm32(0)); - SetJumpTarget(finish); - break; - - default: - INVALIDOP; - } - } - void Jit::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 99f6640c9..8935d59ce 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -2208,8 +2208,8 @@ void CosOnly(SinCosArg angle, float *output) { output[1] = vfpu_cos(angle); } -void ASinScaled(SinCosArg sine, float *output) { - output[0] = vfpu_asin(sine); +void ASinScaled(SinCosArg angle, float *output) { + output[0] = vfpu_asin(angle); } void SinCosNegSin(SinCosArg angle, float *output) { @@ -2217,25 +2217,13 @@ void SinCosNegSin(SinCosArg angle, float *output) { output[0] = -output[0]; } -void Exp2(SinCosArg arg, float *output) { - output[0] = vfpu_exp2(arg); -} - -void Log2(SinCosArg arg, float *output) { - output[0] = vfpu_log2(arg); -} - -void RExp2(SinCosArg arg, float *output) { - output[0] = vfpu_rexp2(arg); -} - void Jit::Comp_VV2Op(MIPSOpcode op) { CONDITIONAL_DISABLE(VFPU_VEC); if (js.HasUnknownPrefix()) DISABLE; - auto specialFuncCallHelper = [this](void (*specialFunc)(SinCosArg, float *output), u8 sreg) { + auto trigCallHelper = [this](void (*sinCosFunc)(SinCosArg, float *output), u8 sreg) { #if PPSSPP_ARCH(AMD64) MOVSS(XMM0, fpr.V(sreg)); // TODO: This reg might be different on Linux... @@ -2244,7 +2232,7 @@ void Jit::Comp_VV2Op(MIPSOpcode op) { #else LEA(64, RDI, MIPSSTATE_VAR(sincostemp[0])); #endif - ABI_CallFunction(thunks.ProtectFunction((const void *)specialFunc, 0)); + ABI_CallFunction(thunks.ProtectFunction((const void *)sinCosFunc, 0)); #else // Sigh, passing floats with cdecl isn't pretty, ends up on the stack. if (fpr.V(sreg).IsSimpleReg()) { @@ -2252,7 +2240,7 @@ void Jit::Comp_VV2Op(MIPSOpcode op) { } else { MOV(32, R(EAX), fpr.V(sreg)); } - CallProtectedFunction((const void *)specialFunc, R(EAX), Imm32((uint32_t)(uintptr_t)&mips_->sincostemp[0])); + CallProtectedFunction((const void *)sinCosFunc, R(EAX), Imm32((uint32_t)(uintptr_t)&mips_->sincostemp[0])); #endif }; @@ -2418,20 +2406,18 @@ void Jit::Comp_VV2Op(MIPSOpcode op) { DIVSS(tempxregs[i], R(XMM0)); break; case 18: // d[i] = sinf((float)M_PI_2 * s[i]); break; //vsin - specialFuncCallHelper(&SinOnly, sregs[i]); + trigCallHelper(&SinOnly, sregs[i]); MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[0])); break; case 19: // d[i] = cosf((float)M_PI_2 * s[i]); break; //vcos - specialFuncCallHelper(&CosOnly, sregs[i]); + trigCallHelper(&CosOnly, sregs[i]); MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[1])); break; case 20: // d[i] = powf(2.0f, s[i]); break; //vexp2 - specialFuncCallHelper(&Exp2, sregs[i]); - MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[0])); + DISABLE; break; case 21: // d[i] = logf(s[i])/log(2.0f); break; //vlog2 - specialFuncCallHelper(&Log2, sregs[i]); - MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[0])); + DISABLE; break; case 22: // d[i] = sqrtf(s[i]); break; //vsqrt SQRTSS(tempxregs[i], fpr.V(sregs[i])); @@ -2439,7 +2425,7 @@ void Jit::Comp_VV2Op(MIPSOpcode op) { ANDPS(tempxregs[i], MatR(TEMPREG)); break; case 23: // d[i] = asinf(s[i]) / M_PI_2; break; //vasin - specialFuncCallHelper(&ASinScaled, sregs[i]); + trigCallHelper(&ASinScaled, sregs[i]); MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[0])); break; case 24: // d[i] = -1.0f / s[i]; break; // vnrcp @@ -2450,12 +2436,11 @@ void Jit::Comp_VV2Op(MIPSOpcode op) { MOVSS(tempxregs[i], R(XMM0)); break; case 26: // d[i] = -sinf((float)M_PI_2 * s[i]); break; // vnsin - specialFuncCallHelper(&NegSinOnly, sregs[i]); + trigCallHelper(&NegSinOnly, sregs[i]); MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[0])); break; case 28: // d[i] = 1.0f / expf(s[i] * (float)M_LOG2E); break; // vrexp2 - specialFuncCallHelper(&RExp2, sregs[i]); - MOVSS(tempxregs[i], MIPSSTATE_VAR(sincostemp[0])); + DISABLE; break; } } @@ -2544,13 +2529,10 @@ void Jit::Comp_Mftv(MIPSOpcode op) { // TODO: Optimization if rt is Imm? if (imm - 128 == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm - 128 == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } else { //ERROR @@ -2599,13 +2581,10 @@ void Jit::Comp_Vmtvc(MIPSOpcode op) { if (imm == VFPU_CTRL_SPREFIX) { js.prefixSFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_TPREFIX) { js.prefixTFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } else if (imm == VFPU_CTRL_DPREFIX) { js.prefixDFlag = JitState::PREFIX_UNKNOWN; - js.blockWrotePrefixes = true; } } } diff --git a/Core/MIPS/x86/IRToX86.cpp b/Core/MIPS/x86/IRToX86.cpp new file mode 100644 index 000000000..f543025cd --- /dev/null +++ b/Core/MIPS/x86/IRToX86.cpp @@ -0,0 +1,299 @@ +#include "ppsspp_config.h" +#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) + +#include "Core/MIPS/x86/IRToX86.h" + +namespace MIPSComp { + +// Initial attempt at converting IR directly to x86. +// This is intended to be an easy way to benefit from the IR with the current infrastructure. +// Later tries may go across multiple blocks and a different representation. + +struct GPRMapping { + Gen::OpArg dest; + Gen::OpArg src1; + Gen::OpArg src2; +}; + +struct FPRMapping { + Gen::OpArg dest; + Gen::OpArg src1; + Gen::OpArg src2; +}; + + +class GreedyRegallocGPR { +public: + GPRMapping Map(IRInst inst, const IRMeta &meta); + +private: + +}; + + +GPRMapping GreedyRegallocGPR::Map(IRInst inst, const IRMeta &meta) { + GPRMapping mapping; + if (meta.types[0] == 'G') { + + } + // etc.. + return mapping; +} + +// Every 4 registers can also be mapped into an SSE register. +// When changing from single to vec4 mapping, we'll just flush, for now. +class GreedyRegallocFPR { +public: + FPRMapping Map(IRInst inst, const IRMeta &meta); +}; + +FPRMapping GreedyRegallocFPR::Map(IRInst inst, const IRMeta &meta) { + FPRMapping mapping; + + return mapping; +} + + +// This requires that ThreeOpToTwoOp has been run as the last pass. +void IRToX86::ConvertIRToNative(const IRInst *instructions, int count, const u32 *constants) { + // Set up regcaches + using namespace Gen; + + GreedyRegallocGPR gprAlloc; + GreedyRegallocFPR fprAlloc; + + // Loop through all the instructions, emitting code as we go. + // Note that we do need to implement them all - fallbacks are not permitted. + for (int i = 0; i < count; i++) { + const IRInst *inst = &instructions[i]; + const IRMeta &meta = *GetIRMeta(inst->op); + GPRMapping gpr = gprAlloc.Map(*inst, meta); + FPRMapping fpr = fprAlloc.Map(*inst, meta); + + bool symmetric = false; + switch (inst->op) { + case IROp::Nop: + _assert_(false); + break; + + // Output-only + case IROp::SetConst: + code_->MOV(32, gpr.dest, Imm32(constants[inst->src1])); + break; + case IROp::SetConstF: + code_->MOV(32, gpr.dest, Imm32(constants[inst->src1])); + break; + + // Add gets to be special cased because we have LEA. + case IROp::Add: + if (gpr.dest.IsSimpleReg() && gpr.src1.IsSimpleReg() && gpr.src2.IsSimpleReg()) { + code_->LEA(32, gpr.dest.GetSimpleReg(), MRegSum(gpr.src1.GetSimpleReg(), gpr.src2.GetSimpleReg())); + break; + } + // Else fall through. + // 3-op arithmetic that directly corresponds to x86 + // (often 2-op in practice if src1 == dst). x86 only does 2-op though so some of these will need splitting. + case IROp::Sub: + case IROp::And: + case IROp::Or: + case IROp::Xor: + if (inst->src1 != inst->dest) { + code_->MOV(32, gpr.dest, gpr.src1); + } + // Emit directly + switch (inst->op) { + case IROp::Add: code_->ADD(32, gpr.dest, gpr.src2); break; + case IROp::Sub: code_->SUB(32, gpr.dest, gpr.src2); break; + case IROp::And: code_->AND(32, gpr.dest, gpr.src2); break; + case IROp::Or: code_->OR(32, gpr.dest, gpr.src2); break; + case IROp::Xor: code_->XOR(32, gpr.dest, gpr.src2); break; + } + break; + + // Variable shifts. + case IROp::Shl: + case IROp::Shr: + case IROp::Sar: + case IROp::Ror: + + case IROp::Slt: + case IROp::SltU: + case IROp::MovZ: + case IROp::MovNZ: + case IROp::Max: + case IROp::Min: + break; + + // 2-op arithmetic with constant + case IROp::AddConst: + case IROp::SubConst: + case IROp::AndConst: + case IROp::OrConst: + case IROp::XorConst: + case IROp::SltConst: + case IROp::SltUConst: + + // 2-op arithmetic with immediate + case IROp::ShlImm: + case IROp::ShrImm: + case IROp::SarImm: + case IROp::RorImm: + + // 2-op arithmetic + case IROp::Mov: + code_->MOV(32, gpr.dest, gpr.src1); + break; + + case IROp::Neg: + case IROp::Not: + case IROp::Ext8to32: + case IROp::Ext16to32: + case IROp::ReverseBits: + case IROp::BSwap16: + case IROp::BSwap32: + case IROp::Clz: + if (inst->dest != inst->src1) { + code_->NEG(32, gpr.dest); break; + } + break; + // Multiplier control + case IROp::MtLo: + case IROp::MtHi: + case IROp::MfLo: + case IROp::MfHi: + case IROp::Mult: + case IROp::MultU: + case IROp::Madd: + case IROp::MaddU: + case IROp::Msub: + case IROp::MsubU: + case IROp::Div: + case IROp::DivU: + + // Memory access + case IROp::Load8: + case IROp::Load8Ext: + case IROp::Load16: + case IROp::Load16Ext: + case IROp::Load32: + case IROp::LoadFloat: + case IROp::Store8: + case IROp::Store16: + case IROp::Store32: + case IROp::StoreFloat: + case IROp::LoadVec4: + case IROp::StoreVec4: + + // Output-only SIMD functions + case IROp::Vec4Init: + case IROp::Vec4Shuffle: + + // 2-op SIMD functions + case IROp::Vec4Mov: + code_->MOVAPS(fpr.dest.GetSimpleReg(), fpr.src1); + break; + case IROp::Vec4Neg: + case IROp::Vec4Abs: + break; + case IROp::Vec4ClampToZero: + code_->PXOR(XMM0, R(XMM0)); + code_->PMAXSW(XMM0, fpr.src1); + code_->MOVAPD(fpr.dest, XMM0); + break; + case IROp::Vec4DuplicateUpperBitsAndShift1: + case IROp::Vec2ClampToZero: + + // 3-op SIMD functions + case IROp::Vec4Add: + case IROp::Vec4Sub: + case IROp::Vec4Mul: + case IROp::Vec4Div: + + case IROp::Vec4Scale: + case IROp::Vec4Dot: + + // Pack-unpack + case IROp::Vec2Unpack16To31: + case IROp::Vec2Unpack16To32: + case IROp::Vec4Unpack8To32: + case IROp::Vec2Pack32To16: + case IROp::Vec2Pack31To16: + case IROp::Vec4Pack32To8: + case IROp::Vec4Pack31To8: + + case IROp::FCmpVfpuBit: + case IROp::FCmpVfpuAggregate: + case IROp::FCmovVfpuCC: + + // Trancendental functions (non-simd) + case IROp::FSin: + case IROp::FCos: + case IROp::FRSqrt: + case IROp::FRecip: + case IROp::FAsin: + + // 3-Op FP + case IROp::FAdd: + case IROp::FSub: + case IROp::FMul: + case IROp::FDiv: + case IROp::FMin: + case IROp::FMax: + + // 2-Op FP + case IROp::FMov: + case IROp::FAbs: + case IROp::FSqrt: + case IROp::FNeg: + case IROp::FSat0_1: + case IROp::FSatMinus1_1: + case IROp::FSign: + case IROp::FCeil: + case IROp::FFloor: + case IROp::FCmp: + case IROp::FCvtSW: + case IROp::FCvtWS: + case IROp::FRound: + case IROp::FTrunc: + + // Cross moves + case IROp::FMovFromGPR: + case IROp::FMovToGPR: + case IROp::FpCondToReg: + case IROp::VfpuCtrlToReg: + + // VFPU flag/control + case IROp::SetCtrlVFPU: + case IROp::SetCtrlVFPUReg: + case IROp::SetCtrlVFPUFReg: + case IROp::ZeroFpCond: + + // Block Exits + case IROp::ExitToConst: + case IROp::ExitToReg: + case IROp::ExitToConstIfEq: + case IROp::ExitToConstIfNeq: + case IROp::ExitToConstIfGtZ: + case IROp::ExitToConstIfGeZ: + case IROp::ExitToConstIfLtZ: + case IROp::ExitToConstIfLeZ: + case IROp::ExitToPC: + + // Utilities + case IROp::Downcount: + case IROp::SetPC: + case IROp::SetPCConst: + case IROp::Syscall: + case IROp::Interpret: // SLOW fallback. Can be made faster. + case IROp::CallReplacement: + case IROp::Break: + default: + break; + } + } + } + + +} // namespace + +#endif // PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) diff --git a/Core/MIPS/x86/IRToX86.h b/Core/MIPS/x86/IRToX86.h new file mode 100644 index 000000000..31a2cc329 --- /dev/null +++ b/Core/MIPS/x86/IRToX86.h @@ -0,0 +1,23 @@ +#include "Core/MIPS/IR/IRInst.h" +#include "Common/x64Emitter.h" + +namespace MIPSComp { + +class IRToNativeInterface { +public: + virtual ~IRToNativeInterface() {} + + virtual void ConvertIRToNative(const IRInst *instructions, int count, const u32 *constants) = 0; +}; + + +class IRToX86 : public IRToNativeInterface { +public: + void SetCodeBlock(Gen::XCodeBlock *code) { code_ = code; } + void ConvertIRToNative(const IRInst *instructions, int count, const u32 *constants) override; + +private: + Gen::XCodeBlock *code_; +}; + +} // namespace diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 2f561a2cd..36acbf5c9 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -144,9 +144,6 @@ void Jit::DoState(PointerWrap &p) { return; Do(p, js.startDefaultPrefix); - if (p.mode == PointerWrap::MODE_READ && !js.startDefaultPrefix) { - WARN_LOG(CPU, "Jit: An uneaten prefix was previously detected. Jitting in unknown-prefix mode."); - } if (s >= 2) { Do(p, js.hasSetRounding); if (p.mode == PointerWrap::MODE_READ) { @@ -182,15 +179,6 @@ void Jit::FlushAll() { } void Jit::FlushPrefixV() { - if (js.startDefaultPrefix && !js.blockWrotePrefixes && js.HasNoPrefix()) { - // They started default, we never modified in memory, and they're default now. - // No reason to modify memory. This is common at end of blocks. Just clear dirty. - js.prefixSFlag = (JitState::PrefixState)(js.prefixSFlag & ~JitState::PREFIX_DIRTY); - js.prefixTFlag = (JitState::PrefixState)(js.prefixTFlag & ~JitState::PREFIX_DIRTY); - js.prefixDFlag = (JitState::PrefixState)(js.prefixDFlag & ~JitState::PREFIX_DIRTY); - return; - } - if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) { MOV(32, MIPSSTATE_VAR(vfpuCtrl[VFPU_CTRL_SPREFIX]), Imm32(js.prefixS)); js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY); @@ -205,9 +193,6 @@ void Jit::FlushPrefixV() { MOV(32, MIPSSTATE_VAR(vfpuCtrl[VFPU_CTRL_DPREFIX]), Imm32(js.prefixD)); js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } - - // If we got here, we must've written prefixes to memory in this block. - js.blockWrotePrefixes = true; } void Jit::WriteDowncount(int offset) { @@ -315,7 +300,6 @@ void Jit::Compile(u32 em_address) { int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); - _assert_msg_(b->originalAddress == em_address, "original %08x != em_address %08x (block %d)", b->originalAddress, em_address, b->blockNum); blocks.FinalizeBlock(block_num, jo.enableBlocklink); EndWrite(); @@ -361,8 +345,7 @@ MIPSOpcode Jit::GetOffsetInstruction(int offset) { const u8 *Jit::DoJit(u32 em_address, JitBlock *b) { js.cancel = false; - js.blockStart = em_address; - js.compilerPC = em_address; + js.blockStart = js.compilerPC = mips_->pc; js.lastContinuedPC = 0; js.initialBlockSize = 0; js.nextExit = 0; @@ -370,7 +353,6 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b) { js.curBlock = b; js.compiling = true; js.inDelaySlot = false; - js.blockWrotePrefixes = false; js.afterOp = JitState::AFTER_NONE; js.PrefixStart(); @@ -605,7 +587,7 @@ void Jit::Comp_ReplacementFunc(MIPSOpcode op) { const ReplacementTableEntry *entry = GetReplacementFunc(index); if (!entry) { - ERROR_LOG_REPORT_ONCE(replFunc, HLE, "Invalid replacement op %08x at %08x", op.encoding, js.compilerPC); + ERROR_LOG(HLE, "Invalid replacement op %08x", op.encoding); return; } @@ -696,10 +678,6 @@ void Jit::Comp_Generic(MIPSOpcode op) { // If it does eat them, it'll happen in MIPSCompileOp(). if ((info & OUT_EAT_PREFIX) == 0) js.PrefixUnknown(); - - // Even if DISABLE'd, we want to set this flag so we overwrite. - if ((info & OUT_VFPU_PREFIX) != 0) - js.blockWrotePrefixes = true; } } @@ -708,7 +686,7 @@ static void HitInvalidBranch(uint32_t dest) { } void Jit::WriteExit(u32 destination, int exit_num) { - _assert_msg_(exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num. dest=%08x", destination); + _dbg_assert_msg_(exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num"); if (!Memory::IsValidAddress(destination) || (destination & 3) != 0) { ERROR_LOG_REPORT(JIT, "Trying to write block exit to illegal destination %08x: pc = %08x", destination, currentMIPS->pc); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 423678500..2e2f806fd 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -69,7 +69,6 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; - void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; @@ -225,7 +224,7 @@ private: void CompITypeMemRead(MIPSOpcode op, u32 bits, void (XEmitter::*mov)(int, int, Gen::X64Reg, Gen::OpArg), T (*safeFunc)(u32 addr)) { CompITypeMemRead(op, bits, mov, (const void *)safeFunc); } - void CompITypeMemWrite(MIPSOpcode op, u32 bits, const void *safeFunc, bool makeRTWritable = false); + void CompITypeMemWrite(MIPSOpcode op, u32 bits, const void *safeFunc); template void CompITypeMemWrite(MIPSOpcode op, u32 bits, void (*safeFunc)(T val, u32 addr)) { CompITypeMemWrite(op, bits, (const void *)safeFunc); diff --git a/Core/MIPS/x86/X64IRAsm.cpp b/Core/MIPS/x86/X64IRAsm.cpp deleted file mode 100644 index 86cb3929c..000000000 --- a/Core/MIPS/x86/X64IRAsm.cpp +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include "Common/Log.h" -#include "Core/CoreTiming.h" -#include "Core/MemMap.h" -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/System.h" - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -static const bool enableDebug = false; -static const bool enableDisasm = false; - -static void ShowPC(void *membase, void *jitbase) { - static int count = 0; - if (currentMIPS) { - u32 downcount = currentMIPS->downcount; - ERROR_LOG(JIT, "[%08x] ShowPC Downcount : %08x %d %p %p", currentMIPS->pc, downcount, count, membase, jitbase); - } else { - ERROR_LOG(JIT, "Universe corrupt?"); - } - //if (count > 2000) - // exit(0); - count++; -} - -void X64JitBackend::GenerateFixedCode(MIPSState *mipsState) { - // This will be used as a writable scratch area, always 32-bit accessible. - const u8 *start = AlignCodePage(); - if (DebugProfilerEnabled()) { - ProtectMemoryPages(start, GetMemoryProtectPageSize(), MEM_PROT_READ | MEM_PROT_WRITE); - hooks_.profilerPC = (uint32_t *)GetWritableCodePtr(); - Write32(0); - hooks_.profilerStatus = (IRProfilerStatus *)GetWritableCodePtr(); - Write32(0); - } - - EmitFPUConstants(); - EmitVecConstants(); - - const u8 *disasmStart = AlignCodePage(); - BeginWrite(GetMemoryProtectPageSize()); - - jo.downcountInRegister = false; -#if PPSSPP_ARCH(AMD64) - bool jitbaseInR15 = false; - int jitbaseCtxDisp = 0; - // We pre-bake the MIPS_EMUHACK_OPCODE subtraction into our jitbase value. - intptr_t jitbase = (intptr_t)GetBasePtr() - MIPS_EMUHACK_OPCODE; - if ((jitbase < -0x80000000LL || jitbase > 0x7FFFFFFFLL) && !Accessible((const u8 *)&mipsState->f[0], (const u8 *)jitbase)) { - jo.reserveR15ForAsm = true; - jitbaseInR15 = true; - } else { - jo.downcountInRegister = true; - jo.reserveR15ForAsm = true; - if (jitbase < -0x80000000LL || jitbase > 0x7FFFFFFFLL) { - jitbaseCtxDisp = (int)(jitbase - (intptr_t)&mipsState->f[0]); - } - } -#endif - - if (jo.useStaticAlloc && false) { - saveStaticRegisters_ = AlignCode16(); - if (jo.downcountInRegister) - MOV(32, MDisp(CTXREG, downcountOffset), R(DOWNCOUNTREG)); - //regs_.EmitSaveStaticRegisters(); - RET(); - - // Note: needs to not modify EAX, or to save it if it does. - loadStaticRegisters_ = AlignCode16(); - //regs_.EmitLoadStaticRegisters(); - if (jo.downcountInRegister) - MOV(32, R(DOWNCOUNTREG), MDisp(CTXREG, downcountOffset)); - RET(); - } else { - saveStaticRegisters_ = nullptr; - loadStaticRegisters_ = nullptr; - } - - restoreRoundingMode_ = AlignCode16(); - { - STMXCSR(MDisp(CTXREG, tempOffset)); - // Clear the rounding mode and flush-to-zero bits back to 0. - AND(32, MDisp(CTXREG, tempOffset), Imm32(~(7 << 13))); - LDMXCSR(MDisp(CTXREG, tempOffset)); - RET(); - } - - applyRoundingMode_ = AlignCode16(); - { - MOV(32, R(SCRATCH1), MDisp(CTXREG, fcr31Offset)); - AND(32, R(SCRATCH1), Imm32(0x01000003)); - - // If it's 0 (nearest + no flush0), we don't actually bother setting - we cleared the rounding - // mode out in restoreRoundingMode anyway. This is the most common. - FixupBranch skip = J_CC(CC_Z); - STMXCSR(MDisp(CTXREG, tempOffset)); - - // The MIPS bits don't correspond exactly, so we have to adjust. - // 0 -> 0 (skip2), 1 -> 3, 2 -> 2 (skip2), 3 -> 1 - TEST(8, R(AL), Imm8(1)); - FixupBranch skip2 = J_CC(CC_Z); - XOR(32, R(SCRATCH1), Imm8(2)); - SetJumpTarget(skip2); - - // Adjustment complete, now reconstruct MXCSR - SHL(32, R(SCRATCH1), Imm8(13)); - // Before setting new bits, we must clear the old ones. - // Clearing bits 13-14 (rounding mode) and 15 (flush to zero.) - AND(32, MDisp(CTXREG, tempOffset), Imm32(~(7 << 13))); - OR(32, MDisp(CTXREG, tempOffset), R(SCRATCH1)); - - TEST(32, MDisp(CTXREG, fcr31Offset), Imm32(1 << 24)); - FixupBranch skip3 = J_CC(CC_Z); - OR(32, MDisp(CTXREG, tempOffset), Imm32(1 << 15)); - SetJumpTarget(skip3); - - LDMXCSR(MDisp(CTXREG, tempOffset)); - SetJumpTarget(skip); - RET(); - } - - hooks_.enterDispatcher = (IRNativeFuncNoArg)AlignCode16(); - - ABI_PushAllCalleeSavedRegsAndAdjustStack(); -#if PPSSPP_ARCH(AMD64) - // Two x64-specific statically allocated registers. - MOV(64, R(MEMBASEREG), ImmPtr(Memory::base)); - if (jitbaseInR15) - MOV(64, R(JITBASEREG), ImmPtr((const void *)jitbase)); -#endif - // From the start of the FP reg, a single byte offset can reach all GPR + all FPR (but not VFPR.) - MOV(PTRBITS, R(CTXREG), ImmPtr(&mipsState->f[0])); - - LoadStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - MovFromPC(SCRATCH1); - WriteDebugPC(SCRATCH1); - outerLoopPCInSCRATCH1_ = GetCodePtr(); - MovToPC(SCRATCH1); - outerLoop_ = GetCodePtr(); - // Advance can change the downcount (or thread), so must save/restore around it. - SaveStaticRegisters(); - RestoreRoundingMode(true); - WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE); - ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - ApplyRoundingMode(true); - LoadStaticRegisters(); - - dispatcherCheckCoreState_ = GetCodePtr(); - // TODO: See if we can get the slice decrement to line up with IR. - - if (RipAccessible((const void *)&coreState)) { - CMP(32, M(&coreState), Imm8(0)); // rip accessible - } else { - MOV(PTRBITS, R(RAX), ImmPtr((const void *)&coreState)); - CMP(32, MatR(RAX), Imm8(0)); - } - FixupBranch badCoreState = J_CC(CC_NZ, true); - - if (jo.downcountInRegister) { - TEST(32, R(DOWNCOUNTREG), R(DOWNCOUNTREG)); - } else { - CMP(32, MDisp(CTXREG, downcountOffset), Imm8(0)); - } - J_CC(CC_S, outerLoop_); - FixupBranch skipToRealDispatch = J(); - - dispatcherPCInSCRATCH1_ = GetCodePtr(); - MovToPC(SCRATCH1); - - hooks_.dispatcher = GetCodePtr(); - - // TODO: See if we can get the slice decrement to line up with IR. - if (jo.downcountInRegister) { - TEST(32, R(DOWNCOUNTREG), R(DOWNCOUNTREG)); - } else { - CMP(32, MDisp(CTXREG, downcountOffset), Imm8(0)); - } - FixupBranch bail = J_CC(CC_S, true); - SetJumpTarget(skipToRealDispatch); - - dispatcherNoCheck_ = GetCodePtr(); - - // Debug - if (enableDebug) { -#if PPSSPP_ARCH(AMD64) - if (jitbaseInR15) { - ABI_CallFunctionAA(reinterpret_cast(&ShowPC), R(MEMBASEREG), R(JITBASEREG)); - } else if (jitbaseCtxDisp != 0) { - LEA(64, SCRATCH1, MDisp(CTXREG, jitbaseCtxDisp)); - ABI_CallFunctionAA(reinterpret_cast(&ShowPC), R(MEMBASEREG), R(SCRATCH1)); - } else { - ABI_CallFunctionAC(reinterpret_cast(&ShowPC), R(MEMBASEREG), (u32)jitbase); - } -#else - ABI_CallFunctionCC(reinterpret_cast(&ShowPC), (u32)Memory::base, (u32)GetBasePtr()); -#endif - } - - MovFromPC(SCRATCH1); - WriteDebugPC(SCRATCH1); -#ifdef MASKED_PSP_MEMORY - AND(32, R(SCRATCH1), Imm32(Memory::MEMVIEW32_MASK)); -#endif - hooks_.dispatchFetch = GetCodePtr(); -#if PPSSPP_ARCH(X86) - _assert_msg_( Memory::base != 0, "Memory base bogus"); - MOV(32, R(SCRATCH1), MDisp(SCRATCH1, (u32)Memory::base)); -#elif PPSSPP_ARCH(AMD64) - MOV(32, R(SCRATCH1), MComplex(MEMBASEREG, SCRATCH1, SCALE_1, 0)); -#endif - _assert_msg_(MIPS_JITBLOCK_MASK == 0xFF000000, "Hardcoded assumption of emuhack mask"); - if (cpu_info.bBMI2) { - RORX(32, EDX, R(SCRATCH1), 24); - CMP(8, R(EDX), Imm8(MIPS_EMUHACK_OPCODE >> 24)); - } else { - MOV(32, R(EDX), R(SCRATCH1)); - SHR(32, R(EDX), Imm8(24)); - CMP(32, R(EDX), Imm8(MIPS_EMUHACK_OPCODE >> 24)); - } - FixupBranch needsCompile = J_CC(CC_NE); - // We don't mask here - that's baked into jitbase. -#if PPSSPP_ARCH(X86) - LEA(32, SCRATCH1, MDisp(SCRATCH1, (u32)GetBasePtr() - MIPS_EMUHACK_OPCODE)); -#elif PPSSPP_ARCH(AMD64) - if (jitbaseInR15) { - ADD(64, R(SCRATCH1), R(JITBASEREG)); - } else if (jitbaseCtxDisp) { - LEA(64, SCRATCH1, MComplex(CTXREG, SCRATCH1, SCALE_1, jitbaseCtxDisp)); - } else { - // See above, reserveR15ForAsm is used when above 0x7FFFFFFF. - LEA(64, SCRATCH1, MDisp(SCRATCH1, (s32)jitbase)); - } -#endif - JMPptr(R(SCRATCH1)); - SetJumpTarget(needsCompile); - - // No block found, let's jit. We don't need to save static regs, they're all callee saved. - RestoreRoundingMode(true); - WriteDebugProfilerStatus(IRProfilerStatus::COMPILING); - ABI_CallFunction(&MIPSComp::JitAt); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - ApplyRoundingMode(true); - // Let's just dispatch again, we'll enter the block since we know it's there. - JMP(dispatcherNoCheck_, true); - - SetJumpTarget(bail); - - if (RipAccessible((const void *)&coreState)) { - CMP(32, M(&coreState), Imm8(0)); // rip accessible - } else { - MOV(PTRBITS, R(RAX), ImmPtr((const void *)&coreState)); - CMP(32, MatR(RAX), Imm8(0)); - } - J_CC(CC_Z, outerLoop_, true); - - const uint8_t *quitLoop = GetCodePtr(); - SetJumpTarget(badCoreState); - - WriteDebugProfilerStatus(IRProfilerStatus::NOT_RUNNING); - SaveStaticRegisters(); - RestoreRoundingMode(true); - ABI_PopAllCalleeSavedRegsAndAdjustStack(); - RET(); - - hooks_.crashHandler = GetCodePtr(); - if (RipAccessible((const void *)&coreState)) { - MOV(32, M(&coreState), Imm32(CORE_RUNTIME_ERROR)); - } else { - MOV(PTRBITS, R(RAX), ImmPtr((const void *)&coreState)); - MOV(32, MatR(RAX), Imm32(CORE_RUNTIME_ERROR)); - } - JMP(quitLoop, true); - - - // Leave this at the end, add more stuff above. - if (enableDisasm) { -#if PPSSPP_ARCH(AMD64) - std::vector lines = DisassembleX86(disasmStart, (int)(GetCodePtr() - disasmStart)); - for (auto s : lines) { - INFO_LOG(JIT, "%s", s.c_str()); - } -#endif - } - - // Let's spare the pre-generated code from unprotect-reprotect. - AlignCodePage(); - jitStartOffset_ = (int)(GetCodePtr() - start); - EndWrite(); -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRCompALU.cpp b/Core/MIPS/x86/X64IRCompALU.cpp deleted file mode 100644 index 66fe205b2..000000000 --- a/Core/MIPS/x86/X64IRCompALU.cpp +++ /dev/null @@ -1,902 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include "Common/CPUDetect.h" -#include "Core/MemMap.h" -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -// This file contains compilation for integer / arithmetic / logic related instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -void X64JitBackend::CompIR_Arith(IRInst inst) { - CONDITIONAL_DISABLE; - - bool allowPtrMath = inst.constant <= 0x7FFFFFFF; -#ifdef MASKED_PSP_MEMORY - // Since we modify it, we can't safely. - allowPtrMath = false; -#endif - - switch (inst.op) { - case IROp::Add: - regs_.Map(inst); - if (inst.src1 == inst.src2) { - LEA(32, regs_.RX(inst.dest), MScaled(regs_.RX(inst.src1), 2, 0)); - } else if (inst.dest == inst.src2) { - ADD(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else if (inst.dest == inst.src1) { - ADD(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - ADD(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - break; - - case IROp::Sub: - regs_.Map(inst); - if (inst.src1 == inst.src2) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.dest == inst.src2) { - NEG(32, regs_.R(inst.src2)); - ADD(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else if (inst.dest == inst.src1) { - SUB(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SUB(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - break; - - case IROp::AddConst: - if (regs_.IsGPRMappedAsPointer(inst.dest) && inst.dest == inst.src1 && allowPtrMath) { - regs_.MarkGPRAsPointerDirty(inst.dest); - LEA(PTRBITS, regs_.RXPtr(inst.dest), MDisp(regs_.RXPtr(inst.dest), inst.constant)); - } else { - regs_.Map(inst); - LEA(32, regs_.RX(inst.dest), MDisp(regs_.RX(inst.src1), inst.constant)); - } - break; - - case IROp::SubConst: - if (regs_.IsGPRMappedAsPointer(inst.dest) && inst.dest == inst.src1 && allowPtrMath) { - regs_.MarkGPRAsPointerDirty(inst.dest); - LEA(PTRBITS, regs_.RXPtr(inst.dest), MDisp(regs_.RXPtr(inst.dest), -(int)inst.constant)); - } else { - regs_.Map(inst); - LEA(32, regs_.RX(inst.dest), MDisp(regs_.RX(inst.src1), -(int)inst.constant)); - } - break; - - case IROp::Neg: - regs_.Map(inst); - if (inst.dest != inst.src1) { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - NEG(32, regs_.R(inst.dest)); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Assign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Mov: - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::Ext8to32: - regs_.MapWithFlags(inst, X64Map::NONE, X64Map::LOW_SUBREG); - MOVSX(32, 8, regs_.RX(inst.dest), regs_.R(inst.src1)); - break; - - case IROp::Ext16to32: - regs_.Map(inst); - MOVSX(32, 16, regs_.RX(inst.dest), regs_.R(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Bits(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::BSwap32: - regs_.Map(inst); - if (inst.src1 != inst.dest) { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - BSWAP(32, regs_.RX(inst.dest)); - break; - - case IROp::ReverseBits: - regs_.Map(inst); - if (inst.src1 != inst.dest) { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - - // Swap even/odd bits (in bits: 0123 -> 1032.) - LEA(32, SCRATCH1, MScaled(regs_.RX(inst.dest), 2, 0)); - SHR(32, regs_.R(inst.dest), Imm8(1)); - XOR(32, regs_.R(inst.dest), R(SCRATCH1)); - AND(32, regs_.R(inst.dest), Imm32(0x55555555)); - XOR(32, regs_.R(inst.dest), R(SCRATCH1)); - - // Swap pairs of bits (in bits: 10325476 -> 32107654.) - LEA(32, SCRATCH1, MScaled(regs_.RX(inst.dest), 4, 0)); - SHR(32, regs_.R(inst.dest), Imm8(2)); - XOR(32, regs_.R(inst.dest), R(SCRATCH1)); - AND(32, regs_.R(inst.dest), Imm32(0x33333333)); - XOR(32, regs_.R(inst.dest), R(SCRATCH1)); - - // Swap nibbles (in nibbles: ABCD -> BADC.) - MOV(32, R(SCRATCH1), regs_.R(inst.dest)); - SHL(32, R(SCRATCH1), Imm8(4)); - SHR(32, regs_.R(inst.dest), Imm8(4)); - XOR(32, regs_.R(inst.dest), R(SCRATCH1)); - AND(32, regs_.R(inst.dest), Imm32(0x0F0F0F0F)); - XOR(32, regs_.R(inst.dest), R(SCRATCH1)); - - // Finally, swap the bytes to drop everything into place (nibbles: BADCFEHG -> HGFEDCBA.) - BSWAP(32, regs_.RX(inst.dest)); - break; - - case IROp::BSwap16: - regs_.Map(inst); - if (cpu_info.bBMI2) { - // Rotate to put it into the correct register, then swap. - if (inst.dest != inst.src1) - RORX(32, regs_.RX(inst.dest), regs_.R(inst.src1), 16); - else - ROR(32, regs_.R(inst.dest), Imm8(16)); - BSWAP(32, regs_.RX(inst.dest)); - } else { - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - BSWAP(32, regs_.RX(inst.dest)); - ROR(32, regs_.R(inst.dest), Imm8(16)); - } - break; - - case IROp::Clz: - regs_.Map(inst); - if (cpu_info.bLZCNT) { - LZCNT(32, regs_.RX(inst.dest), regs_.R(inst.src1)); - } else { - BSR(32, regs_.RX(inst.dest), regs_.R(inst.src1)); - FixupBranch notFound = J_CC(CC_Z); - - // Since one of these bits must be set, and none outside, this subtracts from 31. - XOR(32, regs_.R(inst.dest), Imm8(31)); - FixupBranch skip = J(); - - SetJumpTarget(notFound); - MOV(32, regs_.R(inst.dest), Imm32(32)); - - SetJumpTarget(skip); - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Compare(IRInst inst) { - CONDITIONAL_DISABLE; - - auto setCC = [&](const OpArg &arg, CCFlags cc) { - // If it's carry, we can take advantage of ADC to avoid subregisters. - if (cc == CC_C && inst.dest != inst.src1 && inst.dest != inst.src2) { - XOR(32, regs_.R(inst.dest), regs_.R(inst.dest)); - CMP(32, regs_.R(inst.src1), arg); - ADC(32, regs_.R(inst.dest), Imm8(0)); - } else if (regs_.HasLowSubregister(regs_.RX(inst.dest)) && inst.dest != inst.src1 && inst.dest != inst.src2) { - XOR(32, regs_.R(inst.dest), regs_.R(inst.dest)); - CMP(32, regs_.R(inst.src1), arg); - SETcc(cc, regs_.R(inst.dest)); - } else { - CMP(32, regs_.R(inst.src1), arg); - SETcc(cc, R(SCRATCH1)); - MOVZX(32, 8, regs_.RX(inst.dest), R(SCRATCH1)); - } - }; - - switch (inst.op) { - case IROp::Slt: - regs_.Map(inst); - setCC(regs_.R(inst.src2), CC_L); - break; - - case IROp::SltConst: - if (inst.constant == 0) { - // Basically, getting the sign bit. Let's shift instead. - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SHR(32, regs_.R(inst.dest), Imm8(31)); - } else { - regs_.Map(inst); - setCC(Imm32(inst.constant), CC_L); - } - break; - - case IROp::SltU: - if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) { - // This is kinda common, same as != 0. Avoid flushing src1. - regs_.SpillLockGPR(inst.src2, inst.dest); - regs_.MapGPR(inst.src2); - regs_.MapGPR(inst.dest, MIPSMap::NOINIT); - if (inst.dest != inst.src2 && regs_.HasLowSubregister(regs_.RX(inst.dest))) { - XOR(32, regs_.R(inst.dest), regs_.R(inst.dest)); - TEST(32, regs_.R(inst.src2), regs_.R(inst.src2)); - SETcc(CC_NE, regs_.R(inst.dest)); - } else { - CMP(32, regs_.R(inst.src2), Imm8(0)); - SETcc(CC_NE, R(SCRATCH1)); - MOVZX(32, 8, regs_.RX(inst.dest), R(SCRATCH1)); - } - } else { - regs_.Map(inst); - setCC(regs_.R(inst.src2), CC_B); - } - break; - - case IROp::SltUConst: - if (inst.constant == 0) { - regs_.SetGPRImm(inst.dest, 0); - } else { - regs_.Map(inst); - setCC(Imm32(inst.constant), CC_B); - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_CondAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::MovZ: - if (inst.dest != inst.src2) { - regs_.Map(inst); - TEST(32, regs_.R(inst.src1), regs_.R(inst.src1)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src2), CC_Z); - } - break; - - case IROp::MovNZ: - if (inst.dest != inst.src2) { - regs_.Map(inst); - TEST(32, regs_.R(inst.src1), regs_.R(inst.src1)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src2), CC_NZ); - } - break; - - case IROp::Max: - regs_.Map(inst); - if (inst.src1 == inst.src2) { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else if (inst.dest == inst.src1) { - CMP(32, regs_.R(inst.src1), regs_.R(inst.src2)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src2), CC_L); - } else if (inst.dest == inst.src2) { - CMP(32, regs_.R(inst.src1), regs_.R(inst.src2)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src1), CC_G); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - CMP(32, regs_.R(inst.dest), regs_.R(inst.src2)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src2), CC_L); - } - break; - - case IROp::Min: - regs_.Map(inst); - if (inst.src1 == inst.src2) { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else if (inst.dest == inst.src1) { - CMP(32, regs_.R(inst.src1), regs_.R(inst.src2)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src2), CC_G); - } else if (inst.dest == inst.src2) { - CMP(32, regs_.R(inst.src1), regs_.R(inst.src2)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src1), CC_L); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - CMP(32, regs_.R(inst.dest), regs_.R(inst.src2)); - CMOVcc(32, regs_.RX(inst.dest), regs_.R(inst.src2), CC_G); - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Div(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Div: -#if PPSSPP_ARCH(AMD64) - // We need EDX specifically, so force a spill (before spill locks happen.) - regs_.MapGPR2(IRREG_LO, MIPSMap::NOINIT | X64Map::HIGH_DATA); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT | X64Map::HIGH_DATA } }); -#else // PPSSPP_ARCH(X86) - // Force a spill, it's HI in this path. - regs_.MapGPR(IRREG_HI, MIPSMap::NOINIT | X64Map::HIGH_DATA); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::NOINIT }, { 'G', IRREG_HI, 1, MIPSMap::NOINIT | X64Map::HIGH_DATA } }); -#endif - { - TEST(32, regs_.R(inst.src2), regs_.R(inst.src2)); - FixupBranch divideByZero = J_CC(CC_E, false); - - // Sign extension sets HI to -1 for us on x64. - MOV(PTRBITS, regs_.R(IRREG_LO), Imm32(0x80000000)); -#if PPSSPP_ARCH(X86) - MOV(PTRBITS, regs_.R(IRREG_HI), Imm32(-1)); -#endif - CMP(32, regs_.R(inst.src1), regs_.R(IRREG_LO)); - FixupBranch numeratorNotOverflow = J_CC(CC_NE, false); - CMP(32, regs_.R(inst.src2), Imm32(-1)); - FixupBranch denominatorOverflow = J_CC(CC_E, false); - - SetJumpTarget(numeratorNotOverflow); - - // It's finally time to actually divide. - MOV(32, R(EAX), regs_.R(inst.src1)); - CDQ(); - IDIV(32, regs_.R(inst.src2)); -#if PPSSPP_ARCH(AMD64) - // EDX == RX(IRREG_LO). Put the remainder in the upper bits, done. - SHL(64, R(EDX), Imm8(32)); - OR(64, R(EDX), R(EAX)); -#else // PPSSPP_ARCH(X86) - // EDX is already good (HI), just move EAX into place. - MOV(32, regs_.R(IRREG_LO), R(EAX)); -#endif - FixupBranch done = J(false); - - SetJumpTarget(divideByZero); - X64Reg loReg = SCRATCH1; -#if PPSSPP_ARCH(X86) - if (regs_.HasLowSubregister(regs_.RX(IRREG_LO))) - loReg = regs_.RX(IRREG_LO); -#endif - // Set to -1 if numerator positive using SF. - XOR(32, R(loReg), R(loReg)); - TEST(32, regs_.R(inst.src1), regs_.R(inst.src1)); - SETcc(CC_NS, R(loReg)); - NEG(32, R(loReg)); - // If it was negative, OR in 1 (so we get -1 or 1.) - OR(32, R(loReg), Imm8(1)); - -#if PPSSPP_ARCH(AMD64) - // Move the numerator into the high bits. - MOV(32, regs_.R(IRREG_LO), regs_.R(inst.src1)); - SHL(64, regs_.R(IRREG_LO), Imm8(32)); - OR(64, regs_.R(IRREG_LO), R(loReg)); -#else // PPSSPP_ARCH(X86) - // If we didn't have a subreg, move into place. - if (loReg != regs_.RX(IRREG_LO)) - MOV(32, regs_.R(IRREG_LO), R(loReg)); - MOV(32, regs_.R(IRREG_HI), regs_.R(inst.src1)); -#endif - - SetJumpTarget(denominatorOverflow); - SetJumpTarget(done); - } - break; - - case IROp::DivU: -#if PPSSPP_ARCH(AMD64) - // We need EDX specifically, so force a spill (before spill locks happen.) - regs_.MapGPR2(IRREG_LO, MIPSMap::NOINIT | X64Map::HIGH_DATA); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT | X64Map::HIGH_DATA } }); -#else // PPSSPP_ARCH(X86) - // Force a spill, it's HI in this path. - regs_.MapGPR(IRREG_HI, MIPSMap::NOINIT | X64Map::HIGH_DATA); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::NOINIT }, { 'G', IRREG_HI, 1, MIPSMap::NOINIT | X64Map::HIGH_DATA } }); -#endif - { - TEST(32, regs_.R(inst.src2), regs_.R(inst.src2)); - FixupBranch divideByZero = J_CC(CC_E, false); - - MOV(32, R(EAX), regs_.R(inst.src1)); - XOR(32, R(EDX), R(EDX)); - DIV(32, regs_.R(inst.src2)); -#if PPSSPP_ARCH(AMD64) - // EDX == RX(IRREG_LO). Put the remainder in the upper bits, done. - SHL(64, R(EDX), Imm8(32)); - OR(64, R(EDX), R(EAX)); -#else // PPSSPP_ARCH(X86) - // EDX is already good (HI), just move EAX into place. - MOV(32, regs_.R(IRREG_LO), R(EAX)); -#endif - FixupBranch done = J(false); - - SetJumpTarget(divideByZero); - // First, set LO to 0xFFFF if numerator was <= that value. - MOV(32, regs_.R(IRREG_LO), Imm32(0xFFFF)); - XOR(32, R(SCRATCH1), R(SCRATCH1)); - CMP(32, regs_.R(IRREG_LO), regs_.R(inst.src1)); - // If 0xFFFF was less, CF was set - SBB will subtract 1 from 0, netting -1. - SBB(32, R(SCRATCH1), Imm8(0)); - OR(32, regs_.R(IRREG_LO), R(SCRATCH1)); - -#if PPSSPP_ARCH(AMD64) - // Move the numerator into the high bits. - MOV(32, R(SCRATCH1), regs_.R(inst.src1)); - SHL(64, R(SCRATCH1), Imm8(32)); - OR(64, regs_.R(IRREG_LO), R(SCRATCH1)); -#else // PPSSPP_ARCH(X86) - MOV(32, regs_.R(IRREG_HI), regs_.R(inst.src1)); -#endif - - SetJumpTarget(done); - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_HiLo(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::MtLo: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // First, clear the bits we're replacing. - SHR(64, regs_.R(IRREG_LO), Imm8(32)); - SHL(64, regs_.R(IRREG_LO), Imm8(32)); - // Now clear the high bits and merge. - MOVZX(64, 32, regs_.RX(inst.src1), regs_.R(inst.src1)); - OR(64, regs_.R(IRREG_LO), regs_.R(inst.src1)); -#else // PPSSPP_ARCH(X86) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::DIRTY } }); - MOV(32, regs_.R(IRREG_LO), regs_.R(inst.src1)); -#endif - break; - - case IROp::MtHi: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - // First, clear the bits we're replacing. - MOVZX(64, 32, regs_.RX(IRREG_LO), regs_.R(IRREG_LO)); - // Then move the new bits into place. - MOV(32, R(SCRATCH1), regs_.R(inst.src1)); - SHL(64, R(SCRATCH1), Imm8(32)); - OR(64, regs_.R(IRREG_LO), R(SCRATCH1)); -#else // PPSSPP_ARCH(X86) - regs_.MapWithExtra(inst, { { 'G', IRREG_HI, 1, MIPSMap::DIRTY } }); - MOV(32, regs_.R(IRREG_HI), regs_.R(inst.src1)); -#endif - break; - - case IROp::MfLo: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::INIT } }); - MOV(32, regs_.R(inst.dest), regs_.R(IRREG_LO)); -#else // PPSSPP_ARCH(X86) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::INIT } }); - MOV(32, regs_.R(inst.dest), regs_.R(IRREG_LO)); -#endif - break; - - case IROp::MfHi: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::INIT } }); - MOV(64, regs_.R(inst.dest), regs_.R(IRREG_LO)); - SHR(64, regs_.R(inst.dest), Imm8(32)); -#else // PPSSPP_ARCH(X86) - regs_.MapWithExtra(inst, { { 'G', IRREG_HI, 1, MIPSMap::INIT } }); - MOV(32, regs_.R(inst.dest), regs_.R(IRREG_HI)); -#endif - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Logic(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::And: - regs_.Map(inst); - if (inst.dest == inst.src1) { - AND(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - AND(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - AND(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - break; - - case IROp::Or: - regs_.Map(inst); - if (inst.dest == inst.src1) { - OR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - OR(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - OR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - break; - - case IROp::Xor: - regs_.Map(inst); - if (inst.dest == inst.src1) { - XOR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - XOR(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - XOR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - break; - - case IROp::AndConst: - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - AND(32, regs_.R(inst.dest), SImmAuto((s32)inst.constant)); - break; - - case IROp::OrConst: - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - OR(32, regs_.R(inst.dest), SImmAuto((s32)inst.constant)); - break; - - case IROp::XorConst: - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - XOR(32, regs_.R(inst.dest), SImmAuto((s32)inst.constant)); - break; - - case IROp::Not: - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - NOT(32, regs_.R(inst.dest)); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Mult(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Mult: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - MOVSX(64, 32, regs_.RX(IRREG_LO), regs_.R(inst.src1)); - MOVSX(64, 32, regs_.RX(inst.src2), regs_.R(inst.src2)); - IMUL(64, regs_.RX(IRREG_LO), regs_.R(inst.src2)); -#else // PPSSPP_ARCH(X86) - // Force a spill (before spill locks.) - regs_.MapGPR(IRREG_HI, MIPSMap::NOINIT | X64Map::HIGH_DATA); - // We keep it here so it stays locked. - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::NOINIT }, { 'G', IRREG_HI, 1, MIPSMap::NOINIT | X64Map::HIGH_DATA } }); - MOV(32, R(EAX), regs_.R(inst.src1)); - IMUL(32, regs_.R(inst.src2)); - MOV(32, regs_.R(IRREG_LO), R(EAX)); - // IRREG_HI was mapped to EDX. -#endif - break; - - case IROp::MultU: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::NOINIT } }); - MOVZX(64, 32, regs_.RX(IRREG_LO), regs_.R(inst.src1)); - MOVZX(64, 32, regs_.RX(inst.src2), regs_.R(inst.src2)); - IMUL(64, regs_.RX(IRREG_LO), regs_.R(inst.src2)); -#else // PPSSPP_ARCH(X86) - // Force a spill (before spill locks.) - regs_.MapGPR(IRREG_HI, MIPSMap::NOINIT | X64Map::HIGH_DATA); - // We keep it here so it stays locked. - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::NOINIT }, { 'G', IRREG_HI, 1, MIPSMap::NOINIT | X64Map::HIGH_DATA } }); - MOV(32, R(EAX), regs_.R(inst.src1)); - MUL(32, regs_.R(inst.src2)); - MOV(32, regs_.R(IRREG_LO), R(EAX)); - // IRREG_HI was mapped to EDX. -#endif - break; - - case IROp::Madd: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - MOVSX(64, 32, SCRATCH1, regs_.R(inst.src1)); - MOVSX(64, 32, regs_.RX(inst.src2), regs_.R(inst.src2)); - IMUL(64, SCRATCH1, regs_.R(inst.src2)); - ADD(64, regs_.R(IRREG_LO), R(SCRATCH1)); -#else // PPSSPP_ARCH(X86) - // For ones that modify LO/HI, we can't have anything else in EDX. - regs_.ReserveAndLockXGPR(EDX); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::DIRTY }, { 'G', IRREG_HI, 1, MIPSMap::DIRTY } }); - MOV(32, R(EAX), regs_.R(inst.src1)); - IMUL(32, regs_.R(inst.src2)); - ADD(32, regs_.R(IRREG_LO), R(EAX)); - ADC(32, regs_.R(IRREG_HI), R(EDX)); -#endif - break; - - case IROp::MaddU: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - MOVZX(64, 32, SCRATCH1, regs_.R(inst.src1)); - MOVZX(64, 32, regs_.RX(inst.src2), regs_.R(inst.src2)); - IMUL(64, SCRATCH1, regs_.R(inst.src2)); - ADD(64, regs_.R(IRREG_LO), R(SCRATCH1)); -#else // PPSSPP_ARCH(X86) - // For ones that modify LO/HI, we can't have anything else in EDX. - regs_.ReserveAndLockXGPR(EDX); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::DIRTY }, { 'G', IRREG_HI, 1, MIPSMap::DIRTY } }); - MOV(32, R(EAX), regs_.R(inst.src1)); - MUL(32, regs_.R(inst.src2)); - ADD(32, regs_.R(IRREG_LO), R(EAX)); - ADC(32, regs_.R(IRREG_HI), R(EDX)); -#endif - break; - - case IROp::Msub: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - MOVSX(64, 32, SCRATCH1, regs_.R(inst.src1)); - MOVSX(64, 32, regs_.RX(inst.src2), regs_.R(inst.src2)); - IMUL(64, SCRATCH1, regs_.R(inst.src2)); - SUB(64, regs_.R(IRREG_LO), R(SCRATCH1)); -#else // PPSSPP_ARCH(X86) - // For ones that modify LO/HI, we can't have anything else in EDX. - regs_.ReserveAndLockXGPR(EDX); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::DIRTY }, { 'G', IRREG_HI, 1, MIPSMap::DIRTY } }); - MOV(32, R(EAX), regs_.R(inst.src1)); - IMUL(32, regs_.R(inst.src2)); - SUB(32, regs_.R(IRREG_LO), R(EAX)); - SBB(32, regs_.R(IRREG_HI), R(EDX)); -#endif - break; - - case IROp::MsubU: -#if PPSSPP_ARCH(AMD64) - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 2, MIPSMap::DIRTY } }); - MOVZX(64, 32, SCRATCH1, regs_.R(inst.src1)); - MOVZX(64, 32, regs_.RX(inst.src2), regs_.R(inst.src2)); - IMUL(64, SCRATCH1, regs_.R(inst.src2)); - SUB(64, regs_.R(IRREG_LO), R(SCRATCH1)); -#else // PPSSPP_ARCH(X86) - // For ones that modify LO/HI, we can't have anything else in EDX. - regs_.ReserveAndLockXGPR(EDX); - regs_.MapWithExtra(inst, { { 'G', IRREG_LO, 1, MIPSMap::DIRTY }, { 'G', IRREG_HI, 1, MIPSMap::DIRTY } }); - MOV(32, R(EAX), regs_.R(inst.src1)); - MUL(32, regs_.R(inst.src2)); - SUB(32, regs_.R(IRREG_LO), R(EAX)); - SBB(32, regs_.R(IRREG_HI), R(EDX)); -#endif - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Shift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Shl: - if (cpu_info.bBMI2) { - regs_.Map(inst); - SHLX(32, regs_.RX(inst.dest), regs_.R(inst.src1), regs_.RX(inst.src2)); - } else { - regs_.MapWithFlags(inst, X64Map::NONE, X64Map::NONE, X64Map::SHIFT); - if (inst.dest == inst.src1) { - SHL(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - MOV(32, R(SCRATCH1), regs_.R(inst.src1)); - SHL(32, R(SCRATCH1), regs_.R(inst.src2)); - MOV(32, regs_.R(inst.dest), R(SCRATCH1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SHL(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - } - break; - - case IROp::Shr: - if (cpu_info.bBMI2) { - regs_.Map(inst); - SHRX(32, regs_.RX(inst.dest), regs_.R(inst.src1), regs_.RX(inst.src2)); - } else { - regs_.MapWithFlags(inst, X64Map::NONE, X64Map::NONE, X64Map::SHIFT); - if (inst.dest == inst.src1) { - SHR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - MOV(32, R(SCRATCH1), regs_.R(inst.src1)); - SHR(32, R(SCRATCH1), regs_.R(inst.src2)); - MOV(32, regs_.R(inst.dest), R(SCRATCH1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SHR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - } - break; - - case IROp::Sar: - if (cpu_info.bBMI2) { - regs_.Map(inst); - SARX(32, regs_.RX(inst.dest), regs_.R(inst.src1), regs_.RX(inst.src2)); - } else { - regs_.MapWithFlags(inst, X64Map::NONE, X64Map::NONE, X64Map::SHIFT); - if (inst.dest == inst.src1) { - SAR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - MOV(32, R(SCRATCH1), regs_.R(inst.src1)); - SAR(32, R(SCRATCH1), regs_.R(inst.src2)); - MOV(32, regs_.R(inst.dest), R(SCRATCH1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SAR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - } - break; - - case IROp::Ror: - regs_.MapWithFlags(inst, X64Map::NONE, X64Map::NONE, X64Map::SHIFT); - if (inst.dest == inst.src1) { - ROR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } else if (inst.dest == inst.src2) { - MOV(32, R(SCRATCH1), regs_.R(inst.src1)); - ROR(32, R(SCRATCH1), regs_.R(inst.src2)); - MOV(32, regs_.R(inst.dest), R(SCRATCH1)); - } else { - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - ROR(32, regs_.R(inst.dest), regs_.R(inst.src2)); - } - break; - - case IROp::ShlImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else if (inst.src2 <= 3) { - regs_.Map(inst); - LEA(32, regs_.RX(inst.dest), MScaled(regs_.RX(inst.src1), 1 << inst.src2, 0)); - } else { - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SHL(32, regs_.R(inst.dest), Imm8(inst.src2)); - } - break; - - case IROp::ShrImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.SetGPRImm(inst.dest, 0); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else { - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SHR(32, regs_.R(inst.dest), Imm8(inst.src2)); - } - break; - - case IROp::SarImm: - // Shouldn't happen, but let's be safe of any passes that modify the ops. - if (inst.src2 >= 32) { - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SAR(32, regs_.R(inst.dest), Imm8(31)); - } else if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else { - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - SAR(32, regs_.R(inst.dest), Imm8(inst.src2)); - } - break; - - case IROp::RorImm: - if (inst.src2 == 0) { - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - } - } else if (cpu_info.bBMI2) { - regs_.Map(inst); - RORX(32, regs_.RX(inst.dest), regs_.R(inst.src1), inst.src2 & 31); - } else { - regs_.Map(inst); - if (inst.dest != inst.src1) - MOV(32, regs_.R(inst.dest), regs_.R(inst.src1)); - ROR(32, regs_.R(inst.dest), Imm8(inst.src2 & 31)); - } - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRCompBranch.cpp b/Core/MIPS/x86/X64IRCompBranch.cpp deleted file mode 100644 index a3e463114..000000000 --- a/Core/MIPS/x86/X64IRCompBranch.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -// This file contains compilation for exits. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -void X64JitBackend::CompIR_Exit(IRInst inst) { - CONDITIONAL_DISABLE; - - X64Reg exitReg = INVALID_REG; - switch (inst.op) { - case IROp::ExitToConst: - FlushAll(); - WriteConstExit(inst.constant); - break; - - case IROp::ExitToReg: - exitReg = regs_.MapGPR(inst.src1); - FlushAll(); - MOV(32, R(SCRATCH1), R(exitReg)); - JMP(dispatcherPCInSCRATCH1_, true); - break; - - case IROp::ExitToPC: - FlushAll(); - JMP(dispatcherCheckCoreState_, true); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_ExitIf(IRInst inst) { - CONDITIONAL_DISABLE; - - X64Reg lhs = INVALID_REG; - X64Reg rhs = INVALID_REG; - FixupBranch fixup; - switch (inst.op) { - case IROp::ExitToConstIfEq: - case IROp::ExitToConstIfNeq: - regs_.Map(inst); - lhs = regs_.RX(inst.src1); - rhs = regs_.RX(inst.src2); - // This won't change those regs, intentionally. It might affect flags, though. - FlushAll(); - - CMP(32, R(lhs), R(rhs)); - switch (inst.op) { - case IROp::ExitToConstIfEq: - fixup = J_CC(CC_NE); - break; - - case IROp::ExitToConstIfNeq: - fixup = J_CC(CC_E); - break; - - default: - INVALIDOP; - break; - } - - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfGtZ: - case IROp::ExitToConstIfGeZ: - case IROp::ExitToConstIfLtZ: - case IROp::ExitToConstIfLeZ: - regs_.Map(inst); - lhs = regs_.RX(inst.src1); - FlushAll(); - - CMP(32, R(lhs), Imm32(0)); - switch (inst.op) { - case IROp::ExitToConstIfGtZ: - fixup = J_CC(CC_LE, lhs); - break; - - case IROp::ExitToConstIfGeZ: - fixup = J_CC(CC_L, lhs); - break; - - case IROp::ExitToConstIfLtZ: - fixup = J_CC(CC_GE, lhs); - break; - - case IROp::ExitToConstIfLeZ: - fixup = J_CC(CC_G, lhs); - break; - - default: - INVALIDOP; - break; - } - - WriteConstExit(inst.constant); - SetJumpTarget(fixup); - break; - - case IROp::ExitToConstIfFpTrue: - case IROp::ExitToConstIfFpFalse: - // Note: not used. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRCompFPU.cpp b/Core/MIPS/x86/X64IRCompFPU.cpp deleted file mode 100644 index 175ae3c45..000000000 --- a/Core/MIPS/x86/X64IRCompFPU.cpp +++ /dev/null @@ -1,1082 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#ifndef offsetof -#include -#endif - -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -// This file contains compilation for floating point related instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -void X64JitBackend::EmitFPUConstants() { - EmitConst4x32(&constants.noSignMask, 0x7FFFFFFF); - EmitConst4x32(&constants.signBitAll, 0x80000000); - EmitConst4x32(&constants.positiveZeroes, 0x00000000); - EmitConst4x32(&constants.positiveInfinity, 0x7F800000); - EmitConst4x32(&constants.qNAN, 0x7FC00000); - EmitConst4x32(&constants.positiveOnes, 0x3F800000); - EmitConst4x32(&constants.negativeOnes, 0xBF800000); - EmitConst4x32(&constants.maxIntBelowAsFloat, 0x4EFFFFFF); - - constants.mulTableVi2f = (const float *)GetCodePointer(); - for (uint8_t i = 0; i < 32; ++i) { - float fval = 1.0f / (1UL << i); - uint32_t val; - memcpy(&val, &fval, sizeof(val)); - - Write32(val); - } - - constants.mulTableVf2i = (const float *)GetCodePointer(); - for (uint8_t i = 0; i < 32; ++i) { - float fval = (float)(1ULL << i); - uint32_t val; - memcpy(&val, &fval, sizeof(val)); - - Write32(val); - } -} - -void X64JitBackend::CopyVec4ToFPRLane0(Gen::X64Reg dest, Gen::X64Reg src, int lane) { - // TODO: Move to regcache or emitter maybe? - if (lane == 0) { - if (dest != src) - MOVAPS(dest, R(src)); - } else if (lane == 1 && cpu_info.bSSE3) { - MOVSHDUP(dest, R(src)); - } else if (lane == 2) { - MOVHLPS(dest, src); - } else if (cpu_info.bAVX) { - VPERMILPS(128, dest, R(src), VFPU_SWIZZLE(lane, lane, lane, lane)); - } else { - if (dest != src) - MOVAPS(dest, R(src)); - SHUFPS(dest, R(dest), VFPU_SWIZZLE(lane, lane, lane, lane)); - } -} - -void X64JitBackend::CompIR_FArith(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FAdd: - regs_.Map(inst); - if (inst.dest == inst.src1) { - ADDSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - ADDSS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else if (cpu_info.bAVX) { - VADDSS(regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - ADDSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::FSub: - if (inst.dest == inst.src1) { - regs_.Map(inst); - SUBSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (cpu_info.bAVX) { - regs_.Map(inst); - VSUBSS(regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - MOVAPS(tempReg, regs_.F(inst.src2)); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SUBSS(regs_.FX(inst.dest), R(tempReg)); - } else { - regs_.Map(inst); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SUBSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::FMul: - { - regs_.Map(inst); - - UCOMISS(regs_.FX(inst.src1), regs_.F(inst.src2)); - SETcc(CC_P, R(SCRATCH1)); - - if (inst.dest == inst.src1) { - MULSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - MULSS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else if (cpu_info.bAVX) { - VMULSS(regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MULSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - - UCOMISS(regs_.FX(inst.dest), regs_.F(inst.dest)); - FixupBranch handleNAN = J_CC(CC_P); - FixupBranch finish = J(); - - SetJumpTarget(handleNAN); - TEST(8, R(SCRATCH1), R(SCRATCH1)); - FixupBranch keepNAN = J_CC(CC_NZ); - - MOVSS(regs_.FX(inst.dest), M(constants.qNAN)); // rip accessible - - SetJumpTarget(keepNAN); - SetJumpTarget(finish); - break; - } - - case IROp::FDiv: - if (inst.dest == inst.src1) { - regs_.Map(inst); - DIVSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (cpu_info.bAVX) { - regs_.Map(inst); - VDIVSS(regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - MOVAPS(tempReg, regs_.F(inst.src2)); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - DIVSS(regs_.FX(inst.dest), R(tempReg)); - } else { - regs_.Map(inst); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - DIVSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::FSqrt: - regs_.Map(inst); - SQRTSS(regs_.FX(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FNeg: - regs_.Map(inst); - if (cpu_info.bAVX) { - VXORPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), M(constants.signBitAll)); // rip accessible - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - XORPS(regs_.FX(inst.dest), M(constants.signBitAll)); // rip accessible - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FMov: - // Just to make sure we don't generate bad code. - if (inst.dest == inst.src1) - break; - if (regs_.IsFPRMapped(inst.src1 & 3) && regs_.GetFPRLaneCount(inst.src1) == 4 && (inst.dest & ~3) != (inst.src1 & ~3)) { - // Okay, this is an extract. Avoid unvec4ing src1. - regs_.SpillLockFPR(inst.src1 & ~3); - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - CopyVec4ToFPRLane0(regs_.FX(inst.dest), regs_.FX(inst.src1 & ~3), inst.src1 & 3); - } else { - regs_.Map(inst); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } - break; - - case IROp::FAbs: - regs_.Map(inst); - if (cpu_info.bAVX) { - VANDPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), M(constants.noSignMask)); // rip accessible - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - ANDPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - } - break; - - case IROp::FSign: - { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - - // Set tempReg to +1.0 or -1.0 per sign bit. - if (cpu_info.bAVX) { - VANDPS(128, tempReg, regs_.FX(inst.src1), M(constants.signBitAll)); // rip accessible - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - ANDPS(tempReg, M(constants.signBitAll)); // rip accessible - } - ORPS(tempReg, M(constants.positiveOnes)); // rip accessible - - // Set dest = 0xFFFFFFFF if +0.0 or -0.0. - if (inst.dest != inst.src1) { - XORPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - CMPPS(regs_.FX(inst.dest), regs_.F(inst.src1), CMP_EQ); - } else { - CMPPS(regs_.FX(inst.dest), M(constants.positiveZeroes), CMP_EQ); // rip accessible - } - - // Now not the mask to keep zero if it was zero. - ANDNPS(regs_.FX(inst.dest), R(tempReg)); - break; - } - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FCompare(IRInst inst) { - CONDITIONAL_DISABLE; - - constexpr IRReg IRREG_VFPU_CC = IRREG_VFPU_CTRL_BASE + VFPU_CTRL_CC; - - auto ccToFpcond = [&](IRReg lhs, IRReg rhs, CCFlags cc) { - if (regs_.HasLowSubregister(regs_.RX(IRREG_FPCOND))) { - XOR(32, regs_.R(IRREG_FPCOND), regs_.R(IRREG_FPCOND)); - UCOMISS(regs_.FX(lhs), regs_.F(rhs)); - SETcc(cc, regs_.R(IRREG_FPCOND)); - } else { - UCOMISS(regs_.FX(lhs), regs_.F(rhs)); - SETcc(cc, R(SCRATCH1)); - MOVZX(32, 8, regs_.RX(IRREG_FPCOND), R(SCRATCH1)); - } - }; - - switch (inst.op) { - case IROp::FCmp: - switch (inst.dest) { - case IRFpCompareMode::False: - regs_.SetGPRImm(IRREG_FPCOND, 0); - break; - - case IRFpCompareMode::EitherUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // PF = UNORDERED. - ccToFpcond(inst.src1, inst.src2, CC_P); - break; - - case IRFpCompareMode::EqualOrdered: - { - // Since UCOMISS doesn't give us ordered == directly, CMPSS is better. - regs_.SpillLockFPR(inst.src1, inst.src2); - X64Reg tempReg = regs_.GetAndLockTempFPR(); - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src1), regs_.F(inst.src2), CMP_EQ); - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - CMPSS(tempReg, regs_.F(inst.src2), CMP_EQ); - } - MOVD_xmm(regs_.R(IRREG_FPCOND), tempReg); - AND(32, regs_.R(IRREG_FPCOND), Imm32(1)); - break; - } - - case IRFpCompareMode::EqualUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // E/ZF = EQUAL or UNORDERED. - ccToFpcond(inst.src1, inst.src2, CC_E); - break; - - case IRFpCompareMode::LessEqualOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // AE/!CF = GREATER or EQUAL (src2/src1 reversed.) - ccToFpcond(inst.src2, inst.src1, CC_AE); - break; - - case IRFpCompareMode::LessEqualUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // BE/CF||ZF = LESS THAN or EQUAL or UNORDERED. - ccToFpcond(inst.src1, inst.src2, CC_BE); - break; - - case IRFpCompareMode::LessOrdered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // A/!CF&&!ZF = GREATER (src2/src1 reversed.) - ccToFpcond(inst.src2, inst.src1, CC_A); - break; - - case IRFpCompareMode::LessUnordered: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // B/CF = LESS THAN or UNORDERED. - ccToFpcond(inst.src1, inst.src2, CC_B); - break; - - default: - _assert_msg_(false, "Unexpected IRFpCompareMode %d", inst.dest); - } - break; - - case IROp::FCmovVfpuCC: - regs_.MapWithExtra(inst, { { 'G', IRREG_VFPU_CC, 1, MIPSMap::INIT } }); - if (regs_.HasLowSubregister(regs_.RX(IRREG_VFPU_CC))) { - TEST(8, regs_.R(IRREG_VFPU_CC), Imm8(1 << (inst.src2 & 7))); - } else { - TEST(32, regs_.R(IRREG_VFPU_CC), Imm32(1 << (inst.src2 & 7))); - } - - if ((inst.src2 >> 7) & 1) { - FixupBranch skip = J_CC(CC_Z); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SetJumpTarget(skip); - } else { - FixupBranch skip = J_CC(CC_NZ); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SetJumpTarget(skip); - } - break; - - case IROp::FCmpVfpuBit: - { - regs_.MapGPR(IRREG_VFPU_CC, MIPSMap::DIRTY); - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - uint8_t affectedBit = 1 << (inst.dest >> 4); - bool condNegated = (inst.dest & 4) != 0; - - bool takeBitFromTempReg = true; - switch (VCondition(inst.dest & 0xF)) { - case VC_EQ: - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src1), regs_.F(inst.src2), CMP_EQ); - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - CMPSS(tempReg, regs_.F(inst.src2), CMP_EQ); - } - break; - case VC_NE: - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src1), regs_.F(inst.src2), CMP_NEQ); - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - CMPSS(tempReg, regs_.F(inst.src2), CMP_NEQ); - } - break; - case VC_LT: - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src1), regs_.F(inst.src2), CMP_LT); - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - CMPSS(tempReg, regs_.F(inst.src2), CMP_LT); - } - break; - case VC_LE: - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src1), regs_.F(inst.src2), CMP_LE); - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - CMPSS(tempReg, regs_.F(inst.src2), CMP_LE); - } - break; - case VC_GT: - // This is just LT with src1/src2 swapped. - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src2), regs_.F(inst.src1), CMP_LT); - } else { - MOVAPS(tempReg, regs_.F(inst.src2)); - CMPSS(tempReg, regs_.F(inst.src1), CMP_LT); - } - break; - case VC_GE: - // This is just LE with src1/src2 swapped. - if (cpu_info.bAVX) { - VCMPSS(tempReg, regs_.FX(inst.src2), regs_.F(inst.src1), CMP_LE); - } else { - MOVAPS(tempReg, regs_.F(inst.src2)); - CMPSS(tempReg, regs_.F(inst.src1), CMP_LE); - } - break; - case VC_EZ: - case VC_NZ: - XORPS(tempReg, R(tempReg)); - CMPSS(tempReg, regs_.F(inst.src1), !condNegated ? CMP_EQ : CMP_NEQ); - break; - case VC_EN: - case VC_NN: - CMPSS(tempReg, regs_.F(inst.src1), !condNegated ? CMP_UNORD : CMP_ORD); - break; - case VC_EI: - case VC_NI: - regs_.MapFPR(inst.src1); - if (cpu_info.bAVX) { - VANDPS(128, tempReg, regs_.FX(inst.src1), M(constants.noSignMask)); // rip accessible - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - ANDPS(tempReg, M(constants.noSignMask)); // rip accessible - } - CMPSS(tempReg, M(constants.positiveInfinity), !condNegated ? CMP_EQ : CMP_LT); // rip accessible - break; - case VC_ES: - case VC_NS: - // NAN - NAN is NAN, and Infinity - Infinity is also NAN. - if (cpu_info.bAVX) { - VSUBSS(tempReg, regs_.FX(inst.src1), regs_.F(inst.src1)); - } else { - MOVAPS(tempReg, regs_.F(inst.src1)); - SUBSS(tempReg, regs_.F(inst.src1)); - } - CMPSS(tempReg, regs_.F(inst.src1), !condNegated ? CMP_UNORD : CMP_ORD); - break; - case VC_TR: - OR(32, regs_.R(IRREG_VFPU_CC), Imm8(affectedBit)); - takeBitFromTempReg = true; - break; - case VC_FL: - AND(32, regs_.R(IRREG_VFPU_CC), Imm8(~affectedBit)); - takeBitFromTempReg = false; - break; - } - - if (takeBitFromTempReg) { - MOVD_xmm(R(SCRATCH1), tempReg); - AND(32, R(SCRATCH1), Imm8(affectedBit)); - AND(32, regs_.R(IRREG_VFPU_CC), Imm8(~affectedBit)); - OR(32, regs_.R(IRREG_VFPU_CC), R(SCRATCH1)); - } - break; - } - - case IROp::FCmpVfpuAggregate: - regs_.MapGPR(IRREG_VFPU_CC, MIPSMap::DIRTY); - if (inst.dest == 1) { - // Special case 1, which is not uncommon. - AND(32, regs_.R(IRREG_VFPU_CC), Imm8(0xF)); - BT(32, regs_.R(IRREG_VFPU_CC), Imm8(0)); - FixupBranch skip = J_CC(CC_NC); - OR(32, regs_.R(IRREG_VFPU_CC), Imm8(0x30)); - SetJumpTarget(skip); - } else if (inst.dest == 3) { - AND(32, regs_.R(IRREG_VFPU_CC), Imm8(0xF)); - MOV(32, R(SCRATCH1), regs_.R(IRREG_VFPU_CC)); - AND(32, R(SCRATCH1), Imm8(3)); - // 0, 1, and 3 are already correct for the any and all bits. - CMP(32, R(SCRATCH1), Imm8(2)); - - FixupBranch skip = J_CC(CC_NE); - SUB(32, R(SCRATCH1), Imm8(1)); - SetJumpTarget(skip); - - SHL(32, R(SCRATCH1), Imm8(4)); - OR(32, regs_.R(IRREG_VFPU_CC), R(SCRATCH1)); - } else if (inst.dest == 0xF) { - XOR(32, R(SCRATCH1), R(SCRATCH1)); - - // Clear out the bits we're aggregating. - // The register refuses writes to bits outside 0x3F, and we're setting 0x30. - AND(32, regs_.R(IRREG_VFPU_CC), Imm8(0xF)); - - // Set the any bit, just using the AND above. - FixupBranch noneSet = J_CC(CC_Z); - OR(32, regs_.R(IRREG_VFPU_CC), Imm8(0x10)); - - // Next up, the "all" bit. - CMP(32, regs_.R(IRREG_VFPU_CC), Imm8(0x1F)); - SETcc(CC_E, R(SCRATCH1)); - SHL(32, R(SCRATCH1), Imm8(5)); - OR(32, regs_.R(IRREG_VFPU_CC), R(SCRATCH1)); - - SetJumpTarget(noneSet); - } else { - XOR(32, R(SCRATCH1), R(SCRATCH1)); - - // Clear out the bits we're aggregating. - // The register refuses writes to bits outside 0x3F, and we're setting 0x30. - AND(32, regs_.R(IRREG_VFPU_CC), Imm8(0xF)); - - // Set the any bit. - if (regs_.HasLowSubregister(regs_.RX(IRREG_VFPU_CC))) - TEST(8, regs_.R(IRREG_VFPU_CC), Imm8(inst.dest)); - else - TEST(32, regs_.R(IRREG_VFPU_CC), Imm32(inst.dest)); - FixupBranch noneSet = J_CC(CC_Z); - OR(32, regs_.R(IRREG_VFPU_CC), Imm8(0x10)); - - // Next up, the "all" bit. A bit annoying... - MOV(32, R(SCRATCH1), regs_.R(IRREG_VFPU_CC)); - AND(32, R(SCRATCH1), Imm8(inst.dest)); - CMP(32, R(SCRATCH1), Imm8(inst.dest)); - SETcc(CC_E, R(SCRATCH1)); - SHL(32, R(SCRATCH1), Imm8(5)); - OR(32, regs_.R(IRREG_VFPU_CC), R(SCRATCH1)); - - SetJumpTarget(noneSet); - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FCondAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - FixupBranch skipNAN; - FixupBranch finishNAN; - FixupBranch negativeSigns; - FixupBranch finishNANSigns; - X64Reg tempReg = INVALID_REG; - switch (inst.op) { - case IROp::FMin: - tempReg = regs_.GetAndLockTempGPR(); - regs_.Map(inst); - UCOMISS(regs_.FX(inst.src1), regs_.F(inst.src1)); - skipNAN = J_CC(CC_NP, true); - - // Slow path: NAN case. Check if both are negative. - MOVD_xmm(R(tempReg), regs_.FX(inst.src1)); - MOVD_xmm(R(SCRATCH1), regs_.FX(inst.src2)); - TEST(32, R(SCRATCH1), R(tempReg)); - negativeSigns = J_CC(CC_S); - - // Okay, one or the other positive. - CMP(32, R(tempReg), R(SCRATCH1)); - CMOVcc(32, tempReg, R(SCRATCH1), CC_G); - MOVD_xmm(regs_.FX(inst.dest), R(tempReg)); - finishNAN = J(); - - // Okay, both negative. - SetJumpTarget(negativeSigns); - CMP(32, R(tempReg), R(SCRATCH1)); - CMOVcc(32, tempReg, R(SCRATCH1), CC_L); - MOVD_xmm(regs_.FX(inst.dest), R(tempReg)); - finishNANSigns = J(); - - SetJumpTarget(skipNAN); - if (cpu_info.bAVX) { - VMINSS(regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MINSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - SetJumpTarget(finishNAN); - SetJumpTarget(finishNANSigns); - break; - - case IROp::FMax: - tempReg = regs_.GetAndLockTempGPR(); - regs_.Map(inst); - UCOMISS(regs_.FX(inst.src1), regs_.F(inst.src1)); - skipNAN = J_CC(CC_NP, true); - - // Slow path: NAN case. Check if both are negative. - MOVD_xmm(R(tempReg), regs_.FX(inst.src1)); - MOVD_xmm(R(SCRATCH1), regs_.FX(inst.src2)); - TEST(32, R(SCRATCH1), R(tempReg)); - negativeSigns = J_CC(CC_S); - - // Okay, one or the other positive. - CMP(32, R(tempReg), R(SCRATCH1)); - CMOVcc(32, tempReg, R(SCRATCH1), CC_L); - MOVD_xmm(regs_.FX(inst.dest), R(tempReg)); - finishNAN = J(); - - // Okay, both negative. - SetJumpTarget(negativeSigns); - CMP(32, R(tempReg), R(SCRATCH1)); - CMOVcc(32, tempReg, R(SCRATCH1), CC_G); - MOVD_xmm(regs_.FX(inst.dest), R(tempReg)); - finishNANSigns = J(); - - SetJumpTarget(skipNAN); - if (cpu_info.bAVX) { - VMAXSS(regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MAXSS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - SetJumpTarget(finishNAN); - SetJumpTarget(finishNANSigns); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FCvt(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FCvtWS: - { - regs_.Map(inst); - UCOMISS(regs_.FX(inst.src1), M(constants.maxIntBelowAsFloat)); // rip accessible - - CVTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.src1)); - // UCOMISS set CF if LESS and ZF if EQUAL to maxIntBelowAsFloat. - // We want noSignMask otherwise, GREATER or UNORDERED. - FixupBranch isNAN = J_CC(CC_P); - FixupBranch skip = J_CC(CC_BE); - SetJumpTarget(isNAN); - MOVAPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - - SetJumpTarget(skip); - break; - } - - case IROp::FCvtSW: - regs_.Map(inst); - CVTDQ2PS(regs_.FX(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FCvtScaledWS: - regs_.Map(inst); - if (cpu_info.bSSE4_1) { - int scale = inst.src2 & 0x1F; - IRRoundMode rmode = (IRRoundMode)(inst.src2 >> 6); - - if (scale != 0 && cpu_info.bAVX) { - VMULSS(regs_.FX(inst.dest), regs_.FX(inst.src1), M(&constants.mulTableVf2i[scale])); // rip accessible - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - if (scale != 0) - MULSS(regs_.FX(inst.dest), M(&constants.mulTableVf2i[scale])); // rip accessible - } - - UCOMISS(regs_.FX(inst.dest), M(constants.maxIntBelowAsFloat)); // rip accessible - - switch (rmode) { - case IRRoundMode::RINT_0: - ROUNDNEARPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - CVTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - break; - - case IRRoundMode::CAST_1: - CVTTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - break; - - case IRRoundMode::CEIL_2: - ROUNDCEILPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - CVTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - break; - - case IRRoundMode::FLOOR_3: - ROUNDFLOORPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - CVTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - break; - } - - // UCOMISS set CF if LESS and ZF if EQUAL to maxIntBelowAsFloat. - // We want noSignMask otherwise, GREATER or UNORDERED. - FixupBranch isNAN = J_CC(CC_P); - FixupBranch skip = J_CC(CC_BE); - SetJumpTarget(isNAN); - MOVAPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - SetJumpTarget(skip); - } else { - int scale = inst.src2 & 0x1F; - IRRoundMode rmode = (IRRoundMode)(inst.src2 >> 6); - - int setMXCSR = -1; - bool useTrunc = false; - switch (rmode) { - case IRRoundMode::RINT_0: - // TODO: Could skip if hasSetRounding, but we don't have the flag. - setMXCSR = 0; - break; - case IRRoundMode::CAST_1: - useTrunc = true; - break; - case IRRoundMode::CEIL_2: - setMXCSR = 2; - break; - case IRRoundMode::FLOOR_3: - setMXCSR = 1; - break; - } - - // Except for truncate, we need to update MXCSR to our preferred rounding mode. - // TODO: Might be possible to cache this and update between instructions? - // Probably kinda expensive to switch each time... - if (setMXCSR != -1) { - STMXCSR(MDisp(CTXREG, mxcsrTempOffset)); - MOV(32, R(SCRATCH1), MDisp(CTXREG, mxcsrTempOffset)); - AND(32, R(SCRATCH1), Imm32(~(3 << 13))); - if (setMXCSR != 0) { - OR(32, R(SCRATCH1), Imm32(setMXCSR << 13)); - } - MOV(32, MDisp(CTXREG, tempOffset), R(SCRATCH1)); - LDMXCSR(MDisp(CTXREG, tempOffset)); - } - - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - if (scale != 0) - MULSS(regs_.FX(inst.dest), M(&constants.mulTableVf2i[scale])); // rip accessible - - UCOMISS(regs_.FX(inst.dest), M(constants.maxIntBelowAsFloat)); // rip accessible - - if (useTrunc) { - CVTTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - } else { - CVTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - } - - // UCOMISS set CF if LESS and ZF if EQUAL to maxIntBelowAsFloat. - // We want noSignMask otherwise, GREATER or UNORDERED. - FixupBranch isNAN = J_CC(CC_P); - FixupBranch skip = J_CC(CC_BE); - SetJumpTarget(isNAN); - MOVAPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - SetJumpTarget(skip); - - // Return MXCSR to its previous value. - if (setMXCSR != -1) { - LDMXCSR(MDisp(CTXREG, mxcsrTempOffset)); - } - } - break; - - case IROp::FCvtScaledSW: - regs_.Map(inst); - CVTDQ2PS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MULSS(regs_.FX(inst.dest), M(&constants.mulTableVi2f[inst.src2 & 0x1F])); // rip accessible - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FRound(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::FCeil: - case IROp::FFloor: - case IROp::FRound: - if (cpu_info.bSSE4_1) { - regs_.Map(inst); - UCOMISS(regs_.FX(inst.src1), M(constants.maxIntBelowAsFloat)); // rip accessible - - switch (inst.op) { - case IROp::FCeil: - ROUNDCEILPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FFloor: - ROUNDFLOORPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - break; - - case IROp::FRound: - ROUNDNEARPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - break; - - default: - INVALIDOP; - } - CVTTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.dest)); - // UCOMISS set CF if LESS and ZF if EQUAL to maxIntBelowAsFloat. - // We want noSignMask otherwise, GREATER or UNORDERED. - FixupBranch isNAN = J_CC(CC_P); - FixupBranch skip = J_CC(CC_BE); - SetJumpTarget(isNAN); - MOVAPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - - SetJumpTarget(skip); - } else { - regs_.Map(inst); - - int setMXCSR = -1; - switch (inst.op) { - case IROp::FRound: - // TODO: Could skip if hasSetRounding, but we don't have the flag. - setMXCSR = 0; - break; - case IROp::FCeil: - setMXCSR = 2; - break; - case IROp::FFloor: - setMXCSR = 1; - break; - default: - INVALIDOP; - } - - // TODO: Might be possible to cache this and update between instructions? - // Probably kinda expensive to switch each time... - if (setMXCSR != -1) { - STMXCSR(MDisp(CTXREG, mxcsrTempOffset)); - MOV(32, R(SCRATCH1), MDisp(CTXREG, mxcsrTempOffset)); - AND(32, R(SCRATCH1), Imm32(~(3 << 13))); - if (setMXCSR != 0) { - OR(32, R(SCRATCH1), Imm32(setMXCSR << 13)); - } - MOV(32, MDisp(CTXREG, tempOffset), R(SCRATCH1)); - LDMXCSR(MDisp(CTXREG, tempOffset)); - } - - UCOMISS(regs_.FX(inst.src1), M(constants.maxIntBelowAsFloat)); // rip accessible - - CVTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.src1)); - // UCOMISS set CF if LESS and ZF if EQUAL to maxIntBelowAsFloat. - // We want noSignMask otherwise, GREATER or UNORDERED. - FixupBranch isNAN = J_CC(CC_P); - FixupBranch skip = J_CC(CC_BE); - SetJumpTarget(isNAN); - MOVAPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - - SetJumpTarget(skip); - - // Return MXCSR to its previous value. - if (setMXCSR != -1) { - LDMXCSR(MDisp(CTXREG, mxcsrTempOffset)); - } - } - break; - - case IROp::FTrunc: - { - regs_.Map(inst); - UCOMISS(regs_.FX(inst.src1), M(constants.maxIntBelowAsFloat)); // rip accessible - - CVTTPS2DQ(regs_.FX(inst.dest), regs_.F(inst.src1)); - // UCOMISS set CF if LESS and ZF if EQUAL to maxIntBelowAsFloat. - // We want noSignMask otherwise, GREATER or UNORDERED. - FixupBranch isNAN = J_CC(CC_P); - FixupBranch skip = J_CC(CC_BE); - SetJumpTarget(isNAN); - MOVAPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - - SetJumpTarget(skip); - break; - } - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FSat(IRInst inst) { - CONDITIONAL_DISABLE; - - X64Reg tempReg = INVALID_REG; - switch (inst.op) { - case IROp::FSat0_1: - tempReg = regs_.MapWithFPRTemp(inst); - - // The second argument's NAN is taken if either is NAN, so put known first. - MOVSS(tempReg, M(constants.positiveOnes)); - MINSS(tempReg, regs_.F(inst.src1)); - - // Now for NAN, we want known first again. - // Unfortunately, this will retain -0.0, which we'll fix next. - XORPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - MAXSS(tempReg, regs_.F(inst.dest)); - - // Important: this should clamp -0.0 to +0.0. - ADDSS(regs_.FX(inst.dest), R(tempReg)); - break; - - case IROp::FSatMinus1_1: - tempReg = regs_.MapWithFPRTemp(inst); - - // The second argument's NAN is taken if either is NAN, so put known first. - MOVSS(tempReg, M(constants.negativeOnes)); - MAXSS(tempReg, regs_.F(inst.src1)); - - // Again, stick with the first argument being known. - MOVSS(regs_.FX(inst.dest), M(constants.positiveOnes)); - MINSS(regs_.FX(inst.dest), R(tempReg)); - break; - - default: - INVALIDOP; - break; - } -} - -#if X64JIT_USE_XMM_CALL -static float X64JIT_XMM_CALL x64_sin(float f) { - return vfpu_sin(f); -} - -static float X64JIT_XMM_CALL x64_cos(float f) { - return vfpu_cos(f); -} - -static float X64JIT_XMM_CALL x64_asin(float f) { - return vfpu_asin(f); -} -#else -static uint32_t x64_sin(uint32_t v) { - float f; - memcpy(&f, &v, sizeof(v)); - f = vfpu_sin(f); - memcpy(&v, &f, sizeof(v)); - return v; -} - -static uint32_t x64_cos(uint32_t v) { - float f; - memcpy(&f, &v, sizeof(v)); - f = vfpu_cos(f); - memcpy(&v, &f, sizeof(v)); - return v; -} - -static uint32_t x64_asin(uint32_t v) { - float f; - memcpy(&f, &v, sizeof(v)); - f = vfpu_asin(f); - memcpy(&v, &f, sizeof(v)); - return v; -} -#endif - -void X64JitBackend::CompIR_FSpecial(IRInst inst) { - CONDITIONAL_DISABLE; - - auto callFuncF_F = [&](const void *func) { - regs_.FlushBeforeCall(); - WriteDebugProfilerStatus(IRProfilerStatus::MATH_HELPER); - -#if X64JIT_USE_XMM_CALL - if (regs_.IsFPRMapped(inst.src1)) { - int lane = regs_.GetFPRLane(inst.src1); - CopyVec4ToFPRLane0(XMM0, regs_.FX(inst.src1), lane); - } else { - // Account for CTXREG being increased by 128 to reduce imm sizes. - int offset = offsetof(MIPSState, f) + inst.src1 * 4 - 128; - MOVSS(XMM0, MDisp(CTXREG, offset)); - } - ABI_CallFunction((const void *)func); - - // It's already in place, NOINIT won't modify. - regs_.MapFPR(inst.dest, MIPSMap::NOINIT | X64Map::XMM0); -#else - if (regs_.IsFPRMapped(inst.src1)) { - int lane = regs_.GetFPRLane(inst.src1); - if (lane == 0) { - MOVD_xmm(R(SCRATCH1), regs_.FX(inst.src1)); - } else { - CopyVec4ToFPRLane0(XMM0, regs_.FX(inst.src1), lane); - MOVD_xmm(R(SCRATCH1), XMM0); - } - } else { - int offset = offsetof(MIPSState, f) + inst.src1 * 4; - MOV(32, R(SCRATCH1), MDisp(CTXREG, offset)); - } - ABI_CallFunctionR((const void *)func, SCRATCH1); - - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - MOVD_xmm(regs_.FX(inst.dest), R(SCRATCH1)); -#endif - - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - }; - - switch (inst.op) { - case IROp::FSin: - callFuncF_F((const void *)&x64_sin); - break; - - case IROp::FCos: - callFuncF_F((const void *)&x64_cos); - break; - - case IROp::FRSqrt: - { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - SQRTSS(tempReg, regs_.F(inst.src1)); - - MOVSS(regs_.FX(inst.dest), M(constants.positiveOnes)); // rip accessible - DIVSS(regs_.FX(inst.dest), R(tempReg)); - break; - } - - case IROp::FRecip: - if (inst.dest != inst.src1) { - regs_.Map(inst); - MOVSS(regs_.FX(inst.dest), M(constants.positiveOnes)); // rip accessible - DIVSS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - MOVSS(tempReg, M(constants.positiveOnes)); // rip accessible - if (cpu_info.bAVX) { - VDIVSS(regs_.FX(inst.dest), tempReg, regs_.F(inst.src1)); - } else { - DIVSS(tempReg, regs_.F(inst.src1)); - MOVSS(regs_.FX(inst.dest), R(tempReg)); - } - } - break; - - case IROp::FAsin: - callFuncF_F((const void *)&x64_asin); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_RoundingMode(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::RestoreRoundingMode: - RestoreRoundingMode(); - break; - - case IROp::ApplyRoundingMode: - ApplyRoundingMode(); - break; - - case IROp::UpdateRoundingMode: - // TODO: We might want to do something here? - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRCompLoadStore.cpp b/Core/MIPS/x86/X64IRCompLoadStore.cpp deleted file mode 100644 index 9b3eea134..000000000 --- a/Core/MIPS/x86/X64IRCompLoadStore.cpp +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include "Core/MemMap.h" -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -// This file contains compilation for load/store instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -Gen::OpArg X64JitBackend::PrepareSrc1Address(IRInst inst) { - const IRMeta *m = GetIRMeta(inst.op); - - bool src1IsPointer = regs_.IsGPRMappedAsPointer(inst.src1); - bool readsFromSrc1 = inst.src1 == inst.src3 && (m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0; - // If it's about to be clobbered, don't waste time pointerifying. Use displacement. - bool clobbersSrc1 = !readsFromSrc1 && regs_.IsGPRClobbered(inst.src1); - - int32_t disp = (int32_t)inst.constant; - // It can't be this negative, must be a constant address with the top bit set. - if ((disp & 0xC0000000) == 0x80000000) { - disp = inst.constant & 0x7FFFFFFF; - } - -#ifdef MASKED_PSP_MEMORY - if (disp > 0) - disp &= Memory::MEMVIEW32_MASK; -#endif - - OpArg addrArg; - if (inst.src1 == MIPS_REG_ZERO) { -#ifdef MASKED_PSP_MEMORY - disp &= Memory::MEMVIEW32_MASK; -#endif -#if PPSSPP_ARCH(AMD64) - addrArg = MDisp(MEMBASEREG, disp & 0x7FFFFFFF); -#else - addrArg = M(Memory::base + disp); -#endif - } else if ((jo.cachePointers || src1IsPointer) && !readsFromSrc1 && (!clobbersSrc1 || src1IsPointer)) { - X64Reg src1 = regs_.MapGPRAsPointer(inst.src1); - addrArg = MDisp(src1, disp); - } else { - regs_.MapGPR(inst.src1); -#ifdef MASKED_PSP_MEMORY - LEA(PTRBITS, SCRATCH1, MDisp(regs_.RX(inst.src1), disp)); - AND(PTRBITS, R(SCRATCH1), Imm32(Memory::MEMVIEW32_MASK)); - addrArg = MDisp(SCRATCH1, (intptr_t)Memory::base); -#else -#if PPSSPP_ARCH(AMD64) - addrArg = MComplex(MEMBASEREG, regs_.RX(inst.src1), SCALE_1, disp); -#else - addrArg = MDisp(regs_.RX(inst.src1), Memory::base + disp); -#endif -#endif - } - - return addrArg; -} - -void X64JitBackend::CompIR_CondStore(IRInst inst) { - CONDITIONAL_DISABLE; - if (inst.op != IROp::Store32Conditional) - INVALIDOP; - - regs_.SpillLockGPR(IRREG_LLBIT, inst.src3, inst.src1); - OpArg addrArg = PrepareSrc1Address(inst); - OpArg valueArg = R(regs_.MapGPR(inst.src3, MIPSMap::INIT)); - - regs_.MapGPR(IRREG_LLBIT, MIPSMap::INIT); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - TEST(32, regs_.R(IRREG_LLBIT), regs_.R(IRREG_LLBIT)); - FixupBranch condFailed = J_CC(CC_Z); - MOV(32, addrArg, valueArg); - - if (inst.dest != MIPS_REG_ZERO) { - MOV(32, regs_.R(inst.dest), Imm32(1)); - FixupBranch finish = J(); - - SetJumpTarget(condFailed); - XOR(32, regs_.R(inst.dest), regs_.R(inst.dest)); - SetJumpTarget(finish); - } else { - SetJumpTarget(condFailed); - } -} - -void X64JitBackend::CompIR_FLoad(IRInst inst) { - CONDITIONAL_DISABLE; - - OpArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::LoadFloat: - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - MOVSS(regs_.FX(inst.dest), addrArg); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_FStore(IRInst inst) { - CONDITIONAL_DISABLE; - - OpArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::StoreFloat: - regs_.MapFPR(inst.src3); - MOVSS(addrArg, regs_.FX(inst.src3)); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Load(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.SpillLockGPR(inst.dest, inst.src1); - OpArg addrArg = PrepareSrc1Address(inst); - // With NOINIT, MapReg won't subtract MEMBASEREG even if dest == src1. - regs_.MapGPR(inst.dest, MIPSMap::NOINIT); - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::Load8: - MOVZX(32, 8, regs_.RX(inst.dest), addrArg); - break; - - case IROp::Load8Ext: - MOVSX(32, 8, regs_.RX(inst.dest), addrArg); - break; - - case IROp::Load16: - MOVZX(32, 16, regs_.RX(inst.dest), addrArg); - break; - - case IROp::Load16Ext: - MOVSX(32, 16, regs_.RX(inst.dest), addrArg); - break; - - case IROp::Load32: - MOV(32, regs_.R(inst.dest), addrArg); - break; - - case IROp::Load32Linked: - if (inst.dest != MIPS_REG_ZERO) - MOV(32, regs_.R(inst.dest), addrArg); - regs_.SetGPRImm(IRREG_LLBIT, 1); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_LoadShift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Load32Left: - case IROp::Load32Right: - // Should not happen if the pass to split is active. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Store(IRInst inst) { - CONDITIONAL_DISABLE; - - regs_.SpillLockGPR(inst.src3, inst.src1); - OpArg addrArg = PrepareSrc1Address(inst); - - // i386 can only use certain regs for 8-bit operations. - X64Map valueFlags = inst.op == IROp::Store8 ? X64Map::LOW_SUBREG : X64Map::NONE; - - OpArg valueArg; - X64Reg valueReg = regs_.TryMapTempImm(inst.src3, valueFlags); - if (valueReg != INVALID_REG) { - valueArg = R(valueReg); - } else if (regs_.IsGPRImm(inst.src3)) { - u32 imm = regs_.GetGPRImm(inst.src3); - switch (inst.op) { - case IROp::Store8: valueArg = Imm8((u8)imm); break; - case IROp::Store16: valueArg = Imm16((u16)imm); break; - case IROp::Store32: valueArg = Imm32(imm); break; - default: - INVALIDOP; - break; - } - } else { - valueArg = R(regs_.MapGPR(inst.src3, MIPSMap::INIT | valueFlags)); - } - - // TODO: Safe memory? Or enough to have crash handler + validate? - - switch (inst.op) { - case IROp::Store8: - MOV(8, addrArg, valueArg); - break; - - case IROp::Store16: - MOV(16, addrArg, valueArg); - break; - - case IROp::Store32: - MOV(32, addrArg, valueArg); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_StoreShift(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Store32Left: - case IROp::Store32Right: - // Should not happen if the pass to split is active. - DISABLE; - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_VecLoad(IRInst inst) { - CONDITIONAL_DISABLE; - - OpArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::LoadVec4: - regs_.MapVec4(inst.dest, MIPSMap::NOINIT); - MOVUPS(regs_.FX(inst.dest), addrArg); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_VecStore(IRInst inst) { - CONDITIONAL_DISABLE; - - OpArg addrArg = PrepareSrc1Address(inst); - - switch (inst.op) { - case IROp::StoreVec4: - regs_.MapVec4(inst.src3); - MOVUPS(addrArg, regs_.FX(inst.src3)); - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRCompSystem.cpp b/Core/MIPS/x86/X64IRCompSystem.cpp deleted file mode 100644 index 9d1723aef..000000000 --- a/Core/MIPS/x86/X64IRCompSystem.cpp +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include "Common/Profiler/Profiler.h" -#include "Core/Core.h" -#include "Core/Debugger/Breakpoints.h" -#include "Core/HLE/HLE.h" -#include "Core/HLE/ReplaceTables.h" -#include "Core/MemMap.h" -#include "Core/MIPS/MIPSAnalyst.h" -#include "Core/MIPS/IR/IRInterpreter.h" -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -// This file contains compilation for basic PC/downcount accounting, syscalls, debug funcs, etc. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -void X64JitBackend::CompIR_Basic(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Downcount: - // As long as we don't care about flags, just use LEA. - if (jo.downcountInRegister) - LEA(32, DOWNCOUNTREG, MDisp(DOWNCOUNTREG, -(s32)inst.constant)); - else - SUB(32, MDisp(CTXREG, downcountOffset), SImmAuto((s32)inst.constant)); - break; - - case IROp::SetConst: - regs_.SetGPRImm(inst.dest, inst.constant); - break; - - case IROp::SetConstF: - regs_.Map(inst); - if (inst.constant == 0) { - XORPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - } else if (inst.constant == 0x7FFFFFFF) { - MOVSS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - } else if (inst.constant == 0x80000000) { - MOVSS(regs_.FX(inst.dest), M(constants.signBitAll)); // rip accessible - } else if (inst.constant == 0x7F800000) { - MOVSS(regs_.FX(inst.dest), M(constants.positiveInfinity)); // rip accessible - } else if (inst.constant == 0x7FC00000) { - MOVSS(regs_.FX(inst.dest), M(constants.qNAN)); // rip accessible - } else if (inst.constant == 0x3F800000) { - MOVSS(regs_.FX(inst.dest), M(constants.positiveOnes)); // rip accessible - } else if (inst.constant == 0xBF800000) { - MOVSS(regs_.FX(inst.dest), M(constants.negativeOnes)); // rip accessible - } else if (inst.constant == 0x4EFFFFFF) { - MOVSS(regs_.FX(inst.dest), M(constants.maxIntBelowAsFloat)); // rip accessible - } else { - MOV(32, R(SCRATCH1), Imm32(inst.constant)); - MOVD_xmm(regs_.FX(inst.dest), R(SCRATCH1)); - } - break; - - case IROp::SetPC: - regs_.Map(inst); - MovToPC(regs_.RX(inst.src1)); - break; - - case IROp::SetPCConst: - lastConstPC_ = inst.constant; - MOV(32, R(SCRATCH1), Imm32(inst.constant)); - MovToPC(SCRATCH1); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Breakpoint(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Breakpoint: - FlushAll(); - // Note: the constant could be a delay slot. - ABI_CallFunctionC((const void *)&IRRunBreakpoint, inst.constant); - TEST(32, R(EAX), R(EAX)); - J_CC(CC_NZ, dispatcherCheckCoreState_, true); - break; - - case IROp::MemoryCheck: - if (regs_.IsGPRImm(inst.src1)) { - uint32_t iaddr = regs_.GetGPRImm(inst.src1) + inst.constant; - uint32_t checkedPC = lastConstPC_ + inst.dest; - int size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - if (size == 0) { - checkedPC += 4; - size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - } - bool isWrite = MIPSAnalyst::IsOpMemoryWrite(checkedPC); - - MemCheck check; - if (CBreakPoints::GetMemCheckInRange(iaddr, size, &check)) { - if (!(check.cond & MEMCHECK_READ) && !isWrite) - break; - if (!(check.cond & (MEMCHECK_WRITE | MEMCHECK_WRITE_ONCHANGE)) && isWrite) - break; - - // We need to flush, or conditions and log expressions will see old register values. - FlushAll(); - - ABI_CallFunctionCC((const void *)&IRRunMemCheck, checkedPC, iaddr); - TEST(32, R(EAX), R(EAX)); - J_CC(CC_NZ, dispatcherCheckCoreState_, true); - } - } else { - uint32_t checkedPC = lastConstPC_ + inst.dest; - int size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - if (size == 0) { - checkedPC += 4; - size = MIPSAnalyst::OpMemoryAccessSize(checkedPC); - } - bool isWrite = MIPSAnalyst::IsOpMemoryWrite(checkedPC); - - const auto memchecks = CBreakPoints::GetMemCheckRanges(isWrite); - // We can trivially skip if there are no checks for this type (i.e. read vs write.) - if (memchecks.empty()) - break; - - X64Reg addrBase = regs_.MapGPR(inst.src1); - LEA(32, SCRATCH1, MDisp(addrBase, inst.constant)); - - // We need to flush, or conditions and log expressions will see old register values. - FlushAll(); - - std::vector hitChecks; - for (auto it : memchecks) { - if (it.end != 0) { - CMP(32, R(SCRATCH1), Imm32(it.start - size)); - FixupBranch skipNext = J_CC(CC_BE); - - CMP(32, R(SCRATCH1), Imm32(it.end)); - hitChecks.push_back(J_CC(CC_B, true)); - - SetJumpTarget(skipNext); - } else { - CMP(32, R(SCRATCH1), Imm32(it.start)); - hitChecks.push_back(J_CC(CC_E, true)); - } - } - - FixupBranch noHits = J(true); - - // Okay, now land any hit here. - for (auto &fixup : hitChecks) - SetJumpTarget(fixup); - hitChecks.clear(); - - ABI_CallFunctionAA((const void *)&IRRunMemCheck, Imm32(checkedPC), R(SCRATCH1)); - TEST(32, R(EAX), R(EAX)); - J_CC(CC_NZ, dispatcherCheckCoreState_, true); - - SetJumpTarget(noHits); - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_System(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Syscall: - FlushAll(); - SaveStaticRegisters(); - - WriteDebugProfilerStatus(IRProfilerStatus::SYSCALL); -#ifdef USE_PROFILER - // When profiling, we can't skip CallSyscall, since it times syscalls. - ABI_CallFunctionC((const u8 *)&CallSyscall, inst.constant); -#else - // Skip the CallSyscall where possible. - { - MIPSOpcode op(inst.constant); - void *quickFunc = GetQuickSyscallFunc(op); - if (quickFunc) { - ABI_CallFunctionP((const u8 *)quickFunc, (void *)GetSyscallFuncPointer(op)); - } else { - ABI_CallFunctionC((const u8 *)&CallSyscall, inst.constant); - } - } -#endif - - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - // This is always followed by an ExitToPC, where we check coreState. - break; - - case IROp::CallReplacement: - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::REPLACEMENT); - ABI_CallFunction(GetReplacementFunc(inst.constant)->replaceFunc); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - //SUB(32, R(DOWNCOUNTREG), R(DOWNCOUNTREG), R(EAX)); - SUB(32, MDisp(CTXREG, downcountOffset), R(EAX)); - break; - - case IROp::Break: - FlushAll(); - // This doesn't naturally have restore/apply around it. - RestoreRoundingMode(true); - SaveStaticRegisters(); - MovFromPC(SCRATCH1); - ABI_CallFunctionR((const void *)&Core_Break, SCRATCH1); - LoadStaticRegisters(); - ApplyRoundingMode(true); - MovFromPC(SCRATCH1); - LEA(32, SCRATCH1, MDisp(SCRATCH1, 4)); - JMP(dispatcherPCInSCRATCH1_, true); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_Transfer(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::SetCtrlVFPU: - regs_.SetGPRImm(IRREG_VFPU_CTRL_BASE + inst.dest, (int32_t)inst.constant); - break; - - case IROp::SetCtrlVFPUReg: - regs_.Map(inst); - MOV(32, regs_.R(IRREG_VFPU_CTRL_BASE + inst.dest), regs_.R(inst.src1)); - break; - - case IROp::SetCtrlVFPUFReg: - regs_.Map(inst); - MOVD_xmm(regs_.R(IRREG_VFPU_CTRL_BASE + inst.dest), regs_.FX(inst.src1)); - break; - - case IROp::FpCondFromReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - MOV(32, regs_.R(IRREG_FPCOND), regs_.R(inst.src1)); - break; - - case IROp::FpCondToReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::INIT } }); - MOV(32, regs_.R(inst.dest), regs_.R(IRREG_FPCOND)); - break; - - case IROp::FpCtrlFromReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::NOINIT } }); - // Mask out the unused bits, and store fcr31 (using fpcond as a temp.) - MOV(32, regs_.R(IRREG_FPCOND), Imm32(0x0181FFFF)); - AND(32, regs_.R(IRREG_FPCOND), regs_.R(inst.src1)); - MOV(32, MDisp(CTXREG, fcr31Offset), regs_.R(IRREG_FPCOND)); - - // With that done, grab bit 23, the actual fpcond. - SHR(32, regs_.R(IRREG_FPCOND), Imm8(23)); - AND(32, regs_.R(IRREG_FPCOND), Imm32(1)); - break; - - case IROp::FpCtrlToReg: - regs_.MapWithExtra(inst, { { 'G', IRREG_FPCOND, 1, MIPSMap::INIT } }); - // Start by clearing the fpcond bit (might as well mask while we're here.) - MOV(32, regs_.R(inst.dest), Imm32(0x0101FFFF)); - AND(32, regs_.R(inst.dest), MDisp(CTXREG, fcr31Offset)); - - AND(32, regs_.R(IRREG_FPCOND), Imm32(1)); - if (cpu_info.bBMI2) { - RORX(32, SCRATCH1, regs_.R(IRREG_FPCOND), 32 - 23); - } else { - MOV(32, R(SCRATCH1), regs_.R(IRREG_FPCOND)); - SHL(32, R(SCRATCH1), Imm8(23)); - } - OR(32, regs_.R(inst.dest), R(SCRATCH1)); - - // Update fcr31 while we were here, for consistency. - MOV(32, MDisp(CTXREG, fcr31Offset), regs_.R(inst.dest)); - break; - - case IROp::VfpuCtrlToReg: - regs_.Map(inst); - MOV(32, regs_.R(inst.dest), regs_.R(IRREG_VFPU_CTRL_BASE + inst.src1)); - break; - - case IROp::FMovFromGPR: - if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) { - regs_.MapFPR(inst.dest, MIPSMap::NOINIT); - XORPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - } else { - regs_.Map(inst); - MOVD_xmm(regs_.FX(inst.dest), regs_.R(inst.src1)); - } - break; - - case IROp::FMovToGPR: - regs_.Map(inst); - MOVD_xmm(regs_.R(inst.dest), regs_.FX(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_ValidateAddress(IRInst inst) { - CONDITIONAL_DISABLE; - - bool isWrite = inst.src2 & 1; - int alignment = 0; - switch (inst.op) { - case IROp::ValidateAddress8: - alignment = 1; - break; - - case IROp::ValidateAddress16: - alignment = 2; - break; - - case IROp::ValidateAddress32: - alignment = 4; - break; - - case IROp::ValidateAddress128: - alignment = 16; - break; - - default: - INVALIDOP; - break; - } - - if (regs_.IsGPRMappedAsPointer(inst.src1)) { - LEA(PTRBITS, SCRATCH1, MDisp(regs_.RXPtr(inst.src1), inst.constant)); -#if defined(MASKED_PSP_MEMORY) - SUB(PTRBITS, R(SCRATCH1), ImmPtr(Memory::base)); -#else - SUB(PTRBITS, R(SCRATCH1), R(MEMBASEREG)); -#endif - } else { - regs_.Map(inst); - LEA(PTRBITS, SCRATCH1, MDisp(regs_.RX(inst.src1), inst.constant)); - } - AND(32, R(SCRATCH1), Imm32(0x3FFFFFFF)); - - std::vector validJumps; - - FixupBranch unaligned; - if (alignment != 1) { - TEST(32, R(SCRATCH1), Imm32(alignment - 1)); - unaligned = J_CC(CC_NZ); - } - - CMP(32, R(SCRATCH1), Imm32(PSP_GetUserMemoryEnd() - alignment)); - FixupBranch tooHighRAM = J_CC(CC_A); - CMP(32, R(SCRATCH1), Imm32(PSP_GetKernelMemoryBase())); - validJumps.push_back(J_CC(CC_AE, true)); - - CMP(32, R(SCRATCH1), Imm32(PSP_GetVidMemEnd() - alignment)); - FixupBranch tooHighVid = J_CC(CC_A); - CMP(32, R(SCRATCH1), Imm32(PSP_GetVidMemBase())); - validJumps.push_back(J_CC(CC_AE, true)); - - CMP(32, R(SCRATCH1), Imm32(PSP_GetScratchpadMemoryEnd() - alignment)); - FixupBranch tooHighScratch = J_CC(CC_A); - CMP(32, R(SCRATCH1), Imm32(PSP_GetScratchpadMemoryBase())); - validJumps.push_back(J_CC(CC_AE, true)); - - if (alignment != 1) - SetJumpTarget(unaligned); - SetJumpTarget(tooHighRAM); - SetJumpTarget(tooHighVid); - SetJumpTarget(tooHighScratch); - - // If we got here, something unusual and bad happened, so we'll always go back to the dispatcher. - // Because of that, we can avoid flushing outside this case. - auto regsCopy = regs_; - regsCopy.FlushAll(); - - // Ignores the return value, always returns to the dispatcher. - // Otherwise would need a thunk to restore regs. - ABI_CallFunctionACC((const void *)&ReportBadAddress, R(SCRATCH1), alignment, isWrite); - JMP(dispatcherCheckCoreState_, true); - - for (FixupBranch &b : validJumps) - SetJumpTarget(b); -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRCompVec.cpp b/Core/MIPS/x86/X64IRCompVec.cpp deleted file mode 100644 index a68939a16..000000000 --- a/Core/MIPS/x86/X64IRCompVec.cpp +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include -#include "Common/CPUDetect.h" -#include "Core/MemMap.h" -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -// This file contains compilation for vector instructions. -// -// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly. -// Currently known non working ones should have DISABLE. No flags because that's in IR already. - -// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; } -#define CONDITIONAL_DISABLE {} -#define DISABLE { CompIR_Generic(inst); return; } -#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; } - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -static bool Overlap(IRReg r1, int l1, IRReg r2, int l2) { - return r1 < r2 + l2 && r1 + l1 > r2; -} - -void X64JitBackend::EmitVecConstants() { - static const float vec4InitData[8][4] = { - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { -1.0f, -1.0f, -1.0f, -1.0f }, - { 1.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 1.0f }, - }; - - constants.vec4InitValues = (const Float4Constant *)GetCodePointer(); - for (size_t type = 0; type < ARRAY_SIZE(vec4InitData); ++type) { - for (int i = 0; i < 4; ++i) { - uint32_t val; - memcpy(&val, &vec4InitData[type][i], sizeof(val)); - Write32(val); - } - } -} - -void X64JitBackend::CompIR_VecArith(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Add: - regs_.Map(inst); - if (inst.dest == inst.src1) { - ADDPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - ADDPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else if (cpu_info.bAVX) { - VADDPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - ADDPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::Vec4Sub: - if (inst.dest == inst.src1) { - regs_.Map(inst); - SUBPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (cpu_info.bAVX) { - regs_.Map(inst); - VSUBPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - MOVAPS(tempReg, regs_.F(inst.src2)); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SUBPS(regs_.FX(inst.dest), R(tempReg)); - } else { - regs_.Map(inst); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SUBPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::Vec4Mul: - regs_.Map(inst); - if (inst.dest == inst.src1) { - MULPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - MULPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else if (cpu_info.bAVX) { - VMULPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MULPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::Vec4Div: - if (inst.dest == inst.src1) { - regs_.Map(inst); - DIVPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (cpu_info.bAVX) { - regs_.Map(inst); - VDIVPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - MOVAPS(tempReg, regs_.F(inst.src2)); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - DIVPS(regs_.FX(inst.dest), R(tempReg)); - } else { - regs_.Map(inst); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - DIVPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::Vec4Scale: - // TODO: Handle "aliasing" of sizes. - if (Overlap(inst.dest, 4, inst.src2, 1) || Overlap(inst.src1, 4, inst.src2, 1)) - DISABLE; - - regs_.Map(inst); - SHUFPS(regs_.FX(inst.src2), regs_.F(inst.src2), 0); - if (inst.dest == inst.src1) { - MULPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - MULPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else if (cpu_info.bAVX) { - VMULPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MULPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - break; - - case IROp::Vec4Neg: - regs_.Map(inst); - if (cpu_info.bAVX) { - VXORPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), M(constants.signBitAll)); // rip accessible - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - XORPS(regs_.FX(inst.dest), M(constants.signBitAll)); // rip accessible - } - break; - - case IROp::Vec4Abs: - regs_.Map(inst); - if (cpu_info.bAVX) { - VANDPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), M(constants.noSignMask)); // rip accessible - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - ANDPS(regs_.FX(inst.dest), M(constants.noSignMask)); // rip accessible - } - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_VecAssign(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Init: - regs_.Map(inst); - if (inst.src1 == (int)Vec4Init::AllZERO) { - XORPS(regs_.FX(inst.dest), regs_.F(inst.dest)); - } else { - MOVAPS(regs_.FX(inst.dest), M(&constants.vec4InitValues[inst.src1])); // rip accessible - } - break; - - case IROp::Vec4Shuffle: - if (regs_.GetFPRLaneCount(inst.src1) == 1 && (inst.src1 & 3) == 0 && inst.src2 == 0) { - // This is a broadcast. If dest == src1, this won't clear it. - regs_.SpillLockFPR(inst.src1); - regs_.MapVec4(inst.dest, MIPSMap::NOINIT); - } else { - regs_.Map(inst); - } - if (cpu_info.bAVX) { - VPERMILPS(128, regs_.FX(inst.dest), regs_.F(inst.src1), inst.src2); - } else { - if (inst.dest != inst.src1) - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - SHUFPS(regs_.FX(inst.dest), regs_.F(inst.dest), inst.src2); - } - break; - - case IROp::Vec4Blend: - if (cpu_info.bAVX) { - regs_.Map(inst); - VBLENDPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2), (uint8_t)inst.constant); - } else if (cpu_info.bSSE4_1) { - regs_.Map(inst); - if (inst.dest == inst.src1) { - BLENDPS(regs_.FX(inst.dest), regs_.F(inst.src2), (uint8_t)inst.constant); - } else if (inst.dest == inst.src2) { - BLENDPS(regs_.FX(inst.dest), regs_.F(inst.src1), (uint8_t)~inst.constant); - } else { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - BLENDPS(regs_.FX(inst.dest), regs_.F(inst.src2), (uint8_t)inst.constant); - } - } else { - // Could use some shuffles... - DISABLE; - } - break; - - case IROp::Vec4Mov: - regs_.Map(inst); - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_VecClamp(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4ClampToZero: - case IROp::Vec2ClampToZero: - CompIR_Generic(inst); - break; - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_VecHoriz(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec4Dot: - { - // TODO: Handle "aliasing" of sizes. In theory it should be fine if not dirty... - if (Overlap(inst.dest, 1, inst.src1, 4) || Overlap(inst.dest, 1, inst.src2, 4)) - DISABLE; - - X64Reg tempReg = regs_.MapWithFPRTemp(inst); - - if (inst.dest == inst.src1) { - MULPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } else if (inst.dest == inst.src2) { - MULPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - } else if (cpu_info.bAVX) { - VMULPS(128, regs_.FX(inst.dest), regs_.FX(inst.src1), regs_.F(inst.src2)); - } else if (cpu_info.bSSE4_1) { - MOVAPS(regs_.FX(inst.dest), regs_.F(inst.src1)); - MULPS(regs_.FX(inst.dest), regs_.F(inst.src2)); - } - - // This shuffle can be done in one op for SSE3/AVX, but it's not always faster. - MOVAPS(tempReg, regs_.F(inst.dest)); - SHUFPS(tempReg, regs_.F(inst.dest), VFPU_SWIZZLE(1, 0, 3, 2)); - ADDPS(regs_.FX(inst.dest), R(tempReg)); - MOVHLPS(tempReg, regs_.FX(inst.dest)); - ADDSS(regs_.FX(inst.dest), R(tempReg)); - break; - } - - default: - INVALIDOP; - break; - } -} - -void X64JitBackend::CompIR_VecPack(IRInst inst) { - CONDITIONAL_DISABLE; - - switch (inst.op) { - case IROp::Vec2Unpack16To31: - case IROp::Vec4Pack32To8: - case IROp::Vec2Pack31To16: - case IROp::Vec4Unpack8To32: - case IROp::Vec2Unpack16To32: - case IROp::Vec4DuplicateUpperBitsAndShift1: - case IROp::Vec4Pack31To8: - case IROp::Vec2Pack32To16: - CompIR_Generic(inst); - break; - - default: - INVALIDOP; - break; - } -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRJit.cpp b/Core/MIPS/x86/X64IRJit.cpp deleted file mode 100644 index dbcddee3f..000000000 --- a/Core/MIPS/x86/X64IRJit.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include -#include "Common/StringUtils.h" -#include "Core/MemMap.h" -#include "Core/MIPS/MIPSTables.h" -#include "Core/MIPS/x86/X64IRJit.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -namespace MIPSComp { - -using namespace Gen; -using namespace X64IRJitConstants; - -// Invalidations just need a MOV and JMP. -static constexpr int MIN_BLOCK_NORMAL_LEN = 10; -// As long as we can fit a JMP, we should be fine. -static constexpr int MIN_BLOCK_EXIT_LEN = 5; - -X64JitBackend::X64JitBackend(JitOptions &jitopt, IRBlockCache &blocks) - : IRNativeBackend(blocks), jo(jitopt), regs_(&jo) { - // Automatically disable incompatible options. - if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { - jo.enablePointerify = false; - } - - // Since we store the offset, this is as big as it can be. - AllocCodeSpace(1024 * 1024 * 16); - - regs_.Init(this); -} - -X64JitBackend::~X64JitBackend() {} - -static void NoBlockExits() { - _assert_msg_(false, "Never exited block, invalid IR?"); -} - -bool X64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload) { - if (GetSpaceLeft() < 0x800) - return false; - - u32 startPC = block->GetOriginalStart(); - bool wroteCheckedOffset = false; - if (jo.enableBlocklink && !jo.useBackJump) { - SetBlockCheckedOffset(block_num, (int)GetOffset(GetCodePointer())); - wroteCheckedOffset = true; - - WriteDebugPC(startPC); - - // TODO: See if we can get flags to always have the downcount compare. - if (jo.downcountInRegister) { - TEST(32, R(DOWNCOUNTREG), R(DOWNCOUNTREG)); - } else { - CMP(32, MDisp(CTXREG, downcountOffset), Imm32(0)); - } - FixupBranch normalEntry = J_CC(CC_NS); - MOV(32, R(SCRATCH1), Imm32(startPC)); - JMP(outerLoopPCInSCRATCH1_, true); - SetJumpTarget(normalEntry); - } - - // Don't worry, the codespace isn't large enough to overflow offsets. - const u8 *blockStart = GetCodePointer(); - block->SetTargetOffset((int)GetOffset(blockStart)); - compilingBlockNum_ = block_num; - lastConstPC_ = 0; - - regs_.Start(block); - - std::vector addresses; - addresses.reserve(block->GetNumInstructions()); - for (int i = 0; i < block->GetNumInstructions(); ++i) { - const IRInst &inst = block->GetInstructions()[i]; - regs_.SetIRIndex(i); - addresses.push_back(GetCodePtr()); - - CompileIRInst(inst); - - if (jo.Disabled(JitDisable::REGALLOC_GPR) || jo.Disabled(JitDisable::REGALLOC_FPR)) - regs_.FlushAll(jo.Disabled(JitDisable::REGALLOC_GPR), jo.Disabled(JitDisable::REGALLOC_FPR)); - - // Safety check, in case we get a bunch of really large jit ops without a lot of branching. - if (GetSpaceLeft() < 0x800) { - compilingBlockNum_ = -1; - return false; - } - } - - // We should've written an exit above. If we didn't, bad things will happen. - // Only check if debug stats are enabled - needlessly wastes jit space. - if (DebugStatsEnabled()) { - ABI_CallFunction((const void *)&NoBlockExits); - JMP(hooks_.crashHandler, true); - } - - int len = (int)GetOffset(GetCodePointer()) - block->GetTargetOffset(); - if (len < MIN_BLOCK_NORMAL_LEN) { - // We need at least 10 bytes to invalidate blocks with. - ReserveCodeSpace(MIN_BLOCK_NORMAL_LEN - len); - } - - if (!wroteCheckedOffset) { - // Always record this, even if block link disabled - it's used for size calc. - SetBlockCheckedOffset(block_num, (int)GetOffset(GetCodePointer())); - } - - if (jo.enableBlocklink && jo.useBackJump) { - WriteDebugPC(startPC); - - if (jo.downcountInRegister) { - TEST(32, R(DOWNCOUNTREG), R(DOWNCOUNTREG)); - } else { - CMP(32, MDisp(CTXREG, downcountOffset), Imm32(0)); - } - J_CC(CC_NS, blockStart, true); - - MOV(32, R(SCRATCH1), Imm32(startPC)); - JMP(outerLoopPCInSCRATCH1_, true); - } - - if (logBlocks_ > 0) { - --logBlocks_; - - std::map addressesLookup; - for (int i = 0; i < (int)addresses.size(); ++i) - addressesLookup[addresses[i]] = i; - - INFO_LOG(JIT, "=============== x86 (%08x, %d bytes) ===============", startPC, len); - for (const u8 *p = blockStart; p < GetCodePointer(); ) { - auto it = addressesLookup.find(p); - if (it != addressesLookup.end()) { - const IRInst &inst = block->GetInstructions()[it->second]; - - char temp[512]; - DisassembleIR(temp, sizeof(temp), inst); - INFO_LOG(JIT, "IR: #%d %s", it->second, temp); - } - - auto next = std::next(it); - const u8 *nextp = next == addressesLookup.end() ? GetCodePointer() : next->first; - - auto lines = DisassembleX86(p, (int)(nextp - p)); - for (const auto &line : lines) - INFO_LOG(JIT, " X: %s", line.c_str()); - p = nextp; - } - } - - compilingBlockNum_ = -1; - - return true; -} - -void X64JitBackend::WriteConstExit(uint32_t pc) { - int block_num = blocks_.GetBlockNumberFromStartAddress(pc); - const IRNativeBlock *nativeBlock = GetNativeBlock(block_num); - - int exitStart = (int)GetOffset(GetCodePointer()); - if (block_num >= 0 && jo.enableBlocklink && nativeBlock && nativeBlock->checkedOffset != 0) { - JMP(GetBasePtr() + nativeBlock->checkedOffset, true); - } else { - MOV(32, R(SCRATCH1), Imm32(pc)); - JMP(dispatcherPCInSCRATCH1_, true); - } - - if (jo.enableBlocklink) { - // In case of compression or early link, make sure it's large enough. - int len = (int)GetOffset(GetCodePointer()) - exitStart; - if (len < MIN_BLOCK_EXIT_LEN) { - ReserveCodeSpace(MIN_BLOCK_EXIT_LEN - len); - len = MIN_BLOCK_EXIT_LEN; - } - - AddLinkableExit(compilingBlockNum_, pc, exitStart, len); - } -} - -void X64JitBackend::OverwriteExit(int srcOffset, int len, int block_num) { - _dbg_assert_(len >= MIN_BLOCK_EXIT_LEN); - - const IRNativeBlock *nativeBlock = GetNativeBlock(block_num); - if (nativeBlock) { - u8 *writable = GetWritablePtrFromCodePtr(GetBasePtr()) + srcOffset; - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, len, MEM_PROT_READ | MEM_PROT_WRITE); - } - - XEmitter emitter(writable); - emitter.JMP(GetBasePtr() + nativeBlock->checkedOffset, true); - int bytesWritten = (int)(emitter.GetWritableCodePtr() - writable); - _dbg_assert_(bytesWritten <= MIN_BLOCK_EXIT_LEN); - if (bytesWritten < len) - emitter.ReserveCodeSpace(len - bytesWritten); - - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, 16, MEM_PROT_READ | MEM_PROT_EXEC); - } - } -} - -void X64JitBackend::CompIR_Generic(IRInst inst) { - // If we got here, we're going the slow way. - uint64_t value; - memcpy(&value, &inst, sizeof(inst)); - - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::IR_INTERPRET); -#if PPSSPP_ARCH(AMD64) - ABI_CallFunctionP((const void *)&DoIRInst, (void *)value); -#else - ABI_CallFunctionCC((const void *)&DoIRInst, (u32)(value & 0xFFFFFFFF), (u32)(value >> 32)); -#endif - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); - - // We only need to check the return value if it's a potential exit. - if ((GetIRMeta(inst.op)->flags & IRFLAG_EXIT) != 0) { - // Result in RAX aka SCRATCH1. - _assert_(RAX == SCRATCH1); - CMP(32, R(SCRATCH1), Imm32(0)); - J_CC(CC_NE, dispatcherPCInSCRATCH1_); - } -} - -void X64JitBackend::CompIR_Interpret(IRInst inst) { - MIPSOpcode op(inst.constant); - - // IR protects us against this being a branching instruction (well, hopefully.) - FlushAll(); - SaveStaticRegisters(); - WriteDebugProfilerStatus(IRProfilerStatus::INTERPRET); - if (DebugStatsEnabled()) { - ABI_CallFunctionP((const void *)&NotifyMIPSInterpret, (void *)MIPSGetName(op)); - } - ABI_CallFunctionC((const void *)MIPSGetInterpretFunc(op), inst.constant); - WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT); - LoadStaticRegisters(); -} - -void X64JitBackend::FlushAll() { - regs_.FlushAll(); -} - -bool X64JitBackend::DescribeCodePtr(const u8 *ptr, std::string &name) const { - // Used in disassembly viewer and profiling tools. - // Don't use spaces; profilers get confused or truncate them. - if (ptr == dispatcherPCInSCRATCH1_) { - name = "dispatcherPCInSCRATCH1"; - } else if (ptr == outerLoopPCInSCRATCH1_) { - name = "outerLoopPCInSCRATCH1"; - } else if (ptr == dispatcherNoCheck_) { - name = "dispatcherNoCheck"; - } else if (ptr == saveStaticRegisters_) { - name = "saveStaticRegisters"; - } else if (ptr == loadStaticRegisters_) { - name = "loadStaticRegisters"; - } else if (ptr == restoreRoundingMode_) { - name = "restoreRoundingMode"; - } else if (ptr == applyRoundingMode_) { - name = "applyRoundingMode"; - } else if (ptr >= GetBasePtr() && ptr < GetBasePtr() + jitStartOffset_) { - if (ptr == constants.noSignMask) { - name = "constants.noSignMask"; - } else if (ptr == constants.signBitAll) { - name = "constants.signBitAll"; - } else if (ptr == constants.positiveZeroes) { - name = "constants.positiveZeroes"; - } else if (ptr == constants.positiveInfinity) { - name = "constants.positiveInfinity"; - } else if (ptr == constants.positiveOnes) { - name = "constants.positiveOnes"; - } else if (ptr == constants.negativeOnes) { - name = "constants.negativeOnes"; - } else if (ptr == constants.qNAN) { - name = "constants.qNAN"; - } else if (ptr == constants.maxIntBelowAsFloat) { - name = "constants.maxIntBelowAsFloat"; - } else if ((const float *)ptr >= constants.mulTableVi2f && (const float *)ptr < constants.mulTableVi2f + 32) { - name = StringFromFormat("constants.mulTableVi2f[%d]", (int)((const float *)ptr - constants.mulTableVi2f)); - } else if ((const float *)ptr >= constants.mulTableVf2i && (const float *)ptr < constants.mulTableVf2i + 32) { - name = StringFromFormat("constants.mulTableVf2i[%d]", (int)((const float *)ptr - constants.mulTableVf2i)); - } else if ((const Float4Constant *)ptr >= constants.vec4InitValues && (const Float4Constant *)ptr < constants.vec4InitValues + 8) { - name = StringFromFormat("constants.vec4InitValues[%d]", (int)((const Float4Constant *)ptr - constants.vec4InitValues)); - } else { - name = "fixedCode"; - } - } else { - return IRNativeBackend::DescribeCodePtr(ptr, name); - } - return true; -} - -void X64JitBackend::ClearAllBlocks() { - ClearCodeSpace(jitStartOffset_); - EraseAllLinks(-1); -} - -void X64JitBackend::InvalidateBlock(IRBlock *block, int block_num) { - int offset = block->GetTargetOffset(); - u8 *writable = GetWritablePtrFromCodePtr(GetBasePtr()) + offset; - - // Overwrite the block with a jump to compile it again. - u32 pc = block->GetOriginalStart(); - if (pc != 0) { - // Hopefully we always have at least 16 bytes, which should be all we need. - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, MIN_BLOCK_NORMAL_LEN, MEM_PROT_READ | MEM_PROT_WRITE); - } - - XEmitter emitter(writable); - emitter.MOV(32, R(SCRATCH1), Imm32(pc)); - emitter.JMP(dispatcherPCInSCRATCH1_, true); - int bytesWritten = (int)(emitter.GetWritableCodePtr() - writable); - if (bytesWritten < MIN_BLOCK_NORMAL_LEN) - emitter.ReserveCodeSpace(MIN_BLOCK_NORMAL_LEN - bytesWritten); - - if (PlatformIsWXExclusive()) { - ProtectMemoryPages(writable, MIN_BLOCK_NORMAL_LEN, MEM_PROT_READ | MEM_PROT_EXEC); - } - } - - EraseAllLinks(block_num); -} - -void X64JitBackend::RestoreRoundingMode(bool force) { - CALL(restoreRoundingMode_); -} - -void X64JitBackend::ApplyRoundingMode(bool force) { - CALL(applyRoundingMode_); -} - -void X64JitBackend::MovFromPC(X64Reg r) { - MOV(32, R(r), MDisp(CTXREG, pcOffset)); -} - -void X64JitBackend::MovToPC(X64Reg r) { - MOV(32, MDisp(CTXREG, pcOffset), R(r)); -} - -void X64JitBackend::WriteDebugPC(uint32_t pc) { - if (hooks_.profilerPC) - MOV(32, M(hooks_.profilerPC), Imm32(pc)); -} - -void X64JitBackend::WriteDebugPC(Gen::X64Reg r) { - if (hooks_.profilerPC) - MOV(32, M(hooks_.profilerPC), R(r)); -} - -void X64JitBackend::WriteDebugProfilerStatus(IRProfilerStatus status) { - if (hooks_.profilerPC) - MOV(32, M(hooks_.profilerStatus), Imm32((int32_t)status)); -} - -void X64JitBackend::SaveStaticRegisters() { - if (jo.useStaticAlloc) { - //CALL(saveStaticRegisters_); - } else if (jo.downcountInRegister) { - // Inline the single operation - MOV(32, MDisp(CTXREG, downcountOffset), R(DOWNCOUNTREG)); - } -} - -void X64JitBackend::LoadStaticRegisters() { - if (jo.useStaticAlloc) { - //CALL(loadStaticRegisters_); - } else if (jo.downcountInRegister) { - MOV(32, R(DOWNCOUNTREG), MDisp(CTXREG, downcountOffset)); - } -} - -void X64JitBackend::EmitConst4x32(const void **c, uint32_t v) { - *c = AlignCode16(); - for (int i = 0; i < 4; ++i) - Write32(v); -} - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRJit.h b/Core/MIPS/x86/X64IRJit.h deleted file mode 100644 index 15a2fb9b4..000000000 --- a/Core/MIPS/x86/X64IRJit.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include -#include -#include "Common/x64Emitter.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRNativeCommon.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/x86/X64IRRegCache.h" - -#if PPSSPP_PLATFORM(WINDOWS) && (defined(_MSC_VER) || defined(__clang__) || defined(__INTEL_COMPILER)) -#define X64JIT_XMM_CALL __vectorcall -#define X64JIT_USE_XMM_CALL 1 -#elif PPSSPP_ARCH(AMD64) -// SystemV ABI supports XMM registers. -#define X64JIT_XMM_CALL -#define X64JIT_USE_XMM_CALL 1 -#else -// GCC on x86 doesn't support vectorcall. -#define X64JIT_XMM_CALL -#define X64JIT_USE_XMM_CALL 0 -#endif - -namespace MIPSComp { - -class X64JitBackend : public Gen::XCodeBlock, public IRNativeBackend { -public: - X64JitBackend(JitOptions &jo, IRBlockCache &blocks); - ~X64JitBackend(); - - bool DescribeCodePtr(const u8 *ptr, std::string &name) const override; - - void GenerateFixedCode(MIPSState *mipsState) override; - bool CompileBlock(IRBlock *block, int block_num, bool preload) override; - void ClearAllBlocks() override; - void InvalidateBlock(IRBlock *block, int block_num) override; - -protected: - const CodeBlockCommon &CodeBlock() const override { - return *this; - } - -private: - void RestoreRoundingMode(bool force = false); - void ApplyRoundingMode(bool force = false); - void MovFromPC(Gen::X64Reg r); - void MovToPC(Gen::X64Reg r); - void WriteDebugPC(uint32_t pc); - void WriteDebugPC(Gen::X64Reg r); - void WriteDebugProfilerStatus(IRProfilerStatus status); - - void SaveStaticRegisters(); - void LoadStaticRegisters(); - - // Note: destroys SCRATCH1. - void FlushAll(); - - void WriteConstExit(uint32_t pc); - void OverwriteExit(int srcOffset, int len, int block_num) override; - - void CompIR_Arith(IRInst inst) override; - void CompIR_Assign(IRInst inst) override; - void CompIR_Basic(IRInst inst) override; - void CompIR_Bits(IRInst inst) override; - void CompIR_Breakpoint(IRInst inst) override; - void CompIR_Compare(IRInst inst) override; - void CompIR_CondAssign(IRInst inst) override; - void CompIR_CondStore(IRInst inst) override; - void CompIR_Div(IRInst inst) override; - void CompIR_Exit(IRInst inst) override; - void CompIR_ExitIf(IRInst inst) override; - void CompIR_FArith(IRInst inst) override; - void CompIR_FAssign(IRInst inst) override; - void CompIR_FCompare(IRInst inst) override; - void CompIR_FCondAssign(IRInst inst) override; - void CompIR_FCvt(IRInst inst) override; - void CompIR_FLoad(IRInst inst) override; - void CompIR_FRound(IRInst inst) override; - void CompIR_FSat(IRInst inst) override; - void CompIR_FSpecial(IRInst inst) override; - void CompIR_FStore(IRInst inst) override; - void CompIR_Generic(IRInst inst) override; - void CompIR_HiLo(IRInst inst) override; - void CompIR_Interpret(IRInst inst) override; - void CompIR_Load(IRInst inst) override; - void CompIR_LoadShift(IRInst inst) override; - void CompIR_Logic(IRInst inst) override; - void CompIR_Mult(IRInst inst) override; - void CompIR_RoundingMode(IRInst inst) override; - void CompIR_Shift(IRInst inst) override; - void CompIR_Store(IRInst inst) override; - void CompIR_StoreShift(IRInst inst) override; - void CompIR_System(IRInst inst) override; - void CompIR_Transfer(IRInst inst) override; - void CompIR_VecArith(IRInst inst) override; - void CompIR_VecAssign(IRInst inst) override; - void CompIR_VecClamp(IRInst inst) override; - void CompIR_VecHoriz(IRInst inst) override; - void CompIR_VecLoad(IRInst inst) override; - void CompIR_VecPack(IRInst inst) override; - void CompIR_VecStore(IRInst inst) override; - void CompIR_ValidateAddress(IRInst inst) override; - - void EmitConst4x32(const void **c, uint32_t v); - void EmitFPUConstants(); - void EmitVecConstants(); - - Gen::OpArg PrepareSrc1Address(IRInst inst); - void CopyVec4ToFPRLane0(Gen::X64Reg dest, Gen::X64Reg src, int lane); - - JitOptions &jo; - X64IRRegCache regs_; - - const u8 *outerLoop_ = nullptr; - const u8 *outerLoopPCInSCRATCH1_ = nullptr; - const u8 *dispatcherCheckCoreState_ = nullptr; - const u8 *dispatcherPCInSCRATCH1_ = nullptr; - const u8 *dispatcherNoCheck_ = nullptr; - const u8 *restoreRoundingMode_ = nullptr; - const u8 *applyRoundingMode_ = nullptr; - - const u8 *saveStaticRegisters_ = nullptr; - const u8 *loadStaticRegisters_ = nullptr; - - typedef struct { float f[4]; } Float4Constant; - struct Constants { - const void *noSignMask; - const void *signBitAll; - const void *positiveZeroes; - const void *positiveInfinity; - const void *positiveOnes; - const void *negativeOnes; - const void *qNAN; - const void *maxIntBelowAsFloat; - const float *mulTableVi2f; - const float *mulTableVf2i; - const Float4Constant *vec4InitValues; - }; - Constants constants; - - int jitStartOffset_ = 0; - int compilingBlockNum_ = -1; - int logBlocks_ = 0; - // Only useful in breakpoints, where it's set immediately prior. - uint32_t lastConstPC_ = 0; -}; - -class X64IRJit : public IRNativeJit { -public: - X64IRJit(MIPSState *mipsState) - : IRNativeJit(mipsState), x64Backend_(jo, blocks_) { - Init(x64Backend_); - } - -private: - X64JitBackend x64Backend_; -}; - -} // namespace MIPSComp - -#endif diff --git a/Core/MIPS/x86/X64IRRegCache.cpp b/Core/MIPS/x86/X64IRRegCache.cpp deleted file mode 100644 index cfbb57712..000000000 --- a/Core/MIPS/x86/X64IRRegCache.cpp +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#ifndef offsetof -#include -#endif - -#include "Common/CPUDetect.h" -#include "Core/MemMap.h" -#include "Core/MIPS/IR/IRInst.h" -#include "Core/MIPS/IR/IRAnalysis.h" -#include "Core/MIPS/x86/X64IRRegCache.h" -#include "Core/MIPS/JitCommon/JitState.h" -#include "Core/Reporting.h" - -using namespace Gen; -using namespace X64IRJitConstants; - -X64IRRegCache::X64IRRegCache(MIPSComp::JitOptions *jo) - : IRNativeRegCacheBase(jo) { - config_.totalNativeRegs = NUM_X_REGS + NUM_X_FREGS; - config_.mapFPUSIMD = true; - // XMM regs are used for both FPU and Vec, so we don't need VREGs. - config_.mapUseVRegs = false; -} - -void X64IRRegCache::Init(XEmitter *emitter) { - emit_ = emitter; -} - -const int *X64IRRegCache::GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const { - if (type == MIPSLoc::REG) { - base = RAX; - - static const int allocationOrder[] = { -#if PPSSPP_ARCH(AMD64) -#ifdef _WIN32 - RSI, RDI, R8, R9, R10, R11, R12, R13, RDX, RCX, -#else - RBP, R8, R9, R10, R11, R12, R13, RDX, RCX, -#endif - // Intentionally last. - R15, -#elif PPSSPP_ARCH(X86) - ESI, EDI, EDX, EBX, ECX, -#endif - }; - - if ((flags & X64Map::MASK) == X64Map::SHIFT) { - // It's a single option for shifts. - static const int shiftReg[] = { ECX }; - count = 1; - return shiftReg; - } - if ((flags & X64Map::MASK) == X64Map::HIGH_DATA) { - // It's a single option for shifts. - static const int shiftReg[] = { EDX }; - count = 1; - return shiftReg; - } -#if PPSSPP_ARCH(X86) - if ((flags & X64Map::MASK) == X64Map::LOW_SUBREG) { - static const int lowSubRegAllocationOrder[] = { - EDX, EBX, ECX, - }; - count = ARRAY_SIZE(lowSubRegAllocationOrder); - return lowSubRegAllocationOrder; - } -#else - if (jo_->reserveR15ForAsm) { - count = ARRAY_SIZE(allocationOrder) - 1; - return allocationOrder; - } -#endif - count = ARRAY_SIZE(allocationOrder); - return allocationOrder; - } else if (type == MIPSLoc::FREG) { - base = -NUM_X_REGS; - - // TODO: Might have to change this if we can't live without dedicated temps. - static const int allocationOrder[] = { -#if PPSSPP_ARCH(AMD64) - XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM1, XMM2, XMM3, XMM4, XMM5, XMM0, -#elif PPSSPP_ARCH(X86) - XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM0, -#endif - }; - - if ((flags & X64Map::MASK) == X64Map::XMM0) { - // Certain cases require this reg. - static const int blendReg[] = { XMM0 }; - count = 1; - return blendReg; - } - - count = ARRAY_SIZE(allocationOrder); - return allocationOrder; - } else { - _assert_msg_(false, "Allocation order not yet implemented"); - count = 0; - return nullptr; - } -} - -void X64IRRegCache::FlushBeforeCall() { - // These registers are not preserved by function calls. -#if PPSSPP_ARCH(AMD64) -#ifdef _WIN32 - FlushNativeReg(GPRToNativeReg(RCX)); - FlushNativeReg(GPRToNativeReg(RDX)); - FlushNativeReg(GPRToNativeReg(R8)); - FlushNativeReg(GPRToNativeReg(R9)); - FlushNativeReg(GPRToNativeReg(R10)); - FlushNativeReg(GPRToNativeReg(R11)); - for (int i = 0; i < 6; ++i) - FlushNativeReg(NUM_X_REGS + i); -#else - FlushNativeReg(GPRToNativeReg(R8)); - FlushNativeReg(GPRToNativeReg(R9)); - FlushNativeReg(GPRToNativeReg(R10)); - FlushNativeReg(GPRToNativeReg(R11)); - for (int i = 0; i < NUM_X_FREGS; ++i) - FlushNativeReg(NUM_X_REGS + i); -#endif -#elif PPSSPP_ARCH(X86) - FlushNativeReg(GPRToNativeReg(ECX)); - FlushNativeReg(GPRToNativeReg(EDX)); - for (int i = 0; i < NUM_X_FREGS; ++i) - FlushNativeReg(NUM_X_REGS + i); -#endif -} - -void X64IRRegCache::FlushAll(bool gprs, bool fprs) { - // Note: make sure not to change the registers when flushing: - // Branching code may expect the x64reg to retain its value. - - auto needsFlush = [&](IRReg i) { - if (mr[i].loc != MIPSLoc::MEM || mr[i].isStatic) - return false; - if (mr[i].nReg == -1 || !nr[mr[i].nReg].isDirty) - return false; - return true; - }; - - auto isSingleFloat = [&](IRReg i) { - if (mr[i].lane != -1 || mr[i].loc != MIPSLoc::FREG) - return false; - return true; - }; - - // Sometimes, float/vector regs may be in separate regs in a sequence. - // It's worth combining and flushing together. - for (int i = 1; i < TOTAL_MAPPABLE_IRREGS - 1; ++i) { - if (!needsFlush(i) || !needsFlush(i + 1)) - continue; - // GPRs are probably not worth it. Merging Vec2s might be, but pretty uncommon. - if (!isSingleFloat(i) || !isSingleFloat(i + 1)) - continue; - - X64Reg regs[4]{ INVALID_REG, INVALID_REG, INVALID_REG, INVALID_REG }; - regs[0] = FromNativeReg(mr[i + 0].nReg); - regs[1] = FromNativeReg(mr[i + 1].nReg); - - bool flushVec4 = i + 3 < TOTAL_MAPPABLE_IRREGS && needsFlush(i + 2) && needsFlush(i + 3); - if (flushVec4 && isSingleFloat(i + 2) && isSingleFloat(i + 3) && (i & 3) == 0) { - regs[2] = FromNativeReg(mr[i + 2].nReg); - regs[3] = FromNativeReg(mr[i + 3].nReg); - - // Note that this doesn't change the low lane of any of these regs. - emit_->UNPCKLPS(regs[1], ::R(regs[3])); - emit_->UNPCKLPS(regs[0], ::R(regs[2])); - emit_->UNPCKLPS(regs[0], ::R(regs[1])); - emit_->MOVAPS(MDisp(CTXREG, -128 + GetMipsRegOffset(i)), regs[0]); - - for (int j = 0; j < 4; ++j) - DiscardReg(i + j); - i += 3; - continue; - } - - // TODO: Maybe this isn't always worth doing. - emit_->UNPCKLPS(regs[0], ::R(regs[1])); - emit_->MOVLPS(MDisp(CTXREG, -128 + GetMipsRegOffset(i)), regs[0]); - - DiscardReg(i); - DiscardReg(i + 1); - ++i; - continue; - } - - IRNativeRegCacheBase::FlushAll(gprs, fprs); -} - -X64Reg X64IRRegCache::TryMapTempImm(IRReg r, X64Map flags) { - _dbg_assert_(IsValidGPR(r)); - - auto canUseReg = [flags](X64Reg r) { - switch (flags & X64Map::MASK) { - case X64Map::NONE: - return true; - case X64Map::LOW_SUBREG: - return HasLowSubregister(r); - case X64Map::SHIFT: - return r == RCX; - case X64Map::HIGH_DATA: - return r == RCX; - default: - _assert_msg_(false, "Unexpected flags"); - } - return false; - }; - - // If already mapped, no need for a temporary. - if (IsGPRMapped(r)) { - if (canUseReg(RX(r))) - return RX(r); - } - - if (mr[r].loc == MIPSLoc::IMM) { - // Try our luck - check for an exact match in another xreg. - for (int i = 0; i < TOTAL_MAPPABLE_IRREGS; ++i) { - if (mr[i].loc == MIPSLoc::REG_IMM && mr[i].imm == mr[r].imm) { - // Awesome, let's just use this reg. - if (canUseReg(FromNativeReg(mr[i].nReg))) - return FromNativeReg(mr[i].nReg); - } - } - } - - return INVALID_REG; -} - -X64Reg X64IRRegCache::GetAndLockTempGPR() { - IRNativeReg reg = AllocateReg(MIPSLoc::REG, MIPSMap::INIT); - if (reg != -1) { - nr[reg].tempLockIRIndex = irIndex_; - } - return FromNativeReg(reg); -} - -X64Reg X64IRRegCache::GetAndLockTempFPR() { - IRNativeReg reg = AllocateReg(MIPSLoc::FREG, MIPSMap::INIT); - if (reg != -1) { - nr[reg].tempLockIRIndex = irIndex_; - } - return FromNativeReg(reg); -} - -void X64IRRegCache::ReserveAndLockXGPR(Gen::X64Reg r) { - IRNativeReg nreg = GPRToNativeReg(r); - if (nr[nreg].mipsReg != -1) - FlushNativeReg(nreg); - nr[r].tempLockIRIndex = irIndex_; -} - -X64Reg X64IRRegCache::MapWithFPRTemp(const IRInst &inst) { - return FromNativeReg(MapWithTemp(inst, MIPSLoc::FREG)); -} - -void X64IRRegCache::MapWithFlags(IRInst inst, X64Map destFlags, X64Map src1Flags, X64Map src2Flags) { - Mapping mapping[3]; - MappingFromInst(inst, mapping); - - mapping[0].flags = mapping[0].flags | destFlags; - mapping[1].flags = mapping[1].flags | src1Flags; - mapping[2].flags = mapping[2].flags | src2Flags; - - auto flushReg = [&](IRNativeReg nreg) { - bool mustKeep = false; - bool canDiscard = false; - for (int i = 0; i < 3; ++i) { - if (mapping[i].reg != nr[nreg].mipsReg) - continue; - - if ((mapping[i].flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) { - mustKeep = true; - break; - } else { - canDiscard = true; - } - } - - if (mustKeep || !canDiscard) { - FlushNativeReg(nreg); - } else { - DiscardNativeReg(nreg); - } - }; - - // If there are any special rules, we might need to spill. - for (int i = 0; i < 3; ++i) { - switch (mapping[i].flags & X64Map::MASK) { - case X64Map::SHIFT: - if (nr[RCX].mipsReg != mapping[i].reg) - flushReg(RCX); - break; - - case X64Map::HIGH_DATA: - if (nr[RDX].mipsReg != mapping[i].reg) - flushReg(RDX); - break; - - case X64Map::XMM0: - if (nr[XMMToNativeReg(XMM0)].mipsReg != mapping[i].reg) - flushReg(XMMToNativeReg(XMM0)); - break; - - default: - break; - } - } - - ApplyMapping(mapping, 3); - CleanupMapping(mapping, 3); -} - -X64Reg X64IRRegCache::MapGPR(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidGPR(mipsReg)); - - // Okay, not mapped, so we need to allocate an x64 register. - IRNativeReg nreg = MapNativeReg(MIPSLoc::REG, mipsReg, 1, mapFlags); - return FromNativeReg(nreg); -} - -X64Reg X64IRRegCache::MapGPR2(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidGPR(mipsReg) && IsValidGPR(mipsReg + 1)); - - // Okay, not mapped, so we need to allocate an x64 register. - IRNativeReg nreg = MapNativeReg(MIPSLoc::REG, mipsReg, 2, mapFlags); - return FromNativeReg(nreg); -} - -X64Reg X64IRRegCache::MapGPRAsPointer(IRReg reg) { - return FromNativeReg(MapNativeRegAsPointer(reg)); -} - -X64Reg X64IRRegCache::MapFPR(IRReg mipsReg, MIPSMap mapFlags) { - _dbg_assert_(IsValidFPR(mipsReg)); - _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::MEM || mr[mipsReg + 32].loc == MIPSLoc::FREG); - - IRNativeReg nreg = MapNativeReg(MIPSLoc::FREG, mipsReg + 32, 1, mapFlags); - if (nreg != -1) - return FromNativeReg(nreg); - return INVALID_REG; -} - -X64Reg X64IRRegCache::MapVec4(IRReg first, MIPSMap mapFlags) { - _dbg_assert_(IsValidFPR(first)); - _dbg_assert_((first & 3) == 0); - _dbg_assert_(mr[first + 32].loc == MIPSLoc::MEM || mr[first + 32].loc == MIPSLoc::FREG); - - IRNativeReg nreg = MapNativeReg(MIPSLoc::FREG, first + 32, 4, mapFlags); - if (nreg != -1) - return FromNativeReg(nreg); - return INVALID_REG; -} - -void X64IRRegCache::AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) { - _assert_(nreg >= 0 && nreg < NUM_X_REGS); - X64Reg r = FromNativeReg(nreg); - if (state) { -#if defined(MASKED_PSP_MEMORY) - // This destroys the value... - _dbg_assert_(!nr[nreg].isDirty); - emit_->AND(PTRBITS, ::R(r), Imm32(Memory::MEMVIEW32_MASK)); - emit_->ADD(PTRBITS, ::R(r), ImmPtr(Memory::base)); -#else - emit_->ADD(PTRBITS, ::R(r), ::R(MEMBASEREG)); -#endif - } else { -#if defined(MASKED_PSP_MEMORY) - _dbg_assert_(!nr[nreg].isDirty); - emit_->SUB(PTRBITS, ::R(r), ImmPtr(Memory::base)); -#else - emit_->SUB(PTRBITS, ::R(r), ::R(MEMBASEREG)); -#endif - } -} - -void X64IRRegCache::LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) { - X64Reg r = FromNativeReg(nreg); - _dbg_assert_(first != MIPS_REG_ZERO); - if (nreg < NUM_X_REGS) { - _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); - if (lanes == 1) - emit_->MOV(32, ::R(r), MDisp(CTXREG, -128 + GetMipsRegOffset(first))); -#if PPSSPP_ARCH(AMD64) - else if (lanes == 2) - emit_->MOV(64, ::R(r), MDisp(CTXREG, -128 + GetMipsRegOffset(first))); -#endif - else - _assert_(false); - } else { - _dbg_assert_(nreg < NUM_X_REGS + NUM_X_FREGS); - _assert_msg_(mr[first].loc == MIPSLoc::FREG, "Cannot load this type: %d", (int)mr[first].loc); - if (lanes == 1) - emit_->MOVSS(r, MDisp(CTXREG, -128 + GetMipsRegOffset(first))); - else if (lanes == 2) - emit_->MOVLPS(r, MDisp(CTXREG, -128 + GetMipsRegOffset(first))); - else if (lanes == 4 && (first & 3) == 0) - emit_->MOVAPS(r, MDisp(CTXREG, -128 + GetMipsRegOffset(first))); - else if (lanes == 4) - emit_->MOVUPS(r, MDisp(CTXREG, -128 + GetMipsRegOffset(first))); - else - _assert_(false); - } -} - -void X64IRRegCache::StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) { - X64Reg r = FromNativeReg(nreg); - _dbg_assert_(first != MIPS_REG_ZERO); - if (nreg < NUM_X_REGS) { - _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); - _assert_(mr[first].loc == MIPSLoc::REG || mr[first].loc == MIPSLoc::REG_IMM); - if (lanes == 1) - emit_->MOV(32, MDisp(CTXREG, -128 + GetMipsRegOffset(first)), ::R(r)); -#if PPSSPP_ARCH(AMD64) - else if (lanes == 2) - emit_->MOV(64, MDisp(CTXREG, -128 + GetMipsRegOffset(first)), ::R(r)); -#endif - else - _assert_(false); - } else { - _dbg_assert_(nreg < NUM_X_REGS + NUM_X_FREGS); - _assert_msg_(mr[first].loc == MIPSLoc::FREG, "Cannot store this type: %d", (int)mr[first].loc); - if (lanes == 1) - emit_->MOVSS(MDisp(CTXREG, -128 + GetMipsRegOffset(first)), r); - else if (lanes == 2) - emit_->MOVLPS(MDisp(CTXREG, -128 + GetMipsRegOffset(first)), r); - else if (lanes == 4 && (first & 3) == 0) - emit_->MOVAPS(MDisp(CTXREG, -128 + GetMipsRegOffset(first)), r); - else if (lanes == 4) - emit_->MOVUPS(MDisp(CTXREG, -128 + GetMipsRegOffset(first)), r); - else - _assert_(false); - } -} - -bool X64IRRegCache::TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) { - bool allowed = !mr[nr[nreg].mipsReg].isStatic; - // There's currently no support for non-XMMs here. - allowed = allowed && type == MIPSLoc::FREG; - - if (dest == -1) - dest = nreg; - - if (allowed && (flags == MIPSMap::INIT || flags == MIPSMap::DIRTY)) { - // Alright, changing lane count (possibly including lane position.) - IRReg oldfirst = nr[nreg].mipsReg; - int oldlanes = 0; - while (mr[oldfirst + oldlanes].nReg == nreg) - oldlanes++; - _assert_msg_(oldlanes != 0, "TransferNativeReg encountered nreg mismatch"); - _assert_msg_(oldlanes != lanes, "TransferNativeReg transfer to same lanecount, misaligned?"); - - if (lanes == 1 && TransferVecTo1(nreg, dest, first, oldlanes)) - return true; - if (oldlanes == 1 && Transfer1ToVec(nreg, dest, first, lanes)) - return true; - } - - return IRNativeRegCacheBase::TransferNativeReg(nreg, dest, type, first, lanes, flags); -} - -bool X64IRRegCache::TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes) { - IRReg oldfirst = nr[nreg].mipsReg; - - // Is it worth preserving any of the old regs? - int numKept = 0; - for (int i = 0; i < oldlanes; ++i) { - // Skip whichever one this is extracting. - if (oldfirst + i == first) - continue; - // If 0 isn't being transfered, easy to keep in its original reg. - if (i == 0 && dest != nreg) { - numKept++; - continue; - } - - IRNativeReg freeReg = FindFreeReg(MIPSLoc::FREG, MIPSMap::INIT); - if (freeReg != -1 && IsRegRead(MIPSLoc::FREG, oldfirst + i)) { - // If there's one free, use it. Don't modify nreg, though. - u8 shuf = VFPU_SWIZZLE(i, i, i, i); - if (i == 0) { - emit_->MOVAPS(FromNativeReg(freeReg), ::R(FromNativeReg(nreg))); - } else if (cpu_info.bAVX) { - emit_->VPERMILPS(128, FromNativeReg(freeReg), ::R(FromNativeReg(nreg)), shuf); - } else if (i == 2) { - emit_->MOVHLPS(FromNativeReg(freeReg), FromNativeReg(nreg)); - } else { - emit_->MOVAPS(FromNativeReg(freeReg), ::R(FromNativeReg(nreg))); - emit_->SHUFPS(FromNativeReg(freeReg), ::R(FromNativeReg(freeReg)), shuf); - } - - // Update accounting. - nr[freeReg].isDirty = nr[nreg].isDirty; - nr[freeReg].mipsReg = oldfirst + i; - mr[oldfirst + i].lane = -1; - mr[oldfirst + i].nReg = freeReg; - numKept++; - } - } - - // Unless all other lanes were kept, store. - if (nr[nreg].isDirty && numKept < oldlanes - 1) { - StoreNativeReg(nreg, oldfirst, oldlanes); - // Set false even for regs that were split out, since they were flushed too. - for (int i = 0; i < oldlanes; ++i) { - if (mr[oldfirst + i].nReg != -1) - nr[mr[oldfirst + i].nReg].isDirty = false; - } - } - - // Next, shuffle the desired element into first place. - u8 shuf = VFPU_SWIZZLE(mr[first].lane, mr[first].lane, mr[first].lane, mr[first].lane); - if (mr[first].lane > 0 && cpu_info.bAVX && dest != nreg) { - emit_->VPERMILPS(128, FromNativeReg(dest), ::R(FromNativeReg(nreg)), shuf); - } else if (mr[first].lane <= 0 && dest != nreg) { - emit_->MOVAPS(FromNativeReg(dest), ::R(FromNativeReg(nreg))); - } else if (mr[first].lane == 2) { - emit_->MOVHLPS(FromNativeReg(dest), FromNativeReg(nreg)); - } else if (mr[first].lane > 0) { - if (dest != nreg) - emit_->MOVAPS(FromNativeReg(dest), ::R(FromNativeReg(nreg))); - emit_->SHUFPS(FromNativeReg(dest), ::R(FromNativeReg(dest)), shuf); - } - - // Now update accounting. - for (int i = 0; i < oldlanes; ++i) { - auto &mreg = mr[oldfirst + i]; - if (oldfirst + i == first) { - mreg.lane = -1; - mreg.nReg = dest; - } else if (mreg.nReg == nreg && i == 0 && nreg != dest) { - // Still in the same register, but no longer a vec. - mreg.lane = -1; - } else if (mreg.nReg == nreg) { - // No longer in a register. - mreg.nReg = -1; - mreg.lane = -1; - mreg.loc = MIPSLoc::MEM; - } - } - - if (dest != nreg) { - nr[dest].isDirty = nr[nreg].isDirty; - if (oldfirst == first) { - nr[nreg].mipsReg = -1; - nr[nreg].isDirty = false; - } - } - nr[dest].mipsReg = first; - - return true; -} - -bool X64IRRegCache::Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes) { - X64Reg cur[4]{}; - int numInRegs = 0; - u8 blendMask = 0; - for (int i = 0; i < lanes; ++i) { - if (mr[first + i].lane != -1 || (i != 0 && mr[first + i].spillLockIRIndex >= irIndex_)) { - // Can't do it, either double mapped or overlapping vec. - return false; - } - - if (mr[first + i].nReg == -1) { - cur[i] = INVALID_REG; - blendMask |= 1 << i; - } else { - cur[i] = FromNativeReg(mr[first + i].nReg); - numInRegs++; - } - } - - // Shouldn't happen, this should only get called to transfer one in a reg. - if (numInRegs == 0) - return false; - - // Move things together into a reg. - if (lanes == 4 && cpu_info.bSSE4_1 && numInRegs == 1 && (first & 3) == 0) { - // Use a blend to grab the rest. BLENDPS is pretty good. - if (cpu_info.bAVX && nreg != dest) { - if (cur[0] == INVALID_REG) { - // Broadcast to all lanes, then blend from memory to replace. - emit_->VPERMILPS(128, FromNativeReg(dest), ::R(FromNativeReg(nreg)), 0); - emit_->BLENDPS(FromNativeReg(dest), MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - } else { - emit_->VBLENDPS(128, FromNativeReg(dest), FromNativeReg(nreg), MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - } - cur[0] = FromNativeReg(dest); - } else { - if (cur[0] == INVALID_REG) - emit_->SHUFPS(FromNativeReg(nreg), ::R(FromNativeReg(nreg)), 0); - emit_->BLENDPS(FromNativeReg(nreg), MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - // If this is not dest, it'll get moved there later. - cur[0] = FromNativeReg(nreg); - } - } else if (lanes == 4) { - if (blendMask == 0) { - // y = yw##, x = xz##, x = xyzw. - emit_->UNPCKLPS(cur[1], ::R(cur[3])); - emit_->UNPCKLPS(cur[0], ::R(cur[2])); - emit_->UNPCKLPS(cur[0], ::R(cur[1])); - } else if (blendMask == 0b1100) { - // x = xy##, then load zw. - emit_->UNPCKLPS(cur[0], ::R(cur[1])); - emit_->MOVHPS(cur[0], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 2))); - } else if (blendMask == 0b1010 && cpu_info.bSSE4_1 && (first & 3) == 0) { - // x = x#z#, x = xyzw. - emit_->SHUFPS(cur[0], ::R(cur[2]), VFPU_SWIZZLE(0, 0, 0, 0)); - emit_->BLENDPS(cur[0], MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - } else if (blendMask == 0b0110 && cpu_info.bSSE4_1 && (first & 3) == 0) { - // x = x##w, x = xyzw. - emit_->SHUFPS(cur[0], ::R(cur[3]), VFPU_SWIZZLE(0, 0, 0, 0)); - emit_->BLENDPS(cur[0], MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - } else if (blendMask == 0b1001 && cpu_info.bSSE4_1 && (first & 3) == 0) { - // y = #yz#, y = xyzw. - emit_->SHUFPS(cur[1], ::R(cur[2]), VFPU_SWIZZLE(0, 0, 0, 0)); - emit_->BLENDPS(cur[1], MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - // Will be moved to dest as needed. - cur[0] = cur[1]; - } else if (blendMask == 0b0101 && cpu_info.bSSE4_1 && (first & 3) == 0) { - // y = #y#w, y = xyzw. - emit_->SHUFPS(cur[1], ::R(cur[3]), VFPU_SWIZZLE(0, 0, 0, 0)); - emit_->BLENDPS(cur[1], MDisp(CTXREG, -128 + GetMipsRegOffset(first)), blendMask); - // Will be moved to dest as needed. - cur[0] = cur[1]; - } else if (blendMask == 0b1000) { - // x = xz##, z = w###, y = yw##, x = xyzw. - emit_->UNPCKLPS(cur[0], ::R(cur[2])); - emit_->MOVSS(cur[2], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 3))); - emit_->UNPCKLPS(cur[1], ::R(cur[2])); - emit_->UNPCKLPS(cur[0], ::R(cur[1])); - } else if (blendMask == 0b0100) { - // y = yw##, w = z###, x = xz##, x = xyzw. - emit_->UNPCKLPS(cur[1], ::R(cur[3])); - emit_->MOVSS(cur[3], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 2))); - emit_->UNPCKLPS(cur[0], ::R(cur[3])); - emit_->UNPCKLPS(cur[0], ::R(cur[1])); - } else if (blendMask == 0b0010) { - // z = zw##, w = y###, x = xy##, x = xyzw. - emit_->UNPCKLPS(cur[2], ::R(cur[3])); - emit_->MOVSS(cur[3], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 1))); - emit_->UNPCKLPS(cur[0], ::R(cur[3])); - emit_->MOVLHPS(cur[0], cur[2]); - } else if (blendMask == 0b0001) { - // y = yw##, w = x###, w = xz##, w = xyzw. - emit_->UNPCKLPS(cur[1], ::R(cur[3])); - emit_->MOVSS(cur[3], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 0))); - emit_->UNPCKLPS(cur[3], ::R(cur[2])); - emit_->UNPCKLPS(cur[3], ::R(cur[1])); - // Will be moved to dest as needed. - cur[0] = cur[3]; - } else if (blendMask == 0b0011) { - // z = zw##, w = xy##, w = xyzw. - emit_->UNPCKLPS(cur[2], ::R(cur[3])); - emit_->MOVLPS(cur[3], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 0))); - emit_->MOVLHPS(cur[3], cur[2]); - // Will be moved to dest as needed. - cur[0] = cur[3]; - } else { - // This must mean no SSE4, and numInRegs <= 2 in trickier cases. - return false; - } - } else if (lanes == 2) { - if (cur[0] != INVALID_REG && cur[1] != INVALID_REG) { - emit_->UNPCKLPS(cur[0], ::R(cur[1])); - } else if (cur[0] != INVALID_REG && cpu_info.bSSE4_1) { - emit_->INSERTPS(cur[0], MDisp(CTXREG, -128 + GetMipsRegOffset(first + 1)), 1); - } else { - return false; - } - } else { - return false; - } - - mr[first].lane = 0; - for (int i = 0; i < lanes; ++i) { - if (mr[first + i].nReg != -1) { - // If this was dirty, the combined reg is now dirty. - if (nr[mr[first + i].nReg].isDirty) - nr[dest].isDirty = true; - - // Throw away the other register we're no longer using. - if (i != 0) - DiscardNativeReg(mr[first + i].nReg); - } - - // And set it as using the new one. - mr[first + i].lane = i; - mr[first + i].loc = MIPSLoc::FREG; - mr[first + i].nReg = dest; - } - - if (cur[0] != FromNativeReg(dest)) - emit_->MOVAPS(FromNativeReg(dest), ::R(cur[0])); - - if (dest != nreg) { - nr[dest].mipsReg = first; - nr[nreg].mipsReg = -1; - nr[nreg].isDirty = false; - } - - return true; -} - -void X64IRRegCache::SetNativeRegValue(IRNativeReg nreg, uint32_t imm) { - X64Reg r = FromNativeReg(nreg); - _dbg_assert_(nreg >= 0 && nreg < NUM_X_REGS); - emit_->MOV(32, ::R(r), Imm32(imm)); -} - -void X64IRRegCache::StoreRegValue(IRReg mreg, uint32_t imm) { - _assert_(IsValidGPRNoZero(mreg)); - // Try to optimize using a different reg. - X64Reg storeReg = INVALID_REG; - - // Could we get lucky? Check for an exact match in another xreg. - for (int i = 0; i < TOTAL_MAPPABLE_IRREGS; ++i) { - if (mr[i].loc == MIPSLoc::REG_IMM && mr[i].imm == imm) { - // Awesome, let's just store this reg. - storeReg = (X64Reg)mr[i].nReg; - break; - } - } - - if (storeReg == INVALID_REG) - emit_->MOV(32, MDisp(CTXREG, -128 + GetMipsRegOffset(mreg)), Imm32(imm)); - else - emit_->MOV(32, MDisp(CTXREG, -128 + GetMipsRegOffset(mreg)), ::R(storeReg)); -} - -OpArg X64IRRegCache::R(IRReg mipsReg) { - return ::R(RX(mipsReg)); -} - -OpArg X64IRRegCache::RPtr(IRReg mipsReg) { - return ::R(RXPtr(mipsReg)); -} - -OpArg X64IRRegCache::F(IRReg mipsReg) { - return ::R(FX(mipsReg)); -} - -X64Reg X64IRRegCache::RX(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM); - if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - return FromNativeReg(mr[mipsReg].nReg); - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in x64 reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -X64Reg X64IRRegCache::RXPtr(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM || mr[mipsReg].loc == MIPSLoc::REG_AS_PTR); - if (mr[mipsReg].loc == MIPSLoc::REG_AS_PTR) { - return FromNativeReg(mr[mipsReg].nReg); - } else if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { - int r = mr[mipsReg].nReg; - _dbg_assert_(nr[r].pointerified); - if (nr[r].pointerified) { - return FromNativeReg(mr[mipsReg].nReg); - } else { - ERROR_LOG(JIT, "Tried to use a non-pointer register as a pointer"); - return INVALID_REG; - } - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in x64 reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -X64Reg X64IRRegCache::FX(IRReg mipsReg) { - _dbg_assert_(IsValidFPR(mipsReg)); - _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::FREG); - if (mr[mipsReg + 32].loc == MIPSLoc::FREG) { - return FromNativeReg(mr[mipsReg + 32].nReg); - } else { - ERROR_LOG_REPORT(JIT, "Reg %i not in x64 reg", mipsReg); - return INVALID_REG; // BAAAD - } -} - -bool X64IRRegCache::HasLowSubregister(Gen::X64Reg reg) { -#if !PPSSPP_ARCH(AMD64) - // Can't use ESI or EDI (which we use), no 8-bit versions. Only these. - return reg == EAX || reg == EBX || reg == ECX || reg == EDX; -#else - return true; -#endif -} - -#endif diff --git a/Core/MIPS/x86/X64IRRegCache.h b/Core/MIPS/x86/X64IRRegCache.h deleted file mode 100644 index 8a21f563d..000000000 --- a/Core/MIPS/x86/X64IRRegCache.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include "ppsspp_config.h" -#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - -#include "Common/x64Emitter.h" -#include "Core/MIPS/MIPS.h" -#include "Core/MIPS/IR/IRJit.h" -#include "Core/MIPS/IR/IRRegCache.h" - -namespace X64IRJitConstants { - -#if PPSSPP_ARCH(AMD64) -const Gen::X64Reg MEMBASEREG = Gen::RBX; -const Gen::X64Reg CTXREG = Gen::R14; -// Note: this is actually offset from the base. -const Gen::X64Reg JITBASEREG = Gen::R15; -const Gen::X64Reg DOWNCOUNTREG = Gen::R15; -#else -const Gen::X64Reg CTXREG = Gen::EBP; -const Gen::X64Reg DOWNCOUNTREG = Gen::INVALID_REG; -#endif -const Gen::X64Reg SCRATCH1 = Gen::EAX; - -static constexpr auto downcountOffset = offsetof(MIPSState, downcount) - 128; -static constexpr auto tempOffset = offsetof(MIPSState, temp) - 128; -static constexpr auto fcr31Offset = offsetof(MIPSState, fcr31) - 128; -static constexpr auto pcOffset = offsetof(MIPSState, pc) - 128; -static constexpr auto mxcsrTempOffset = offsetof(MIPSState, mxcsrTemp) - 128; - -enum class X64Map : uint8_t { - NONE = 0, - // On 32-bit: EAX, EBX, ECX, EDX - LOW_SUBREG = 0x10, - // EDX/RDX for DIV/MUL/similar. - HIGH_DATA = 0x20, - // ECX/RCX only, for shifts. - SHIFT = 0x30, - // XMM0 for BLENDVPS, funcs. - XMM0 = 0x40, - MASK = 0xF0, -}; -static inline MIPSMap operator |(const MIPSMap &lhs, const X64Map &rhs) { - return MIPSMap((uint8_t)lhs | (uint8_t)rhs); -} -static inline X64Map operator |(const X64Map &lhs, const X64Map &rhs) { - return X64Map((uint8_t)lhs | (uint8_t)rhs); -} -static inline X64Map operator &(const MIPSMap &lhs, const X64Map &rhs) { - return X64Map((uint8_t)lhs & (uint8_t)rhs); -} -static inline X64Map operator &(const X64Map &lhs, const X64Map &rhs) { - return X64Map((uint8_t)lhs & (uint8_t)rhs); -} - -} // namespace X64IRJitConstants - -class X64IRRegCache : public IRNativeRegCacheBase { -public: - X64IRRegCache(MIPSComp::JitOptions *jo); - - void Init(Gen::XEmitter *emitter); - - // May fail and return INVALID_REG if it needs flushing. - Gen::X64Reg TryMapTempImm(IRReg reg, X64IRJitConstants::X64Map flags = X64IRJitConstants::X64Map::NONE); - - // Returns an X64 register containing the requested MIPS register. - Gen::X64Reg MapGPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - Gen::X64Reg MapGPR2(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - Gen::X64Reg MapGPRAsPointer(IRReg reg); - Gen::X64Reg MapFPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT); - Gen::X64Reg MapVec4(IRReg first, MIPSMap mapFlags = MIPSMap::INIT); - - Gen::X64Reg MapWithFPRTemp(const IRInst &inst); - - void MapWithFlags(IRInst inst, X64IRJitConstants::X64Map destFlags, X64IRJitConstants::X64Map src1Flags = X64IRJitConstants::X64Map::NONE, X64IRJitConstants::X64Map src2Flags = X64IRJitConstants::X64Map::NONE); - - // Note: may change the high lanes of single-register XMMs. - void FlushAll(bool gprs = true, bool fprs = true) override; - void FlushBeforeCall(); - - Gen::X64Reg GetAndLockTempGPR(); - Gen::X64Reg GetAndLockTempFPR(); - void ReserveAndLockXGPR(Gen::X64Reg r); - - Gen::OpArg R(IRReg preg); - Gen::OpArg RPtr(IRReg preg); - Gen::OpArg F(IRReg preg); - Gen::X64Reg RX(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer - Gen::X64Reg RXPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer - Gen::X64Reg FX(IRReg preg); - - static bool HasLowSubregister(Gen::X64Reg reg); - -protected: - const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const override; - void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) override; - - void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; - void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; - void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) override; - void StoreRegValue(IRReg mreg, uint32_t imm) override; - bool TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) override; - -private: - bool TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes); - bool Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes); - - IRNativeReg GPRToNativeReg(Gen::X64Reg r) { - return (IRNativeReg)r; - } - IRNativeReg XMMToNativeReg(Gen::X64Reg r) { - return (IRNativeReg)(r + NUM_X_REGS); - } - Gen::X64Reg FromNativeReg(IRNativeReg r) { - if (r >= NUM_X_REGS) - return (Gen::X64Reg)(Gen::XMM0 + (r - NUM_X_REGS)); - return (Gen::X64Reg)(Gen::RAX + r); - } - - Gen::XEmitter *emit_ = nullptr; - - enum { -#if PPSSPP_ARCH(AMD64) - NUM_X_REGS = 16, - NUM_X_FREGS = 16, -#elif PPSSPP_ARCH(X86) - NUM_X_REGS = 8, - NUM_X_FREGS = 8, -#endif - }; -}; - -#endif diff --git a/Core/MemFault.cpp b/Core/MemFault.cpp index 95a7088ae..fe413d6a2 100644 --- a/Core/MemFault.cpp +++ b/Core/MemFault.cpp @@ -263,15 +263,10 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) { #endif Core_ExecException(targetAddr, currentMIPS->pc, ExecExceptionType::JUMP); // Redirect execution to a crash handler that will switch to CoreState::CORE_RUNTIME_ERROR immediately. - uintptr_t crashHandler = (uintptr_t)MIPSComp::jit->GetCrashHandler(); - if (crashHandler != 0) { - context->CTX_PC = crashHandler; - ERROR_LOG(MEMMAP, "Bad execution access detected, halting: %08x (last known pc %08x, host: %p)", targetAddr, currentMIPS->pc, (void *)hostAddress); - inCrashHandler = false; - return true; - } - - type = MemoryExceptionType::UNKNOWN; + context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler(); + ERROR_LOG(MEMMAP, "Bad execution access detected, halting: %08x (last known pc %08x, host: %p)", targetAddr, currentMIPS->pc, (void *)hostAddress); + inCrashHandler = false; + return true; } else if (success) { if (info.isMemoryWrite) { type = MemoryExceptionType::WRITE_WORD; @@ -308,11 +303,8 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) { g_lastCrashAddress = codePtr; // Redirect execution to a crash handler that will switch to CoreState::CORE_RUNTIME_ERROR immediately. - uintptr_t crashHandler = 0; if (MIPSComp::jit) - crashHandler = (uintptr_t)MIPSComp::jit->GetCrashHandler(); - if (crashHandler != 0) - context->CTX_PC = crashHandler; + context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler(); else handled = false; ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation. Info:\n%s", guestAddress, (void *)hostAddress, infoString.c_str()); diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index f47836dc5..95e86aafc 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -95,7 +95,7 @@ static MemoryView views[] = {&m_pPhysicalRAM[0], 0x08000000, g_MemorySize, MV_IS_PRIMARY_RAM}, // only from 0x08800000 is it usable (last 24 megs) {&m_pUncachedRAM[0], 0x48000000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_PRIMARY_RAM}, {&m_pKernelRAM[0], 0x88000000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_PRIMARY_RAM | MV_KERNEL}, - {&m_pUncachedKernelRAM[0],0xC8000000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_PRIMARY_RAM | MV_KERNEL}, + {&m_pUncachedKernelRAM[0],0xC0000000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_PRIMARY_RAM | MV_KERNEL}, // Starts at memory + 31 MB. {&m_pPhysicalRAM[1], 0x09F00000, g_MemorySize, MV_IS_EXTRA1_RAM}, {&m_pUncachedRAM[1], 0x49F00000, g_MemorySize, MV_MIRROR_PREVIOUS | MV_IS_EXTRA1_RAM}, @@ -187,7 +187,7 @@ bail: SKIP(flags, views[i].flags); if (*views[j].out_ptr) { if (!CanIgnoreView(views[j])) { - g_arena.ReleaseView(0, *views[j].out_ptr, views[j].size); + g_arena.ReleaseView(*views[j].out_ptr, views[j].size); } *views[j].out_ptr = NULL; } @@ -265,24 +265,13 @@ bool MemoryMap_Setup(u32 flags) { } void MemoryMap_Shutdown(u32 flags) { - size_t position = 0; - size_t last_position = 0; - for (int i = 0; i < num_views; i++) { if (views[i].size == 0) continue; SKIP(flags, views[i].flags); - - if (views[i].flags & MV_MIRROR_PREVIOUS) { - position = last_position; - } - if (*views[i].out_ptr) - g_arena.ReleaseView(position, *views[i].out_ptr, views[i].size); + g_arena.ReleaseView(*views[i].out_ptr, views[i].size); *views[i].out_ptr = nullptr; - - last_position = position; - position += g_arena.roundup(views[i].size); } g_arena.ReleaseSpace(); diff --git a/Core/MemMap.h b/Core/MemMap.h index 67e17babc..7a0af4625 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -67,7 +67,7 @@ extern u32 g_PSPModel; // UWP has such limited memory management that we need to mask // even in 64-bit mode. Also, when using the sanitizer, we need to mask as well. -#if PPSSPP_ARCH(32BIT) || PPSSPP_PLATFORM(UWP) || USE_ASAN || PPSSPP_PLATFORM(IOS) || defined(__EMSCRIPTEN__) +#if PPSSPP_ARCH(32BIT) || PPSSPP_PLATFORM(UWP) || USE_ASAN || PPSSPP_PLATFORM(IOS) #define MASKED_PSP_MEMORY #endif diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index 5f89f6031..6f2ceaca6 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -69,12 +69,13 @@ inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, memcpy(to, from, len); if (MemBlockInfoDetailed(len)) { + char tagData[128]; if (!tag) { - NotifyMemInfoCopy(to_address, from_address, len, "Memcpy/"); - } else { - NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); - NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); + tagLen = FormatMemWriteTagAt(tagData, sizeof(tagData), "Memcpy/", from_address, len); + tag = tagData; } + NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); } } diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index d07368bac..c23c29ed4 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -21,7 +21,6 @@ #include "Common/Thread/ThreadUtil.h" #include "Common/System/Request.h" -#include "Common/File/AndroidContentURI.h" #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" #ifdef _WIN32 @@ -306,7 +305,7 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) { //in case we didn't go through EmuScreen::boot g_Config.loadGameConfig(id, g_paramSFO.GetValueString("TITLE")); - System_PostUIMessage(UIMessage::CONFIG_LOADED); + System_PostUIMessage("config_loaded", ""); INFO_LOG(LOADER, "Loading %s...", bootpath.c_str()); PSPLoaders_Shutdown(); @@ -381,10 +380,6 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { std::string path = full_path.GetDirectory(); std::string file = full_path.GetFilename(); - if (full_path.Type() == PathType::CONTENT_URI) { - path = AndroidContentURI(full_path.GetDirectory()).FilePath(); - } - size_t pos = path.find("PSP/GAME/"); std::string ms_path; if (pos != std::string::npos) { @@ -398,11 +393,7 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { if (!PSP_CoreParameter().mountRoot.empty()) { // We don't want to worry about .. and cwd and such. const Path rootNorm = NormalizePath(PSP_CoreParameter().mountRoot); - Path pathNorm = NormalizePath(Path(path)); - - if (full_path.Type() == PathType::CONTENT_URI) { - pathNorm = full_path.NavigateUp(); - } + const Path pathNorm = NormalizePath(Path(path)); // If root is not a subpath of path, we can't boot the game. if (!pathNorm.StartsWith(rootNorm)) { @@ -411,17 +402,10 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { return false; } - std::string filepath; - if (full_path.Type() == PathType::CONTENT_URI) { - std::string rootFilePath = AndroidContentURI(rootNorm.c_str()).FilePath(); - std::string pathFilePath = AndroidContentURI(pathNorm.c_str()).FilePath(); - filepath = pathFilePath.substr(rootFilePath.size()); - } else { - filepath = ReplaceAll(pathNorm.ToString().substr(rootNorm.ToString().size()), "\\", "/"); - } - + // TODO(scoped): This won't work! + const std::string filepath = ReplaceAll(pathNorm.ToString().substr(rootNorm.ToString().size()), "\\", "/"); file = filepath + "/" + file; - path = rootNorm.ToString(); + path = rootNorm.ToString() + "/"; pspFileSystem.SetStartingDirectory(filepath); } else { pspFileSystem.SetStartingDirectory(ms_path); @@ -434,11 +418,6 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { std::string homebrewName = PSP_CoreParameter().fileToStart.ToVisualString(); std::size_t lslash = homebrewName.find_last_of("/"); -#if PPSSPP_PLATFORM(UWP) - if (lslash == homebrewName.npos) { - lslash = homebrewName.find_last_of("\\"); - } -#endif if (lslash != homebrewName.npos) homebrewName = homebrewName.substr(lslash + 1); std::string homebrewTitle = g_paramSFO.GetValueString("TITLE"); diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 172562795..bedcbf8d8 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -24,19 +24,12 @@ #include #include -// for crc32 -extern "C" { -#include "zlib.h" -} - #include "Core/Reporting.h" #include "Common/File/VFS/VFS.h" #include "Common/CPUDetect.h" #include "Common/File/FileUtil.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/StringUtils.h" -#include "Common/System/OSD.h" -#include "Common/Data/Text/I18n.h" #include "Core/Core.h" #include "Core/CoreTiming.h" #include "Core/Config.h" @@ -115,31 +108,6 @@ namespace Reporting static volatile bool crcCancel = false; static std::thread crcThread; - static u32 CalculateCRC(BlockDevice *blockDevice, volatile bool *cancel) { - auto ga = GetI18NCategory(I18NCat::GAME); - - u32 crc = crc32(0, Z_NULL, 0); - - u8 block[2048]; - u32 numBlocks = blockDevice->GetNumBlocks(); - for (u32 i = 0; i < numBlocks; ++i) { - if (cancel && *cancel) { - g_OSD.RemoveProgressBar("crc", false, 0.0f); - return 0; - } - if (!blockDevice->ReadBlock(i, block, true)) { - ERROR_LOG(FILESYS, "Failed to read block for CRC"); - g_OSD.RemoveProgressBar("crc", false, 0.0f); - return 0; - } - crc = crc32(crc, block, 2048); - g_OSD.SetProgressBar("crc", std::string(ga->T("Calculate CRC")), 0.0f, (float)numBlocks, (float)i, 0.5f); - } - - g_OSD.RemoveProgressBar("crc", true, 0.0f); - return crc; - } - static int CalculateCRCThread() { SetCurrentThreadName("ReportCRC"); @@ -150,7 +118,7 @@ namespace Reporting u32 crc = 0; if (blockDevice) { - crc = CalculateCRC(blockDevice, &crcCancel); + crc = blockDevice->CalculateCRC(&crcCancel); } delete blockDevice; @@ -160,7 +128,6 @@ namespace Reporting crcResults[crcFilename] = crc; crcPending = false; crcCond.notify_one(); - return 0; } @@ -305,7 +272,7 @@ namespace Reporting bool SendReportRequest(const char *uri, const std::string &data, const std::string &mimeType, Buffer *output = NULL) { http::Client http; - net::RequestProgress progress(&pendingMessagesDone); + http::RequestProgress progress(&pendingMessagesDone); Buffer theVoid = Buffer::Void(); http.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION)); diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp deleted file mode 100644 index 3478d8fda..000000000 --- a/Core/RetroAchievements.cpp +++ /dev/null @@ -1,911 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-2.0 OR GPL-3.0 OR CC-BY-NC-ND-4.0) - -// Derived from Duckstation's RetroAchievements implementation by stenzek as can be seen -// above, relicensed to GPL 2.0. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ext/rcheevos/include/rcheevos.h" -#include "ext/rcheevos/include/rc_client.h" -#include "ext/rcheevos/include/rc_api_user.h" -#include "ext/rcheevos/include/rc_api_info.h" -#include "ext/rcheevos/include/rc_api_request.h" -#include "ext/rcheevos/include/rc_api_runtime.h" -#include "ext/rcheevos/include/rc_api_user.h" -#include "ext/rcheevos/include/rc_url.h" -#include "ext/rcheevos/include/rc_hash.h" -#include "ext/rcheevos/src/rhash/md5.h" - -#include "ext/rapidjson/include/rapidjson/document.h" - -#include "Common/Log.h" -#include "Common/File/Path.h" -#include "Common/File/FileUtil.h" -#include "Core/FileLoaders/LocalFileLoader.h" -#include "Core/FileSystems/BlockDevices.h" -#include "Common/Net/HTTPClient.h" -#include "Common/System/OSD.h" -#include "Common/System/System.h" -#include "Common/System/NativeApp.h" -#include "Common/TimeUtil.h" -#include "Common/Data/Text/I18n.h" -#include "Common/Serialize/Serializer.h" -#include "Common/Serialize/SerializeFuncs.h" -#include "Common/StringUtils.h" -#include "Common/Crypto/md5.h" -#include "Common/UI/IconCache.h" - -#include "Core/MemMap.h" -#include "Core/Config.h" -#include "Core/CoreParameter.h" -#include "Core/ELF/ParamSFO.h" -#include "Core/System.h" -#include "Core/FileSystems/MetaFileSystem.h" -#include "Core/RetroAchievements.h" - -static inline const char *DeNull(const char *ptr) { - return ptr ? ptr : ""; -} - -void OnAchievementsLoginStateChange() { - System_PostUIMessage(UIMessage::ACHIEVEMENT_LOGIN_STATE_CHANGE); -} - -namespace Achievements { - -// It's the name of the secret, not a secret name - the value is not secret :) -static const char *RA_TOKEN_SECRET_NAME = "retroachievements"; - -static Achievements::Statistics g_stats; - -const std::string g_gameIconCachePrefix = "game:"; -const std::string g_iconCachePrefix = "badge:"; - -Path s_game_path; -std::string s_game_hash; - -std::set g_activeChallenges; -bool g_isIdentifying = false; -bool g_isLoggingIn = false; -int g_loginResult; - -double g_lastLoginAttemptTime; - -// rc_client implementation -static rc_client_t *g_rcClient; -static const std::string g_RAImageID = "I_RETROACHIEVEMENTS_LOGO"; -constexpr double LOGIN_ATTEMPT_INTERVAL_S = 10.0; - -struct FileContext { - BlockDevice *bd; - int64_t seekPos; -}; -static BlockDevice *g_blockDevice; - -#define PSP_MEMORY_OFFSET 0x08000000 - -static void TryLoginByToken(bool isInitialAttempt); - -rc_client_t *GetClient() { - return g_rcClient; -} - -bool IsLoggedIn() { - return rc_client_get_user_info(g_rcClient) != nullptr && !g_isLoggingIn; -} - -bool EncoreModeActive() { - if (!g_rcClient) { - return false; - } - return rc_client_get_encore_mode_enabled(g_rcClient); -} - -bool UnofficialEnabled() { - if (!g_rcClient) { - return false; - } - return rc_client_get_unofficial_enabled(g_rcClient); -} - -bool ChallengeModeActive() { - if (!g_rcClient) { - return false; - } - return IsLoggedIn() && rc_client_get_hardcore_enabled(g_rcClient); -} - -bool WarnUserIfChallengeModeActive(bool isSaveStateAction, const char *message) { - if (!ChallengeModeActive() || (isSaveStateAction && g_Config.bAchievementsSaveStateInChallengeMode)) { - return false; - } - - const char *showMessage = message; - if (!message) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - showMessage = ac->T("This feature is not available in Hardcore Mode"); - } - - g_OSD.Show(OSDType::MESSAGE_WARNING, showMessage, "", g_RAImageID, 3.0f); - return true; -} - -bool IsBlockingExecution() { - if (g_isLoggingIn || g_isIdentifying) { - // Useful for debugging race conditions. - // INFO_LOG(ACHIEVEMENTS, "isLoggingIn: %d isIdentifying: %d", (int)g_isLoggingIn, (int)g_isIdentifying); - } - return g_isLoggingIn || g_isIdentifying; -} - -// This is the RetroAchievements game ID, rather than the PSP game ID. -static u32 GetGameID() { - if (!g_rcClient) { - return 0; - } - - const rc_client_game_t *info = rc_client_get_game_info(g_rcClient); - if (!info) { - return 0; - } - return info->id; // 0 if not identified -} - -bool IsActive() { - return GetGameID() != 0; -} - -static uint32_t read_memory_callback(uint32_t address, uint8_t *buffer, uint32_t num_bytes, rc_client_t *client) { - // Achievements are traditionally defined relative to the base of main memory of the emulated console. - // This is some kind of RetroArch-related legacy. In the PSP's case, this is simply a straight offset of 0x08000000. - uint32_t orig_address = address; - address += PSP_MEMORY_OFFSET; - - if (!Memory::ValidSize(address, num_bytes)) { - // Some achievement packs are really, really spammy. - // So we'll just count the bad accesses. - Achievements::g_stats.badMemoryAccessCount++; - if (g_Config.bAchievementsLogBadMemReads) { - WARN_LOG(G3D, "RetroAchievements PeekMemory: Bad address %08x (%d bytes) (%08x was passed in)", address, num_bytes, orig_address); - } - - // This tells rcheevos that the access was bad, which should now be handled properly. - return 0; - } - - Memory::MemcpyUnchecked(buffer, address, num_bytes); - return num_bytes; -} - -// This is the HTTP request dispatcher that is provided to the rc_client. Whenever the client -// needs to talk to the server, it will call this function. -static void server_call_callback(const rc_api_request_t *request, - rc_client_server_callback_t callback, void *callback_data, rc_client_t *client) -{ - // If post data is provided, we need to make a POST request, otherwise, a GET request will suffice. - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - if (request->post_data) { - std::shared_ptr download = g_DownloadManager.AsyncPostWithCallback(std::string(request->url), std::string(request->post_data), "application/x-www-form-urlencoded", http::ProgressBarMode::DELAYED, [=](http::Request &download) { - std::string buffer; - download.buffer().TakeAll(&buffer); - rc_api_server_response_t response{}; - response.body = buffer.c_str(); - response.body_length = buffer.size(); - response.http_status_code = download.ResultCode(); - callback(&response, callback_data); - }, ac->T("Contacting RetroAchievements server...")); - } else { - std::shared_ptr download = g_DownloadManager.StartDownloadWithCallback(std::string(request->url), Path(), http::ProgressBarMode::DELAYED, [=](http::Request &download) { - std::string buffer; - download.buffer().TakeAll(&buffer); - rc_api_server_response_t response{}; - response.body = buffer.c_str(); - response.body_length = buffer.size(); - response.http_status_code = download.ResultCode(); - callback(&response, callback_data); - }, ac->T("Contacting RetroAchievements server...")); - } -} - -static void log_message_callback(const char *message, const rc_client_t *client) { - INFO_LOG(ACHIEVEMENTS, "RetroAchievements: %s", message); -} - -// For detailed documentation, see https://github.com/RetroAchievements/rcheevos/wiki/rc_client_set_event_handler. -static void event_handler_callback(const rc_client_event_t *event, rc_client_t *client) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - switch (event->type) { - case RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED: - // An achievement was earned by the player. The handler should notify the player that the achievement was earned. - g_OSD.ShowAchievementUnlocked(event->achievement->id); - System_PostUIMessage(UIMessage::REQUEST_PLAY_SOUND, "achievement_unlocked"); - INFO_LOG(ACHIEVEMENTS, "Achievement unlocked: '%s' (%d)", event->achievement->title, event->achievement->id); - break; - - case RC_CLIENT_EVENT_GAME_COMPLETED: - { - // TODO: Do some zany fireworks! - - // All achievements for the game have been earned. The handler should notify the player that the game was completed or mastered, depending on mode, hardcore or not. - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - const rc_client_game_t *gameInfo = rc_client_get_game_info(g_rcClient); - - // TODO: Translation? - std::string title = ApplySafeSubstitutions(ac->T("Mastered %1"), gameInfo->title); - - rc_client_user_game_summary_t summary; - rc_client_get_user_game_summary(g_rcClient, &summary); - - std::string message = ApplySafeSubstitutions(ac->T("%1 achievements, %2 points"), summary.num_unlocked_achievements, summary.points_unlocked); - - g_OSD.Show(OSDType::MESSAGE_INFO, title, message, DeNull(gameInfo->badge_name), 10.0f); - - System_PostUIMessage(UIMessage::REQUEST_PLAY_SOUND, "achievement_unlocked"); - - INFO_LOG(ACHIEVEMENTS, "%s", message.c_str()); - break; - } - case RC_CLIENT_EVENT_LEADERBOARD_STARTED: - case RC_CLIENT_EVENT_LEADERBOARD_FAILED: - { - bool started = event->type == RC_CLIENT_EVENT_LEADERBOARD_STARTED; - // A leaderboard attempt has started. The handler may show a message with the leaderboard title and /or description indicating the attempt started. - const char *title = ""; - const char *description = ""; - // Hack around some problematic events in Burnout Legends. Hopefully this can be fixed in the backend. - if (strlen(event->leaderboard->title) > 0) { - title = event->leaderboard->title; - description = event->leaderboard->description; - } else { - title = event->leaderboard->description; - } - INFO_LOG(ACHIEVEMENTS, "Attempt %s: %s", started ? "started" : "failed", title); - g_OSD.ShowLeaderboardStartEnd(ApplySafeSubstitutions(ac->T(started ? "%1: Attempt started" : "%1: Attempt failed"), title), description, started); - break; - } - case RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED: - { - INFO_LOG(ACHIEVEMENTS, "Leaderboard result submitted: %s", event->leaderboard->title); - const char *title = ""; - // Hack around some problematic events in Burnout Legends. Hopefully this can be fixed in the backend. - if (strlen(event->leaderboard->title) > 0) { - title = event->leaderboard->title; - } else { - title = event->leaderboard->description; - } - g_OSD.ShowLeaderboardSubmitted(ApplySafeSubstitutions(ac->T("Submitted %1 for %2"), DeNull(event->leaderboard->tracker_value), title), ""); - System_PostUIMessage(UIMessage::REQUEST_PLAY_SOUND, "leaderboard_submitted"); - break; - } - case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW: - INFO_LOG(ACHIEVEMENTS, "Challenge indicator show: %s", event->achievement->title); - g_OSD.ShowChallengeIndicator(event->achievement->id, true); - g_activeChallenges.insert(event->achievement->id); - // A challenge achievement has become active. The handler should show a small version of the achievement icon - // to indicate the challenge is active. - break; - case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE: - INFO_LOG(ACHIEVEMENTS, "Challenge indicator hide: %s", event->achievement->title); - g_OSD.ShowChallengeIndicator(event->achievement->id, false); - g_activeChallenges.erase(event->achievement->id); - // The handler should hide the small version of the achievement icon that was shown by the corresponding RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW event. - break; - case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW: - INFO_LOG(ACHIEVEMENTS, "Progress indicator show: %s, progress: '%s' (%f)", event->achievement->title, event->achievement->measured_progress, event->achievement->measured_percent); - // An achievement that tracks progress has changed the amount of progress that has been made. - // The handler should show a small version of the achievement icon along with the achievement->measured_progress text (for two seconds). - // Only one progress indicator should be shown at a time. - // If a progress indicator is already visible, it should be updated with the new icon and text, and the two second timer should be restarted. - g_OSD.ShowAchievementProgress(event->achievement->id, true); - break; - case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE: - INFO_LOG(ACHIEVEMENTS, "Progress indicator update: %s, progress: '%s' (%f)", event->achievement->title, event->achievement->measured_progress, event->achievement->measured_percent); - g_OSD.ShowAchievementProgress(event->achievement->id, true); - break; - case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE: - INFO_LOG(ACHIEVEMENTS, "Progress indicator hide"); - // An achievement that tracks progress has changed the amount of progress that has been made. - // The handler should show a small version of the achievement icon along with the achievement->measured_progress text (for two seconds). - // Only one progress indicator should be shown at a time. - // If a progress indicator is already visible, it should be updated with the new icon and text, and the two second timer should be restarted. - g_OSD.ShowAchievementProgress(0, false); - break; - case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW: - INFO_LOG(ACHIEVEMENTS, "Leaderboard tracker show: '%s' (id %d)", event->leaderboard_tracker->display, event->leaderboard_tracker->id); - // A leaderboard_tracker has become active. The handler should show the tracker text on screen. - // Multiple active leaderboards may share a single tracker if they have the same definition and value. - // As such, the leaderboard tracker IDs are unique amongst the leaderboard trackers, and have no correlation to the active leaderboard(s). - // Use event->leaderboard_tracker->id for uniqueness checks, and display event->leaderboard_tracker->display (string) - g_OSD.ShowLeaderboardTracker(event->leaderboard_tracker->id, event->leaderboard_tracker->display, true); - break; - case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE: - // A leaderboard_tracker has become inactive. The handler should hide the tracker text from the screen. - INFO_LOG(ACHIEVEMENTS, "Leaderboard tracker hide: '%s' (id %d)", event->leaderboard_tracker->display, event->leaderboard_tracker->id); - g_OSD.ShowLeaderboardTracker(event->leaderboard_tracker->id, nullptr, false); - break; - case RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE: - // A leaderboard_tracker value has been updated. The handler should update the tracker text on the screen. - INFO_LOG(ACHIEVEMENTS, "Leaderboard tracker update: '%s' (id %d)", event->leaderboard_tracker->display, event->leaderboard_tracker->id); - g_OSD.ShowLeaderboardTracker(event->leaderboard_tracker->id, event->leaderboard_tracker->display, true); - break; - case RC_CLIENT_EVENT_RESET: - WARN_LOG(ACHIEVEMENTS, "Resetting game due to achievement setting change!"); - // Hardcore mode was enabled, or something else that forces a game reset. - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); - break; - case RC_CLIENT_EVENT_SERVER_ERROR: - ERROR_LOG(ACHIEVEMENTS, "Server error: %s: %s", event->server_error->api, event->server_error->error_message); - g_OSD.Show(OSDType::MESSAGE_ERROR, "Server error", "", g_RAImageID); - break; - default: - WARN_LOG(ACHIEVEMENTS, "Unhandled rc_client event %d, ignoring", event->type); - break; - } -} - -static void login_token_callback(int result, const char *error_message, rc_client_t *client, void *userdata) { - bool isInitialAttempt = userdata != nullptr; - switch (result) { - case RC_OK: - { - INFO_LOG(ACHIEVEMENTS, "Successful login by token."); - OnAchievementsLoginStateChange(); - if (!isInitialAttempt) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - g_OSD.Show(OSDType::MESSAGE_SUCCESS, ac->T("Reconnected to RetroAchievements."), "", g_RAImageID); - } - break; - } - case RC_NO_RESPONSE: - { - if (isInitialAttempt) { - auto di = GetI18NCategory(I18NCat::DIALOG); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Failed to connect to server, check your internet connection."), "", g_RAImageID); - } - break; - } - case RC_ACCESS_DENIED: - case RC_INVALID_CREDENTIALS: - case RC_EXPIRED_TOKEN: - case RC_API_FAILURE: - case RC_INVALID_STATE: - case RC_MISSING_VALUE: - case RC_INVALID_JSON: - default: - { - ERROR_LOG(ACHIEVEMENTS, "Callback: Failure logging in via token: %d, %s", result, error_message); - if (isInitialAttempt) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Failed logging in to RetroAchievements"), "", g_RAImageID); - } - OnAchievementsLoginStateChange(); - break; - } - } - g_loginResult = result; - g_isLoggingIn = false; -} - -void Initialize() { - if (!g_Config.bAchievementsEnable) { - _dbg_assert_(!g_rcClient); - INFO_LOG(ACHIEVEMENTS, "Achievements are disabled, not initializing."); - return; - } - _assert_msg_(!g_rcClient, "Achievements already initialized"); - - g_rcClient = rc_client_create(read_memory_callback, server_call_callback); - if (!g_rcClient) { - // Shouldn't happen really. - return; - } - - // Provide a logging function to simplify debugging - rc_client_enable_logging(g_rcClient, RC_CLIENT_LOG_LEVEL_VERBOSE, log_message_callback); - - if (!System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) { - // Disable SSL if not supported by our platform implementation. - rc_client_set_host(g_rcClient, "http://retroachievements.org"); - } - - rc_client_set_event_handler(g_rcClient, event_handler_callback); - - rc_hash_filereader rc_filereader; - rc_filereader.open = [](const char *utf8Path) -> void *{ - if (!g_blockDevice) { - ERROR_LOG(ACHIEVEMENTS, "No block device"); - return nullptr; - } - - return (void *) new FileContext{ g_blockDevice, 0 }; - }; - rc_filereader.seek = [](void *file_handle, int64_t offset, int origin) { - FileContext *ctx = (FileContext *)file_handle; - switch (origin) { - case SEEK_SET: ctx->seekPos = offset; break; - case SEEK_END: ctx->seekPos = ctx->bd->GetBlockSize() * ctx->bd->GetNumBlocks() + offset; break; - case SEEK_CUR: ctx->seekPos += offset; break; - default: break; - } - }; - rc_filereader.tell = [](void *file_handle) -> int64_t { - return ((FileContext *)file_handle)->seekPos; - }; - rc_filereader.read = [](void *file_handle, void *buffer, size_t requested_bytes) -> size_t { - FileContext *ctx = (FileContext *)file_handle; - - int blockSize = ctx->bd->GetBlockSize(); - - int64_t offset = ctx->seekPos; - int64_t endOffset = ctx->seekPos + requested_bytes; - int firstBlock = offset / blockSize; - int afterLastBlock = (endOffset + blockSize - 1) / blockSize; - int numBlocks = afterLastBlock - firstBlock; - // This is suboptimal, but good enough since we're not doing a lot of accesses. - uint8_t *buf = new uint8_t[numBlocks * blockSize]; - bool success = ctx->bd->ReadBlocks(firstBlock, numBlocks, (u8 *)buf); - if (success) { - int64_t firstOffset = firstBlock * blockSize; - memcpy(buffer, buf + (offset - firstOffset), requested_bytes); - ctx->seekPos += requested_bytes; - delete[] buf; - return requested_bytes; - } else { - delete[] buf; - ERROR_LOG(ACHIEVEMENTS, "Block device load fail"); - return 0; - } - }; - rc_filereader.close = [](void *file_handle) { - FileContext *ctx = (FileContext *)file_handle; - delete ctx->bd; - delete ctx; - }; - rc_hash_init_custom_filereader(&rc_filereader); - rc_hash_init_default_cdreader(); - - TryLoginByToken(true); -} - -bool HasToken() { - return !NativeLoadSecret(RA_TOKEN_SECRET_NAME).empty(); -} - -bool LoginProblems(std::string *errorString) { - // TODO: Set error string. - return g_loginResult != RC_OK; -} - -static void TryLoginByToken(bool isInitialAttempt) { - if (g_Config.sAchievementsUserName.empty()) { - // Don't even look for a token - without a username we can't login. - return; - } - std::string api_token = NativeLoadSecret(RA_TOKEN_SECRET_NAME); - if (!api_token.empty()) { - g_isLoggingIn = true; - rc_client_begin_login_with_token(g_rcClient, g_Config.sAchievementsUserName.c_str(), api_token.c_str(), &login_token_callback, (void *)isInitialAttempt); - } -} - -static void login_password_callback(int result, const char *error_message, rc_client_t *client, void *userdata) { - auto di = GetI18NCategory(I18NCat::DIALOG); - switch (result) { - case RC_OK: - { - // Get the token and store it. - const rc_client_user_t *user = rc_client_get_user_info(client); - g_Config.sAchievementsUserName = user->username; - NativeSaveSecret(RA_TOKEN_SECRET_NAME, std::string(user->token)); - OnAchievementsLoginStateChange(); - g_OSD.Show(OSDType::MESSAGE_SUCCESS, di->T("Logged in!"), "", g_RAImageID); - break; - } - case RC_NO_RESPONSE: - { - auto di = GetI18NCategory(I18NCat::DIALOG); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Failed to connect to server, check your internet connection."), "", g_RAImageID); - break; - } - case RC_INVALID_STATE: - case RC_API_FAILURE: - case RC_MISSING_VALUE: - case RC_INVALID_JSON: - case RC_ACCESS_DENIED: - case RC_INVALID_CREDENTIALS: - case RC_EXPIRED_TOKEN: - default: - { - ERROR_LOG(ACHIEVEMENTS, "Failure logging in via password: %d, %s", result, error_message); - g_OSD.Show(OSDType::MESSAGE_WARNING, di->T("Failed to log in, check your username and password."), "", g_RAImageID); - OnAchievementsLoginStateChange(); - break; - } - } - - g_OSD.RemoveProgressBar("cheevos_async_login", true, 0.1f); - g_loginResult = RC_OK; // For these, we don't want the "permanence" of the login-by-token failure, this prevents LoginProblems from returning true. - g_isLoggingIn = false; -} - -bool LoginAsync(const char *username, const char *password) { - auto di = GetI18NCategory(I18NCat::DIALOG); - if (IsLoggedIn() || std::strlen(username) == 0 || std::strlen(password) == 0 || IsUsingRAIntegration()) - return false; - - g_OSD.SetProgressBar("cheevos_async_login", di->T("Logging in..."), 0, 0, 0, 0.0f); - - g_isLoggingIn = true; - rc_client_begin_login_with_password(g_rcClient, username, password, &login_password_callback, nullptr); - return true; -} - -void Logout() { - rc_client_logout(g_rcClient); - // remove from config - g_Config.sAchievementsUserName.clear(); - NativeSaveSecret(RA_TOKEN_SECRET_NAME, ""); - g_Config.Save("Achievements logout"); - g_activeChallenges.clear(); - g_loginResult = RC_OK; // Allow trying again - OnAchievementsLoginStateChange(); -} - -void UpdateSettings() { - if (g_rcClient && !g_Config.bAchievementsEnable) { - // we're done here - Shutdown(); - return; - } - - if (!g_rcClient && g_Config.bAchievementsEnable) { - // we just got enabled. - Initialize(); - } -} - -bool Shutdown() { - g_activeChallenges.clear(); - rc_client_destroy(g_rcClient); - g_rcClient = nullptr; - INFO_LOG(ACHIEVEMENTS, "Achievements shut down."); - return true; -} - -void ResetRuntime() { - INFO_LOG(ACHIEVEMENTS, "Resetting rcheevos state..."); - rc_client_reset(g_rcClient); - g_activeChallenges.clear(); -} - -void FrameUpdate() { - if (!g_rcClient) - return; - rc_client_do_frame(g_rcClient); -} - -void Idle() { - rc_client_idle(g_rcClient); - - double now = time_now_d(); - - // If failed to log in, occasionally try again while the user is at the menu. - // Do not try if if in-game, that could get confusing. - if (g_Config.bAchievementsEnable && GetUIState() == UISTATE_MENU && now > g_lastLoginAttemptTime + LOGIN_ATTEMPT_INTERVAL_S) { - g_lastLoginAttemptTime = now; - if (g_rcClient && IsLoggedIn()) { - return; // All good. - } - if (g_Config.sAchievementsUserName.empty() || g_isLoggingIn || !HasToken()) { - // Didn't try to login yet or is in the process of logging in. Also OK. - return; - } - - // In this situation, there's a token, but we're not logged in. Probably disrupted internet connection - // during startup. - // Let's make an attempt. - INFO_LOG(ACHIEVEMENTS, "Retrying login.."); - TryLoginByToken(false); - } -} - -void DoState(PointerWrap &p) { - auto sw = p.Section("Achievements", 0, 1); - if (!sw) { - // Save state is missing the section. - // Reset the runtime. - if (HasAchievementsOrLeaderboards()) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Save state loaded without achievement data"), "", g_RAImageID, 5.0f, ""); - } - rc_client_reset(g_rcClient); - return; - } - - uint32_t data_size = 0; - - if (!IsActive()) { - Do(p, data_size); - if (p.mode == PointerWrap::MODE_READ) { - WARN_LOG(ACHIEVEMENTS, "Save state contained achievement data, but achievements are not active. Ignore."); - } - p.SkipBytes(data_size); - return; - } - - if (p.mode == PointerWrap::MODE_MEASURE || p.mode == PointerWrap::MODE_WRITE || p.mode == PointerWrap::MODE_VERIFY || p.mode == PointerWrap::MODE_NOOP) { - data_size = (uint32_t)(g_rcClient ? rc_client_progress_size(g_rcClient) : 0); - } - Do(p, data_size); - - if (data_size > 0) { - uint8_t *buffer = new uint8_t[data_size]; - switch (p.mode) { - case PointerWrap::MODE_NOOP: - case PointerWrap::MODE_MEASURE: - case PointerWrap::MODE_WRITE: - case PointerWrap::MODE_VERIFY: - { - int retval = rc_client_serialize_progress(g_rcClient, buffer); - if (retval != RC_OK) { - ERROR_LOG(ACHIEVEMENTS, "Error %d serializing achievement data. Ignoring.", retval); - } - break; - } - default: - break; - } - - DoArray(p, buffer, data_size); - - switch (p.mode) { - case PointerWrap::MODE_READ: - { - int retval = rc_client_deserialize_progress(g_rcClient, buffer); - if (retval != RC_OK) { - // TODO: What should we really do here? - ERROR_LOG(ACHIEVEMENTS, "Error %d deserializing achievement data. Ignoring.", retval); - } - break; - } - default: - break; - } - delete[] buffer; - } else { - if (IsActive()) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Save state loaded without achievement data"), "", g_RAImageID, 5.0f); - } - rc_client_reset(g_rcClient); - } -} - -bool HasAchievementsOrLeaderboards() { - if (!g_rcClient) { - return false; - } - return IsActive(); -} - -void DownloadImageIfMissing(const std::string &cache_key, std::string &&url) { - if (g_iconCache.MarkPending(cache_key)) { - INFO_LOG(ACHIEVEMENTS, "Downloading image: %s (%s)", url.c_str(), cache_key.c_str()); - g_DownloadManager.StartDownloadWithCallback(url, Path(), http::ProgressBarMode::NONE, [cache_key](http::Request &download) { - if (download.ResultCode() != 200) - return; - std::string data; - download.buffer().TakeAll(&data); - g_iconCache.InsertIcon(cache_key, IconFormat::PNG, std::move(data)); - }); - } -} - -Statistics GetStatistics() { - return g_stats; -} - -std::string GetGameAchievementSummary() { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - rc_client_user_game_summary_t summary; - rc_client_get_user_game_summary(g_rcClient, &summary); - - std::string summaryString; - if (summary.num_core_achievements + summary.num_unofficial_achievements == 0) { - summaryString = ac->T("This game has no achievements"); - } else { - summaryString = ApplySafeSubstitutions(ac->T("Earned", "You have unlocked %1 of %2 achievements, earning %3 of %4 points"), - summary.num_unlocked_achievements, summary.num_core_achievements + summary.num_unofficial_achievements, - summary.points_unlocked, summary.points_core); - if (ChallengeModeActive()) { - summaryString.append("\n"); - summaryString.append(ac->T("Hardcore Mode")); - } - if (EncoreModeActive()) { - summaryString.append("\n"); - summaryString.append(ac->T("Encore Mode")); - } - if (UnofficialEnabled()) { - summaryString.append("\n"); - summaryString.append(ac->T("Unofficial achievements")); - } - } - return summaryString; -} - -// Can happen two ways. -void ShowNotLoggedInMessage() { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - g_OSD.Show(OSDType::MESSAGE_ERROR, ac->T("Failed to connect to RetroAchievements. Achievements will not unlock."), "", g_RAImageID, 6.0f); -} - -void identify_and_load_callback(int result, const char *error_message, rc_client_t *client, void *userdata) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - NOTICE_LOG(ACHIEVEMENTS, "Load callback: %d (%s)", result, error_message); - - switch (result) { - case RC_OK: - { - // Successful! Show a message that we're active. - const rc_client_game_t *gameInfo = rc_client_get_game_info(client); - - char cacheId[128]; - snprintf(cacheId, sizeof(cacheId), "gi:%s", gameInfo->badge_name); - - char temp[512]; - if (RC_OK == rc_client_game_get_image_url(gameInfo, temp, sizeof(temp))) { - Achievements::DownloadImageIfMissing(cacheId, std::string(temp)); - } - g_OSD.Show(OSDType::MESSAGE_INFO, std::string(gameInfo->title), GetGameAchievementSummary(), cacheId, 5.0f); - break; - } - case RC_NO_GAME_LOADED: - // The current game does not support achievements. - g_OSD.Show(OSDType::MESSAGE_INFO, ac->T("RetroAchievements are not available for this game"), "", g_RAImageID, 3.0f); - break; - case RC_NO_RESPONSE: - // We lost the internet connection at some point and can't report achievements. - ShowNotLoggedInMessage(); - break; - default: - // Other various errors. - ERROR_LOG(ACHIEVEMENTS, "Failed to identify/load game: %d (%s)", result, error_message); - g_OSD.Show(OSDType::MESSAGE_ERROR, ac->T("Failed to identify game. Achievements will not unlock."), "", g_RAImageID, 6.0f); - break; - } - - g_isIdentifying = false; -} - -bool IsReadyToStart() { - return !g_isLoggingIn; -} - -void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoader) { - switch (fileType) { - case IdentifiedFileType::PSP_ISO: - case IdentifiedFileType::PSP_ISO_NP: - // These file types are OK. - break; - default: - // Other file types are not yet supported. - // TODO: Should we show an OSD popup here? - WARN_LOG(ACHIEVEMENTS, "File type of '%s' is not yet compatible with RetroAchievements", path.c_str()); - return; - } - - if (g_isLoggingIn) { - // IsReadyToStart should have been checked the same frame, so we shouldn't be here. - // Maybe there's a race condition possible, but don't think so. - ERROR_LOG(ACHIEVEMENTS, "Still logging in during SetGame - shouldn't happen"); - } - - if (!g_rcClient || !IsLoggedIn()) { - if (g_Config.bAchievementsEnable && HasToken()) { - ShowNotLoggedInMessage(); - } - // Nothing to do. - return; - } - - _dbg_assert_(!g_blockDevice); - - // TODO: Fish the block device out of the loading process somewhere else. Though, probably easier to just do it here. - g_blockDevice = constructBlockDevice(fileLoader); - if (!g_blockDevice) { - ERROR_LOG(ACHIEVEMENTS, "Failed to construct block device for '%s' - can't identify", path.c_str()); - return; - } - - // The caller should hold off on executing game code until this turns false, checking with IsBlockingExecution() - g_isIdentifying = true; - - // Apply pre-load settings. - rc_client_set_hardcore_enabled(g_rcClient, g_Config.bAchievementsChallengeMode ? 1 : 0); - rc_client_set_encore_mode_enabled(g_rcClient, g_Config.bAchievementsEncoreMode ? 1 : 0); - rc_client_set_unofficial_enabled(g_rcClient, g_Config.bAchievementsUnofficial ? 1 : 0); - - rc_client_begin_identify_and_load_game(g_rcClient, RC_CONSOLE_PSP, path.c_str(), nullptr, 0, &identify_and_load_callback, nullptr); - - // fclose above will have deleted it. - g_blockDevice = nullptr; -} - -void UnloadGame() { - if (g_rcClient) { - rc_client_unload_game(g_rcClient); - } -} - -void change_media_callback(int result, const char *error_message, rc_client_t *client, void *userdata) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - NOTICE_LOG(ACHIEVEMENTS, "Change media callback: %d (%s)", result, error_message); - g_isIdentifying = false; - - switch (result) { - case RC_OK: - { - // Successful! Later, show a message that we succeeded. - break; - } - case RC_NO_GAME_LOADED: - // The current game does not support achievements. - g_OSD.Show(OSDType::MESSAGE_INFO, ac->T("RetroAchievements are not available for this game"), "", g_RAImageID, 3.0f); - break; - case RC_NO_RESPONSE: - // We lost the internet connection at some point and can't report achievements. - ShowNotLoggedInMessage(); - break; - default: - // Other various errors. - ERROR_LOG(ACHIEVEMENTS, "Failed to identify/load game: %d (%s)", result, error_message); - g_OSD.Show(OSDType::MESSAGE_ERROR, ac->T("Failed to identify game. Achievements will not unlock."), "", g_RAImageID, 6.0f); - break; - } -} - -void ChangeUMD(const Path &path, FileLoader *fileLoader) { - if (!IsActive()) { - // Nothing to do. - return; - } - - g_blockDevice = constructBlockDevice(fileLoader); - if (!g_blockDevice) { - ERROR_LOG(ACHIEVEMENTS, "Failed to construct block device for '%s' - can't identify", path.c_str()); - return; - } - - g_isIdentifying = true; - - rc_client_begin_change_media(g_rcClient, - path.c_str(), - nullptr, - 0, - &change_media_callback, - nullptr - ); - - // fclose above will have deleted it. - g_blockDevice = nullptr; -} - -std::set GetActiveChallengeIDs() { - return g_activeChallenges; -} - -} // namespace Achievements diff --git a/Core/RetroAchievements.h b/Core/RetroAchievements.h deleted file mode 100644 index 083570377..000000000 --- a/Core/RetroAchievements.h +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-2.0 OR GPL-3.0 OR CC-BY-NC-ND-4.0) - -// Derived from Duckstation's RetroAchievements implementation by stenzek as can be seen -// above, relicensed to GPL 2.0. -// Modifications and deletions have been made where needed. -// Refactoring it into a more PPSSPP-like style may or may not be a good idea - -// it'll make it harder to copy new achievement features from Duckstation. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "Common/StringUtils.h" -#include "Common/CommonTypes.h" -#include "Core/Loaders.h" // for IdentifiedFileType - -#include "ext/rcheevos/include/rc_client.h" - -class Path; -class PointerWrap; -class FileLoader; - -namespace Achievements { - -struct Statistics { - // Debug stats - int badMemoryAccessCount; -}; - -// RAIntegration only exists for Windows, so no point checking it on other platforms. -#ifdef WITH_RAINTEGRATION - -bool IsUsingRAIntegration(); - -#else - -static inline bool IsUsingRAIntegration() -{ - return false; -} - -#endif - -// Returns true if the user is logged in properly, and everything is set up for playing games with achievements. -bool IsLoggedIn(); - -// Returns true if in a game, and achievements are active in the current game. -bool IsActive(); - -// Returns true if unofficial achievements are enabled. -bool UnofficialEnabled(); - -// Returns true if encore-mode is active. -bool EncoreModeActive(); - -// Returns true if the emulator should hold off on executing game code, such as during game identification. -bool IsBlockingExecution(); - -// Returns true if features such as save states should be disabled. -// This should only be used for controlling functionality of the following things, which are banned in Challenge/Hardcore mode: -// -// * Savestates -// * Slowdown time (though hard to fully prevent, could use crazy post shaders or software rendering...) -bool ChallengeModeActive(); - -// Same as ChallengeModeActive but comes with a convenient user message. Don't use for every-frame checks or UI enablement, -// only for shortcut keys and commands. You should look up the message in I18NCat::ACHIEVEMENTS. -// If no message is specified, a standard "This feature is not available in Hardcore Mode" message will be shown. -// Also returns true if hardcore mode is active. -// Specify isSaveAction so we can still permit saves (but not loads) in hardcore mode if that option is enabled. -bool WarnUserIfChallengeModeActive(bool isSaveStateAction, const char *message = nullptr); - -// The new API is so much nicer that we can use it directly instead of wrapping it. So let's expose the client. -// Will of course return nullptr if not active. -rc_client_t *GetClient(); - -void Initialize(); -void UpdateSettings(); - -bool LoginProblems(std::string *errorString); -bool HasToken(); - -/// Called when the system is being shut down. If Shutdown() returns false, the shutdown should be aborted if possible. -bool Shutdown(); - -void DownloadImageIfMissing(const std::string &cache_key, std::string &&url); - -/// Called once a frame at vsync time on the CPU thread, during gameplay. -void FrameUpdate(); - -/// Called every frame to let background processing happen. -void Idle(); - -/// Saves/loads state. -void DoState(PointerWrap &p); - -/// Returns true if the current game has any achievements or leaderboards. -bool HasAchievementsOrLeaderboards(); - -bool LoginAsync(const char *username, const char *password); -void Logout(); - -bool IsReadyToStart(); -void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoader); -void ChangeUMD(const Path &path, FileLoader *fileLoader); // for in-game UMD change -void UnloadGame(); // Call when leaving a game. - -Statistics GetStatistics(); - -std::string GetGameAchievementSummary(); - -std::set GetActiveChallengeIDs(); - -} // namespace Achievements diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 9d59730d4..08f5052bd 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -47,7 +47,6 @@ #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/JitCommon/JitBlockCache.h" -#include "Core/RetroAchievements.h" #include "HW/MemoryStick.h" #include "GPU/GPUState.h" @@ -392,22 +391,12 @@ namespace SaveState currentMIPS->DoState(p); HLEDoState(p); __KernelDoState(p); - Achievements::DoState(p); // Kernel object destructors might close open files, so do the filesystem last. pspFileSystem.DoState(p); } void Enqueue(SaveState::Operation op) { - if (Achievements::ChallengeModeActive()) { - if (g_Config.bAchievementsSaveStateInChallengeMode && (op.type == SaveState::SAVESTATE_SAVE) || (op.type == SAVESTATE_SAVE_SCREENSHOT)) { - // We allow saving in hardcore mode if this setting is on. - } else { - // Operation not allowed - return; - } - } - std::lock_guard guard(mutex); pending.push_back(op); @@ -536,11 +525,6 @@ namespace SaveState return g_Config.iCurrentStateSlot; } - void PrevSlot() - { - g_Config.iCurrentStateSlot = (g_Config.iCurrentStateSlot - 1 + NUM_SLOTS) % NUM_SLOTS; - } - void NextSlot() { g_Config.iCurrentStateSlot = (g_Config.iCurrentStateSlot + 1) % NUM_SLOTS; @@ -884,12 +868,12 @@ namespace SaveState // Sometimes this exposes game bugs that were rarely seen on real devices, // because few people played on a real PSP for 10 hours straight. callbackMessage = sc->T("Loaded. Save in game, restart, and load for less bugs."); - return Status::SUCCESS; + return Status::WARNING; } if (IsOldVersion()) { // Save states also preserve bugs from old PPSSPP versions, so warn. callbackMessage = sc->T("Loaded. Save in game, restart, and load for less bugs."); - return Status::SUCCESS; + return Status::WARNING; } // If the loaded state (saveDataGeneration) is older, the game may prevent saving again. // This can happen with newer too, but ignore to/from 0 as a common likely safe case. diff --git a/Core/SaveState.h b/Core/SaveState.h index d7bd484c5..274052fed 100644 --- a/Core/SaveState.h +++ b/Core/SaveState.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - #include #include #include @@ -45,7 +43,6 @@ namespace SaveState void Shutdown(); // Cycle through the 5 savestate slots - void PrevSlot(); void NextSlot(); void SaveSlot(const Path &gameFilename, int slot, Callback callback, void *cbUserData = 0); void LoadSlot(const Path &gameFilename, int slot, Callback callback, void *cbUserData = 0); diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 6bb52cab0..492ffab35 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -359,8 +359,8 @@ bool TakeGameScreenshot(const Path &filename, ScreenshotFormat fmt, ScreenshotTy return false; } + u8 *flipbuffer = nullptr; if (success) { - u8 *flipbuffer = nullptr; const u8 *buffer = ConvertBufferToScreenshot(buf, false, flipbuffer, w, h); success = buffer != nullptr; if (success) { @@ -371,13 +371,12 @@ bool TakeGameScreenshot(const Path &filename, ScreenshotFormat fmt, ScreenshotTy success = Save888RGBScreenshot(filename, fmt, buffer, w, h); } - delete[] flipbuffer; } + delete [] flipbuffer; if (!success) { ERROR_LOG(IO, "Failed to write screenshot."); } - return success; } diff --git a/Core/System.cpp b/Core/System.cpp index 0c7bf42fb..fc4d207fd 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -43,7 +43,6 @@ #include "Common/TimeUtil.h" #include "Common/GraphicsContext.h" -#include "Core/RetroAchievements.h" #include "Core/MemFault.h" #include "Core/HDRemaster.h" #include "Core/MIPS/MIPS.h" @@ -73,7 +72,6 @@ #include "GPU/GPUState.h" #include "GPU/GPUInterface.h" #include "GPU/Debugger/RecordFormat.h" -#include "Core/RetroAchievements.h" enum CPUThreadState { CPU_THREAD_NOT_RUNNING, @@ -91,7 +89,7 @@ MetaFileSystem pspFileSystem; ParamSFOData g_paramSFO; static GlobalUIState globalUIState; CoreParameter g_CoreParameter; -static FileLoader *g_loadedFile; +static FileLoader *loadedFile; // For background loading thread. static std::mutex loadingLock; // For loadingReason updates. @@ -236,7 +234,7 @@ bool DiscIDFromGEDumpPath(const Path &path, FileLoader *fileLoader, std::string } } -bool CPU_Init(std::string *errorString, FileLoader *loadedFile) { +bool CPU_Init(std::string *errorString) { coreState = CORE_POWERUP; currentMIPS = &mipsr4k; @@ -251,6 +249,12 @@ bool CPU_Init(std::string *errorString, FileLoader *loadedFile) { Memory::g_PSPModel = g_Config.iPSPModel; Path filename = g_CoreParameter.fileToStart; + loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename)); +#if PPSSPP_ARCH(AMD64) + if (g_Config.bCacheFullIsoInRam) { + loadedFile = new RamCachingFileLoader(loadedFile); + } +#endif IdentifiedFileType type = Identify_File(loadedFile, errorString); @@ -324,7 +328,6 @@ bool CPU_Init(std::string *errorString, FileLoader *loadedFile) { // If they shut down early, we'll catch it when load completes. // Note: this may return before init is complete, which is checked if CPU_IsReady(). - g_loadedFile = loadedFile; if (!LoadFile(&loadedFile, &g_CoreParameter.errorString)) { CPU_Shutdown(); g_CoreParameter.fileToStart.clear(); @@ -369,8 +372,8 @@ void CPU_Shutdown() { Memory::Shutdown(); HLEPlugins::Shutdown(); - delete g_loadedFile; - g_loadedFile = nullptr; + delete loadedFile; + loadedFile = nullptr; delete g_CoreParameter.mountIsoLoader; delete g_symbolMap; @@ -381,8 +384,8 @@ void CPU_Shutdown() { // TODO: Maybe loadedFile doesn't even belong here... void UpdateLoadedFile(FileLoader *fileLoader) { - delete g_loadedFile; - g_loadedFile = fileLoader; + delete loadedFile; + loadedFile = fileLoader; } void Core_UpdateState(CoreState newState) { @@ -419,10 +422,6 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { return false; } - if (!Achievements::IsReadyToStart()) { - return false; - } - #if defined(_WIN32) && PPSSPP_ARCH(AMD64) NOTICE_LOG(BOOT, "PPSSPP %s Windows 64 bit", PPSSPP_GIT_VERSION); #elif defined(_WIN32) && !PPSSPP_ARCH(AMD64) @@ -441,23 +440,7 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { pspIsIniting = true; PSP_SetLoading("Loading game..."); - Path filename = g_CoreParameter.fileToStart; - FileLoader *loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename)); -#if PPSSPP_ARCH(AMD64) - if (g_Config.bCacheFullIsoInRam) { - loadedFile = new RamCachingFileLoader(loadedFile); - } -#endif - - if (g_Config.bAchievementsEnable) { - // Need to re-identify after ResolveFileLoaderTarget - although in practice probably not, - // but also, re-using the identification would require some plumbing, to be done later. - std::string errorString; - IdentifiedFileType type = Identify_File(loadedFile, &errorString); - Achievements::SetGame(filename, type, loadedFile); - } - - if (!CPU_Init(&g_CoreParameter.errorString, loadedFile)) { + if (!CPU_Init(&g_CoreParameter.errorString)) { *error_string = g_CoreParameter.errorString; if (error_string->empty()) { *error_string = "Failed initializing CPU/Memory"; @@ -493,10 +476,7 @@ bool PSP_InitUpdate(std::string *error_string) { } bool success = !g_CoreParameter.fileToStart.empty(); - if (!g_CoreParameter.errorString.empty()) { - *error_string = g_CoreParameter.errorString; - } - + *error_string = g_CoreParameter.errorString; if (success && gpu == nullptr) { PSP_SetLoading("Starting graphics..."); Draw::DrawContext *draw = g_CoreParameter.graphicsContext ? g_CoreParameter.graphicsContext->GetDrawContext() : nullptr; @@ -554,8 +534,6 @@ bool PSP_IsQuitting() { } void PSP_Shutdown() { - Achievements::UnloadGame(); - // Do nothing if we never inited. if (!pspIsInited && !pspIsIniting && !pspIsQuitting) { return; @@ -714,42 +692,84 @@ Path GetSysDirectory(PSPDirectories directoryType) { } } -bool CreateSysDirectories() { -#if PPSSPP_PLATFORM(ANDROID) - const bool createNoMedia = true; -#else - const bool createNoMedia = false; -#endif +#if PPSSPP_PLATFORM(WINDOWS) +// Run this at startup time. Please use GetSysDirectory if you need to query where folders are. +void InitSysDirectories() { + if (!g_Config.memStickDirectory.empty() && !g_Config.flash0Directory.empty()) + return; - Path pspDir = GetSysDirectory(DIRECTORY_PSP); - INFO_LOG(IO, "Creating '%s' and subdirs:", pspDir.c_str()); - File::CreateDir(pspDir); - if (!File::Exists(pspDir)) { - INFO_LOG(IO, "Not a workable memstick directory. Giving up"); - return false; + const Path &path = File::GetExeDirectory(); + + // Mount a filesystem + g_Config.flash0Directory = path / "assets/flash0"; + + // Detect the "My Documents"(XP) or "Documents"(on Vista/7/8) folder. +#if PPSSPP_PLATFORM(UWP) + // We set g_Config.memStickDirectory outside. + +#else + // Caller sets this to the Documents folder. + const Path rootMyDocsPath = g_Config.internalDataDirectory; + const Path myDocsPath = rootMyDocsPath / "PPSSPP"; + const Path installedFile = path / "installed.txt"; + const bool installed = File::Exists(installedFile); + + // If installed.txt exists(and we can determine the Documents directory) + if (installed && !rootMyDocsPath.empty()) { + FILE *fp = File::OpenCFile(installedFile, "rt"); + if (fp) { + char temp[2048]; + char *tempStr = fgets(temp, sizeof(temp), fp); + // Skip UTF-8 encoding bytes if there are any. There are 3 of them. + if (tempStr && strncmp(tempStr, "\xEF\xBB\xBF", 3) == 0) { + tempStr += 3; + } + std::string tempString = tempStr ? tempStr : ""; + if (!tempString.empty() && tempString.back() == '\n') + tempString.resize(tempString.size() - 1); + + g_Config.memStickDirectory = Path(tempString); + fclose(fp); + } + + // Check if the file is empty first, before appending the slash. + if (g_Config.memStickDirectory.empty()) + g_Config.memStickDirectory = myDocsPath; + } else { + g_Config.memStickDirectory = path / "memstick"; } + // Create the memstickpath before trying to write to it, and fall back on Documents yet again + // if we can't make it. + if (!File::Exists(g_Config.memStickDirectory)) { + if (!File::CreateDir(g_Config.memStickDirectory)) + g_Config.memStickDirectory = myDocsPath; + INFO_LOG(COMMON, "Memstick directory not present, creating at '%s'", g_Config.memStickDirectory.c_str()); + } + + Path testFile = g_Config.memStickDirectory / "_writable_test.$$$"; + + // If any directory is read-only, fall back to the Documents directory. + // We're screwed anyway if we can't write to Documents, or can't detect it. + if (!File::CreateEmptyFile(testFile)) + g_Config.memStickDirectory = myDocsPath; + + // Clean up our mess. + if (File::Exists(testFile)) + File::Delete(testFile); +#endif + // Create the default directories that a real PSP creates. Good for homebrew so they can // expect a standard environment. Skipping THEME though, that's pointless. - static const PSPDirectories sysDirs[] = { - DIRECTORY_CHEATS, - DIRECTORY_SAVEDATA, - DIRECTORY_SAVESTATE, - DIRECTORY_GAME, - DIRECTORY_SYSTEM, - DIRECTORY_TEXTURES, - DIRECTORY_PLUGINS, - DIRECTORY_CACHE, - }; + File::CreateDir(GetSysDirectory(DIRECTORY_PSP)); + File::CreateDir(GetSysDirectory(DIRECTORY_PSP) / "COMMON"); + File::CreateDir(GetSysDirectory(DIRECTORY_GAME)); + File::CreateDir(GetSysDirectory(DIRECTORY_SAVEDATA)); + File::CreateDir(GetSysDirectory(DIRECTORY_SAVESTATE)); + File::CreateDir(GetSysDirectory(DIRECTORY_SYSTEM)); - for (auto dir : sysDirs) { - Path path = GetSysDirectory(dir); - File::CreateFullPath(path); - if (createNoMedia) { - // Create a nomedia file in each specified subdirectory. - File::CreateEmptyFile(path / ".nomedia"); - } + if (g_Config.currentDirectory.empty()) { + g_Config.currentDirectory = GetSysDirectory(DIRECTORY_GAME); } - - return true; } +#endif diff --git a/Core/System.h b/Core/System.h index c6bc27ffc..c90b84054 100644 --- a/Core/System.h +++ b/Core/System.h @@ -106,7 +106,9 @@ void UpdateLoadedFile(FileLoader *fileLoader); // they are not stored anywhere. Path GetSysDirectory(PSPDirectories directoryType); -bool CreateSysDirectories(); +#ifdef _WIN32 +void InitSysDirectories(); +#endif // RUNNING must be at 0, NEXTFRAME must be at 1. enum CoreState { diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 63003d47f..9b4bdecda 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -19,12 +19,6 @@ static u32 tiltButtonsDown = 0; float rawTiltAnalogX; float rawTiltAnalogY; -float g_currentYAngle = 0.0f; - -float GetCurrentYAngle() { - return g_currentYAngle; -} - // These functions generate tilt events given the current Tilt amount, // and the deadzone radius. void GenerateAnalogStickEvent(float analogX, float analogY); @@ -35,11 +29,8 @@ void GenerateTriggerButtonEvent(int digitalX, int digitalY); // deadzone is normalized - 0 to 1 // sensitivity controls how fast the deadzone reaches max value inline float ApplyDeadzone(float x, float deadzone) { - if (deadzone >= 0.99f) { - // Meaningless, and not reachable with normal controls. - return x; - } const float factor = 1.0f / (1.0f - deadzone); + if (x > deadzone) { return (x - deadzone) * factor + deadzone; } else if (x < -deadzone) { @@ -49,26 +40,6 @@ inline float ApplyDeadzone(float x, float deadzone) { } } -// Also clamps to -1.0..1.0. -// This applies a (circular if desired) inverse deadzone. -inline void ApplyInverseDeadzone(float x, float y, float *outX, float *outY, float inverseDeadzone, bool circular) { - if (inverseDeadzone == 0.0f) { - *outX = Clamp(x, -1.0f, 1.0f); - *outY = Clamp(y, -1.0f, 1.0f); - } - if (circular) { - float magnitude = sqrtf(x * x + y * y); - if (magnitude > 0.00001f) { - magnitude = (magnitude + inverseDeadzone) / magnitude; - } - *outX = Clamp(x * magnitude, -1.0f, 1.0f); - *outY = Clamp(y * magnitude, -1.0f, 1.0f); - } else { - *outX = Clamp(x + copysignf(inverseDeadzone, x), -1.0f, 1.0f); - *outY = Clamp(y + copysignf(inverseDeadzone, y), -1.0f, 1.0f); - } -} - void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity) { if (g_Config.iTiltInputType == TILT_NULL) { // Turned off - nothing to do. @@ -84,14 +55,9 @@ void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float Lin::Vec3 down = Lin::Vec3(x, y, z).normalized(); float angleAroundX = atan2(down.z, down.y); - g_currentYAngle = angleAroundX; // TODO: Should smooth this out over time a bit. float yAngle = angleAroundX - calibrationAngle; float xAngle = asinf(down.x); - _dbg_assert_(!my_isnanorinf(angleAroundX)); - _dbg_assert_(!my_isnanorinf(yAngle)); - _dbg_assert_(!my_isnanorinf(xAngle)); - float tiltX = xAngle; float tiltY = yAngle; @@ -113,20 +79,9 @@ void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float if (g_Config.iTiltInputType == TILT_ANALOG) { // Only analog mappings use the deadzone. + float adjustedTiltX = ApplyDeadzone(tiltX, g_Config.fTiltAnalogDeadzoneRadius); float adjustedTiltY = ApplyDeadzone(tiltY, g_Config.fTiltAnalogDeadzoneRadius); - - _dbg_assert_(!my_isnanorinf(adjustedTiltX)); - _dbg_assert_(!my_isnanorinf(adjustedTiltY)); - - // Unlike regular deadzone, where per-axis is okay, inverse deadzone (to compensate for game deadzones) really needs to be - // applied on the two axes together. - // TODO: Share this code with the joystick code. For now though, we keep it separate. - ApplyInverseDeadzone(adjustedTiltX, adjustedTiltY, &adjustedTiltX, &adjustedTiltY, g_Config.fTiltInverseDeadzone, g_Config.bTiltCircularInverseDeadzone); - - _dbg_assert_(!my_isnanorinf(adjustedTiltX)); - _dbg_assert_(!my_isnanorinf(adjustedTiltY)); - rawTiltAnalogX = adjustedTiltX; rawTiltAnalogY = adjustedTiltY; GenerateAnalogStickEvent(adjustedTiltX, adjustedTiltY); diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index d16f0020d..3eda969e1 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -1,7 +1,5 @@ #pragma once -#include "Common/Math/lin/vec3.h" - namespace TiltEventProcessor { // generates a tilt in the correct coordinate system based on @@ -9,8 +7,6 @@ namespace TiltEventProcessor { void ProcessTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity); void ResetTiltEvents(); -float GetCurrentYAngle(); - // Lets you preview the amount of tilt in TiltAnalogSettingsScreen. extern float rawTiltAnalogX; extern float rawTiltAnalogY; diff --git a/Core/Util/DisArm64.h b/Core/Util/DisArm64.h index feb98ea9b..ced77f2cc 100644 --- a/Core/Util/DisArm64.h +++ b/Core/Util/DisArm64.h @@ -18,8 +18,6 @@ // Basic ARM64 disassembler. // No promises of accuracy, mostly just made to debug JIT code. -#pragma once - #include typedef bool (*SymbolCallback)(char *buffer, int bufsize, uint8_t *address); diff --git a/Core/Util/GameDB.cpp b/Core/Util/GameDB.cpp deleted file mode 100644 index 97fc02b0c..000000000 --- a/Core/Util/GameDB.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include - -#include "Core/Util/GameDB.h" -#include "Common/Log.h" -#include "Common/File/VFS/VFS.h" -#include "Common/StringUtils.h" - -GameDB g_gameDB; - -static void SplitCSVLine(const std::string_view str, std::vector &result) { - result.clear(); - - int indexCommaToLeftOfColumn = 0; - int indexCommaToRightOfColumn = -1; - - bool inQuote = false; - - for (int i = 0; i < static_cast(str.size()); i++) { - if (str[i] == '\"') { - inQuote = !inQuote; - } else if (str[i] == ',' && !inQuote) { - indexCommaToLeftOfColumn = indexCommaToRightOfColumn; - indexCommaToRightOfColumn = i; - int index = indexCommaToLeftOfColumn + 1; - int length = indexCommaToRightOfColumn - index; - std::string_view column(str.data() + index, length); - // Remove quotes if possible - column = StripQuotes(column); - result.push_back(column); - } - } - - const std::string_view finalColumn(str.data() + indexCommaToRightOfColumn + 1, str.size() - indexCommaToRightOfColumn - 1); - result.push_back(finalColumn); -} - -static std::vector splitSV(std::string_view strv, char delim, bool removeWhiteSpace) { - std::vector output; - size_t first = 0; - while (first < strv.size()) { - const auto second = strv.find(delim, first); - if (first != second) { - std::string_view line = strv.substr(first, second - first); - if (line.back() == '\r') { - line = strv.substr(first, second - first - 1); - } - if (removeWhiteSpace) { - line = StripSpaces(line); - } - output.emplace_back(line); - } - if (second == std::string_view::npos) - break; - first = second + 1; - } - return output; -} - -bool GameDB::LoadFromVFS(VFSInterface &vfs, const char *filename) { - size_t size; - uint8_t *data = vfs.ReadFile(filename, &size); - if (!data) - return false; - contents_ = std::string((const char *)data, size); - delete[] data; - - // Split the string into views of each line, keeping the original. - std::vector lines = splitSV(contents_, '\n', false); - - SplitCSVLine(lines[0], columns_); - - const size_t titleColumn = GetColumnIndex("Title"); - const size_t foreignTitleColumn = GetColumnIndex("Foreign Title"); - const size_t serialColumn = GetColumnIndex("Serial"); - const size_t crcColumn = GetColumnIndex("CRC32"); - const size_t sizeColumn = GetColumnIndex("Size"); - - std::vector items; - for (size_t i = 1; i < lines.size(); i++) { - auto &lineString = lines[i]; - SplitCSVLine(lineString, items); - if (items.size() != columns_.size()) { - // Bad line - ERROR_LOG(SYSTEM, "Bad line in CSV file: %s", std::string(lineString).c_str()); - continue; - } - - Line line; - line.title = items[titleColumn]; - line.foreignTitle = items[foreignTitleColumn]; - line.serials = splitSV(items[serialColumn], ',', true); - line.crc = items[crcColumn]; - line.size = items[sizeColumn]; - lines_.push_back(line); - } - return true; -} - -size_t GameDB::GetColumnIndex(std::string_view name) const { - for (size_t i = 0; i < columns_.size(); i++) { - if (name == columns_[i]) { - return i; - } - } - return (size_t)-1; -} - -// Our IDs are ULUS12345, while the DB has them in some different forms, with a space or dash as separator. -// TODO: report to redump -static bool IDMatches(std::string_view id, std::string_view dbId) { - if (id.size() < 9 || dbId.size() < 10) - return false; - if (id.substr(0, 4) != dbId.substr(0, 4)) - return false; - if (id.substr(4, 5) != dbId.substr(5, 5)) - return false; - return true; -} - -bool GameDB::GetGameInfos(std::string_view id, std::vector *infos) { - if (id.size() < 9) { - // Not a game. - return false; - } - - for (auto &line : lines_) { - for (auto serial : line.serials) { - // Ignore version and stuff for now - if (IDMatches(id, serial)) { - GameDBInfo info; - sscanf(line.crc.data(), "%08x", &info.crc); - sscanf(line.size.data(), "%llu", &info.size); - info.title = line.title; - info.foreignTitle = line.foreignTitle; - infos->push_back(info); - } - } - } - return !infos->empty(); -} diff --git a/Core/Util/GameDB.h b/Core/Util/GameDB.h deleted file mode 100644 index d2c24f97a..000000000 --- a/Core/Util/GameDB.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class VFSInterface; - -// Serial/id doesn't need including here since we look up by it. -struct GameDBInfo { - std::string title; - std::string foreignTitle; - uint32_t crc; - uint64_t size; -}; - -class GameDB { -public: - bool LoadFromVFS(VFSInterface &vfs, const char *filename); - bool GetGameInfos(std::string_view id, std::vector *infos); - -private: - size_t GetColumnIndex(std::string_view name) const; - - struct Line { - // The exact same ISO can have multiple serials. - std::vector serials; - // The below fields should match GameDBInfo. - std::string_view title; - std::string_view foreignTitle; - std::string_view size; - std::string_view crc; - }; - - std::string contents_; - std::vector lines_; - std::vector columns_; -}; - -extern GameDB g_gameDB; diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index c8e09e4ab..37b3b1dd6 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -102,7 +102,7 @@ bool GameManager::DownloadAndInstall(std::string storeFileUrl) { Path filename = GetTempFilename(); const char *acceptMime = "application/zip, application/x-cso, application/x-iso9660-image, application/octet-stream; q=0.9, */*; q=0.8"; - curDownload_ = g_DownloadManager.StartDownload(storeFileUrl, filename, http::ProgressBarMode::VISIBLE, acceptMime); + curDownload_ = g_DownloadManager.StartDownload(storeFileUrl, filename, acceptMime); return true; } diff --git a/Core/Util/GameManager.h b/Core/Util/GameManager.h index 8aff30da0..336a38908 100644 --- a/Core/Util/GameManager.h +++ b/Core/Util/GameManager.h @@ -91,7 +91,7 @@ private: std::string GetGameID(const Path &path) const; std::string GetPBPGameID(FileLoader *loader) const; std::string GetISOGameID(FileLoader *loader) const; - std::shared_ptr curDownload_; + std::shared_ptr curDownload_; std::shared_ptr installThread_; bool installInProgress_ = false; bool installDonePending_ = false; diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 8a4f3f90f..76d00d840 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -197,11 +197,9 @@ static void Vertex(float x, float y, float u, float v, int tw, int th, u32 color static void EndVertexDataAndDraw(int prim) { _assert_msg_(vertexStart != 0, "Missing matching call to BeginVertexData()"); - if (vertexCount != 0) { - NotifyMemInfo(MemBlockFlags::WRITE, vertexStart, dataWritePtr - vertexStart, "PPGe Vertex"); - WriteCmdAddrWithBase(GE_CMD_VADDR, vertexStart); - WriteCmd(GE_CMD_PRIM, (prim << 16) | vertexCount); - } + NotifyMemInfo(MemBlockFlags::WRITE, vertexStart, dataWritePtr - vertexStart, "PPGe Vertex"); + WriteCmdAddrWithBase(GE_CMD_VADDR, vertexStart); + WriteCmd(GE_CMD_PRIM, (prim << 16) | vertexCount); vertexStart = 0; } @@ -824,67 +822,30 @@ static void PPGeResetCurrentText() { char_lines_metrics = zeroBox; } -// Draws some text using the one font we have in the atlas. -void PPGeDrawCurrentText(u32 color) { - // If the atlas is larger than 512x512, need to use windows into it. - bool useTextureWindow = g_Config.bSoftwareRendering && (atlasWidth > 512 || atlasHeight > 512); - uint32_t texturePosX = 0; - uint32_t texturePosY = 0; - - // Use half the available size just in case a character straddles a boundary. - const float textureMaxPosX = !useTextureWindow ? 1.0f : atlasWidth / 256.0f; - const float textureMaxPosY = !useTextureWindow ? 1.0f : atlasHeight / 256.0f; - // These are the actual scale used. - const float textureWindowW = !useTextureWindow ? atlasWidth : 512.0f; - const float textureWindowH = !useTextureWindow ? atlasHeight : 512.0f; - const float textureScaleX = !useTextureWindow ? 1.0f : atlasWidth / 512.0f; - const float textureScaleY = !useTextureWindow ? 1.0f : atlasWidth / 512.0f; - - if (dlPtr) { +// Draws some text using the one font we have. +// Mostly rewritten. +void PPGeDrawCurrentText(u32 color) +{ + if (dlPtr) + { float scale = char_lines_metrics.scale; - - if (useTextureWindow) { - WriteCmd(GE_CMD_TEXWRAP, 0); - WriteCmd(GE_CMD_TEXSIZE0, 9 | (9 << 8)); - } - BeginVertexData(); - for (auto i = char_lines.begin(); i != char_lines.end(); ++i) { - for (auto j = i->begin(); j != i->end(); ++j) { - const AtlasChar &c = *j->c; - - int wantedPosX = (int)floorf(c.sx * textureMaxPosX); - int wantedPosY = (int)floorf(c.sy * textureMaxPosY); - if (useTextureWindow && (wantedPosX != texturePosX || wantedPosY != texturePosY)) { - EndVertexDataAndDraw(GE_PRIM_RECTANGLES); - - uint32_t offset = atlasWidth * wantedPosY * 256 + wantedPosX * 256; - WriteCmd(GE_CMD_TEXADDR0, (atlasPtr & 0xFFFFF0) + offset / 2); - texturePosX = wantedPosX; - texturePosY = wantedPosY; - - BeginVertexData(); - } - - float sx = (c.sx - texturePosX / textureMaxPosX) * textureScaleX; - float sy = (c.sy - texturePosY / textureMaxPosY) * textureScaleY; - float ex = (c.ex - texturePosX / textureMaxPosX) * textureScaleX; - float ey = (c.ey - texturePosY / textureMaxPosY) * textureScaleY; - + for (auto i = char_lines.begin(); i != char_lines.end(); ++i) + { + for (auto j = i->begin(); j != i->end(); ++j) + { float cx1 = j->x; float cy1 = j->y; + const AtlasChar &c = *j->c; float cx2 = cx1 + c.pw * scale; float cy2 = cy1 + c.ph * scale; - Vertex(cx1, cy1, sx, sy, textureWindowW, textureWindowH, color); - Vertex(cx2, cy2, ex, ey, textureWindowW, textureWindowH, color); + Vertex(cx1, cy1, c.sx, c.sy, atlasWidth, atlasHeight, color); + Vertex(cx2, cy2, c.ex, c.ey, atlasWidth, atlasHeight, color); } } EndVertexDataAndDraw(GE_PRIM_RECTANGLES); } PPGeResetCurrentText(); - if (useTextureWindow) { - PPGeSetDefaultTexture(); - } } // Return a value such that (1 << value) >= x @@ -1082,7 +1043,7 @@ void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { PPGeDrawCurrentText(style.color); } -static std::string_view StripTrailingWhite(std::string_view s) { +static std::string StripTrailingWhite(const std::string &s) { size_t lastChar = s.find_last_not_of(" \t\r\n"); if (lastChar != s.npos) { return s.substr(0, lastChar + 1); @@ -1090,8 +1051,8 @@ static std::string_view StripTrailingWhite(std::string_view s) { return s; } -static std::string_view CropLinesToCount(std::string_view s, int numLines) { - std::vector lines; +static std::string CropLinesToCount(const std::string &s, int numLines) { + std::vector lines; SplitString(s, '\n', lines); if ((int)lines.size() <= numLines) { return s; @@ -1099,7 +1060,7 @@ static std::string_view CropLinesToCount(std::string_view s, int numLines) { size_t len = 0; for (int i = 0; i < numLines; ++i) { - len += lines[i].size() + 1; + len += lines[i].length() + 1; } return s.substr(0, len); @@ -1138,8 +1099,7 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl actualHeight = (maxLines + 1) * lineHeight; // Add an ellipsis if it's just too long to be readable. // On a PSP, it does this without scaling it down. - s2 = StripTrailingWhite(CropLinesToCount(s2, (int)maxLines)); - s2.append("\n..."); + s2 = StripTrailingWhite(CropLinesToCount(s2, (int)maxLines)) + "\n..."; } adjustedStyle.scale *= wrapHeight / actualHeight; @@ -1165,8 +1125,7 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl actualHeight = (maxLines + 1) * char_lines_metrics.lineHeight; // Add an ellipsis if it's just too long to be readable. // On a PSP, it does this without scaling it down. - s = StripTrailingWhite(CropLinesToCount(s, (int)maxLines)); - s.append("\n..."); + s = StripTrailingWhite(CropLinesToCount(s, (int)maxLines)) + "\n..."; } // Measure the text again after scaling down. diff --git a/Core/Util/PortManager.cpp b/Core/Util/PortManager.cpp index cfb81e9db..1a4590070 100644 --- a/Core/Util/PortManager.cpp +++ b/Core/Util/PortManager.cpp @@ -35,7 +35,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Net/Resolve.h" #include "Common/Thread/ThreadUtil.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Log.h" #include "Core/Config.h" #include "Core/System.h" @@ -49,20 +49,21 @@ std::recursive_mutex upnpLock; std::deque upnpReqs; PortManager::PortManager(): + urls(0), + datas(0), m_InitState(UPNP_INITSTATE_NONE), m_LocalPort(UPNP_LOCAL_PORT_ANY), m_leaseDuration("43200") { - // Don't call net::Init or similar here, we don't want stuff like that to happen before main. + // Since WSAStartup can be used multiple times it should be safe to do this right? + net::Init(); } PortManager::~PortManager() { // FIXME: On Windows it seems using any UPnP functions in this destructor that gets triggered when exiting PPSSPP will resulting to UPNPCOMMAND_HTTP_ERROR due to early WSACleanup (miniupnpc was getting WSANOTINITIALISED internally) -} - -void PortManager::Shutdown() { Clear(); Restore(); Terminate(); + net::Shutdown(); } void PortManager::Terminate() { @@ -189,7 +190,7 @@ bool PortManager::Initialize(const unsigned int timeout) { ERROR_LOG(SCENET, "PortManager - upnpDiscover failed (error: %i) or No UPnP device detected", error); if (g_Config.bEnableUPnP) { auto n = GetI18NCategory(I18NCat::NETWORKING); - g_OSD.Show(OSDType::MESSAGE_ERROR, n->T("Unable to find UPnP device")); + System_NotifyUserMessage(n->T("Unable to find UPnP device"), 2.0f, 0x0000ff); } m_InitState = UPNP_INITSTATE_NONE; #endif // WITH_UPNP @@ -214,12 +215,11 @@ bool PortManager::Add(const char* protocol, unsigned short port, unsigned short { if (g_Config.bEnableUPnP) { WARN_LOG(SCENET, "PortManager::Add - the init was not done !"); - g_OSD.Show(OSDType::MESSAGE_INFO, n->T("UPnP need to be reinitialized")); + System_NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); } Terminate(); return false; } - snprintf(port_str, sizeof(port_str), "%d", port); snprintf(intport_str, sizeof(intport_str), "%d", intport); // Only add new port map if it's not previously created by PPSSPP for current IP @@ -244,7 +244,7 @@ bool PortManager::Add(const char* protocol, unsigned short port, unsigned short ERROR_LOG(SCENET, "PortManager - AddPortMapping failed (error: %i)", r); if (r == UPNPCOMMAND_HTTP_ERROR) { if (g_Config.bEnableUPnP) { - g_OSD.Show(OSDType::MESSAGE_INFO, n->T("UPnP need to be reinitialized")); + System_NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); } Terminate(); // Most of the time errors occurred because the router is no longer reachable (ie. changed networks) so we should invalidate the state to prevent further lags due to timeouts return false; @@ -270,7 +270,7 @@ bool PortManager::Remove(const char* protocol, unsigned short port) { { if (g_Config.bEnableUPnP) { WARN_LOG(SCENET, "PortManager::Remove - the init was not done !"); - g_OSD.Show(OSDType::MESSAGE_INFO, n->T("UPnP need to be reinitialized")); + System_NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); } Terminate(); return false; @@ -282,7 +282,7 @@ bool PortManager::Remove(const char* protocol, unsigned short port) { ERROR_LOG(SCENET, "PortManager - DeletePortMapping failed (error: %i)", r); if (r == UPNPCOMMAND_HTTP_ERROR) { if (g_Config.bEnableUPnP) { - g_OSD.Show(OSDType::MESSAGE_INFO, n->T("UPnP need to be reinitialized")); + System_NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); } Terminate(); // Most of the time errors occurred because the router is no longer reachable (ie. changed networks) so we should invalidate the state to prevent further lags due to timeouts return false; @@ -501,7 +501,9 @@ int upnpService(const unsigned int timeout) // Cleaning up regardless of g_Config.bEnableUPnP to prevent lingering open ports on the router if (g_PortManager.GetInitState() == UPNP_INITSTATE_DONE) { - g_PortManager.Shutdown(); + g_PortManager.Clear(); + g_PortManager.Restore(); + g_PortManager.Terminate(); } // Should we ingore any leftover UPnP requests? instead of processing it on the next game start diff --git a/Core/Util/PortManager.h b/Core/Util/PortManager.h index e5d778283..67f99a8fc 100644 --- a/Core/Util/PortManager.h +++ b/Core/Util/PortManager.h @@ -37,12 +37,18 @@ #include #include -struct UPnPArgs { +#ifdef _MSC_VER +#pragma pack(push,1) +#endif +typedef struct UPnPArgs { int cmd; std::string protocol; unsigned short port; unsigned short intport; -}; +} PACK; +#ifdef _MSC_VER +#pragma pack(pop) +#endif #define IP_PROTOCOL_TCP "TCP" #define IP_PROTOCOL_UDP "UDP" @@ -77,6 +83,9 @@ public: // timeout: milliseconds to wait for a router to respond (default = 2000 ms) bool Initialize(const unsigned int timeout = 2000); + // Uninitialize/Reset the state + void Terminate(); + // Get UPnP Initialization status int GetInitState(); @@ -86,24 +95,18 @@ public: // Remove a port mapping (external port) bool Remove(const char* protocol, unsigned short port); - // Call on exit. Does a full shutdown. - void Shutdown(); - -private: - // Retrieves port lists mapped by PPSSPP for current LAN IP & other's applications - bool RefreshPortList(); - // Removes any lingering mapped ports created by PPSSPP (including from previous crashes) bool Clear(); // Restore ports mapped by others that were taken by PPSSPP, better used after Clear() bool Restore(); - // Uninitialize/Reset the state - void Terminate(); + // Retrieves port lists mapped by PPSSPP for current LAN IP & other's applications + bool RefreshPortList(); - struct UPNPUrls* urls = nullptr; - struct IGDdatas* datas = nullptr; +protected: + struct UPNPUrls* urls = NULL; + struct IGDdatas* datas = NULL; int m_InitState = UPNP_INITSTATE_NONE; int m_LocalPort = UPNP_LOCAL_PORT_ANY; diff --git a/Core/WebServer.cpp b/Core/WebServer.cpp index a2192984c..9db7b0f5f 100644 --- a/Core/WebServer.cpp +++ b/Core/WebServer.cpp @@ -64,8 +64,7 @@ static ServerStatus RetrieveStatus() { static bool RegisterServer(int port) { bool success = false; http::Client http; - bool cancelled = false; - net::RequestProgress progress(&cancelled); + http::RequestProgress progress; Buffer theVoid = Buffer::Void(); http.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION)); @@ -160,7 +159,7 @@ static Path LocalFromRemotePath(const std::string &path) { return Path(); } -static void DiscHandler(const http::ServerRequest &request, const Path &filename) { +static void DiscHandler(const http::Request &request, const Path &filename) { s64 sz = File::GetFileSize(filename); std::string range; @@ -212,7 +211,7 @@ static void DiscHandler(const http::ServerRequest &request, const Path &filename } } -static void HandleListing(const http::ServerRequest &request) { +static void HandleListing(const http::Request &request) { AndroidJNIThreadContext jniContext; request.WriteHttpResponseHeader("1.0", 200, -1, "text/plain"); @@ -231,7 +230,7 @@ static void HandleListing(const http::ServerRequest &request) { } } -static bool ServeDebuggerFile(const http::ServerRequest &request) { +static bool ServeDebuggerFile(const http::Request &request) { // Skip the slash at the start of the resource path. const char *filename = request.resource() + 1; if (strstr(filename, "..") != nullptr) @@ -265,13 +264,13 @@ static bool ServeDebuggerFile(const http::ServerRequest &request) { return true; } -static void RedirectToDebugger(const http::ServerRequest &request) { +static void RedirectToDebugger(const http::Request &request) { static const std::string payload = "Redirecting to debugger UI...\r\n"; request.WriteHttpResponseHeader("1.0", 301, (int)payload.size(), "text/plain", "Location: /debugger/index.html\r\n"); request.Out()->Push(payload); } -static void HandleFallback(const http::ServerRequest &request) { +static void HandleFallback(const http::Request &request) { AndroidJNIThreadContext jniContext; if (serverFlags & (int)WebServerFlags::DISCS) { @@ -297,7 +296,7 @@ static void HandleFallback(const http::ServerRequest &request) { request.Out()->Push(payload); } -static void ForwardDebuggerRequest(const http::ServerRequest &request) { +static void ForwardDebuggerRequest(const http::Request &request) { AndroidJNIThreadContext jniContext; if (serverFlags & (int)WebServerFlags::DEBUGGER) { diff --git a/Core/WebServer.h b/Core/WebServer.h index e2713a6e0..d04b88876 100644 --- a/Core/WebServer.h +++ b/Core/WebServer.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - enum class WebServerFlags { DISCS = 1, DEBUGGER = 2, diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index a52a9e385..a29c99577 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -131,10 +131,12 @@ Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, ShaderModule *readbackVs = draw->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vs, strlen(vs), vsTag); _assert_(readbackFs && readbackVs); - static const InputLayoutDesc desc = { - 8, + InputLayoutDesc desc = { { - { SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, + { 8, false }, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, }, }; InputLayout *inputLayout = draw->CreateInputLayout(desc); diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index ebf9dec68..95a53bf2c 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -265,10 +265,12 @@ Draw2DPipeline *Draw2D::Create2DPipeline(std::functionCreateInputLayout(desc); diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 8927a1c2a..ac0d368b2 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -19,9 +19,9 @@ #include #include "Common/Data/Convert/ColorConv.h" +#include "Common/Math/lin/matrix4x4.h" #include "Common/Profiler/Profiler.h" #include "Common/LogReporting.h" -#include "Common/Math/lin/matrix4x4.h" #include "Core/Config.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/SplineCommon.h" @@ -36,20 +36,20 @@ enum { }; DrawEngineCommon::DrawEngineCommon() : decoderMap_(16) { - if (g_Config.bVertexDecoderJit && (g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR)) { + if (g_Config.bVertexDecoderJit && g_Config.iCpuCore == (int)CPUCore::JIT) { decJitCache_ = new VertexDecoderJitCache(); } - transformed_ = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); - transformedExpanded_ = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); - decoded_ = (u8 *)AllocateMemoryPages(DECODED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); - decIndex_ = (u16 *)AllocateMemoryPages(DECODED_INDEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); + transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); + transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); + decoded = (u8 *)AllocateMemoryPages(DECODED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); + decIndex = (u16 *)AllocateMemoryPages(DECODED_INDEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); } DrawEngineCommon::~DrawEngineCommon() { - FreeMemoryPages(decoded_, DECODED_VERTEX_BUFFER_SIZE); - FreeMemoryPages(decIndex_, DECODED_INDEX_BUFFER_SIZE); - FreeMemoryPages(transformed_, TRANSFORMED_VERTEX_BUFFER_SIZE); - FreeMemoryPages(transformedExpanded_, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE); + FreeMemoryPages(decoded, DECODED_VERTEX_BUFFER_SIZE); + FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE); + FreeMemoryPages(transformed, TRANSFORMED_VERTEX_BUFFER_SIZE); + FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE); delete decJitCache_; decoderMap_.Iterate([&](const uint32_t vtype, VertexDecoder *decoder) { delete decoder; @@ -62,8 +62,8 @@ void DrawEngineCommon::Init() { } VertexDecoder *DrawEngineCommon::GetVertexDecoder(u32 vtype) { - VertexDecoder *dec; - if (decoderMap_.Get(vtype, &dec)) + VertexDecoder *dec = decoderMap_.Get(vtype); + if (dec) return dec; dec = new VertexDecoder(); _assert_(dec); @@ -72,6 +72,52 @@ VertexDecoder *DrawEngineCommon::GetVertexDecoder(u32 vtype) { return dec; } +int DrawEngineCommon::ComputeNumVertsToDecode() const { + int vertsToDecode = 0; + if (drawCalls[0].indexType == GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT) { + for (int i = 0; i < numDrawCalls; i++) { + const DeferredDrawCall &dc = drawCalls[i]; + vertsToDecode += dc.vertexCount; + } + } else { + // TODO: Share this computation with DecodeVertsStep? + for (int i = 0; i < numDrawCalls; i++) { + const DeferredDrawCall &dc = drawCalls[i]; + int lastMatch = i; + const int total = numDrawCalls; + int indexLowerBound = dc.indexLowerBound; + int indexUpperBound = dc.indexUpperBound; + for (int j = i + 1; j < total; ++j) { + if (drawCalls[j].verts != dc.verts) + break; + + indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); + indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); + lastMatch = j; + } + vertsToDecode += indexUpperBound - indexLowerBound + 1; + i = lastMatch; + } + } + return vertsToDecode; +} + +void DrawEngineCommon::DecodeVerts(u8 *dest) { + const UVScale origUV = gstate_c.uv; + for (; decodeCounter_ < numDrawCalls; decodeCounter_++) { + gstate_c.uv = drawCalls[decodeCounter_].uvScale; + DecodeVertsStep(dest, decodeCounter_, decodedVerts_); // NOTE! DecodeVertsStep can modify decodeCounter_! + } + gstate_c.uv = origUV; + + // Sanity check + if (indexGen.Prim() < 0) { + ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim()); + // Force to points (0) + indexGen.AddPrim(GE_PRIM_POINTS, 0, true); + } +} + std::vector DrawEngineCommon::DebugGetVertexLoaderIDs() { std::vector ids; decoderMap_.Iterate([&](const uint32_t vtype, VertexDecoder *decoder) { @@ -86,12 +132,23 @@ std::vector DrawEngineCommon::DebugGetVertexLoaderIDs() { std::string DrawEngineCommon::DebugGetVertexLoaderString(std::string id, DebugShaderStringType stringType) { u32 mapId; memcpy(&mapId, &id[0], sizeof(mapId)); - VertexDecoder *dec; - if (decoderMap_.Get(mapId, &dec)) { - return dec->GetString(stringType); - } else { - return "N/A"; - } + VertexDecoder *dec = decoderMap_.Get(mapId); + return dec ? dec->GetString(stringType) : "N/A"; +} + +struct Plane { + float x, y, z, w; + void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } + float Test(const float f[3]) const { return x * f[0] + y * f[1] + z * f[2] + w; } +}; + +static void PlanesFromMatrix(const float mtx[16], Plane planes[6]) { + planes[0].Set(mtx[3]-mtx[0], mtx[7]-mtx[4], mtx[11]-mtx[8], mtx[15]-mtx[12]); // Right + planes[1].Set(mtx[3]+mtx[0], mtx[7]+mtx[4], mtx[11]+mtx[8], mtx[15]+mtx[12]); // Left + planes[2].Set(mtx[3]+mtx[1], mtx[7]+mtx[5], mtx[11]+mtx[9], mtx[15]+mtx[13]); // Bottom + planes[3].Set(mtx[3]-mtx[1], mtx[7]-mtx[5], mtx[11]-mtx[9], mtx[15]-mtx[13]); // Top + planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near + planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far } static Vec3f ClipToScreen(const Vec4f& coords) { @@ -179,24 +236,74 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex // Code checks this reg directly, not just the vtype ID. if (!prevThrough) { gstate.vertType |= GE_VTYPE_THROUGH; - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_UVSCALEOFFSET | DIRTY_CULLRANGE); } int bytesRead; uint32_t vertTypeID = GetVertTypeID(vtype, 0, decOptions_.applySkinInDecode); - - bool clockwise = !gstate.isCullEnabled() || gstate.getCullMode() == cullMode; - SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, clockwise, &bytesRead); + SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, cullMode, &bytesRead); DispatchFlush(); if (!prevThrough) { gstate.vertType &= ~GE_VTYPE_THROUGH; - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_UVSCALEOFFSET | DIRTY_CULLRANGE); } } -// Gated by DIRTY_CULL_PLANES -void DrawEngineCommon::UpdatePlanes() { +// This code has plenty of potential for optimization. +// +// It does the simplest and safest test possible: If all points of a bbox is outside a single of +// our clipping planes, we reject the box. Tighter bounds would be desirable but would take more calculations. +bool DrawEngineCommon::TestBoundingBox(const void *control_points, const void *inds, int vertexCount, u32 vertType) { + SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12); + float *verts = (float *)(decoded + 65536 * 18); + + // Although this may lead to drawing that shouldn't happen, the viewport is more complex on VR. + // Let's always say objects are within bounds. + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) + return true; + + // Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder + // and a large vertex format. + if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT && !inds) { + verts = (float *)control_points; + } else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT && !inds) { + const s8 *vtx = (const s8 *)control_points; + for (int i = 0; i < vertexCount * 3; i++) { + verts[i] = vtx[i] * (1.0f / 128.0f); + } + } else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT && !inds) { + const s16 *vtx = (const s16*)control_points; + for (int i = 0; i < vertexCount * 3; i++) { + verts[i] = vtx[i] * (1.0f / 32768.0f); + } + } else { + // Simplify away indices, bones, and morph before proceeding. + u8 *temp_buffer = decoded + 65536 * 24; + int vertexSize = 0; + + u16 indexLowerBound = 0; + u16 indexUpperBound = (u16)vertexCount - 1; + if (vertexCount > 0 && inds) { + GetIndexBounds(inds, vertexCount, vertType, &indexLowerBound, &indexUpperBound); + } + + // Force software skinning. + bool wasApplyingSkinInDecode = decOptions_.applySkinInDecode; + decOptions_.applySkinInDecode = true; + NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)control_points, indexLowerBound, indexUpperBound, vertType); + decOptions_.applySkinInDecode = wasApplyingSkinInDecode; + + IndexConverter conv(vertType, inds); + for (int i = 0; i < vertexCount; i++) { + verts[i * 3] = corners[conv(i)].pos.x; + verts[i * 3 + 1] = corners[conv(i)].pos.y; + verts[i * 3 + 2] = corners[conv(i)].pos.z; + } + } + + Plane planes[6]; + float world[16]; float view[16]; float worldview[16]; @@ -211,171 +318,54 @@ void DrawEngineCommon::UpdatePlanes() { // Note that the PSP does not clip against the viewport. const Vec2f baseOffset = Vec2f(gstate.getOffsetX(), gstate.getOffsetY()); // Region1 (rate) is used as an X1/Y1 here, matching PSP behavior. - minOffset_ = baseOffset + Vec2f(std::max(gstate.getRegionRateX() - 0x100, gstate.getScissorX1()), std::max(gstate.getRegionRateY() - 0x100, gstate.getScissorY1())) - Vec2f(1.0f, 1.0f); - maxOffset_ = baseOffset + Vec2f(std::min(gstate.getRegionX2(), gstate.getScissorX2()), std::min(gstate.getRegionY2(), gstate.getScissorY2())) + Vec2f(1.0f, 1.0f); + Vec2f minOffset = baseOffset + Vec2f(std::max(gstate.getRegionRateX() - 0x100, gstate.getScissorX1()), std::max(gstate.getRegionRateY() - 0x100, gstate.getScissorY1())) - Vec2f(1.0f, 1.0f); + Vec2f maxOffset = baseOffset + Vec2f(std::min(gstate.getRegionX2(), gstate.getScissorX2()), std::min(gstate.getRegionY2(), gstate.getScissorY2())) + Vec2f(1.0f, 1.0f); // Now let's apply the viewport to our scissor/region + offset range. Vec2f inverseViewportScale = Vec2f(1.0f / gstate.getViewportXScale(), 1.0f / gstate.getViewportYScale()); - Vec2f minViewport = (minOffset_ - Vec2f(gstate.getViewportXCenter(), gstate.getViewportYCenter())) * inverseViewportScale; - Vec2f maxViewport = (maxOffset_ - Vec2f(gstate.getViewportXCenter(), gstate.getViewportYCenter())) * inverseViewportScale; + Vec2f minViewport = (minOffset - Vec2f(gstate.getViewportXCenter(), gstate.getViewportYCenter())) * inverseViewportScale; + Vec2f maxViewport = (maxOffset - Vec2f(gstate.getViewportXCenter(), gstate.getViewportYCenter())) * inverseViewportScale; - Vec2f viewportInvSize = Vec2f(1.0f / (maxViewport.x - minViewport.x), 1.0f / (maxViewport.y - minViewport.y)); - - Lin::Matrix4x4 applyViewport{}; + Lin::Matrix4x4 applyViewport; + applyViewport.empty(); // Scale to the viewport's size. - applyViewport.xx = 2.0f * viewportInvSize.x; - applyViewport.yy = 2.0f * viewportInvSize.y; + applyViewport.xx = 2.0f / (maxViewport.x - minViewport.x); + applyViewport.yy = 2.0f / (maxViewport.y - minViewport.y); applyViewport.zz = 1.0f; applyViewport.ww = 1.0f; // And offset to the viewport's centers. - applyViewport.wx = -(maxViewport.x + minViewport.x) * viewportInvSize.x; - applyViewport.wy = -(maxViewport.y + minViewport.y) * viewportInvSize.y; + applyViewport.wx = -(maxViewport.x + minViewport.x) / (maxViewport.x - minViewport.x); + applyViewport.wy = -(maxViewport.y + minViewport.y) / (maxViewport.y - minViewport.y); - float mtx[16]; - Matrix4ByMatrix4(mtx, worldviewproj, applyViewport.m); - - planes_[0].Set(mtx[3] - mtx[0], mtx[7] - mtx[4], mtx[11] - mtx[8], mtx[15] - mtx[12]); // Right - planes_[1].Set(mtx[3] + mtx[0], mtx[7] + mtx[4], mtx[11] + mtx[8], mtx[15] + mtx[12]); // Left - planes_[2].Set(mtx[3] + mtx[1], mtx[7] + mtx[5], mtx[11] + mtx[9], mtx[15] + mtx[13]); // Bottom - planes_[3].Set(mtx[3] - mtx[1], mtx[7] - mtx[5], mtx[11] - mtx[9], mtx[15] - mtx[13]); // Top - planes_[4].Set(mtx[3] + mtx[2], mtx[7] + mtx[6], mtx[11] + mtx[10], mtx[15] + mtx[14]); // Near - planes_[5].Set(mtx[3] - mtx[2], mtx[7] - mtx[6], mtx[11] - mtx[10], mtx[15] - mtx[14]); // Far -} - -// This code has plenty of potential for optimization. -// -// It does the simplest and safest test possible: If all points of a bbox is outside a single of -// our clipping planes, we reject the box. Tighter bounds would be desirable but would take more calculations. -// The name is a slight misnomer, because any bounding shape will work, not just boxes. -// -// Potential optimizations: -// * SIMD-ify the plane culling, and also the vertex data conversion (could even group together xxxxyyyyzzzz for example) -// * Compute min/max of the verts, and then compute a bounding sphere and check that against the planes. -// - Less accurate, but.. -// - Only requires six plane evaluations then. - -bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int vertexCount, u32 vertType) { - // Grab temp buffer space from large offsets in decoded_. Not exactly safe for large draws. - if (vertexCount > 1024) { - return true; - } - - SimpleVertex *corners = (SimpleVertex *)(decoded_ + 65536 * 12); - float *verts = (float *)(decoded_ + 65536 * 18); - int vertStride = 3; - - // Although this may lead to drawing that shouldn't happen, the viewport is more complex on VR. - // Let's always say objects are within bounds. - if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) - return true; - - // Due to world matrix updates per "thing", this isn't quite as effective as it could be if we did world transform - // in here as well. Though, it still does cut down on a lot of updates in Tekken 6. - if (gstate_c.IsDirty(DIRTY_CULL_PLANES)) { - UpdatePlanes(); - gpuStats.numPlaneUpdates++; - gstate_c.Clean(DIRTY_CULL_PLANES); - } - - // Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder - // and a large vertex format. - if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT && !inds) { - verts = (float *)vdata; - } else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT && !inds) { - const s8 *vtx = (const s8 *)vdata; - for (int i = 0; i < vertexCount * 3; i++) { - verts[i] = vtx[i] * (1.0f / 128.0f); - } - } else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT && !inds) { - const s16 *vtx = (const s16 *)vdata; - for (int i = 0; i < vertexCount * 3; i++) { - verts[i] = vtx[i] * (1.0f / 32768.0f); - } - } else { - // Simplify away indices, bones, and morph before proceeding. - u8 *temp_buffer = decoded_ + 65536 * 24; - - if ((inds || (vertType & (GE_VTYPE_WEIGHT_MASK | GE_VTYPE_MORPHCOUNT_MASK)))) { - u16 indexLowerBound = 0; - u16 indexUpperBound = (u16)vertexCount - 1; - - if (vertexCount > 0 && inds) { - GetIndexBounds(inds, vertexCount, vertType, &indexLowerBound, &indexUpperBound); - } - // TODO: Avoid normalization if just plain skinning. - // Force software skinning. - bool wasApplyingSkinInDecode = decOptions_.applySkinInDecode; - decOptions_.applySkinInDecode = true; - NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, vertType); - decOptions_.applySkinInDecode = wasApplyingSkinInDecode; - - IndexConverter conv(vertType, inds); - for (int i = 0; i < vertexCount; i++) { - verts[i * 3] = corners[conv(i)].pos.x; - verts[i * 3 + 1] = corners[conv(i)].pos.y; - verts[i * 3 + 2] = corners[conv(i)].pos.z; - } - } else { - // Simple, most common case. - VertexDecoder *dec = GetVertexDecoder(vertType); - int stride = dec->VertexSize(); - int offset = dec->posoff; - switch (vertType & GE_VTYPE_POS_MASK) { - case GE_VTYPE_POS_8BIT: - for (int i = 0; i < vertexCount; i++) { - const s8 *data = (const s8 *)vdata + i * stride + offset; - for (int j = 0; j < 3; j++) { - verts[i * 3 + j] = data[j] * (1.0f / 128.0f); - } - } - break; - case GE_VTYPE_POS_16BIT: - for (int i = 0; i < vertexCount; i++) { - const s16 *data = ((const s16 *)((const s8 *)vdata + i * stride + offset)); - for (int j = 0; j < 3; j++) { - verts[i * 3 + j] = data[j] * (1.0f / 32768.0f); - } - } - break; - case GE_VTYPE_POS_FLOAT: - // No need to copy in this case, we can just read directly from the source format with a stride. - verts = (float *)((uint8_t *)vdata + offset); - vertStride = stride / 4; - // Previous code: - // for (int i = 0; i < vertexCount; i++) - // memcpy(&verts[i * 3], (const u8 *)vdata + stride * i + offset, sizeof(float) * 3); - break; - } - } - } + float screenBounds[16]; + Matrix4ByMatrix4(screenBounds, worldviewproj, applyViewport.m); + PlanesFromMatrix(screenBounds, planes); // Note: near/far are not checked without clamp/clip enabled, so we skip those planes. int totalPlanes = gstate.isDepthClampEnabled() ? 6 : 4; for (int plane = 0; plane < totalPlanes; plane++) { int inside = 0; int out = 0; for (int i = 0; i < vertexCount; i++) { - // Test against the frustum planes, and count. - // TODO: We should test 4 vertices at a time using SIMD. - // I guess could also test one vertex against 4 planes at a time, though a lot of waste at the common case of 6. - const float *pos = verts + i * vertStride; - float value = planes_[plane].Test(pos); - if (value <= -FLT_EPSILON) // Not sure why we use exactly this value. Probably '< 0' would do. + // Here we can test against the frustum planes! + float value = planes[plane].Test(verts + i * 3); + if (value <= -FLT_EPSILON) out++; else inside++; } - // No vertices inside this one plane? Don't need to draw. if (inside == 0) { // All out - but check for X and Y if the offset was near the cullbox edge. bool outsideEdge = false; - switch (plane) { - case 0: outsideEdge = maxOffset_.x >= 4096.0f; break; - case 1: outsideEdge = minOffset_.x < 1.0f; break; - case 2: outsideEdge = minOffset_.y < 1.0f; break; - case 3: outsideEdge = maxOffset_.y >= 4096.0f; break; - } + if (plane == 1) + outsideEdge = minOffset.x < 1.0f; + if (plane == 2) + outsideEdge = minOffset.y < 1.0f; + else if (plane == 0) + outsideEdge = maxOffset.x >= 4096.0f; + else if (plane == 3) + outsideEdge = maxOffset.y >= 4096.0f; // Only consider this outside if offset + scissor/region is fully inside the cullbox. if (!outsideEdge) @@ -515,7 +505,7 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vectorDecodeVerts(bufPtr, inPtr, &gstate_c.uv, lowerBound, upperBound); + dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound); // OK, morphing eliminated but bones still remain to be taken care of. // Let's do a partial software transform where we only do skinning. @@ -622,61 +612,191 @@ void DrawEngineCommon::ApplyFramebufferRead(FBOTexState *fboTexState) { gstate_c.Dirty(DIRTY_SHADERBLEND); } -int DrawEngineCommon::ComputeNumVertsToDecode() const { - int sum = 0; - for (int i = 0; i < numDrawVerts_; i++) { - sum += drawVerts_[i].indexUpperBound + 1 - drawVerts_[i].indexLowerBound; +void DrawEngineCommon::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) { + PROFILE_THIS_SCOPE("vertdec"); + + const DeferredDrawCall &dc = drawCalls[i]; + + indexGen.SetIndex(decodedVerts); + int indexLowerBound = dc.indexLowerBound; + int indexUpperBound = dc.indexUpperBound; + + if (dc.indexType == GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT) { + // Decode the verts (and at the same time apply morphing/skinning). Simple. + dec_->DecodeVerts(dest + decodedVerts * (int)dec_->GetDecVtxFmt().stride, + dc.verts, indexLowerBound, indexUpperBound); + decodedVerts += indexUpperBound - indexLowerBound + 1; + + bool clockwise = true; + if (gstate.isCullEnabled() && gstate.getCullMode() != dc.cullMode) { + clockwise = false; + } + indexGen.AddPrim(dc.prim, dc.vertexCount, clockwise); + } else { + // It's fairly common that games issue long sequences of PRIM calls, with differing + // inds pointer but the same base vertex pointer. We'd like to reuse vertices between + // these as much as possible, so we make sure here to combine as many as possible + // into one nice big drawcall, sharing data. + + // 1. Look ahead to find the max index, only looking as "matching" drawcalls. + // Expand the lower and upper bounds as we go. + int lastMatch = i; + const int total = numDrawCalls; + for (int j = i + 1; j < total; ++j) { + if (drawCalls[j].verts != dc.verts) + break; + + indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound); + indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound); + lastMatch = j; + } + + // 2. Loop through the drawcalls, translating indices as we go. + switch (dc.indexType) { + case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT: + for (int j = i; j <= lastMatch; j++) { + bool clockwise = true; + if (gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) { + clockwise = false; + } + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound, clockwise); + } + break; + case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT: + for (int j = i; j <= lastMatch; j++) { + bool clockwise = true; + if (gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) { + clockwise = false; + } + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16_le *)drawCalls[j].inds, indexLowerBound, clockwise); + } + break; + case GE_VTYPE_IDX_32BIT >> GE_VTYPE_IDX_SHIFT: + for (int j = i; j <= lastMatch; j++) { + bool clockwise = true; + if (gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) { + clockwise = false; + } + indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u32_le *)drawCalls[j].inds, indexLowerBound, clockwise); + } + break; + } + + const int vertexCount = indexUpperBound - indexLowerBound + 1; + + // This check is a workaround for Pangya Fantasy Golf, which sends bogus index data when switching items in "My Room" sometimes. + if (decodedVerts + vertexCount > VERTEX_BUFFER_MAX) { + return; + } + + // 3. Decode that range of vertex data. + dec_->DecodeVerts(dest + decodedVerts * (int)dec_->GetDecVtxFmt().stride, + dc.verts, indexLowerBound, indexUpperBound); + decodedVerts += vertexCount; + + // 4. Advance indexgen vertex counter. + indexGen.Advance(vertexCount); + i = lastMatch; } - return sum; } -int DrawEngineCommon::ExtendNonIndexedPrim(const uint32_t *cmd, const uint32_t *stall, u32 vertTypeID, bool clockwise, int *bytesRead, bool isTriangle) { - const uint32_t *start = cmd; - int prevDrawVerts = numDrawVerts_ - 1; - DeferredVerts &dv = drawVerts_[prevDrawVerts]; - int offset = dv.vertexCount; +inline u32 ComputeMiniHashRange(const void *ptr, size_t sz) { + // Switch to u32 units, and round up to avoid unaligned accesses. + // Probably doesn't matter if we skip the first few bytes in some cases. + const u32 *p = (const u32 *)(((uintptr_t)ptr + 3) & ~3); + sz >>= 2; - _dbg_assert_(numDrawInds_ <= MAX_DEFERRED_DRAW_INDS); // if it's equal, the check below will take care of it before any action is taken. - _dbg_assert_(numDrawVerts_ > 0); + if (sz > 100) { + size_t step = sz / 4; + u32 hash = 0; + for (size_t i = 0; i < sz; i += step) { + hash += XXH3_64bits(p + i, 100); + } + return hash; + } else { + return p[0] + p[sz - 1]; + } +} - while (cmd != stall) { - uint32_t data = *cmd; - if ((data & 0xFFF80000) != 0x04000000) { - break; +u32 DrawEngineCommon::ComputeMiniHash() { + u32 fullhash = 0; + const int vertexSize = dec_->GetDecVtxFmt().stride; + const int indexSize = IndexSize(dec_->VertexType()); + + int step; + if (numDrawCalls < 3) { + step = 1; + } else if (numDrawCalls < 8) { + step = 4; + } else { + step = numDrawCalls / 8; + } + for (int i = 0; i < numDrawCalls; i += step) { + const DeferredDrawCall &dc = drawCalls[i]; + if (!dc.inds) { + fullhash += ComputeMiniHashRange(dc.verts, vertexSize * dc.vertexCount); + } else { + int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound; + fullhash += ComputeMiniHashRange((const u8 *)dc.verts + vertexSize * indexLowerBound, vertexSize * (indexUpperBound - indexLowerBound)); + fullhash += ComputeMiniHashRange(dc.inds, indexSize * dc.vertexCount); } - GEPrimitiveType newPrim = static_cast((data >> 16) & 7); - if (IsTrianglePrim(newPrim) != isTriangle) - break; - int vertexCount = data & 0xFFFF; - if (numDrawInds_ >= MAX_DEFERRED_DRAW_INDS || vertexCountInDrawCalls_ + offset + vertexCount > VERTEX_BUFFER_MAX) { - break; - } - DeferredInds &di = drawInds_[numDrawInds_++]; - di.indexType = 0; - di.prim = newPrim; - di.clockwise = clockwise; - di.vertexCount = vertexCount; - di.vertDecodeIndex = prevDrawVerts; - di.offset = offset; - offset += vertexCount; - cmd++; } - int totalCount = offset - dv.vertexCount; - dv.vertexCount = offset; - dv.indexUpperBound = dv.vertexCount - 1; - vertexCountInDrawCalls_ += totalCount; - *bytesRead = totalCount * dec_->VertexSize(); - return cmd - start; + return fullhash; +} + +uint64_t DrawEngineCommon::ComputeHash() { + uint64_t fullhash = 0; + const int vertexSize = dec_->GetDecVtxFmt().stride; + const int indexSize = IndexSize(dec_->VertexType()); + + // TODO: Add some caps both for numDrawCalls and num verts to check? + // It is really very expensive to check all the vertex data so often. + for (int i = 0; i < numDrawCalls; i++) { + const DeferredDrawCall &dc = drawCalls[i]; + if (!dc.inds) { + fullhash += XXH3_64bits((const char *)dc.verts, vertexSize * dc.vertexCount); + } else { + int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound; + int j = i + 1; + int lastMatch = i; + while (j < numDrawCalls) { + if (drawCalls[j].verts != dc.verts) + break; + indexLowerBound = std::min(indexLowerBound, (int)dc.indexLowerBound); + indexUpperBound = std::max(indexUpperBound, (int)dc.indexUpperBound); + lastMatch = j; + j++; + } + // This could get seriously expensive with sparse indices. Need to combine hashing ranges the same way + // we do when drawing. + fullhash += XXH3_64bits((const char *)dc.verts + vertexSize * indexLowerBound, + vertexSize * (indexUpperBound - indexLowerBound)); + // Hm, we will miss some indices when combining above, but meh, it should be fine. + fullhash += XXH3_64bits((const char *)dc.inds, indexSize * dc.vertexCount); + i = lastMatch; + } + } + + fullhash += XXH3_64bits(&drawCalls[0].uvScale, sizeof(drawCalls[0].uvScale) * numDrawCalls); + return fullhash; +} + +// Cheap bit scrambler from https://nullprogram.com/blog/2018/07/31/ +inline uint32_t lowbias32_r(uint32_t x) { + x ^= x >> 16; + x *= 0x43021123U; + x ^= x >> 15 ^ x >> 30; + x *= 0x1d69e2a5U; + x ^= x >> 16; + return x; } // vertTypeID is the vertex type but with the UVGen mode smashed into the top bits. -bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, bool clockwise, int *bytesRead) { - if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawVerts_ >= MAX_DEFERRED_DRAW_VERTS || numDrawInds_ >= MAX_DEFERRED_DRAW_INDS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) { +void DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) { + if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) { DispatchFlush(); } - _dbg_assert_(numDrawVerts_ < MAX_DEFERRED_DRAW_VERTS); - _dbg_assert_(numDrawInds_ < MAX_DEFERRED_DRAW_INDS); // This isn't exactly right, if we flushed, since prims can straddle previous calls. // But it generally works for common usage. @@ -689,8 +809,8 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti prevPrim_ = prim; } - // If vtype has changed, setup the vertex decoder. Don't need to nullcheck dec_ since we set lastVType_ to an invalid value whenever we null it. - if (vertTypeID != lastVType_) { + // If vtype has changed, setup the vertex decoder. + if (vertTypeID != lastVType_ || !dec_) { dec_ = GetVertexDecoder(vertTypeID); lastVType_ = vertTypeID; } @@ -698,107 +818,46 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti *bytesRead = vertexCount * dec_->VertexSize(); // Check that we have enough vertices to form the requested primitive. - if (vertexCount < 3 && ((vertexCount < 2 && prim > 0) || (prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES))) - return false; + if ((vertexCount < 2 && prim > 0) || (vertexCount < 3 && prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES)) + return; - bool applySkin = (vertTypeID & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode; - - DeferredInds &di = drawInds_[numDrawInds_++]; - di.inds = inds; - di.indexType = (vertTypeID & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; - di.prim = prim; - di.clockwise = clockwise; - di.vertexCount = vertexCount; - di.vertDecodeIndex = numDrawVerts_; - di.offset = 0; - - _dbg_assert_(numDrawVerts_ <= MAX_DEFERRED_DRAW_VERTS); - _dbg_assert_(numDrawInds_ <= MAX_DEFERRED_DRAW_INDS); - - if (inds && numDrawVerts_ > decodeVertsCounter_ && drawVerts_[numDrawVerts_ - 1].verts == verts && !applySkin) { - // Same vertex pointer as a previous un-decoded draw call - let's just extend the decode! - di.vertDecodeIndex = numDrawVerts_ - 1; - DeferredVerts &dv = drawVerts_[numDrawVerts_ - 1]; - u16 lb; - u16 ub; - GetIndexBounds(inds, vertexCount, vertTypeID, &lb, &ub); - if (lb < dv.indexLowerBound) - dv.indexLowerBound = lb; - if (ub > dv.indexUpperBound) - dv.indexUpperBound = ub; - } else { - // Record a new draw, and a new index gen. - DeferredVerts &dv = drawVerts_[numDrawVerts_++]; - dv.verts = verts; - dv.vertexCount = vertexCount; - dv.uvScale = gstate_c.uv; - if (inds) { - GetIndexBounds(inds, vertexCount, vertTypeID, &dv.indexLowerBound, &dv.indexUpperBound); - } else { - dv.indexLowerBound = 0; - dv.indexUpperBound = vertexCount - 1; - } + if (g_Config.bVertexCache) { + u32 dhash = dcid_; + dhash = __rotl(dhash ^ (u32)(uintptr_t)verts, 13); + dhash = __rotl(dhash ^ (u32)(uintptr_t)inds, 19); + dhash = __rotl(dhash ^ (u32)vertTypeID, 7); + dhash = __rotl(dhash ^ (u32)vertexCount, 11); + dcid_ = lowbias32_r(dhash ^ (u32)prim); } + DeferredDrawCall &dc = drawCalls[numDrawCalls]; + dc.verts = verts; + dc.inds = inds; + dc.vertexCount = vertexCount; + dc.indexType = (vertTypeID & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; + dc.prim = prim; + dc.cullMode = cullMode; + dc.uvScale = gstate_c.uv; + if (inds) { + GetIndexBounds(inds, vertexCount, vertTypeID, &dc.indexLowerBound, &dc.indexUpperBound); + } else { + dc.indexLowerBound = 0; + dc.indexUpperBound = vertexCount - 1; + } + + numDrawCalls++; vertexCountInDrawCalls_ += vertexCount; + if (decOptions_.applySkinInDecode && (vertTypeID & GE_VTYPE_WEIGHT_MASK)) { + DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); + decodeCounter_++; + } + if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) { - // This prevents issues with consecutive self-renders in Ridge Racer. + // Rendertarget == texture? Shouldn't happen. Still, try some mitigations. gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); DispatchFlush(); } - return true; -} - -void DrawEngineCommon::DecodeVerts(u8 *dest) { - int i = decodeVertsCounter_; - int stride = (int)dec_->GetDecVtxFmt().stride; - for (; i < numDrawVerts_; i++) { - DeferredVerts &dv = drawVerts_[i]; - - int indexLowerBound = dv.indexLowerBound; - drawVertexOffsets_[i] = decodedVerts_ - indexLowerBound; - - int indexUpperBound = dv.indexUpperBound; - // Decode the verts (and at the same time apply morphing/skinning). Simple. - dec_->DecodeVerts(dest + decodedVerts_ * stride, dv.verts, &dv.uvScale, indexLowerBound, indexUpperBound); - decodedVerts_ += indexUpperBound - indexLowerBound + 1; - } - decodeVertsCounter_ = i; -} - -void DrawEngineCommon::DecodeInds() { - int i = decodeIndsCounter_; - for (; i < numDrawInds_; i++) { - const DeferredInds &di = drawInds_[i]; - - int indexOffset = drawVertexOffsets_[di.vertDecodeIndex] + di.offset; - bool clockwise = di.clockwise; - // We've already collapsed subsequent draws with the same vertex pointer, so no tricky logic here anymore. - // 2. Loop through the drawcalls, translating indices as we go. - switch (di.indexType) { - case GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT: - indexGen.AddPrim(di.prim, di.vertexCount, indexOffset, clockwise); - break; - case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(di.prim, di.vertexCount, (const u8 *)di.inds, indexOffset, clockwise); - break; - case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(di.prim, di.vertexCount, (const u16_le *)di.inds, indexOffset, clockwise); - break; - case GE_VTYPE_IDX_32BIT >> GE_VTYPE_IDX_SHIFT: - indexGen.TranslatePrim(di.prim, di.vertexCount, (const u32_le *)di.inds, indexOffset, clockwise); - break; - } - } - decodeIndsCounter_ = i; - - // Sanity check - if (indexGen.Prim() < 0) { - ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim()); - // Force to points (0) - indexGen.AddPrim(GE_PRIM_POINTS, 0, 0, true); - } } bool DrawEngineCommon::CanUseHardwareTransform(int prim) { diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index e9e8870ef..23f42f8c1 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -22,7 +22,6 @@ #include "Common/CommonTypes.h" #include "Common/Data/Collections/Hashmaps.h" -#include "GPU/Math3D.h" #include "GPU/GPUState.h" #include "GPU/Common/GPUStateUtils.h" #include "GPU/Common/GPUDebugInterface.h" @@ -69,13 +68,6 @@ public: virtual void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) = 0; }; -// Culling plane. -struct Plane { - float x, y, z, w; - void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } - float Test(const float f[3]) const { return x * f[0] + y * f[1] + z * f[2] + w; } -}; - class DrawEngineCommon { public: DrawEngineCommon(); @@ -96,23 +88,15 @@ public: // This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim // is different. Should probably refactor that. // Note that vertTypeID should be computed using GetVertTypeID(). - virtual void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, bool clockwise, int *bytesRead) { - SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, clockwise, bytesRead); + virtual void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) { + SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, cullMode, bytesRead); } virtual void DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode, bool continuation); bool TestBoundingBox(const void *control_points, const void *inds, int vertexCount, u32 vertType); - void FlushSkin() { - bool applySkin = (lastVType_ & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode; - if (applySkin) { - DecodeVerts(decoded_); - } - } - - int ExtendNonIndexedPrim(const uint32_t *cmd, const uint32_t *stall, u32 vertTypeID, bool clockwise, int *bytesRead, bool isTriangle); - bool SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, bool clockwise, int *bytesRead); + void SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead); template void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope); void ClearSplineBezierWeights(); @@ -138,7 +122,7 @@ public: return false; } int GetNumDrawCalls() const { - return numDrawVerts_; + return numDrawCalls; } VertexDecoder *GetVertexDecoder(u32 vtype); @@ -146,20 +130,20 @@ public: virtual void ClearTrackedVertexArrays() {} protected: - virtual bool UpdateUseHWTessellation(bool enabled) const { return enabled; } - void UpdatePlanes(); + virtual bool UpdateUseHWTessellation(bool enabled) { return enabled; } + int ComputeNumVertsToDecode() const; void DecodeVerts(u8 *dest); - void DecodeInds(); - - int MaxIndex() const { - return decodedVerts_; - } // Preprocessing for spline/bezier u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize = nullptr); - int ComputeNumVertsToDecode() const; + // Utility for vertex caching + u32 ComputeMiniHash(); + uint64_t ComputeHash(); + + // Vertex decoding + void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts); void ApplyFramebufferRead(FBOTexState *fboTexState); @@ -191,30 +175,6 @@ protected: } } - inline void ResetAfterDrawInline() { - gpuStats.numFlushes++; - gpuStats.numDrawCalls += numDrawInds_; - gpuStats.numVertexDecodes += numDrawVerts_; - gpuStats.numVertsSubmitted += vertexCountInDrawCalls_; - - indexGen.Reset(); - decodedVerts_ = 0; - numDrawVerts_ = 0; - numDrawInds_ = 0; - vertexCountInDrawCalls_ = 0; - decodeIndsCounter_ = 0; - decodeVertsCounter_ = 0; - gstate_c.vertexFullAlpha = true; - - // Now seems as good a time as any to reset the min/max coords, which we may examine later. - gstate_c.vertBounds.minU = 512; - gstate_c.vertBounds.minV = 512; - gstate_c.vertBounds.maxU = 0; - gstate_c.vertBounds.maxV = 0; - } - - uint32_t ComputeDrawcallsHash() const; - bool useHWTransform_ = false; bool useHWTessellation_ = false; // Used to prevent unnecessary flushing in softgpu. @@ -225,50 +185,40 @@ protected: bool everUsedExactEqualDepth_ = false; // Vertex collector buffers - u8 *decoded_ = nullptr; - u16 *decIndex_ = nullptr; + u8 *decoded = nullptr; + u16 *decIndex = nullptr; // Cached vertex decoders u32 lastVType_ = -1; // corresponds to dec_. Could really just pick it out of dec_... - DenseHashMap decoderMap_; + DenseHashMap decoderMap_; VertexDecoder *dec_ = nullptr; VertexDecoderJitCache *decJitCache_ = nullptr; VertexDecoderOptions decOptions_{}; - TransformedVertex *transformed_ = nullptr; - TransformedVertex *transformedExpanded_ = nullptr; + TransformedVertex *transformed = nullptr; + TransformedVertex *transformedExpanded = nullptr; // Defer all vertex decoding to a "Flush" (except when software skinning) - struct DeferredVerts { + struct DeferredDrawCall { const void *verts; + const void *inds; u32 vertexCount; + u8 indexType; + s8 prim; + u8 cullMode; u16 indexLowerBound; u16 indexUpperBound; UVScale uvScale; }; - struct DeferredInds { - const void *inds; - u32 vertexCount; - u8 vertDecodeIndex; // index into the drawVerts_ array to look up the vertexOffset. - u8 indexType; - s8 prim; - bool clockwise; - u16 offset; - }; - - enum { MAX_DEFERRED_DRAW_VERTS = 128 }; // If you change this to more than 256, change type of DeferredInds::vertDecodeIndex. - enum { MAX_DEFERRED_DRAW_INDS = 512 }; // Monster Hunter spams indexed calls that we end up merging. - DeferredVerts drawVerts_[MAX_DEFERRED_DRAW_VERTS]; - uint32_t drawVertexOffsets_[MAX_DEFERRED_DRAW_VERTS]; - DeferredInds drawInds_[MAX_DEFERRED_DRAW_INDS]; - - int numDrawVerts_ = 0; - int numDrawInds_ = 0; + enum { MAX_DEFERRED_DRAW_CALLS = 128 }; + DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS]; + int numDrawCalls = 0; int vertexCountInDrawCalls_ = 0; - int decodeVertsCounter_ = 0; - int decodeIndsCounter_ = 0; + int decimationCounter_ = 0; + int decodeCounter_ = 0; + u32 dcid_ = 0; // Vertex collector state IndexGenerator indexGen; @@ -285,9 +235,4 @@ protected: // Hardware tessellation TessellationDataTransfer *tessDataTransfer; - - // Culling - Plane planes_[6]; - Vec2f minOffset_; - Vec2f maxOffset_; }; diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 1bbdd19ac..efa17e650 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -107,11 +107,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu bool colorTestAgainstZero = id.Bit(FS_BIT_COLOR_AGAINST_ZERO); bool doTextureProjection = id.Bit(FS_BIT_DO_TEXTURE_PROJ); - bool ubershader = id.Bit(FS_BIT_UBERSHADER); - // ubershader-controlled bits. If ubershader is on, these will not be used below (and will be false). - bool useTexAlpha = id.Bit(FS_BIT_TEXALPHA); - bool enableColorDouble = id.Bit(FS_BIT_DOUBLE_COLOR); - if (texture3D && arrayTexture) { *errorString = "Invalid combination of 3D texture and array texture, shouldn't happen"; return false; @@ -171,8 +166,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu bool fetchFramebuffer = needFramebufferRead && id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH); bool readFramebufferTex = needFramebufferRead && !id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH); - if (fetchFramebuffer && (compat.shaderLanguage != GLSL_3xx || !compat.lastFragData)) { - *errorString = "framebuffer fetch requires GLSL 3xx"; + if (fetchFramebuffer && compat.shaderLanguage != GLSL_VULKAN && (compat.shaderLanguage != GLSL_3xx || !compat.lastFragData)) { + *errorString = "framebuffer fetch requires GLSL: vulkan or 3xx"; return false; } @@ -204,6 +199,9 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu if (readFramebufferTex) { // The framebuffer texture is always bound as an array. p.F("layout (set = 0, binding = %d) uniform sampler2DArray fbotex;\n", DRAW_BINDING_2ND_TEXTURE); + } else if (fetchFramebuffer) { + p.F("layout (input_attachment_index = 0, set = 0, binding = %d) uniform subpassInput inputColor;\n", DRAW_BINDING_INPUT_ATTACHMENT); + *fragmentShaderFlags |= FragmentShaderFlags::INPUT_ATTACHMENT; } if (shaderDepalMode != ShaderDepalMode::OFF) { @@ -266,9 +264,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu if (texFunc == GE_TEXFUNC_BLEND) { WRITE(p, "float3 u_texenv : register(c%i);\n", CONST_PS_TEXENV); } - if (ubershader) { - WRITE(p, "float2 u_texNoAlphaMul : register(c%i);\n", CONST_PS_TEX_NO_ALPHA_MUL); - } + WRITE(p, "float u_texNoAlpha : register(c%i);\n", CONST_PS_TEX_NO_ALPHA); + WRITE(p, "float u_texMul : register(c%i);\n", CONST_PS_TEX_MUL); } if (enableFog) { WRITE(p, "float3 u_fogcolor : register(c%i);\n", CONST_PS_FOGCOLOR); @@ -367,9 +364,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, "uniform sampler2D tex;\n"); } *uniformMask |= DIRTY_TEX_ALPHA_MUL; - if (ubershader) { - WRITE(p, "uniform vec2 u_texNoAlphaMul;\n"); - } + WRITE(p, "uniform float u_texNoAlpha;\n"); + WRITE(p, "uniform float u_texMul;\n"); } if (readFramebufferTex) { @@ -717,7 +713,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu // lookup with the filtered value once. p.F(" vec4 t = ").SampleTexture2D("tex", "uv").C(";\n"); p.C(" uint depalShift = (u_depal_mask_shift_off_fmt >> 0x8u) & 0xFFu;\n"); - p.C(" uint depalOffset = ((u_depal_mask_shift_off_fmt >> 0x10u) & 0xFFu) << 0x4u;\n"); p.C(" uint depalFmt = (u_depal_mask_shift_off_fmt >> 0x18u) & 0x3u;\n"); p.C(" float index0 = t.r;\n"); p.C(" float factor = 31.0 / 256.0;\n"); @@ -728,8 +723,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu p.C(" if (depalShift == 0x5u) { index0 = t.g; }\n"); p.C(" else if (depalShift == 0xAu) { index0 = t.b; }\n"); p.C(" }\n"); - p.C(" float offset = float(depalOffset) / 256.0;\n"); - p.F(" t = ").SampleTexture2D("pal", "vec2((index0 * factor + offset) * 0.5 + 0.5 / 512.0, 0.0)").C(";\n"); // 0.5 for 512-entry CLUT. + p.F(" t = ").SampleTexture2D("pal", "vec2(index0 * factor * 0.5, 0.0)").C(";\n"); // 0.5 for 512-entry CLUT. break; case ShaderDepalMode::NORMAL: if (doTextureProjection) { @@ -850,11 +844,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " vec4 p = v_color0;\n"); if (texFunc != GE_TEXFUNC_REPLACE) { - if (ubershader) { - WRITE(p, " t.a = max(t.a, u_texNoAlphaMul.x);\n"); - } else if (!useTexAlpha) { - WRITE(p, " t.a = 1.0;\n"); - } + WRITE(p, " t.a = max(t.a, u_texNoAlpha);\n"); } switch (texFunc) { @@ -869,11 +859,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu break; case GE_TEXFUNC_REPLACE: WRITE(p, " vec4 r = t;\n"); - if (ubershader) { - WRITE(p, " r.a = mix(r.a, p.a, u_texNoAlphaMul.x);\n"); - } else if (!useTexAlpha) { - WRITE(p, " r.a = p.a;\n"); - } + WRITE(p, " r.a = mix(r.a, p.a, u_texNoAlpha);\n"); WRITE(p, " vec4 v = r%s;\n", secondary); break; case GE_TEXFUNC_ADD: @@ -892,14 +878,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu *uniformMask |= DIRTY_TEX_ALPHA_MUL; // We only need a clamp if the color will be further processed. Otherwise the hardware color conversion will clamp for us. - if (ubershader) { - if (enableFog || enableColorTest || replaceBlend != REPLACE_BLEND_NO || simulateLogicOpType != LOGICOPTYPE_NORMAL || colorWriteMask || blueToAlpha) { - WRITE(p, " v.rgb = clamp(v.rgb * u_texNoAlphaMul.y, 0.0, 1.0);\n"); - } else { - WRITE(p, " v.rgb *= u_texNoAlphaMul.y;\n"); - } - } else if (enableColorDouble) { - p.C(" v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n"); + if (enableFog || enableColorTest || replaceBlend != REPLACE_BLEND_NO || simulateLogicOpType != LOGICOPTYPE_NORMAL || colorWriteMask || blueToAlpha) { + WRITE(p, " v.rgb = clamp(v.rgb * u_texMul, 0.0, 1.0);\n"); + } else { + WRITE(p, " v.rgb *= u_texMul;\n"); } } else { // No texture mapping diff --git a/GPU/Common/FragmentShaderGenerator.h b/GPU/Common/FragmentShaderGenerator.h index 63f0a5204..abfa97ff1 100644 --- a/GPU/Common/FragmentShaderGenerator.h +++ b/GPU/Common/FragmentShaderGenerator.h @@ -36,7 +36,8 @@ struct FShaderID; #define CONST_PS_TEXCLAMP 8 #define CONST_PS_TEXCLAMPOFF 9 #define CONST_PS_MIPBIAS 10 -#define CONST_PS_TEX_NO_ALPHA_MUL 11 +#define CONST_PS_TEX_NO_ALPHA 11 +#define CONST_PS_TEX_MUL 12 // For stencil upload #define BCONST_PS_STENCILVALUE 13 @@ -46,6 +47,7 @@ struct FShaderID; // Can technically be deduced from the fragment shader ID, but this is safer. enum class FragmentShaderFlags : u32 { + INPUT_ATTACHMENT = 1, USES_DISCARD = 2, }; ENUM_CLASS_BITOPS(FragmentShaderFlags); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 20f3bc87c..9876952f3 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -28,7 +28,7 @@ #include "Common/Math/lin/matrix4x4.h" #include "Common/Math/math_util.h" #include "Common/System/Display.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/VR/PPSSPPVR.h" #include "Common/CommonTypes.h" #include "Common/StringUtils.h" @@ -426,6 +426,14 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer u32 v_fb_end_ptr = v->fb_address + v->fb_stride * v->height * bpp; if (params.fb_address > v->fb_address && params.fb_address < v_fb_first_line_end_ptr) { + // If the framebuffer we can join to is currently bound as a texture, we likely have + // a situation like in #9324 and don't want to do this. + u32 curTextureAddress = gstate.getTextureAddress(0); + if (v->fb_address == curTextureAddress) { + // Don't try these joining shenanigans. + continue; + } + const int x_offset = (params.fb_address - v->fb_address) / bpp; if (x_offset < params.fb_stride && v->height >= drawing_height) { // Pretty certainly a pure render-to-X-offset. @@ -1208,6 +1216,8 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int vfb ? vfb->bufferHeight : g_display.pixel_yres, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags); + gpuStats.numUploads++; + pixelsTex->Release(); draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); @@ -1310,46 +1320,17 @@ void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { Draw::DataFormat depthFormat = Draw::DataFormat::UNDEFINED; - - int bpp = BufferFormatBytesPerPixel(srcPixelFormat); - int srcStrideInBytes = srcStride * bpp; - int widthInBytes = width * bpp; - - // Compute hash of contents. - uint64_t imageHash; - if (widthInBytes == srcStrideInBytes) { - imageHash = XXH3_64bits(srcPixels, widthInBytes * height); - } else { - XXH3_state_t *hashState = XXH3_createState(); - XXH3_64bits_reset(hashState); - for (int y = 0; y < height; y++) { - XXH3_64bits_update(hashState, srcPixels + srcStrideInBytes * y, widthInBytes); - } - imageHash = XXH3_64bits_digest(hashState); - XXH3_freeState(hashState); - } - - Draw::DataFormat texFormat = preferredPixelsFormat_; - if (srcPixelFormat == GE_FORMAT_DEPTH16) { if ((draw_->GetDataFormatSupport(Draw::DataFormat::R16_UNORM) & Draw::FMT_TEXTURE) != 0) { - texFormat = Draw::DataFormat::R16_UNORM; + depthFormat = Draw::DataFormat::R16_UNORM; } else if ((draw_->GetDataFormatSupport(Draw::DataFormat::R8_UNORM) & Draw::FMT_TEXTURE) != 0) { // This could be improved by using specific draw shaders to pack full precision in two channels. // However, not really worth the trouble until we find a game that requires it. - texFormat = Draw::DataFormat::R8_UNORM; + depthFormat = Draw::DataFormat::R8_UNORM; } else { // No usable single channel format. Can't be bothered. return nullptr; } - } else if (srcPixelFormat == GE_FORMAT_565) { - // Check for supported matching formats. - // This mainly benefits the redundant copies in God of War on low-end platforms. - if ((draw_->GetDataFormatSupport(Draw::DataFormat::B5G6R5_UNORM_PACK16) & Draw::FMT_TEXTURE) != 0) { - texFormat = Draw::DataFormat::B5G6R5_UNORM_PACK16; - } else if ((draw_->GetDataFormatSupport(Draw::DataFormat::R5G6B5_UNORM_PACK16) & Draw::FMT_TEXTURE) != 0) { - texFormat = Draw::DataFormat::R5G6B5_UNORM_PACK16; - } } // TODO: We can just change the texture format and flip some bits around instead of this. @@ -1363,33 +1344,28 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G u8 *dst8 = (u8 *)(data + byteStride * y); switch (srcPixelFormat) { case GE_FORMAT_565: - if (texFormat == Draw::DataFormat::B5G6R5_UNORM_PACK16) { - memcpy(dst16, src16, w * sizeof(uint16_t)); - } else if (texFormat == Draw::DataFormat::R5G6B5_UNORM_PACK16) { - ConvertRGB565ToBGR565(dst16, src16, width); // Fast! - } else if (texFormat == Draw::DataFormat::B8G8R8A8_UNORM) { + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) ConvertRGB565ToBGRA8888(dst, src16, width); - } else { + else ConvertRGB565ToRGBA8888(dst, src16, width); - } break; case GE_FORMAT_5551: - if (texFormat == Draw::DataFormat::B8G8R8A8_UNORM) + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) ConvertRGBA5551ToBGRA8888(dst, src16, width); else ConvertRGBA5551ToRGBA8888(dst, src16, width); break; case GE_FORMAT_4444: - if (texFormat == Draw::DataFormat::B8G8R8A8_UNORM) + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) ConvertRGBA4444ToBGRA8888(dst, src16, width); else ConvertRGBA4444ToRGBA8888(dst, src16, width); break; case GE_FORMAT_8888: - if (texFormat == Draw::DataFormat::B8G8R8A8_UNORM) + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) ConvertRGBA8888ToBGRA8888(dst, src32, width); // This means use original pointer as-is. May avoid or optimize a copy. else if (srcStride == width) @@ -1404,10 +1380,10 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G // to do one of two different swizzle operations. However, for the only use of this so far, // the Burnout lens flare trickery, swizzle doesn't matter since it's just a 0, 7fff, 0, 7fff pattern // which comes out the same. - if (texFormat == Draw::DataFormat::R16_UNORM) { + if (depthFormat == Draw::DataFormat::R16_UNORM) { // We just use this format straight. memcpy(dst16, src16, w * 2); - } else if (texFormat == Draw::DataFormat::R8_UNORM) { + } else if (depthFormat == Draw::DataFormat::R8_UNORM) { // We fall back to R8_UNORM. Precision is enough for most cases of depth clearing and initialization we've seen, // but hardly ideal. for (int i = 0; i < width; i++) { @@ -1425,38 +1401,11 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G return true; }; - int frameNumber = draw_->GetFrameCount(); - - // First look for an exact match (including contents hash) that we can re-use. - for (auto &iter : drawPixelsCache_) { - if (iter.contentsHash == imageHash && iter.tex->Width() == width && iter.tex->Height() == height && iter.tex->Format() == texFormat) { - iter.frameNumber = frameNumber; - gpuStats.numCachedUploads++; - return iter.tex; - } - } - - // Then, look for an alternative one that's not been used recently that we can overwrite. - for (auto &iter : drawPixelsCache_) { - if (iter.frameNumber >= frameNumber - 3 || iter.tex->Width() != width || iter.tex->Height() != height || iter.tex->Format() != texFormat) { - continue; - } - - // OK, current one seems good, let's use it (and mark it used). - gpuStats.numUploads++; - draw_->UpdateTextureLevels(iter.tex, &srcPixels, generateTexture, 1); - // NOTE: numFlips is no good - this is called every frame when paused sometimes! - iter.frameNumber = frameNumber; - // We need to update the hash for future matching. - iter.contentsHash = imageHash; - return iter.tex; - } - // Note: For depth, we create an R16_UNORM texture, that'll be just fine for uploading depth through a shader, // and likely more efficient. Draw::TextureDesc desc{ Draw::TextureType::LINEAR2D, - texFormat, + srcPixelFormat == GE_FORMAT_DEPTH16 ? depthFormat : preferredPixelsFormat_, width, height, 1, @@ -1469,18 +1418,10 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G }; // Hot Shots Golf (#12355) does tons of these in a frame in some situations! So creating textures - // better be fast. So does God of War, a lot of the time, a bit unclear what it's doing. + // better be fast. Draw::Texture *tex = draw_->CreateTexture(desc); - if (!tex) { + if (!tex) ERROR_LOG(G3D, "Failed to create DrawPixels texture"); - } - // We don't need to count here, already counted by numUploads by the caller. - - // INFO_LOG(G3D, "Creating drawPixelsCache texture: %dx%d", tex->Width(), tex->Height()); - - DrawPixelsEntry entry{ tex, imageHash, frameNumber }; - drawPixelsCache_.push_back(entry); - gpuStats.numUploads++; return tex; } @@ -1507,6 +1448,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int presentation_->UpdateUniforms(textureCache_->VideoIsPlaying()); presentation_->SourceTexture(pixelsTex, 512, 272); presentation_->CopyToOutput(flags, uvRotation, u0, v0, u1, v1); + pixelsTex->Release(); // PresentationCommon sets all kinds of state, we can't rely on anything. gstate_c.Dirty(DIRTY_ALL); @@ -1593,8 +1535,10 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { if (!vfb) { if (Memory::IsValidAddress(fbaddr)) { // The game is displaying something directly from RAM. In GTA, it's decoded video. - DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_); - return; + if (!vfb) { + DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_); + return; + } } else { DEBUG_LOG(FRAMEBUF, "Found no FBO to display! displayFBPtr = %08x", fbaddr); // No framebuffer to display! Clear to black. @@ -1726,20 +1670,6 @@ void FramebufferManagerCommon::DecimateFBOs() { bvfbs_.erase(bvfbs_.begin() + i--); } } - - // And DrawPixels cached textures. - - for (auto it = drawPixelsCache_.begin(); it != drawPixelsCache_.end(); ) { - int age = draw_->GetFrameCount() - it->frameNumber; - if (age > 10) { - // INFO_LOG(G3D, "Releasing drawPixelsCache texture: %dx%d", it->tex->Width(), it->tex->Height()); - it->tex->Release(); - it->tex = nullptr; - it = drawPixelsCache_.erase(it); - } else { - ++it; - } - } } // Requires width/height to be set already. @@ -1857,46 +1787,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, } } -struct CopyCandidate { - VirtualFramebuffer *vfb = nullptr; - int y; - int h; - - std::string ToString(RasterChannel channel) const { - return StringFromFormat("%08x %s %dx%d y=%d h=%d", vfb->Address(channel), GeBufferFormatToString(vfb->Format(channel)), vfb->width, vfb->height, y, h); - } -}; - -static const CopyCandidate *GetBestCopyCandidate(const TinySet &candidates, uint32_t basePtr, RasterChannel channel) { - const CopyCandidate *best = nullptr; - - // Pick the "best" candidate by comparing to the old best using heuristics. - for (size_t i = 0; i < candidates.size(); i++) { - const CopyCandidate *candidate = &candidates[i]; - - bool better = !best; - if (!better) { - // Heuristics determined from the old algorithm, that we might want to keep: - // * Lower yOffsets are prioritized. - // * Bindseq - better = candidate->y < best->y; - if (!better) { - better = candidate->vfb->BindSeq(channel) > best->vfb->BindSeq(channel); - } - } - - if (better) { - best = candidate; - } - } - return best; -} - // This is called from detected memcopies and framebuffer initialization from VRAM. Not block transfers. -// Also with specialized flags from some replacement functions. Only those will currently request depth copies! -// NOTE: This is very tricky because there's no information about color depth here, so we'll have to make guesses -// about what underlying framebuffer is the most likely to be the relevant ones. For src, we can probably prioritize recent -// ones. For dst, less clear. bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, GPUCopyFlag flags, u32 skipDrawReason) { if (size == 0) { return false; @@ -1913,158 +1804,91 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, // Or at least this should be like the other ones, gathering possible candidates // with the ability to list them out for debugging. + VirtualFramebuffer *dstBuffer = nullptr; + VirtualFramebuffer *srcBuffer = nullptr; bool ignoreDstBuffer = flags & GPUCopyFlag::FORCE_DST_MATCH_MEM; bool ignoreSrcBuffer = flags & (GPUCopyFlag::FORCE_SRC_MATCH_MEM | GPUCopyFlag::MEMSET); - - // TODO: In the future we should probably check both channels. Currently depth is only on request. RasterChannel channel = flags & GPUCopyFlag::DEPTH_REQUESTED ? RASTER_DEPTH : RASTER_COLOR; - TinySet srcCandidates; - TinySet dstCandidates; - - // TODO: These two loops should be merged into one utility function, similar to what's done with rectangle copies. - - // First find candidates for the source. - // We only look at the color channel for now. + u32 dstY = (u32)-1; + u32 dstH = 0; + u32 srcY = (u32)-1; + u32 srcH = 0; for (auto vfb : vfbs_) { - if (vfb->fb_stride == 0 || ignoreSrcBuffer) { + if (vfb->fb_stride == 0 || channel != RASTER_COLOR) { continue; } // We only remove the kernel and uncached bits when comparing. - const u32 vfb_address = vfb->Address(channel); - const u32 vfb_size = vfb->BufferByteSize(channel); - const u32 vfb_byteStride = vfb->BufferByteStride(channel); - const int vfb_byteWidth = vfb->BufferByteWidth(channel); - - CopyCandidate srcCandidate; - srcCandidate.vfb = vfb; - - // Special path for depth for now. - if (channel == RASTER_DEPTH) { - if (src == vfb->z_address && size == vfb->z_stride * 2 * vfb->height) { - srcCandidate.y = 0; - srcCandidate.h = vfb->height; - srcCandidates.push_back(srcCandidate); - } - continue; - } - - if (src >= vfb_address && (src + size <= vfb_address + vfb_size || src == vfb_address)) { - if ((u32)size > vfb_size + 0x1000 && vfb->fb_format != GE_FORMAT_8888 && vfb->last_frame_render < gpuStats.numFlips) { - // Seems likely we are looking at a potential copy of 32-bit pixels (like video) to an old 16-bit buffer, - // which is very likely simply the wrong target, so skip it. See issue #17740 where this happens in Naruto Ultimate Ninja Heroes 2. - // Probably no point to give it a bad score and let it pass to sorting, as we're pretty sure here. - WARN_LOG_N_TIMES(notify_copy_2x, 5, G3D, "Framebuffer size %08x too small for %08x bytes of data and also 16-bit (%s), and not rendered to this frame. Ignoring.", vfb_size, size, GeBufferFormatToString(vfb->fb_format)); - continue; - } - - const u32 offset = src - vfb_address; - const u32 yOffset = offset / vfb_byteStride; - if ((offset % vfb_byteStride) == 0 && (size == vfb_byteWidth || (size % vfb_byteStride) == 0)) { - srcCandidate.y = yOffset; - srcCandidate.h = size == vfb_byteWidth ? 1 : std::min((u32)size / vfb_byteStride, (u32)vfb->height); - } else if ((offset % vfb_byteStride) == 0 && size == vfb->fb_stride) { - // Valkyrie Profile reads 512 bytes at a time, rather than 2048. So, let's whitelist fb_stride also. - srcCandidate.y = yOffset; - srcCandidate.h = 1; - } else if (yOffset == 0 && (vfb->usageFlags & FB_USAGE_CLUT)) { - // Okay, last try - it might be a clut. - srcCandidate.y = yOffset; - srcCandidate.h = 1; - } else { - continue; - } - srcCandidates.push_back(srcCandidate); - } - } - - for (auto vfb : vfbs_) { - if (vfb->fb_stride == 0 || ignoreDstBuffer) { - continue; - } - - // We only remove the kernel and uncached bits when comparing. - const u32 vfb_address = vfb->Address(channel); - const u32 vfb_size = vfb->BufferByteSize(channel); - const u32 vfb_byteStride = vfb->BufferByteStride(channel); - const int vfb_byteWidth = vfb->BufferByteWidth(channel); + const u32 vfb_address = vfb->fb_address; + const u32 vfb_size = vfb->BufferByteSize(RASTER_COLOR); + const u32 vfb_bpp = BufferFormatBytesPerPixel(vfb->fb_format); + const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp; + const int vfb_byteWidth = vfb->width * vfb_bpp; // Heuristic to try to prevent potential glitches with video playback. - if (vfb_address == dst && ((size == 0x44000 && vfb_size == 0x88000) || (size == 0x88000 && vfb_size == 0x44000))) { + if (!ignoreDstBuffer && vfb_address == dst && ((size == 0x44000 && vfb_size == 0x88000) || (size == 0x88000 && vfb_size == 0x44000))) { // Not likely to be a correct color format copy for this buffer. Ignore it, there will either be RAM // that can be displayed from, or another matching buffer with the right format if rendering is going on. - // If we had scoring here, we should strongly penalize this target instead of ignoring it. WARN_LOG_N_TIMES(notify_copy_2x, 5, G3D, "Framebuffer size %08x conspicuously not matching copy size %08x in NotifyFramebufferCopy. Ignoring.", size, vfb_size); continue; } - CopyCandidate dstCandidate; - dstCandidate.vfb = vfb; - - // Special path for depth for now. - if (channel == RASTER_DEPTH) { - // Let's assume exact matches only for simplicity. - if (dst == vfb->z_address && size == vfb->z_stride * 2 * vfb->height) { - dstCandidate.y = 0; - dstCandidate.h = vfb->height; - dstCandidates.push_back(dstCandidate); - } - continue; - } - if (!ignoreDstBuffer && dst >= vfb_address && (dst + size <= vfb_address + vfb_size || dst == vfb_address)) { const u32 offset = dst - vfb_address; const u32 yOffset = offset / vfb_byteStride; - if ((offset % vfb_byteStride) == 0 && (size == vfb_byteWidth || (size % vfb_byteStride) == 0)) { - dstCandidate.y = yOffset; - dstCandidate.h = (size == vfb_byteWidth) ? 1 : std::min((u32)size / vfb_byteStride, (u32)vfb->height); - dstCandidates.push_back(dstCandidate); + if ((offset % vfb_byteStride) == 0 && (size == vfb_byteWidth || (size % vfb_byteStride) == 0) && yOffset < dstY) { + dstBuffer = vfb; + dstY = yOffset; + dstH = size == vfb_byteWidth ? 1 : std::min((u32)size / vfb_byteStride, (u32)vfb->height); + } + } + + if (!ignoreSrcBuffer && src >= vfb_address && (src + size <= vfb_address + vfb_size || src == vfb_address)) { + const u32 offset = src - vfb_address; + const u32 yOffset = offset / vfb_byteStride; + if ((offset % vfb_byteStride) == 0 && (size == vfb_byteWidth || (size % vfb_byteStride) == 0) && yOffset < srcY) { + srcBuffer = vfb; + srcY = yOffset; + srcH = size == vfb_byteWidth ? 1 : std::min((u32)size / vfb_byteStride, (u32)vfb->height); + } else if ((offset % vfb_byteStride) == 0 && size == vfb->fb_stride && yOffset < srcY) { + // Valkyrie Profile reads 512 bytes at a time, rather than 2048. So, let's whitelist fb_stride also. + srcBuffer = vfb; + srcY = yOffset; + srcH = 1; + } else if (yOffset == 0 && yOffset < srcY) { + // Okay, last try - it might be a clut. + if (vfb->usageFlags & FB_USAGE_CLUT) { + srcBuffer = vfb; + srcY = yOffset; + srcH = 1; + } } } } - if (srcCandidates.size() > 1) { - if (Reporting::ShouldLogNTimes("mulblock", 5)) { - std::string log; - for (size_t i = 0; i < srcCandidates.size(); i++) { - log += " - " + srcCandidates[i].ToString(channel) + "\n"; + if (channel == RASTER_DEPTH) { + srcBuffer = nullptr; + dstBuffer = nullptr; + // Let's assume exact matches only for simplicity. + for (auto vfb : vfbs_) { + if (!ignoreDstBuffer && dst == vfb->z_address && size == vfb->z_stride * 2 * vfb->height) { + if (!dstBuffer || dstBuffer->depthBindSeq < vfb->depthBindSeq) { + dstBuffer = vfb; + dstY = 0; + dstH = vfb->height; + } } - WARN_LOG(G3D, "Copy: Multiple src vfb candidates for (src: %08x, size: %d, %s):\n%s (%s)", src, size, log.c_str(), RasterChannelToString(channel)); - } - } - - if (dstCandidates.size() > 1) { - if (Reporting::ShouldLogNTimes("mulblock", 5)) { - std::string log; - for (size_t i = 0; i < dstCandidates.size(); i++) { - log += " - " + dstCandidates[i].ToString(channel) + "\n"; + if (!ignoreSrcBuffer && src == vfb->z_address && size == vfb->z_stride * 2 * vfb->height) { + if (!srcBuffer || srcBuffer->depthBindSeq < vfb->depthBindSeq) { + srcBuffer = vfb; + srcY = 0; + srcH = vfb->height; + } } - WARN_LOG(G3D, "Copy: Multiple dst vfb candidates for (dst: %08x, size: %d):\n%s (%s)", src, size, log.c_str(), RasterChannelToString(channel)); } } - // For now fill in these old variables from the candidates to reduce the initial diff. - VirtualFramebuffer *dstBuffer = nullptr; - VirtualFramebuffer *srcBuffer = nullptr; - int srcY; - int srcH; - int dstY; - int dstH; - - const CopyCandidate *bestSrc = GetBestCopyCandidate(srcCandidates, src, channel); - if (bestSrc) { - srcBuffer = bestSrc->vfb; - srcY = bestSrc->y; - srcH = bestSrc->h; - } - const CopyCandidate *bestDst = GetBestCopyCandidate(dstCandidates, dst, channel); - if (bestDst) { - dstBuffer = bestDst->vfb; - dstY = bestDst->y; - dstH = bestDst->h; - } - if (!useBufferedRendering_) { // If we're copying into a recently used display buf, it's probably destined for the screen. if (channel == RASTER_DEPTH || srcBuffer || (dstBuffer != displayFramebuf_ && dstBuffer != prevDisplayFramebuf_)) { @@ -2103,12 +1927,8 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, if (flags & GPUCopyFlag::MEMSET) { gpuStats.numClears++; } - WARN_LOG_N_TIMES(btucpy, 5, G3D, "Memcpy fbo upload %08x -> %08x (size: %x)", src, dst, size); + WARN_LOG_ONCE(btucpy, G3D, "Memcpy fbo upload %08x -> %08x (size: %x)", src, dst, size); FlushBeforeCopy(); - - // TODO: Hot Shots Golf makes a lot of these during the "meter", to copy back the image to the screen, it copies line by line. - // We could collect these in a buffer and flush on the next draw, or something like that, to avoid that. The line copies cause - // awkward visual artefacts. const u8 *srcBase = Memory::GetPointerUnchecked(src); GEBufferFormat srcFormat = channel == RASTER_DEPTH ? GE_FORMAT_DEPTH16 : dstBuffer->fb_format; int srcStride = channel == RASTER_DEPTH ? dstBuffer->z_stride : dstBuffer->fb_stride; @@ -2118,18 +1938,12 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, // This is a memcpy, let's still copy just in case. return false; } else if (srcBuffer) { - WARN_LOG_N_TIMES(btdcpy, 5, G3D, "Memcpy fbo download %08x -> %08x", src, dst); + WARN_LOG_ONCE(btdcpy, G3D, "Memcpy fbo download %08x -> %08x", src, dst); FlushBeforeCopy(); - // TODO: In Hot Shots Golf, check if we can do a readback to a framebuffer here. - // Again we have the problem though that it's doing a lot of small copies here, one for each line. if (srcH == 0 || srcY + srcH > srcBuffer->bufferHeight) { WARN_LOG_ONCE(btdcpyheight, G3D, "Memcpy fbo download %08x -> %08x skipped, %d+%d is taller than %d", src, dst, srcY, srcH, srcBuffer->bufferHeight); } else if (!g_Config.bSkipGPUReadbacks && (!srcBuffer->memoryUpdated || channel == RASTER_DEPTH)) { - Draw::ReadbackMode readbackMode = Draw::ReadbackMode::BLOCK; - if (PSP_CoreParameter().compat.flags().AllowDelayedReadbacks) { - readbackMode = Draw::ReadbackMode::OLD_DATA_OK; - } - ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH, channel, readbackMode); + ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH, channel, Draw::ReadbackMode::BLOCK); srcBuffer->usageFlags = (srcBuffer->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; } return false; @@ -2653,11 +2467,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst if (tooTall) { WARN_LOG_ONCE(btdheight, G3D, "Block transfer download %08x -> %08x dangerous, %d+%d is taller than %d", srcBasePtr, dstBasePtr, srcRect.y, srcRect.h, srcRect.vfb->bufferHeight); } - Draw::ReadbackMode readbackMode = Draw::ReadbackMode::BLOCK; - if (PSP_CoreParameter().compat.flags().AllowDelayedReadbacks) { - readbackMode = Draw::ReadbackMode::OLD_DATA_OK; - } - ReadFramebufferToMemory(srcRect.vfb, static_cast(srcX * srcXFactor), srcY, static_cast(srcRect.w_bytes * srcXFactor), srcRect.h, RASTER_COLOR, readbackMode); + ReadFramebufferToMemory(srcRect.vfb, static_cast(srcX * srcXFactor), srcY, static_cast(srcRect.w_bytes * srcXFactor), srcRect.h, RASTER_COLOR, Draw::ReadbackMode::BLOCK); srcRect.vfb->usageFlags = (srcRect.vfb->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; } } @@ -2735,8 +2545,6 @@ void FramebufferManagerCommon::NotifyDisplayResized() { pixelHeight_ = PSP_CoreParameter().pixelHeight; presentation_->UpdateDisplaySize(pixelWidth_, pixelHeight_); - INFO_LOG(G3D, "FramebufferManagerCommon::NotifyDisplayResized: %dx%d", pixelWidth_, pixelHeight_); - // No drawing is allowed here. This includes anything that might potentially touch a command buffer, like creating images! // So we need to defer the post processing initialization. updatePostShaders_ = true; @@ -2758,6 +2566,13 @@ void FramebufferManagerCommon::NotifyRenderResized(int msaaLevel) { // No drawing is allowed here. This includes anything that might potentially touch a command buffer, like creating images! // So we need to defer the post processing initialization. updatePostShaders_ = true; + +#ifdef _WIN32 + // Seems related - if you're ok with numbers all the time, show some more :) + if (g_Config.iShowStatusFlags != 0) { + ShowScreenResolution(); + } +#endif } void FramebufferManagerCommon::NotifyConfigChanged() { @@ -2787,15 +2602,10 @@ void FramebufferManagerCommon::DestroyAllFBOs() { } tempFBOs_.clear(); - for (auto &iter : fbosToDelete_) { + for (auto iter : fbosToDelete_) { iter->Release(); } fbosToDelete_.clear(); - - for (auto &iter : drawPixelsCache_) { - iter.tex->Release(); - } - drawPixelsCache_.clear(); } static const char *TempFBOReasonToString(TempFBO reason) { @@ -2847,6 +2657,24 @@ void FramebufferManagerCommon::UpdateFramebufUsage(VirtualFramebuffer *vfb) { checkFlag(FB_USAGE_CLUT, vfb->last_frame_clut); } +void FramebufferManagerCommon::ShowScreenResolution() { + auto gr = GetI18NCategory(I18NCat::GRAPHICS); + + std::ostringstream messageStream; + messageStream << gr->T("Internal Resolution") << ": "; + messageStream << PSP_CoreParameter().renderWidth << "x" << PSP_CoreParameter().renderHeight << " "; + if (postShaderIsUpscalingFilter_) { + messageStream << gr->T("(upscaling)") << " "; + } else if (postShaderIsSupersampling_) { + messageStream << gr->T("(supersampling)") << " "; + } + messageStream << gr->T("Window Size") << ": "; + messageStream << PSP_CoreParameter().pixelWidth << "x" << PSP_CoreParameter().pixelHeight; + + System_NotifyUserMessage(messageStream.str(), 2.0f, 0xFFFFFF, "resize"); + INFO_LOG(SYSTEM, "%s", messageStream.str().c_str()); +} + void FramebufferManagerCommon::ClearAllDepthBuffers() { for (auto vfb : vfbs_) { vfb->usageFlags |= FB_USAGE_INVALIDATE_DEPTH; @@ -3195,11 +3023,20 @@ void FramebufferManagerCommon::RebindFramebuffer(const char *tag) { } } -std::vector FramebufferManagerCommon::GetFramebufferList() const { - std::vector list; +std::vector FramebufferManagerCommon::GetFramebufferList() const { + std::vector list; + for (auto vfb : vfbs_) { - list.push_back(vfb); + FramebufferInfo info; + info.fb_address = vfb->fb_address; + info.z_address = vfb->z_address; + info.format = vfb->fb_format; + info.width = vfb->width; + info.height = vfb->height; + info.fbo = vfb->fbo; + list.push_back(info); } + return list; } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index c2d98509d..0c23a7e41 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -161,13 +161,8 @@ struct VirtualFramebuffer { inline GEBufferFormat Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; } inline int BindSeq(RasterChannel channel) const { return channel == RASTER_COLOR ? colorBindSeq : depthBindSeq; } - // Computed from stride. - int BufferByteSize(RasterChannel channel) const { return BufferByteStride(channel) * height; } - int BufferByteStride(RasterChannel channel) const { - return channel == RASTER_COLOR ? fb_stride * (fb_format == GE_FORMAT_8888 ? 4 : 2) : z_stride * 2; - } - int BufferByteWidth(RasterChannel channel) const { - return channel == RASTER_COLOR ? width * (fb_format == GE_FORMAT_8888 ? 4 : 2) : width * 2; + int BufferByteSize(RasterChannel channel) const { + return channel == RASTER_COLOR ? fb_stride * height * (fb_format == GE_FORMAT_8888 ? 4 : 2) : z_stride * height * 2; } }; @@ -272,12 +267,6 @@ namespace Draw { class DrawContext; } -struct DrawPixelsEntry { - Draw::Texture *tex; - uint64_t contentsHash; - int frameNumber; -}; - struct GPUDebugBuffer; class DrawEngineCommon; class PresentationCommon; @@ -327,7 +316,7 @@ public: void SetDepthFrameBuffer(bool isClearingDepth); void RebindFramebuffer(const char *tag); - std::vector GetFramebufferList() const; + std::vector GetFramebufferList() const; void CopyDisplayToOutput(bool reallyDirty); @@ -515,6 +504,7 @@ protected: void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst); void ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, int h, bool force = false, bool skipCopy = false); + void ShowScreenResolution(); bool ShouldDownloadFramebufferColor(const VirtualFramebuffer *vfb) const; bool ShouldDownloadFramebufferDepth(const VirtualFramebuffer *vfb) const; @@ -581,8 +571,6 @@ protected: std::vector vfbs_; std::vector bvfbs_; // blitting framebuffers (for download) - std::vector drawPixelsCache_; - bool gameUsesSequentialCopies_ = false; // Sampled in BeginFrame/UpdateSize for safety. diff --git a/GPU/Common/GPUDebugInterface.cpp b/GPU/Common/GPUDebugInterface.cpp index 743d88409..c6df47e93 100644 --- a/GPU/Common/GPUDebugInterface.cpp +++ b/GPU/Common/GPUDebugInterface.cpp @@ -17,7 +17,6 @@ #include "Common/Log.h" #include "Common/Math/expression_parser.h" -#include "Common/StringUtils.h" #include "Core/Debugger/SymbolMap.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Debugger/Debugger.h" @@ -517,7 +516,7 @@ public: bool parseSymbol(char *str, uint32_t &symbolValue) override; uint32_t getReferenceValue(uint32_t referenceIndex) override; ExpressionType getReferenceType(uint32_t referenceIndex) override; - bool getMemoryValue(uint32_t address, int size, uint32_t &dest, std::string *error) override; + bool getMemoryValue(uint32_t address, int size, uint32_t &dest, char *error, size_t errorBufSize) override; private: bool parseFieldReference(const char *ref, const char *field, uint32_t &referenceIndex); @@ -927,7 +926,7 @@ ExpressionType GEExpressionFunctions::getFieldType(GECmdFormat fmt, GECmdField f return EXPR_TYPE_UINT; } -bool GEExpressionFunctions::getMemoryValue(uint32_t address, int size, uint32_t &dest, std::string *error) { +bool GEExpressionFunctions::getMemoryValue(uint32_t address, int size, uint32_t &dest, char *error, size_t errorBufSize) { // We allow, but ignore, bad access. // If we didn't, log/condition statements that reference registers couldn't be configured. uint32_t valid = Memory::ValidSize(address, size); @@ -947,7 +946,7 @@ bool GEExpressionFunctions::getMemoryValue(uint32_t address, int size, uint32_t return true; } - *error = StringFromFormat("Unexpected memory access size %d", size); + snprintf(error, errorBufSize, "Unexpected memory access size %d", size); return false; } diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index 974ebc241..54ff31481 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -252,6 +252,14 @@ public: virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer) { return false; } + + // TODO: + // cached framebuffers / textures / vertices? + // get content of specific framebuffer / texture? + // vertex / texture decoding? + + // Note: Wanted to name it GetProfileString but clashes with a Windows API. + virtual std::string GetGpuProfileString() { return ""; } }; bool GPUDebugInitExpression(GPUDebugInterface *g, const char *str, PostfixExpression &exp); diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 2177bf31d..bf8816945 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -290,15 +290,8 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) { return REPLACE_BLEND_READ_FRAMEBUFFER; } - case GE_BLENDMODE_MUL_AND_ADD: - case GE_BLENDMODE_MUL_AND_SUBTRACT: - case GE_BLENDMODE_MUL_AND_SUBTRACT_REVERSE: - // Handled below. - break; - default: - // Other blend equations simply don't blend on hardware. - return REPLACE_BLEND_NO; + break; } GEBlendSrcFactor funcA = gstate.getBlendFuncA(); diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index af1f6c6ed..a786190f6 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -249,6 +249,8 @@ struct GenericLogicState { // Same logicOp is kept. } } + + void Log(); }; struct ComputedPipelineState { diff --git a/GPU/Common/IndexGenerator.cpp b/GPU/Common/IndexGenerator.cpp index 45a23d991..446d7a680 100644 --- a/GPU/Common/IndexGenerator.cpp +++ b/GPU/Common/IndexGenerator.cpp @@ -50,39 +50,45 @@ void IndexGenerator::Setup(u16 *inds) { Reset(); } -void IndexGenerator::AddPrim(int prim, int vertexCount, int indexOffset, bool clockwise) { +void IndexGenerator::AddPrim(int prim, int vertexCount, bool clockwise) { switch (prim) { - case GE_PRIM_POINTS: AddPoints(vertexCount, indexOffset); break; - case GE_PRIM_LINES: AddLineList(vertexCount, indexOffset); break; - case GE_PRIM_LINE_STRIP: AddLineStrip(vertexCount, indexOffset); break; - case GE_PRIM_TRIANGLES: AddList(vertexCount, indexOffset, clockwise); break; - case GE_PRIM_TRIANGLE_STRIP: AddStrip(vertexCount, indexOffset, clockwise); break; - case GE_PRIM_TRIANGLE_FAN: AddFan(vertexCount, indexOffset, clockwise); break; - case GE_PRIM_RECTANGLES: AddRectangles(vertexCount, indexOffset); break; // Same + case GE_PRIM_POINTS: AddPoints(vertexCount); break; + case GE_PRIM_LINES: AddLineList(vertexCount); break; + case GE_PRIM_LINE_STRIP: AddLineStrip(vertexCount); break; + case GE_PRIM_TRIANGLES: AddList(vertexCount, clockwise); break; + case GE_PRIM_TRIANGLE_STRIP: AddStrip(vertexCount, clockwise); break; + case GE_PRIM_TRIANGLE_FAN: AddFan(vertexCount, clockwise); break; + case GE_PRIM_RECTANGLES: AddRectangles(vertexCount); break; // Same } } -void IndexGenerator::AddPoints(int numVerts, int indexOffset) { +void IndexGenerator::AddPoints(int numVerts) { u16 *outInds = inds_; + const int startIndex = index_; for (int i = 0; i < numVerts; i++) - *outInds++ = indexOffset + i; + *outInds++ = startIndex + i; inds_ = outInds; // ignore overflow verts + index_ += numVerts; + count_ += numVerts; prim_ = GE_PRIM_POINTS; seenPrims_ |= 1 << GE_PRIM_POINTS; } -void IndexGenerator::AddList(int numVerts, int indexOffset, bool clockwise) { +void IndexGenerator::AddList(int numVerts, bool clockwise) { u16 *outInds = inds_; + const int startIndex = index_; const int v1 = clockwise ? 1 : 2; const int v2 = clockwise ? 2 : 1; for (int i = 0; i < numVerts; i += 3) { - *outInds++ = indexOffset + i; - *outInds++ = indexOffset + i + v1; - *outInds++ = indexOffset + i + v2; + *outInds++ = startIndex + i; + *outInds++ = startIndex + i + v1; + *outInds++ = startIndex + i + v2; } inds_ = outInds; // ignore overflow verts + index_ += numVerts; + count_ += numVerts; prim_ = GE_PRIM_TRIANGLES; seenPrims_ |= 1 << GE_PRIM_TRIANGLES; if (!clockwise) { @@ -113,11 +119,9 @@ alignas(16) static const uint16_t offsets_counter_clockwise[24] = { 7, (u16)(7 + 1), (u16)(7 + 2), }; -void IndexGenerator::AddStrip(int numVerts, int indexOffset, bool clockwise) { +void IndexGenerator::AddStrip(int numVerts, bool clockwise) { int numTris = numVerts - 2; - if (numTris <= 0) { - return; - } + #ifdef _M_SSE // In an SSE2 register we can fit 8 16-bit integers. // However, we need to output a multiple of 3 indices. @@ -126,63 +130,44 @@ void IndexGenerator::AddStrip(int numVerts, int indexOffset, bool clockwise) { // We allow ourselves to write some extra indices to avoid the fallback loop. // That's alright as we're appending to a buffer - they will get overwritten anyway. - __m128i ibase8 = _mm_set1_epi16(indexOffset); + int numChunks = (numTris + 7) / 8; + __m128i ibase8 = _mm_set1_epi16(index_); + __m128i increment = _mm_set1_epi16(8); const __m128i *offsets = (const __m128i *)(clockwise ? offsets_clockwise : offsets_counter_clockwise); + __m128i offsets0 = _mm_load_si128(offsets); + __m128i offsets1 = _mm_load_si128(offsets + 1); + __m128i offsets2 = _mm_load_si128(offsets + 2); __m128i *dst = (__m128i *)inds_; - __m128i offsets0 = _mm_add_epi16(ibase8, _mm_load_si128(offsets)); - // A single store is always enough for two triangles, which is a very common case. - _mm_storeu_si128(dst, offsets0); - if (numTris > 2) { - __m128i offsets1 = _mm_add_epi16(ibase8, _mm_load_si128(offsets + 1)); - _mm_storeu_si128(dst + 1, offsets1); - if (numTris > 5) { - __m128i offsets2 = _mm_add_epi16(ibase8, _mm_load_si128(offsets + 2)); - _mm_storeu_si128(dst + 2, offsets2); - __m128i increment = _mm_set1_epi16(8); - int numChunks = (numTris + 7) >> 3; - for (int i = 1; i < numChunks; i++) { - dst += 3; - offsets0 = _mm_add_epi16(offsets0, increment); - offsets1 = _mm_add_epi16(offsets1, increment); - offsets2 = _mm_add_epi16(offsets2, increment); - _mm_storeu_si128(dst, offsets0); - _mm_storeu_si128(dst + 1, offsets1); - _mm_storeu_si128(dst + 2, offsets2); - } - } + for (int i = 0; i < numChunks; i++) { + _mm_storeu_si128(dst, _mm_add_epi16(ibase8, offsets0)); + _mm_storeu_si128(dst + 1, _mm_add_epi16(ibase8, offsets1)); + _mm_storeu_si128(dst + 2, _mm_add_epi16(ibase8, offsets2)); + ibase8 = _mm_add_epi16(ibase8, increment); + dst += 3; } inds_ += numTris * 3; // wind doesn't need to be updated, an even number of triangles have been drawn. #elif PPSSPP_ARCH(ARM_NEON) - uint16x8_t ibase8 = vdupq_n_u16(indexOffset); + int numChunks = (numTris + 7) / 8; + uint16x8_t ibase8 = vdupq_n_u16(index_); + uint16x8_t increment = vdupq_n_u16(8); const u16 *offsets = clockwise ? offsets_clockwise : offsets_counter_clockwise; + uint16x8_t offsets0 = vld1q_u16(offsets); + uint16x8_t offsets1 = vld1q_u16(offsets + 8); + uint16x8_t offsets2 = vld1q_u16(offsets + 16); u16 *dst = inds_; - uint16x8_t offsets0 = vaddq_u16(ibase8, vld1q_u16(offsets)); - vst1q_u16(dst, offsets0); - if (numTris > 2) { - uint16x8_t offsets1 = vaddq_u16(ibase8, vld1q_u16(offsets + 8)); - vst1q_u16(dst + 8, offsets1); - if (numTris > 5) { - uint16x8_t offsets2 = vaddq_u16(ibase8, vld1q_u16(offsets + 16)); - vst1q_u16(dst + 16, offsets2); - uint16x8_t increment = vdupq_n_u16(8); - int numChunks = (numTris + 7) >> 3; - for (int i = 1; i < numChunks; i++) { - dst += 3 * 8; - offsets0 = vaddq_u16(offsets0, increment); - offsets1 = vaddq_u16(offsets1, increment); - offsets2 = vaddq_u16(offsets2, increment); - vst1q_u16(dst, offsets0); - vst1q_u16(dst + 8, offsets1); - vst1q_u16(dst + 16, offsets2); - } - } + for (int i = 0; i < numChunks; i++) { + vst1q_u16(dst, vaddq_u16(ibase8, offsets0)); + vst1q_u16(dst + 8, vaddq_u16(ibase8, offsets1)); + vst1q_u16(dst + 16, vaddq_u16(ibase8, offsets2)); + ibase8 = vaddq_u16(ibase8, increment); + dst += 3 * 8; } inds_ += numTris * 3; #else // Slow fallback loop. int wind = clockwise ? 1 : 2; - int ibase = indexOffset; + int ibase = index_; size_t numPairs = numTris / 2; u16 *outInds = inds_; while (numPairs > 0) { @@ -204,6 +189,9 @@ void IndexGenerator::AddStrip(int numVerts, int indexOffset, bool clockwise) { inds_ = outInds; #endif + index_ += numVerts; + if (numTris > 0) + count_ += numTris * 3; // This is so we can detect one single strip by just looking at seenPrims_. if (!seenPrims_ && clockwise) { seenPrims_ = 1 << GE_PRIM_TRIANGLE_STRIP; @@ -216,17 +204,20 @@ void IndexGenerator::AddStrip(int numVerts, int indexOffset, bool clockwise) { } } -void IndexGenerator::AddFan(int numVerts, int indexOffset, bool clockwise) { +void IndexGenerator::AddFan(int numVerts, bool clockwise) { const int numTris = numVerts - 2; u16 *outInds = inds_; + const int startIndex = index_; const int v1 = clockwise ? 1 : 2; const int v2 = clockwise ? 2 : 1; for (int i = 0; i < numTris; i++) { - *outInds++ = indexOffset; - *outInds++ = indexOffset + i + v1; - *outInds++ = indexOffset + i + v2; + *outInds++ = startIndex; + *outInds++ = startIndex + i + v1; + *outInds++ = startIndex + i + v2; } inds_ = outInds; + index_ += numVerts; + count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; seenPrims_ |= 1 << GE_PRIM_TRIANGLE_FAN; if (!clockwise) { @@ -236,54 +227,66 @@ void IndexGenerator::AddFan(int numVerts, int indexOffset, bool clockwise) { } //Lines -void IndexGenerator::AddLineList(int numVerts, int indexOffset) { +void IndexGenerator::AddLineList(int numVerts) { u16 *outInds = inds_; + const int startIndex = index_; for (int i = 0; i < numVerts; i += 2) { - *outInds++ = indexOffset + i; - *outInds++ = indexOffset + i + 1; + *outInds++ = startIndex + i; + *outInds++ = startIndex + i + 1; } inds_ = outInds; + index_ += numVerts; + count_ += numVerts; prim_ = GE_PRIM_LINES; seenPrims_ |= 1 << prim_; } -void IndexGenerator::AddLineStrip(int numVerts, int indexOffset) { +void IndexGenerator::AddLineStrip(int numVerts) { const int numLines = numVerts - 1; u16 *outInds = inds_; + const int startIndex = index_; for (int i = 0; i < numLines; i++) { - *outInds++ = indexOffset + i; - *outInds++ = indexOffset + i + 1; + *outInds++ = startIndex + i; + *outInds++ = startIndex + i + 1; } inds_ = outInds; + index_ += numVerts; + count_ += numLines * 2; prim_ = GE_PRIM_LINES; seenPrims_ |= 1 << GE_PRIM_LINE_STRIP; } -void IndexGenerator::AddRectangles(int numVerts, int indexOffset) { +void IndexGenerator::AddRectangles(int numVerts) { u16 *outInds = inds_; + const int startIndex = index_; //rectangles always need 2 vertices, disregard the last one if there's an odd number numVerts = numVerts & ~1; for (int i = 0; i < numVerts; i += 2) { - *outInds++ = indexOffset + i; - *outInds++ = indexOffset + i + 1; + *outInds++ = startIndex + i; + *outInds++ = startIndex + i + 1; } inds_ = outInds; + index_ += numVerts; + count_ += numVerts; prim_ = GE_PRIM_RECTANGLES; seenPrims_ |= 1 << GE_PRIM_RECTANGLES; } template void IndexGenerator::TranslatePoints(int numInds, const ITypeLE *inds, int indexOffset) { + indexOffset = index_ - indexOffset; u16 *outInds = inds_; for (int i = 0; i < numInds; i++) *outInds++ = indexOffset + inds[i]; inds_ = outInds; + count_ += numInds; prim_ = GE_PRIM_POINTS; seenPrims_ |= (1 << GE_PRIM_POINTS) | flag; } template void IndexGenerator::TranslateLineList(int numInds, const ITypeLE *inds, int indexOffset) { + indexOffset = index_ - indexOffset; u16 *outInds = inds_; numInds = numInds & ~1; for (int i = 0; i < numInds; i += 2) { @@ -291,12 +294,14 @@ void IndexGenerator::TranslateLineList(int numInds, const ITypeLE *inds, int ind *outInds++ = indexOffset + inds[i + 1]; } inds_ = outInds; + count_ += numInds; prim_ = GE_PRIM_LINES; seenPrims_ |= (1 << GE_PRIM_LINES) | flag; } template void IndexGenerator::TranslateLineStrip(int numInds, const ITypeLE *inds, int indexOffset) { + indexOffset = index_ - indexOffset; int numLines = numInds - 1; u16 *outInds = inds_; for (int i = 0; i < numLines; i++) { @@ -304,30 +309,33 @@ void IndexGenerator::TranslateLineStrip(int numInds, const ITypeLE *inds, int in *outInds++ = indexOffset + inds[i + 1]; } inds_ = outInds; + count_ += numLines * 2; prim_ = GE_PRIM_LINES; seenPrims_ |= (1 << GE_PRIM_LINE_STRIP) | flag; } template void IndexGenerator::TranslateList(int numInds, const ITypeLE *inds, int indexOffset, bool clockwise) { + indexOffset = index_ - indexOffset; // We only bother doing this minor optimization in triangle list, since it's by far the most // common operation that can benefit. if (sizeof(ITypeLE) == sizeof(inds_[0]) && indexOffset == 0 && clockwise) { memcpy(inds_, inds, numInds * sizeof(ITypeLE)); inds_ += numInds; + count_ += numInds; } else { u16 *outInds = inds_; int numTris = numInds / 3; // Round to whole triangles numInds = numTris * 3; const int v1 = clockwise ? 1 : 2; const int v2 = clockwise ? 2 : 1; - // TODO: This can actually be SIMD-d, although will need complex shuffles if clockwise. for (int i = 0; i < numInds; i += 3) { *outInds++ = indexOffset + inds[i]; *outInds++ = indexOffset + inds[i + v1]; *outInds++ = indexOffset + inds[i + v2]; } inds_ = outInds; + count_ += numInds; } prim_ = GE_PRIM_TRIANGLES; seenPrims_ |= (1 << GE_PRIM_TRIANGLES) | flag; @@ -336,6 +344,7 @@ void IndexGenerator::TranslateList(int numInds, const ITypeLE *inds, int indexOf template void IndexGenerator::TranslateStrip(int numInds, const ITypeLE *inds, int indexOffset, bool clockwise) { int wind = clockwise ? 1 : 2; + indexOffset = index_ - indexOffset; int numTris = numInds - 2; u16 *outInds = inds_; for (int i = 0; i < numTris; i++) { @@ -345,6 +354,7 @@ void IndexGenerator::TranslateStrip(int numInds, const ITypeLE *inds, int indexO *outInds++ = indexOffset + inds[i + wind]; } inds_ = outInds; + count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; seenPrims_ |= (1 << GE_PRIM_TRIANGLE_STRIP) | flag; } @@ -352,6 +362,7 @@ void IndexGenerator::TranslateStrip(int numInds, const ITypeLE *inds, int indexO template void IndexGenerator::TranslateFan(int numInds, const ITypeLE *inds, int indexOffset, bool clockwise) { if (numInds <= 0) return; + indexOffset = index_ - indexOffset; int numTris = numInds - 2; u16 *outInds = inds_; const int v1 = clockwise ? 1 : 2; @@ -362,12 +373,14 @@ void IndexGenerator::TranslateFan(int numInds, const ITypeLE *inds, int indexOff *outInds++ = indexOffset + inds[i + v2]; } inds_ = outInds; + count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; seenPrims_ |= (1 << GE_PRIM_TRIANGLE_FAN) | flag; } template inline void IndexGenerator::TranslateRectangles(int numInds, const ITypeLE *inds, int indexOffset) { + indexOffset = index_ - indexOffset; u16 *outInds = inds_; //rectangles always need 2 vertices, disregard the last one if there's an odd number numInds = numInds & ~1; @@ -376,6 +389,7 @@ inline void IndexGenerator::TranslateRectangles(int numInds, const ITypeLE *inds *outInds++ = indexOffset + inds[i+1]; } inds_ = outInds; + count_ += numInds; prim_ = GE_PRIM_RECTANGLES; seenPrims_ |= (1 << GE_PRIM_RECTANGLES) | flag; } diff --git a/GPU/Common/IndexGenerator.h b/GPU/Common/IndexGenerator.h index 77a49f39e..e8c257840 100644 --- a/GPU/Common/IndexGenerator.h +++ b/GPU/Common/IndexGenerator.h @@ -27,6 +27,8 @@ public: void Setup(u16 *indexptr); void Reset() { prim_ = GE_PRIM_INVALID; + count_ = 0; + index_ = 0; seenPrims_ = 0; pureCount_ = 0; this->inds_ = indsBase_; @@ -55,12 +57,19 @@ public: } } - void AddPrim(int prim, int vertexCount, int indexOffset, bool clockwise); + void AddPrim(int prim, int vertexCount, bool clockwise); void TranslatePrim(int prim, int numInds, const u8 *inds, int indexOffset, bool clockwise); void TranslatePrim(int prim, int numInds, const u16_le *inds, int indexOffset, bool clockwise); void TranslatePrim(int prim, int numInds, const u32_le *inds, int indexOffset, bool clockwise); - int VertexCount() const { return inds_ - indsBase_; } + void Advance(int numVerts) { + index_ += numVerts; + } + + void SetIndex(int ind) { index_ = ind; } + int MaxIndex() const { return index_; } // Really NextIndex rather than MaxIndex, it's one more than the highest index generated + int VertexCount() const { return count_; } + bool Empty() const { return index_ == 0; } int SeenPrims() const { return seenPrims_; } int PureCount() const { return pureCount_; } bool SeenOnlyPurePrims() const { @@ -72,16 +81,16 @@ public: private: // Points (why index these? code simplicity) - void AddPoints(int numVerts, int indexOffset); + void AddPoints(int numVerts); // Triangles - void AddList(int numVerts, int indexOffset, bool clockwise); - void AddStrip(int numVerts, int indexOffset, bool clockwise); - void AddFan(int numVerts, int indexOffset, bool clockwise); + void AddList(int numVerts, bool clockwise); + void AddStrip(int numVerts, bool clockwise); + void AddFan(int numVerts, bool clockwise); // Lines - void AddLineList(int numVerts, int indexOffset); - void AddLineStrip(int numVerts, int indexOffset); + void AddLineList(int numVerts); + void AddLineStrip(int numVerts); // Rectangles - void AddRectangles(int numVerts, int indexOffset); + void AddRectangles(int numVerts); // These translate already indexed lists template @@ -109,6 +118,8 @@ private: u16 *indsBase_; u16 *inds_; + int index_; + int count_; int pureCount_; GEPrimitiveType prim_; int seenPrims_; diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index 37066703e..51864c903 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -100,7 +100,7 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector &direct // Alright, let's loop through the sections and see if any is a shader. for (size_t i = 0; i < ini.Sections().size(); i++) { - Section §ion = *(ini.Sections()[i].get()); + Section §ion = ini.Sections()[i]; std::string shaderType; section.Get("Type", &shaderType, "render"); @@ -126,8 +126,6 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector &direct blacklistedVendor = Draw::GPUVendor::VENDOR_APPLE; } else if (item == "Intel") { blacklistedVendor = Draw::GPUVendor::VENDOR_INTEL; - } else if (item == "Mesa") { - blacklistedVendor = Draw::GPUVendor::VENDOR_MESA; } if (blacklistedVendor == gpuVendor && blacklistedVendor != Draw::GPUVendor::VENDOR_UNKNOWN) { skipped = true; diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index d86db4bd9..4ff4b5ed1 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -24,7 +24,6 @@ #include "Common/System/Display.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/File/VFS/VFS.h" #include "Common/VR/PPSSPPVR.h" #include "Common/Log.h" @@ -294,8 +293,6 @@ bool PresentationCommon::UpdatePostShader() { int w = usePreviousAtOutputResolution ? pixelWidth_ : renderWidth_; int h = usePreviousAtOutputResolution ? pixelHeight_ : renderHeight_; - _dbg_assert_(w > 0 && h > 0); - static constexpr int FRAMES = 2; previousFramebuffers_.resize(FRAMES); previousIndex_ = 0; @@ -451,9 +448,9 @@ void PresentationCommon::ShowPostShaderError(const std::string &errorString) { } } if (!firstLine.empty()) { - g_OSD.Show(OSDType::MESSAGE_ERROR_DUMP, "Post-shader error: " + firstLine + "...:\n" + errorString, 10.0f); + System_NotifyUserMessage("Post-shader error: " + firstLine + "...:\n" + errorString, 10.0f, 0xFF3090FF); } else { - g_OSD.Show(OSDType::MESSAGE_ERROR, "Post-shader error, see log for details", 10.0f); + System_NotifyUserMessage("Post-shader error, see log for details", 10.0f, 0xFF3090FF); } } @@ -480,11 +477,13 @@ Draw::Pipeline *PresentationCommon::CreatePipeline(std::vectorAddRef(); - DoRelease(srcTexture_); DoRelease(srcFramebuffer_); + texture->AddRef(); srcTexture_ = texture; srcWidth_ = bufferWidth; srcHeight_ = bufferHeight; } void PresentationCommon::SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidth, int bufferHeight) { - fb->AddRef(); - DoRelease(srcTexture_); DoRelease(srcFramebuffer_); + fb->AddRef(); srcFramebuffer_ = fb; srcWidth_ = bufferWidth; srcHeight_ = bufferHeight; @@ -672,7 +668,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u float finalU0 = u0, finalU1 = u1, finalV0 = v0, finalV1 = v1; - if (usePostShader && !(isFinalAtOutputResolution && postShaderPipelines_.size() == 1)) { + if (usePostShader) { // The final blit will thus use the full texture. finalU0 = 0.0f; finalV0 = 0.0f; @@ -789,7 +785,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u if (shaderInfo->usePreviousFrame) draw_->BindSamplerStates(2, 1, &sampler); - draw_->BindVertexBuffer(vdata_, vertsOffset); + draw_->BindVertexBuffers(0, 1, &vdata_, &vertsOffset); draw_->Draw(4, 0); postShaderOutput = postShaderFramebuffer; @@ -896,7 +892,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub)); } - draw_->BindVertexBuffer(vdata_, 0); + draw_->BindVertexBuffers(0, 1, &vdata_, nullptr); Draw::SamplerState *sampler = useNearest ? samplerNearest_ : samplerLinear_; draw_->BindSamplerStates(0, 1, &sampler); diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 84fd0e2d9..53668c89c 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -513,10 +513,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc || *pixelFormat == Draw::DataFormat::R8G8B8A8_UNORM); - if (bc && ((level.w & 3) != 0 || (level.h & 3) != 0)) { - WARN_LOG(G3D, "Block compressed replacement texture '%s' not divisible by 4x4 (%dx%d). In D3D11 (only!) we will have to expand (potentially causing glitches).", filename.c_str(), level.w, level.h); - } - data_.resize(numMips); basist::ktx2_transcoder_state transcodeState; // Each thread needs one of these. @@ -550,7 +546,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } transcoder.clear(); vfs_->CloseFile(openFile); - return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::DDS) { // TODO: Do better with alphaStatus, it's possible. @@ -567,10 +562,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc); - if (bc && ((level.w & 3) != 0 || (level.h & 3) != 0)) { - WARN_LOG(G3D, "Block compressed replacement texture '%s' not divisible by 4x4 (%dx%d). In D3D11 (only!) we will have to expand (potentially causing glitches).", filename.c_str(), level.w, level.h); - } - data_.resize(numMips); // A DDS File can contain multiple mipmaps. @@ -592,7 +583,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. } vfs_->CloseFile(openFile); - return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::ZIM) { @@ -672,7 +662,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference png.format = PNG_FORMAT_RGBA; std::vector &out = data_[mipLevel]; - // TODO: Should probably try to handle out-of-memory gracefully here. out.resize(level.w * level.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 7474bae11..4273ffead 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -128,7 +128,7 @@ public: void GetSize(int level, int *w, int *h) const { _dbg_assert_(State() == ReplacementState::ACTIVE); - _dbg_assert_((size_t)level < levels_.size()); + _dbg_assert_(level < levels_.size()); *w = levels_[level].fullW; *h = levels_[level].fullH; } diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 95cf3908f..513024224 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -93,7 +93,7 @@ enum : uint64_t { DIRTY_LIGHT_CONTROL = 1ULL << 38, DIRTY_TEX_ALPHA_MUL = 1ULL << 39, - // Bits 40-42 are free for new uniforms. Then we're really out and need to start merging. + // Bits 40-43 are free for new uniforms. Then we're really out and need to start merging. // Don't forget to update DIRTY_ALL_UNIFORMS when you start using them. DIRTY_BONE_UNIFORMS = 0xFF000000ULL, @@ -101,7 +101,6 @@ enum : uint64_t { DIRTY_ALL_UNIFORMS = 0x0FFFFFFFFFFULL, // Other dirty elements that aren't uniforms - DIRTY_CULL_PLANES = 1ULL << 43, DIRTY_FRAMEBUF = 1ULL << 44, DIRTY_TEXTURE_IMAGE = 1ULL << 45, // Means that the definition of the texture image has changed (address, stride etc), and we need to look up again. DIRTY_TEXTURE_PARAMS = 1ULL << 46, diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index a23c37cd0..b435cd2d7 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -190,11 +190,8 @@ std::string FragmentShaderDesc(const FShaderID &id) { if (id.Bit(FS_BIT_DO_TEXTURE_PROJ)) desc << "TexProj "; if (id.Bit(FS_BIT_ENABLE_FOG)) desc << "Fog "; if (id.Bit(FS_BIT_LMODE)) desc << "LM "; - if (id.Bit(FS_BIT_TEXALPHA)) desc << "TexAlpha "; - if (id.Bit(FS_BIT_DOUBLE_COLOR)) desc << "Double "; if (id.Bit(FS_BIT_FLATSHADE)) desc << "Flat "; if (id.Bit(FS_BIT_BGRA_TEXTURE)) desc << "BGRA "; - if (id.Bit(FS_BIT_UBERSHADER)) desc << "FragUber "; switch ((ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2)) { case ShaderDepalMode::OFF: break; case ShaderDepalMode::NORMAL: desc << "Depal "; break; @@ -288,14 +285,9 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip bool enableFog = gstate.isFogEnabled() && !isModeThrough; bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue(); bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue(); - bool enableColorDouble = gstate.isColorDoublingEnabled(); bool doTextureProjection = (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX && MatrixNeedsProjection(gstate.tgenMatrix, gstate.getUVProjMode())); bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT; - bool enableTexAlpha = gstate.isTextureAlphaUsed(); - - bool uberShader = gstate_c.Use(GPU_USE_FRAGMENT_UBERSHADER); - ShaderDepalMode shaderDepalMode = gstate_c.shaderDepalMode; bool colorWriteMask = pipelineState.maskState.applyFramebufferRead; @@ -337,14 +329,7 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip id.SetBit(FS_BIT_TEST_DISCARD_TO_ZERO, !NeedsTestDiscard()); } - id.SetBit(FS_BIT_ENABLE_FOG, enableFog); // TODO: Will be moved back to the ubershader. - - id.SetBit(FS_BIT_UBERSHADER, uberShader); - if (!uberShader) { - id.SetBit(FS_BIT_TEXALPHA, enableTexAlpha); - id.SetBit(FS_BIT_DOUBLE_COLOR, enableColorDouble); - } - + id.SetBit(FS_BIT_ENABLE_FOG, enableFog); id.SetBit(FS_BIT_DO_TEXTURE_PROJ, doTextureProjection); // 2 bits @@ -377,7 +362,7 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip id.SetBit(FS_BIT_COLOR_WRITEMASK, colorWriteMask); // All framebuffers are array textures in Vulkan now. - if (gstate_c.textureIsArray && gstate_c.Use(GPU_USE_FRAMEBUFFER_ARRAYS)) { + if (gstate_c.arrayTexture && g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { id.SetBit(FS_BIT_SAMPLE_ARRAY_TEXTURE); } diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 830abd044..1dc2781b5 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -68,12 +68,12 @@ enum FShaderBit : uint8_t { FS_BIT_CLEARMODE = 0, FS_BIT_DO_TEXTURE = 1, FS_BIT_TEXFUNC = 2, // 3 bits - FS_BIT_DOUBLE_COLOR = 5, // Not used with FS_BIT_UBERSHADER + // 1 bit free at position 5 FS_BIT_3D_TEXTURE = 6, FS_BIT_SHADER_TEX_CLAMP = 7, FS_BIT_CLAMP_S = 8, FS_BIT_CLAMP_T = 9, - FS_BIT_TEXALPHA = 10, // Not used with FS_BIT_UBERSHADER + // 1 bit free FS_BIT_LMODE = 11, FS_BIT_ALPHA_TEST = 12, FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits @@ -81,7 +81,7 @@ enum FShaderBit : uint8_t { FS_BIT_COLOR_TEST = 17, FS_BIT_COLOR_TEST_FUNC = 18, // 2 bits FS_BIT_COLOR_AGAINST_ZERO = 20, - FS_BIT_ENABLE_FOG = 21, // Not used with FS_BIT_UBERSHADER + FS_BIT_ENABLE_FOG = 21, FS_BIT_DO_TEXTURE_PROJ = 22, // 1 free bit FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits @@ -101,7 +101,6 @@ enum FShaderBit : uint8_t { FS_BIT_SAMPLE_ARRAY_TEXTURE = 57, // For multiview, framebuffers are array textures and we need to sample the two layers correctly. FS_BIT_STEREO = 58, FS_BIT_USE_FRAMEBUFFER_FETCH = 59, - FS_BIT_UBERSHADER = 60, }; static inline FShaderBit operator +(FShaderBit bit, int i) { diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 5da2b65fa..c020eb108 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -215,16 +215,12 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView // Texturing if (dirtyUniforms & DIRTY_UVSCALEOFFSET) { - float widthFactor = 1.0f; - float heightFactor = 1.0f; - if (gstate_c.textureIsFramebuffer) { - const float invW = 1.0f / (float)gstate_c.curTextureWidth; - const float invH = 1.0f / (float)gstate_c.curTextureHeight; - const int w = gstate.getTextureWidth(0); - const int h = gstate.getTextureHeight(0); - widthFactor = (float)w * invW; - heightFactor = (float)h * invH; - } + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + const float widthFactor = (float)w * invW; + const float heightFactor = (float)h * invH; if (gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE) { // When we are generating UV coordinates through the bezier/spline, we need to apply the scaling. // However, this is missing a check that we're not getting our UV:s supplied for us in the vertices. @@ -275,8 +271,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView int format = gstate_c.depalFramebufferFormat; uint32_t val = BytesToUint32(indexMask, indexShift, indexOffset, format); // Poke in a bilinear filter flag in the top bit. - if (gstate.isMagnifyFilteringEnabled()) - val |= 0x80000000; + val |= gstate.isMagnifyFilteringEnabled() << 31; ub->depal_mask_shift_off_fmt = val; } } diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 77c8ebc8d..cd9120d8e 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -33,13 +33,13 @@ struct alignas(16) UB_VS_FS_Base { uint32_t spline_counts; uint32_t depal_mask_shift_off_fmt; // 4 params packed into one. uint32_t colorWriteMask; float mipBias; // Fragment data - float texNoAlpha; float texMul; float padding[2]; // this vec4 will hold ubershader stuff. We won't use integer flags in the fragment shader. float fogColor[3]; uint32_t alphaColorRef; float texEnvColor[3]; uint32_t colorTestMask; - float texClamp[4]; - float texClampOffset[2]; float fogCoef[2]; float blendFixA[3]; float stencilReplaceValue; float blendFixB[3]; float rotation; + float texClamp[4]; + float texClampOffset[2]; float fogCoef[2]; + float texNoAlpha; float texMul; float padding[2]; // VR stuff is to go here, later. For normal drawing, we can then get away // with just uploading the first 448 bytes of the struct (up to and including fogCoef). }; @@ -59,13 +59,14 @@ R"( mat4 u_proj; uint u_depal_mask_shift_off_fmt; uint u_colorWriteMask; float u_mipBias; - vec2 u_texNoAlphaMul; float pad1; float pad2; vec3 u_fogcolor; uint u_alphacolorref; vec3 u_texenv; uint u_alphacolormask; - vec4 u_texclamp; - vec2 u_texclampoff; vec2 u_fogcoef; vec3 u_blendFixA; float u_stencilReplaceValue; vec3 u_blendFixB; float u_rotation; + vec4 u_texclamp; + vec2 u_texclampoff; + vec2 u_fogcoef; + float u_texNoAlpha; float u_texMul; float pad1; float pad2; )"; // 512 bytes. Would like to shrink more. Some colors only have 8-bit precision and we expand diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 15ae074d1..b918a0d45 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -90,22 +90,19 @@ static void RotateUVThrough(TransformedVertex v[4]) { // Clears on the PSP are best done by drawing a series of vertical strips // in clear mode. This tries to detect that. static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts, float x2, float y2) { - if (transformed[0].x < 0.0f || transformed[0].y < 0.0f || transformed[0].x > 0.5f || transformed[0].y > 0.5f) + if (transformed[0].x != 0.0f || transformed[0].y != 0.0f) return false; - const float originY = transformed[0].y; - // Color and Z are decided by the second vertex, so only need to check those for matching color. - const u32 matchcolor = transformed[1].color0_32; - const float matchz = transformed[1].z; + u32 matchcolor = transformed[1].color0_32; + float matchz = transformed[1].z; for (int i = 1; i < numVerts; i++) { if ((i & 1) == 0) { // Top left of a rectangle - if (transformed[i].y != originY) + if (transformed[i].y != 0.0f) return false; - float gap = fabsf(transformed[i].x - transformed[i - 1].x); // Should probably do some smarter check. - if (i > 0 && gap > 0.0625) + if (i > 0 && transformed[i].x != transformed[i - 1].x) return false; } else { if (transformed[i].color0_32 != matchcolor || transformed[i].z != matchz) @@ -862,7 +859,6 @@ void SoftwareTransform::ExpandLines(int vertexCount, int &maxIndex, u16 *&inds, inds = newInds; } - void SoftwareTransform::ExpandPoints(int vertexCount, int &maxIndex, u16 *&inds, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode) { numTrans = 0; TransformedVertex *trans = &transformedExpanded[0]; diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 69c80d1c0..ce6fef470 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -498,7 +498,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic if (surface.num_points_u < 4 || surface.num_points_v < 4) return; - SimpleBufferManager managedBuf(decoded_, DECODED_VERTEX_BUFFER_SIZE / 2); + SimpleBufferManager managedBuf(decoded, DECODED_VERTEX_BUFFER_SIZE / 2); int num_points = surface.num_points_u * surface.num_points_v; u16 index_lower_bound = 0; @@ -544,8 +544,8 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx); OutputBuffers output; - output.vertices = (SimpleVertex *)(decoded_ + DECODED_VERTEX_BUFFER_SIZE / 2); - output.indices = decIndex_; + output.vertices = (SimpleVertex *)(decoded + DECODED_VERTEX_BUFFER_SIZE / 2); + output.indices = decIndex; output.count = 0; int maxVerts = DECODED_VERTEX_BUFFER_SIZE / 2 / vertexSize; @@ -577,7 +577,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), decOptions_.applySkinInDecode); int generatedBytesRead; if (output.count) - DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, true, &generatedBytesRead); + DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, gstate.getCullMode(), &generatedBytesRead); if (flushOnParams_) DispatchFlush(); diff --git a/GPU/Common/StencilCommon.cpp b/GPU/Common/StencilCommon.cpp index 07c191e46..00e81b19d 100644 --- a/GPU/Common/StencilCommon.cpp +++ b/GPU/Common/StencilCommon.cpp @@ -230,9 +230,11 @@ bool FramebufferManagerCommon::PerformWriteStencilFromMemory(u32 addr, int size, _assert_(stencilUploadFs && stencilUploadVs); InputLayoutDesc desc = { - 8, { - { SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, + { 8, false }, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, }, }; InputLayout *inputLayout = draw_->CreateInputLayout(desc); @@ -352,6 +354,7 @@ bool FramebufferManagerCommon::PerformWriteStencilFromMemory(u32 addr, int size, draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST, "WriteStencilFromMemory_Blit"); RebindFramebuffer("RebindFramebuffer - Stencil"); } + tex->Release(); draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index efa2aac69..1ec6378c7 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -97,6 +97,15 @@ // GL_UNSIGNED_BYTE/RGBA: AAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR (match) // These are Data::Format:: B4G4R4A4_PACK16, B5G6R6_PACK16, B5G5R5A1_PACK16, R8G8B8A8 +// Allow the extra bits from the remasters for the purposes of this. +inline int dimWidth(u16 dim) { + return 1 << (dim & 0xFF); +} + +inline int dimHeight(u16 dim) { + return 1 << ((dim >> 8) & 0xFF); +} + TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D) : draw_(draw), draw2D_(draw2D), replacer_(draw) { decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; @@ -133,7 +142,7 @@ void TextureCacheCommon::StartFrame() { timesInvalidatedAllThisFrame_ = 0; replacementTimeThisFrame_ = 0.0; - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS) { + if (g_Config.bShowDebugStats) { gpuStats.numReplacerTrackedTex = replacer_.GetNumTrackedTextures(); gpuStats.numCachedReplacedTextures = replacer_.GetNumCachedReplacedTextures(); } @@ -190,6 +199,10 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac // If mip level is forced to zero, disable mipmapping. bool noMip = maxLevel == 0 || (!autoMip && lodBias <= 0.0f); + if (IsFakeMipmapChange()) { + noMip = noMip || !autoMip; + } + if (noMip) { // Enforce no mip filtering, for safety. key.mipEnable = false; @@ -244,9 +257,6 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac key.mipEnable = true; key.mipFilt = 1; key.maxLevel = 9 * 256; - if (gstate_c.Use(GPU_USE_ANISOTROPY) && g_Config.iAnisotropyLevel > 0) { - key.aniso = true; - } } useReplacerFiltering = entry->replacedTexture->ForceFiltering(&forceFiltering); } @@ -396,7 +406,6 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { Unbind(); gstate_c.SetTextureIs3D(false); gstate_c.SetTextureIsArray(false); - gstate_c.SetTextureIsFramebuffer(false); return nullptr; } @@ -564,10 +573,10 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0); gstate_c.SetTextureIsArray(false); gstate_c.SetTextureIsBGRA((entry->status & TexCacheEntry::STATUS_BGRA) != 0); - gstate_c.SetTextureIsFramebuffer(false); if (rehash) { // Update in case any of these changed. + entry->sizeInRAM = (textureBitsPerPixel[texFormat] * bufw * h / 2) / 8; entry->bufw = bufw; entry->cluthash = cluthash; } @@ -661,6 +670,9 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { entry->maxLevel = maxLevel; entry->status &= ~TexCacheEntry::STATUS_BGRA; + // This would overestimate the size in many cases so we underestimate instead + // to avoid excessive clearing caused by cache invalidations. + entry->sizeInRAM = (textureBitsPerPixel[texFormat] * bufw * h / 2) / 8; entry->bufw = bufw; entry->cluthash = cluthash; @@ -669,7 +681,6 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { gstate_c.curTextureHeight = h; gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0); gstate_c.SetTextureIsArray(false); // Ordinary 2D textures still aren't used by array view in VK. We probably might as well, though, at this point.. - gstate_c.SetTextureIsFramebuffer(false); failedTexture_ = false; nextTexture_ = entry; @@ -756,7 +767,7 @@ bool TextureCacheCommon::GetBestFramebufferCandidate(const TextureDefinition &en } cands += "\n"; - WARN_LOG(G3D, "GetFramebufferCandidates(tex): Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s", + WARN_LOG(G3D, "GetFramebufferCandidates: Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s", (int)candidates.size(), entry.addr, texAddrOffset, dimWidth(entry.dim), dimHeight(entry.dim), entry.bufw, GeTextureFormatToString(entry.format), cands.c_str() @@ -1097,8 +1108,8 @@ bool TextureCacheCommon::MatchFramebuffer( return true; } } else { - WARN_LOG_ONCE(diffFormat2, G3D, "Ignoring possible texturing from framebuffer at %08x with incompatible format %s != %s (+%dx%d)", - fb_address, GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format), matchInfo->xOffset, matchInfo->yOffset); + WARN_LOG_ONCE(diffFormat2, G3D, "Ignoring possible texturing from framebuffer with incompatible format %s != %s at %08x (+%dx%d)", + GeTextureFormatToString(entry.format), GeBufferFormatToString(fb_format), fb_address, matchInfo->xOffset, matchInfo->yOffset); return false; } } @@ -1127,26 +1138,22 @@ void TextureCacheCommon::SetTextureFramebuffer(const AttachCandidate &candidate) bool needsDepthXSwizzle = depthUpperBits == 2; // We need to force it, since we may have set it on a texture before attaching. - int texWidth = framebuffer->bufferWidth; - int texHeight = framebuffer->bufferHeight; + gstate_c.curTextureWidth = framebuffer->bufferWidth; + gstate_c.curTextureHeight = framebuffer->bufferHeight; + if (candidate.channel == RASTER_COLOR && gstate.getTextureFormat() == GE_TFMT_CLUT8 && framebuffer->fb_format == GE_FORMAT_5551 && PSP_CoreParameter().compat.flags().SOCOMClut8Replacement) { // See #16210. UV must be adjusted as if the texture was twice the width. - texWidth *= 2.0f; + gstate_c.curTextureWidth *= 2.0f; } if (needsDepthXSwizzle) { - texWidth = RoundUpToPowerOf2(texWidth); + gstate_c.curTextureWidth = RoundUpToPowerOf2(gstate_c.curTextureWidth); } - gstate_c.curTextureWidth = texWidth; - gstate_c.curTextureHeight = texHeight; - gstate_c.SetTextureIsFramebuffer(true); - gstate_c.SetTextureIsBGRA(false); - if ((gstate_c.curTextureXOffset == 0) != (fbInfo.xOffset == 0) || (gstate_c.curTextureYOffset == 0) != (fbInfo.yOffset == 0)) { gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } - + gstate_c.SetTextureIsBGRA(false); gstate_c.curTextureXOffset = fbInfo.xOffset; gstate_c.curTextureYOffset = fbInfo.yOffset; u32 texW = (u32)gstate.getTextureWidth(0); @@ -1338,24 +1345,19 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { // the framebuffer with the smallest offset. This is yet another framebuffer matching // loop with its own rules, eventually we'll probably want to do something // more systematic. - bool okAge = !PSP_CoreParameter().compat.flags().LoadCLUTFromCurrentFrameOnly || framebuffer->last_frame_render == gpuStats.numFlips; // Here we can try heuristics. if (matchRange && !inMargin && offset < (int)clutRenderOffset_) { - if (okAge) { - WARN_LOG_N_TIMES(clutfb, 5, G3D, "Detected LoadCLUT(%d bytes) from framebuffer %08x (%s), last render %d frames ago, byte offset %d, pixel offset %d", - loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), gpuStats.numFlips - framebuffer->last_frame_render, offset, offset / fb_bpp); - framebuffer->last_frame_clut = gpuStats.numFlips; - // Also mark used so it's not decimated. - framebuffer->last_frame_used = gpuStats.numFlips; - framebuffer->usageFlags |= FB_USAGE_CLUT; - bestClutAddress = framebuffer->fb_address; - clutRenderOffset_ = (u32)offset; - chosenFramebuffer = framebuffer; - if (offset == 0) { - // Not gonna find a better match according to the smallest-offset rule, so we'll go with this one. - break; - } - } else { - WARN_LOG(G3D, "Ignoring CLUT load from %d frames old buffer at %08x", gpuStats.numFlips - framebuffer->last_frame_render, fb_address); + WARN_LOG_N_TIMES(clutfb, 5, G3D, "Detected LoadCLUT(%d bytes) from framebuffer %08x (%s), byte offset %d, pixel offset %d", + loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), offset, offset / fb_bpp); + framebuffer->last_frame_clut = gpuStats.numFlips; + // Also mark used so it's not decimated. + framebuffer->last_frame_used = gpuStats.numFlips; + framebuffer->usageFlags |= FB_USAGE_CLUT; + bestClutAddress = framebuffer->fb_address; + clutRenderOffset_ = (u32)offset; + chosenFramebuffer = framebuffer; + if (offset == 0) { + // Not gonna find a better match according to the smallest-offset rule, so we'll go with this one. + break; } } } @@ -2194,28 +2196,26 @@ static bool CanDepalettize(GETextureFormat texFormat, GEBufferFormat bufferForma // If the palette is detected as a smooth ramp, we can interpolate for higher color precision. // But we only do it if the mask/shift exactly matches a color channel, else something different might be going // on and we definitely don't want to interpolate. -// Great enhancement for Test Drive and Manhunt 2. -static bool CanUseSmoothDepal(const GPUgstate &gstate, GEBufferFormat framebufferFormat, const ClutTexture &clutTexture) { - for (int i = 0; i < ClutTexture::MAX_RAMPS; i++) { - if (gstate.getClutIndexStartPos() == clutTexture.rampStarts[i] && - gstate.getClutIndexMask() < clutTexture.rampLengths[i]) { - switch (framebufferFormat) { - case GE_FORMAT_565: - if (gstate.getClutIndexShift() == 0 || gstate.getClutIndexShift() == 11) { - return gstate.getClutIndexMask() == 0x1F; - } else if (gstate.getClutIndexShift() == 5) { - return gstate.getClutIndexMask() == 0x3F; - } - break; - case GE_FORMAT_5551: - if (gstate.getClutIndexShift() == 0 || gstate.getClutIndexShift() == 5 || gstate.getClutIndexShift() == 10) { - return gstate.getClutIndexMask() == 0x1F; - } - break; - default: - // No uses for the other formats yet, add if needed. - break; +// Great enhancement for Test Drive. +static bool CanUseSmoothDepal(const GPUgstate &gstate, GEBufferFormat framebufferFormat, int rampLength) { + if (gstate.getClutIndexStartPos() == 0 && + gstate.getClutIndexMask() < rampLength) { + switch (framebufferFormat) { + case GE_FORMAT_565: + if (gstate.getClutIndexShift() == 0 || gstate.getClutIndexShift() == 11) { + return gstate.getClutIndexMask() == 0x1F; + } else if (gstate.getClutIndexShift() == 5) { + return gstate.getClutIndexMask() == 0x3F; } + break; + case GE_FORMAT_5551: + if (gstate.getClutIndexShift() == 0 || gstate.getClutIndexShift() == 5 || gstate.getClutIndexShift() == 10) { + return gstate.getClutIndexMask() == 0x1F; + } + break; + default: + // No uses for the other formats yet, add if needed. + break; } } return false; @@ -2255,7 +2255,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer if (need_depalettize) { if (clutRenderAddress_ == 0xFFFFFFFF) { clutTexture = textureShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBufRaw_); - smoothedDepal = CanUseSmoothDepal(gstate, framebuffer->fb_format, clutTexture); + smoothedDepal = CanUseSmoothDepal(gstate, framebuffer->fb_format, clutTexture.rampLength); } else { // The CLUT texture is dynamic, it's the framebuffer pointed to by clutRenderAddress. // Instead of texturing directly from that, we copy to a temporary CLUT texture. @@ -2360,7 +2360,6 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer gpuStats.numDepal++; gstate_c.curTextureWidth = texWidth; - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); draw_->BindTexture(0, nullptr); framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer"); @@ -2462,7 +2461,6 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { gpuStats.numDepal++; gstate_c.curTextureWidth = texWidth; - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); draw_->BindTexture(0, nullptr); framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer"); @@ -2642,8 +2640,7 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type for (TexCache::iterator iter = cache_.lower_bound(startKey), end = cache_.upper_bound(endKey); iter != end; ++iter) { auto &entry = iter->second; u32 texAddr = entry->addr; - // Intentional underestimate here. - u32 texEnd = entry->addr + entry->SizeInRAM() / 2; + u32 texEnd = entry->addr + entry->sizeInRAM; // Quick check for overlap. Yes the check is right. if (addr < texEnd && addr_end > texAddr) { @@ -2755,30 +2752,21 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt plan.scaleFactor = plan.scaleFactor > 4 ? 4 : (plan.scaleFactor > 2 ? 2 : 1); } - bool isFakeMipmapChange = false; - if (plan.badMipSizes) { - isFakeMipmapChange = IsFakeMipmapChange(); + bool isFakeMipmapChange = IsFakeMipmapChange(); + if (plan.badMipSizes) { // Check for pure 3D texture. int tw = gstate.getTextureWidth(0); int th = gstate.getTextureHeight(0); bool pure3D = true; - for (int i = 0; i < plan.levelsToLoad; i++) { - if (gstate.getTextureWidth(i) != gstate.getTextureWidth(0) || gstate.getTextureHeight(i) != gstate.getTextureHeight(0)) { - pure3D = false; - break; + if (!isFakeMipmapChange) { + for (int i = 0; i < plan.levelsToLoad; i++) { + if (gstate.getTextureWidth(i) != gstate.getTextureWidth(0) || gstate.getTextureHeight(i) != gstate.getTextureHeight(0)) { + pure3D = false; + break; + } } - } - - // Check early for the degenerate case from Tactics Ogre. - if (pure3D && plan.levelsToLoad == 2 && gstate.getTextureAddress(0) == gstate.getTextureAddress(1)) { - // Simply treat it as a regular 2D texture, no fake mipmaps or anything. - // levelsToLoad/Create gets set to 1 on the way out from the surrounding if. - isFakeMipmapChange = false; - pure3D = false; - } else if (isFakeMipmapChange) { - // We don't want to create a volume texture, if this is a "fake mipmap change". - // In practice due to the compat flag, the only time we end up here is in JP Tactics Ogre. + } else { pure3D = false; } @@ -2803,7 +2791,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt plan.w = gstate.getTextureWidth(0); plan.h = gstate.getTextureHeight(0); - bool isPPGETexture = entry->addr >= PSP_GetKernelMemoryBase() && entry->addr < PSP_GetKernelMemoryEnd(); + bool isPPGETexture = entry->addr > 0x05000000 && entry->addr < PSP_GetKernelMemoryEnd(); // Don't scale the PPGe texture. if (isPPGETexture) { @@ -2906,13 +2894,6 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (isFakeMipmapChange) { // NOTE: Since the level is not part of the cache key, we assume it never changes. plan.baseLevelSrc = std::max(0, gstate.getTexLevelOffset16() / 16); - // Tactics Ogre: If this is an odd level and it has the same texture address the below even level, - // let's just say it's the even level for the purposes of replacement. - // I assume this is done to avoid blending between levels accidentally? - // The Japanese version of Tactics Ogre uses multiple of these "double" levels to fit more characters. - if ((plan.baseLevelSrc & 1) && gstate.getTextureAddress(plan.baseLevelSrc) == gstate.getTextureAddress(plan.baseLevelSrc & ~1)) { - plan.baseLevelSrc &= ~1; - } plan.levelsToCreate = 1; plan.levelsToLoad = 1; // Make sure we already decided not to do a 3D texture above. @@ -2920,10 +2901,9 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt } if (plan.isVideo || plan.depth != 1 || plan.decodeToClut8) { - plan.levelsToLoad = 1; plan.maxPossibleLevels = 1; } else { - plan.maxPossibleLevels = log2i(std::max(plan.createW, plan.createH)) + 1; + plan.maxPossibleLevels = log2i(std::min(plan.createW, plan.createH)) + 1; } if (plan.levelsToCreate == 1) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 9523da30f..3692dbd83 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -97,15 +97,6 @@ struct SamplerCacheKey { class GLRTexture; class VulkanTexture; -// Allow the extra bits from the remasters for the purposes of this. -inline int dimWidth(u16 dim) { - return 1 << (dim & 0xFF); -} - -inline int dimHeight(u16 dim) { - return 1 << ((dim >> 8) & 0xFF); -} - // Enough information about a texture to match it to framebuffers. struct TextureDefinition { u32 addr; @@ -174,6 +165,7 @@ struct TexCacheEntry { u32 addr; u32 minihash; + u32 sizeInRAM; // Could be computed u8 format; // GeTextureFormat u8 maxLevel; u16 dim; @@ -222,11 +214,6 @@ struct TexCacheEntry { } } - // This is the full size in RAM, not the half size we use sometimes as a "safe" underestimate. - u32 SizeInRAM() const { - return (textureBitsPerPixel[format] * bufw * dimHeight(dim)) / 8; - } - bool Matches(u16 dim2, u8 format2, u8 maxLevel2) const; u64 CacheKey() const; static u64 CacheKey(u32 addr, u8 format, u16 dim, u32 cluthash); diff --git a/GPU/Common/TextureDecoder.cpp b/GPU/Common/TextureDecoder.cpp index da58590db..32da2dffa 100644 --- a/GPU/Common/TextureDecoder.cpp +++ b/GPU/Common/TextureDecoder.cpp @@ -243,13 +243,8 @@ static u32 QuickTexHashNonSSE(const void *checkp, u32 size) { if (((intptr_t)checkp & 0xf) == 0 && (size & 0x3f) == 0) { static const u16 cursor2_initial[8] = {0xc00bU, 0x9bd9U, 0x4b73U, 0xb651U, 0x4d9bU, 0x4309U, 0x0083U, 0x0001U}; union u32x4_u16x8 { -#if defined(__GNUC__) - uint32_t x32 __attribute__((vector_size(16))); - uint16_t x16 __attribute__((vector_size(16))); -#else u32 x32[4]; u16 x16[8]; -#endif }; u32x4_u16x8 cursor{}; u32x4_u16x8 cursor2; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index cc60129d4..116473e5e 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -37,7 +37,7 @@ #include "Common/File/VFS/VFS.h" #include "Common/LogReporting.h" #include "Common/StringUtils.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Thread/ParallelLoop.h" #include "Common/Thread/Waitable.h" #include "Common/Thread/ThreadManager.h" @@ -92,13 +92,6 @@ void TextureReplacer::NotifyConfigChanged() { } enabled_ = File::IsDirectory(basePath_); - - if (g_Config.bSaveNewTextures) { - // Somewhat crude message, re-using translation strings. - auto d = GetI18NCategory(I18NCat::DEVELOPER); - auto di = GetI18NCategory(I18NCat::DIALOG); - g_OSD.Show(OSDType::MESSAGE_INFO, std::string(d->T("Save new textures")) + ": " + di->T("Enabled"), 2.0f); - } } else if (wasEnabled) { delete vfs_; vfs_ = nullptr; @@ -233,10 +226,34 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri ERROR_LOG(G3D, "Unsupported texture replacement version %d, trying anyway", version); } - int badFileNameCount = 0; + bool filenameWarning = false; std::map> filenameMap; - std::string badFilenames; + + if (ini.HasSection("hashes")) { + auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); + // Format: hashname = filename.png + bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; + + for (const auto &item : hashes) { + ReplacementCacheKey key(0, 0); + int level = 0; // sscanf might fail to pluck the level, but that's ok, we default to 0. sscanf doesn't write to non-matched outputs. + if (sscanf(item.first.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &level) >= 1) { + filenameMap[key][level] = item.second; + if (checkFilenames) { +#if PPSSPP_PLATFORM(WINDOWS) + // Uppercase probably means the filenames don't match. + // Avoiding an actual check of the filenames to avoid performance impact. + filenameWarning = filenameWarning || item.second.find_first_of("\\ABCDEFGHIJKLMNOPQRSTUVWXYZ:<>|?*") != std::string::npos; +#else + filenameWarning = filenameWarning || item.second.find_first_of("\\:<>|?*") != std::string::npos; +#endif + } + } else { + ERROR_LOG(G3D, "Unsupported syntax under [hashes]: %s", item.first.c_str()); + } + } + } // Scan the root of the texture folder/zip and preinitialize the hash map. std::vector filesInRoot; @@ -266,46 +283,6 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri } } - if (ini.HasSection("hashes")) { - auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); - // Format: hashname = filename.png - bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; - - for (const auto &item : hashes) { - ReplacementCacheKey key(0, 0); - // sscanf might fail to pluck the level if omitted from the line, but that's ok, we default level to 0. - // sscanf doesn't write to non-matched outputs. - int level = 0; - if (sscanf(item.first.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &level) >= 1) { - // We allow empty filenames, to mark textures that we don't want to keep saving. - filenameMap[key][level] = item.second; - if (checkFilenames) { - // TODO: We should check for the union of these on all platforms, really. -#if PPSSPP_PLATFORM(WINDOWS) - bool bad = item.second.find_first_of("\\ABCDEFGHIJKLMNOPQRSTUVWXYZ:<>|?*") != std::string::npos; - // Uppercase probably means the filenames don't match. - // Avoiding an actual check of the filenames to avoid performance impact. -#else - bool bad = item.second.find_first_of("\\:<>|?*") != std::string::npos; -#endif - if (bad) { - badFileNameCount++; - if (badFileNameCount == 10) { - badFilenames.append("..."); - } else if (badFileNameCount < 10) { - badFilenames.append(item.second); - badFilenames.push_back('\n'); - } - } - } - } else if (item.first.empty()) { - INFO_LOG(G3D, "Ignoring [hashes] line with empty key: '= %s'", item.second.c_str()); - } else { - ERROR_LOG(G3D, "Unsupported syntax under [hashes], ignoring: %s = ", item.first.c_str()); - } - } - } - // Now, translate the filenameMap to the final aliasMap. for (auto &pair : filenameMap) { std::string alias; @@ -331,10 +308,9 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri aliases_[pair.first] = alias; } - if (badFileNameCount > 0) { + if (filenameWarning) { auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("textures.ini filenames may not be cross - platform(banned characters)"), badFilenames, 6.0f); - WARN_LOG(G3D, "Potentially bad filenames: %s", badFilenames.c_str()); + System_NotifyUserMessage(err->T("textures.ini filenames may not be cross-platform (banned characters)"), 6.0f); } if (ini.HasSection("hashranges")) { @@ -361,9 +337,6 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri } } - auto gr = GetI18NCategory(I18NCat::GRAPHICS); - - g_OSD.Show(OSDType::MESSAGE_SUCCESS, gr->T("Texture replacement pack activated"), 2.0f); return true; } @@ -809,13 +782,9 @@ void TextureReplacer::Decimate(ReplacerDecimateMode mode) { const double threshold = time_now_d() - age; size_t totalSize = 0; for (auto &item : levelCache_) { - // During decimation, it's fine to try-lock here to avoid blocking the main thread while - // the level is being loaded - in that case we don't want to decimate anyway. - if (item.second->lock_.try_lock()) { - item.second->PurgeIfNotUsedSinceTime(threshold); - totalSize += item.second->GetTotalDataSize(); // TODO: Make something better. - item.second->lock_.unlock(); - } + std::lock_guard guard(item.second->lock_); + item.second->PurgeIfNotUsedSinceTime(threshold); + totalSize += item.second->GetTotalDataSize(); // TODO: Make something better. // don't actually delete the items here, just clean out the data. } diff --git a/GPU/Common/TextureShaderCommon.cpp b/GPU/Common/TextureShaderCommon.cpp index 2e8b59780..e7faf67ac 100644 --- a/GPU/Common/TextureShaderCommon.cpp +++ b/GPU/Common/TextureShaderCommon.cpp @@ -95,43 +95,33 @@ ClutTexture TextureShaderCache::GetClutTexture(GEPaletteFormat clutFormat, const break; } + int lastR = 0; + int lastG = 0; + int lastB = 0; + int lastA = 0; - for (int i = 0; i < 3; i++) { - tex->rampLengths[i] = 0; - tex->rampStarts[i] = 0; - } + int rampLength = 0; // Quick check for how many continuously growing entries we have at the start. // Bilinearly filtering CLUTs only really makes sense for this kind of ramp. - int i = 0; - for (int j = 0; j < ClutTexture::MAX_RAMPS; j++) { - tex->rampStarts[j] = i; - int lastR = 0; - int lastG = 0; - int lastB = 0; - int lastA = 0; - for (; i < maxClutEntries; i++) { - int r = desc.initData[0][i * 4]; - int g = desc.initData[0][i * 4 + 1]; - int b = desc.initData[0][i * 4 + 2]; - int a = desc.initData[0][i * 4 + 3]; - if (r < lastR || g < lastG || b < lastB || a < lastA) { - lastR = r; lastG = g; lastB = b; lastA = a; - break; - } else { - lastR = r; - lastG = g; - lastB = b; - lastA = a; - } - } - tex->rampLengths[j] = i - tex->rampStarts[j]; - if (i >= maxClutEntries) { + for (int i = 0; i < maxClutEntries; i++) { + rampLength = i; + int r = desc.initData[0][i * 4]; + int g = desc.initData[0][i * 4 + 1]; + int b = desc.initData[0][i * 4 + 2]; + int a = desc.initData[0][i * 4 + 3]; + if (r < lastR || g < lastG || b < lastB || a < lastA) { break; + } else { + lastR = r; + lastG = g; + lastB = b; + lastA = a; } } tex->texture = draw_->CreateTexture(desc); tex->lastFrame = gpuStats.numFlips; + tex->rampLength = rampLength; texCache_[clutId] = tex; return *tex; diff --git a/GPU/Common/TextureShaderCommon.h b/GPU/Common/TextureShaderCommon.h index 8aa881fdc..d6a6096f0 100644 --- a/GPU/Common/TextureShaderCommon.h +++ b/GPU/Common/TextureShaderCommon.h @@ -29,14 +29,11 @@ #include "GPU/Common/ShaderCommon.h" #include "GPU/Common/DepalettizeShaderCommon.h" - class ClutTexture { public: - enum { MAX_RAMPS = 3 }; Draw::Texture *texture; int lastFrame; - int rampLengths[MAX_RAMPS]; - int rampStarts[MAX_RAMPS]; + int rampLength; }; // For CLUT depal shaders, and other pre-bind texture shaders. diff --git a/GPU/Common/VertexDecoderArm.cpp b/GPU/Common/VertexDecoderArm.cpp index 84ae0db67..ed57fd89c 100644 --- a/GPU/Common/VertexDecoderArm.cpp +++ b/GPU/Common/VertexDecoderArm.cpp @@ -190,6 +190,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Keep the scale/offset in a few fp registers if we need it. if (prescaleStep) { + MOVP2R(R3, &gstate_c.uv); VLD1(F_32, neonUVScaleReg, R3, 2, ALIGN_NONE); if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { VMOV_neon(F_32, neonScratchReg, by128); @@ -248,7 +249,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int MOV(fullAlphaReg, 0xFF); } - JumpTarget loopStart = NopAlignCode16(); + JumpTarget loopStart = GetCodePtr(); // Preload data cache ahead of reading. This offset seems pretty good. PLD(srcReg, 64); for (int i = 0; i < dec.numSteps_; i++) { diff --git a/GPU/Common/VertexDecoderArm64.cpp b/GPU/Common/VertexDecoderArm64.cpp index 830196323..837e0ec83 100644 --- a/GPU/Common/VertexDecoderArm64.cpp +++ b/GPU/Common/VertexDecoderArm64.cpp @@ -27,6 +27,10 @@ #include "GPU/Common/VertexDecoderCommon.h" alignas(16) static float bones[16 * 8]; // First four are kept in registers +alignas(16) static float boneMask[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + +static const float by128 = 1.0f / 128.0f; +static const float by32768 = 1.0f / 32768.0f; using namespace Arm64Gen; @@ -35,9 +39,6 @@ static const ARM64Reg srcReg = X0; static const ARM64Reg dstReg = X1; static const ARM64Reg counterReg = W2; - -static const ARM64Reg uvScaleReg = X3; - static const ARM64Reg tempReg1 = W3; static const ARM64Reg tempRegPtr = X3; static const ARM64Reg tempReg2 = W4; @@ -46,7 +47,7 @@ static const ARM64Reg scratchReg = W6; static const ARM64Reg scratchReg64 = X6; static const ARM64Reg scratchReg2 = W7; static const ARM64Reg scratchReg3 = W8; -static const ARM64Reg alphaNonFullReg = W12; +static const ARM64Reg fullAlphaReg = W12; static const ARM64Reg boundsMinUReg = W13; static const ARM64Reg boundsMinVReg = W14; static const ARM64Reg boundsMaxUReg = W15; @@ -59,15 +60,13 @@ static const ARM64Reg fpScratchReg4 = S7; static const ARM64Reg neonScratchRegD = D2; static const ARM64Reg neonScratchRegQ = Q2; -static const ARM64Reg neonScratchReg2D = D3; -static const ARM64Reg neonScratchReg2Q = Q3; static const ARM64Reg neonUVScaleReg = D0; static const ARM64Reg neonUVOffsetReg = D1; -static const ARM64Reg src[2] = {S2, S3}; -static const ARM64Reg srcD = D2; -static const ARM64Reg srcQ = Q2; +static const ARM64Reg src[3] = {S2, S3, S8}; +static const ARM64Reg srcD[3] = {D2, D3, D8}; +static const ARM64Reg srcQ[3] = {Q2, Q3, Q8}; static const ARM64Reg srcNEON = Q8; static const ARM64Reg accNEON = Q9; @@ -148,7 +147,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int bool prescaleStep = false; bool skinning = false; - bool updateTexBounds = false; bool log = false; @@ -164,9 +162,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int dec.steps_[i] == &VertexDecoder::Step_WeightsFloatSkin) { skinning = true; } - if (dec.steps_[i] == &VertexDecoder::Step_TcU16ThroughToFloat) { - updateTexBounds = true; - } } // Not used below, but useful for logging. @@ -174,22 +169,22 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // if (skinning) log = true; - bool updateFullAlpha = dec.col; - if (updateFullAlpha && (dec.VertexType() & GE_VTYPE_COL_MASK) == GE_VTYPE_COL_565) - updateFullAlpha = false; - - // GPRs 0-15 do not need to be saved. - // We don't use any higher GPRs than 16. So: - uint64_t regs_to_save = updateTexBounds ? 1 << 16 : 0; - // We only need to save Q8-Q15 if skinning is used. - uint64_t regs_to_save_fp = dec.skinInDecode ? Arm64Gen::ALL_CALLEE_SAVED_FP : 0; - // Only bother making stack space and setting up FP if there are saved regs. - if (regs_to_save || regs_to_save_fp) - fp.ABI_PushRegisters(regs_to_save, regs_to_save_fp); + uint64_t regs_to_save = Arm64Gen::ALL_CALLEE_SAVED; + uint64_t regs_to_save_fp = Arm64Gen::ALL_CALLEE_SAVED_FP; + fp.ABI_PushRegisters(regs_to_save, regs_to_save_fp); // Keep the scale/offset in a few fp registers if we need it. if (prescaleStep) { - fp.LDP(64, INDEX_SIGNED, neonUVScaleReg, neonUVOffsetReg, X3, 0); + MOVP2R(X3, &gstate_c.uv); + fp.LDR(64, INDEX_UNSIGNED, neonUVScaleReg, X3, 0); + fp.LDR(64, INDEX_UNSIGNED, neonUVOffsetReg, X3, 8); + if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { + fp.MOVI2FDUP(neonScratchRegD, by128, scratchReg); + fp.FMUL(32, neonUVScaleReg, neonUVScaleReg, neonScratchRegD); + } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { + fp.MOVI2FDUP(neonScratchRegD, by32768, scratchReg); + fp.FMUL(32, neonUVScaleReg, neonUVScaleReg, neonScratchRegD); + } } // Add code to convert matrices to 4x4. @@ -197,48 +192,43 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int if (dec.skinInDecode) { // Copying from R3 to R4 MOVP2R(X3, gstate.boneMatrix); - // This is only used with more than 4 weights, and points to the first of them. - if (dec.nweights > 4) - MOVP2R(X4, &bones[16 * 4]); - - // Construct a mask to zero out the top lane with. - fp.MVNI(32, Q3, 0); - fp.MOVI(32, Q4, 0); - fp.EXT(Q3, Q3, Q4, 4); - + MOVP2R(X4, bones); + MOVP2R(X5, boneMask); + fp.LDR(128, INDEX_UNSIGNED, Q3, X5, 0); for (int i = 0; i < dec.nweights; i++) { - // This loads Q4,Q5,Q6 with 12 floats and increases X3, all in one go. - fp.LD1(32, 3, INDEX_POST, Q4, X3); - // Now sort those floats into 4 regs: ABCD EFGH IJKL -> ABC0 DEF0 GHI0 JKL0. - // Go backwards to avoid overwriting. - fp.EXT(Q7, Q6, Q6, 4); // I[JKLI]JKL - fp.EXT(Q6, Q5, Q6, 8); // EF[GHIJ]KL - fp.EXT(Q5, Q4, Q5, 12); // ABC[DEFG]H - - ARM64Reg matrixRow[4]{ Q4, Q5, Q6, Q7 }; + // Note that INDEX_UNSIGNED does not support offsets not aligned to the data size so we must use POST. + fp.LDR(128, INDEX_POST, Q4, X3, 12); // Load 128 bits even though we just want 96 + fp.LDR(128, INDEX_POST, Q5, X3, 12); + fp.LDR(128, INDEX_POST, Q6, X3, 12); + fp.LDR(128, INDEX_POST, Q7, X3, 12); // First four matrices are in registers Q16+. if (i < 4) { - for (int w = 0; w < 4; ++w) - matrixRow[w] = (ARM64Reg)(Q16 + i * 4 + w); + fp.FMUL(32, (ARM64Reg)(Q16 + i * 4), Q4, Q3); + fp.FMUL(32, (ARM64Reg)(Q17 + i * 4), Q5, Q3); + fp.FMUL(32, (ARM64Reg)(Q18 + i * 4), Q6, Q3); + fp.FMUL(32, (ARM64Reg)(Q19 + i * 4), Q7, Q3); + ADDI2R(X4, X4, 16 * 4); + } else { + fp.FMUL(32, Q4, Q4, Q3); + fp.FMUL(32, Q5, Q5, Q3); + fp.FMUL(32, Q6, Q6, Q3); + fp.FMUL(32, Q7, Q7, Q3); + fp.STR(128, INDEX_UNSIGNED, Q4, X4, 0); + fp.STR(128, INDEX_UNSIGNED, Q5, X4, 16); + fp.STR(128, INDEX_UNSIGNED, Q6, X4, 32); + fp.STR(128, INDEX_UNSIGNED, Q7, X4, 48); + ADDI2R(X4, X4, 16 * 4); } - // Zero out the top lane of each one with the mask created above. - fp.AND(matrixRow[0], Q4, Q3); - fp.AND(matrixRow[1], Q5, Q3); - fp.AND(matrixRow[2], Q6, Q3); - fp.AND(matrixRow[3], Q7, Q3); - - if (i >= 4) - fp.ST1(32, 4, INDEX_POST, matrixRow[0], X4); } } - if (updateFullAlpha) { - // This ends up non-zero if alpha is not full. - // Often we just ORN into it. - MOVI2R(alphaNonFullReg, 0); + if (dec.col) { + // Or LDB and skip the conditional? This is probably cheaper. + MOVI2R(fullAlphaReg, 0xFF); } - if (updateTexBounds) { + if (dec.tc && dec.throughmode) { + // TODO: Smarter, only when doing bounds. MOVP2R(scratchReg64, &gstate_c.vertBounds.minU); LDRH(INDEX_UNSIGNED, boundsMinUReg, scratchReg64, offsetof(KnownVertexBounds, minU)); LDRH(INDEX_UNSIGNED, boundsMaxUReg, scratchReg64, offsetof(KnownVertexBounds, maxU)); @@ -246,7 +236,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int LDRH(INDEX_UNSIGNED, boundsMaxVReg, scratchReg64, offsetof(KnownVertexBounds, maxV)); } - const u8 *loopStart = NopAlignCode16(); + const u8 *loopStart = GetCodePtr(); for (int i = 0; i < dec.numSteps_; i++) { if (!CompileStep(dec, i)) { EndWrite(); @@ -264,14 +254,16 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int SUBS(counterReg, counterReg, 1); B(CC_NEQ, loopStart); - if (updateFullAlpha) { - FixupBranch skip = CBZ(alphaNonFullReg); + if (dec.col) { MOVP2R(tempRegPtr, &gstate_c.vertexFullAlpha); - STRB(INDEX_UNSIGNED, WZR, tempRegPtr, 0); + CMP(fullAlphaReg, 0); + FixupBranch skip = B(CC_NEQ); + STRB(INDEX_UNSIGNED, fullAlphaReg, tempRegPtr, 0); SetJumpTarget(skip); } - if (updateTexBounds) { + if (dec.tc && dec.throughmode) { + // TODO: Smarter, only when doing bounds. MOVP2R(scratchReg64, &gstate_c.vertBounds.minU); STRH(INDEX_UNSIGNED, boundsMinUReg, scratchReg64, offsetof(KnownVertexBounds, minU)); STRH(INDEX_UNSIGNED, boundsMaxUReg, scratchReg64, offsetof(KnownVertexBounds, maxU)); @@ -279,8 +271,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int STRH(INDEX_UNSIGNED, boundsMaxVReg, scratchReg64, offsetof(KnownVertexBounds, maxV)); } - if (regs_to_save || regs_to_save_fp) - fp.ABI_PopRegisters(regs_to_save, regs_to_save_fp); + fp.ABI_PopRegisters(regs_to_save, regs_to_save_fp); RET(); @@ -315,7 +306,7 @@ bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { void VertexDecoderJitCache::Jit_ApplyWeights() { // We construct a matrix in Q4-Q7 - if (dec_->nweights > 4) { + if (dec_->nweights >= 4) { MOVP2R(scratchReg64, bones + 16 * 4); } for (int i = 0; i < dec_->nweights; i++) { @@ -346,11 +337,13 @@ void VertexDecoderJitCache::Jit_ApplyWeights() { break; default: // Matrices 4+ need to be loaded from memory. - fp.LD1(32, 4, INDEX_POST, Q8, scratchReg64); + fp.LDP(128, INDEX_SIGNED, Q8, Q9, scratchReg64, 0); + fp.LDP(128, INDEX_SIGNED, Q10, Q11, scratchReg64, 2 * 16); fp.FMLA(32, Q4, Q8, neonWeightRegsQ[i >> 2], i & 3); fp.FMLA(32, Q5, Q9, neonWeightRegsQ[i >> 2], i & 3); fp.FMLA(32, Q6, Q10, neonWeightRegsQ[i >> 2], i & 3); fp.FMLA(32, Q7, Q11, neonWeightRegsQ[i >> 2], i & 3); + ADDI2R(scratchReg64, scratchReg64, 4 * 16); break; } } @@ -484,8 +477,13 @@ void VertexDecoderJitCache::Jit_WeightsFloatSkin() { void VertexDecoderJitCache::Jit_Color8888() { LDR(INDEX_UNSIGNED, tempReg1, srcReg, dec_->coloff); - // Or any non-set bits into alphaNonFullReg. This way it's non-zero if not full. - ORN(alphaNonFullReg, alphaNonFullReg, tempReg1, ArithOption(tempReg1, ST_ASR, 24)); + // Set flags to determine if alpha != 0xFF. + ORN(tempReg2, WZR, tempReg1, ArithOption(tempReg1, ST_ASR, 24)); + CMP(tempReg2, 0); + + // Clear fullAlphaReg when the inverse was not 0. + // fullAlphaReg = tempReg2 == 0 ? fullAlphaReg : 0 + 1; + CSEL(fullAlphaReg, fullAlphaReg, WZR, CC_EQ); STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.c0off); } @@ -505,10 +503,15 @@ void VertexDecoderJitCache::Jit_Color4444() { // And expand to 8 bits. ORR(tempReg1, tempReg2, tempReg2, ArithOption(tempReg2, ST_LSL, 4)); - // Or any non-set bits into alphaNonFullReg. This way it's non-zero if not full. - ORN(alphaNonFullReg, alphaNonFullReg, tempReg1, ArithOption(tempReg1, ST_ASR, 24)); - STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.c0off); + + // Set flags to determine if alpha != 0xFF. + ORN(tempReg2, WZR, tempReg1, ArithOption(tempReg1, ST_ASR, 24)); + CMP(tempReg2, 0); + + // Clear fullAlphaReg when the inverse was not 0. + // fullAlphaReg = tempReg2 == 0 ? fullAlphaReg : 0 + 1; + CSEL(fullAlphaReg, fullAlphaReg, WZR, CC_EQ); } void VertexDecoderJitCache::Jit_Color565() { @@ -532,7 +535,7 @@ void VertexDecoderJitCache::Jit_Color565() { ORR(tempReg3, tempReg3, tempReg1, ArithOption(tempReg1, ST_LSR, 4)); ORR(tempReg2, tempReg2, tempReg3, ArithOption(tempReg3, ST_LSL, 8)); - // Add in full alpha. No need to update alphaNonFullReg. + // Add in full alpha. No need to update fullAlphaReg. ORRI2R(tempReg1, tempReg2, 0xFF000000, scratchReg); STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.c0off); @@ -558,10 +561,15 @@ void VertexDecoderJitCache::Jit_Color5551() { ANDI2R(tempReg1, tempReg1, 0xFF000000, scratchReg); ORR(tempReg2, tempReg2, tempReg1); - // Or any non-set bits into alphaNonFullReg. This way it's non-zero if not full. - ORN(alphaNonFullReg, alphaNonFullReg, tempReg1, ArithOption(tempReg1, ST_ASR, 24)); + // Set flags to determine if alpha != 0xFF. + ORN(tempReg3, WZR, tempReg1, ArithOption(tempReg1, ST_ASR, 24)); + CMP(tempReg3, 0); STR(INDEX_UNSIGNED, tempReg2, dstReg, dec_->decFmt.c0off); + + // Clear fullAlphaReg when the inverse was not 0. + // fullAlphaReg = tempReg3 == 0 ? fullAlphaReg : 0 + 1; + CSEL(fullAlphaReg, fullAlphaReg, WZR, CC_EQ); } void VertexDecoderJitCache::Jit_TcU16ThroughToFloat() { @@ -595,12 +603,12 @@ void VertexDecoderJitCache::Jit_TcFloat() { } void VertexDecoderJitCache::Jit_TcU8Prescale() { - fp.LDUR(16, neonScratchReg2D, srcReg, dec_->tcoff); - fp.UXTL(8, neonScratchReg2Q, neonScratchReg2D); // Widen to 16-bit - fp.UXTL(16, neonScratchReg2Q, neonScratchReg2D); // Widen to 32-bit - fp.UCVTF(32, neonScratchReg2D, neonScratchReg2D, 7); - fp.MOV(neonScratchRegD, neonUVOffsetReg); - fp.FMLA(32, neonScratchRegD, neonScratchReg2D, neonUVScaleReg); + fp.LDUR(16, neonScratchRegD, srcReg, dec_->tcoff); + fp.UXTL(8, neonScratchRegQ, neonScratchRegD); // Widen to 16-bit + fp.UXTL(16, neonScratchRegQ, neonScratchRegD); // Widen to 32-bit + fp.UCVTF(32, neonScratchRegD, neonScratchRegD); + fp.FMUL(32, neonScratchRegD, neonScratchRegD, neonUVScaleReg); // TODO: FMLA + fp.FADD(32, neonScratchRegD, neonScratchRegD, neonUVOffsetReg); fp.STUR(64, neonScratchRegD, dstReg, dec_->decFmt.uvoff); } @@ -613,11 +621,11 @@ void VertexDecoderJitCache::Jit_TcU8ToFloat() { } void VertexDecoderJitCache::Jit_TcU16Prescale() { - fp.LDUR(32, neonScratchReg2D, srcReg, dec_->tcoff); - fp.UXTL(16, neonScratchReg2Q, neonScratchReg2D); // Widen to 32-bit - fp.UCVTF(32, neonScratchReg2D, neonScratchReg2D, 15); - fp.MOV(neonScratchRegD, neonUVOffsetReg); - fp.FMLA(32, neonScratchRegD, neonScratchReg2D, neonUVScaleReg); + fp.LDUR(32, neonScratchRegD, srcReg, dec_->tcoff); + fp.UXTL(16, neonScratchRegQ, neonScratchRegD); // Widen to 32-bit + fp.UCVTF(32, neonScratchRegD, neonScratchRegD); + fp.FMUL(32, neonScratchRegD, neonScratchRegD, neonUVScaleReg); // TODO: FMLA + fp.FADD(32, neonScratchRegD, neonScratchRegD, neonUVOffsetReg); fp.STUR(64, neonScratchRegD, dstReg, dec_->decFmt.uvoff); } @@ -629,20 +637,20 @@ void VertexDecoderJitCache::Jit_TcU16ToFloat() { } void VertexDecoderJitCache::Jit_TcFloatPrescale() { - fp.LDUR(64, neonScratchReg2D, srcReg, dec_->tcoff); - fp.MOV(neonScratchRegD, neonUVOffsetReg); - fp.FMLA(32, neonScratchRegD, neonScratchReg2D, neonUVScaleReg); + fp.LDUR(64, neonScratchRegD, srcReg, dec_->tcoff); + fp.FMUL(32, neonScratchRegD, neonScratchRegD, neonUVScaleReg); // TODO: FMLA + fp.FADD(32, neonScratchRegD, neonScratchRegD, neonUVOffsetReg); fp.STUR(64, neonScratchRegD, dstReg, dec_->decFmt.uvoff); } void VertexDecoderJitCache::Jit_PosS8() { Jit_AnyS8ToFloat(dec_->posoff); - fp.STUR(128, srcQ, dstReg, dec_->decFmt.posoff); + fp.STUR(128, srcQ[0], dstReg, dec_->decFmt.posoff); } void VertexDecoderJitCache::Jit_PosS16() { Jit_AnyS16ToFloat(dec_->posoff); - fp.STUR(128, srcQ, dstReg, dec_->decFmt.posoff); + fp.STUR(128, srcQ[0], dstReg, dec_->decFmt.posoff); } void VertexDecoderJitCache::Jit_PosFloat() { @@ -660,16 +668,17 @@ void VertexDecoderJitCache::Jit_PosFloat() { void VertexDecoderJitCache::Jit_PosS8Through() { // 8-bit positions in throughmode always decode to 0, depth included. - STR(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.posoff); - STR(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.posoff + 4); - STR(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.posoff + 8); + fp.EOR(fpScratchReg, fpScratchReg, fpScratchReg); + STR(INDEX_UNSIGNED, fpScratchReg, dstReg, dec_->decFmt.posoff); + STR(INDEX_UNSIGNED, fpScratchReg, dstReg, dec_->decFmt.posoff + 4); + STR(INDEX_UNSIGNED, fpScratchReg, dstReg, dec_->decFmt.posoff + 8); } void VertexDecoderJitCache::Jit_PosS16Through() { // Start with X and Y (which is signed.) fp.LDUR(32, src[0], srcReg, dec_->posoff); - fp.SXTL(16, srcD, src[0]); - fp.SCVTF(32, srcD, srcD); + fp.SXTL(16, srcD[0], src[0]); + fp.SCVTF(32, srcD[0], srcD[0]); fp.STUR(64, src[0], dstReg, dec_->decFmt.posoff); // Now load in Z (which is unsigned.) LDRH(INDEX_UNSIGNED, tempReg3, srcReg, dec_->posoff + 4); @@ -735,7 +744,7 @@ void VertexDecoderJitCache::Jit_NormalS16Skin() { } void VertexDecoderJitCache::Jit_NormalFloatSkin() { - fp.LDUR(128, srcQ, srcReg, dec_->nrmoff); + fp.LDUR(128, srcQ[0], srcReg, dec_->nrmoff); Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); } @@ -750,28 +759,28 @@ void VertexDecoderJitCache::Jit_PosS16Skin() { } void VertexDecoderJitCache::Jit_PosFloatSkin() { - fp.LDUR(128, srcQ, srcReg, dec_->posoff); + fp.LDUR(128, srcQ[0], srcReg, dec_->posoff); Jit_WriteMatrixMul(dec_->decFmt.posoff, true); } void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { fp.LDUR(32, src[0], srcReg, srcoff); - fp.SXTL(8, srcD, src[0]); - fp.SXTL(16, srcQ, srcD); - fp.SCVTF(32, srcQ, srcQ, 7); + fp.SXTL(8, srcD[0], src[0]); + fp.SXTL(16, srcQ[0], srcD[0]); + fp.SCVTF(32, srcQ[0], srcQ[0], 7); } void VertexDecoderJitCache::Jit_AnyS16ToFloat(int srcoff) { fp.LDUR(64, src[0], srcReg, srcoff); - fp.SXTL(16, srcQ, srcD); - fp.SCVTF(32, srcQ, srcQ, 15); + fp.SXTL(16, srcQ[0], srcD[0]); + fp.SCVTF(32, srcQ[0], srcQ[0], 15); } void VertexDecoderJitCache::Jit_WriteMatrixMul(int outOff, bool pos) { - // Multiply srcQ with the matrix sitting in Q4-Q7. - fp.FMUL(32, accNEON, Q4, srcQ, 0); - fp.FMLA(32, accNEON, Q5, srcQ, 1); - fp.FMLA(32, accNEON, Q6, srcQ, 2); + // Multiply with the matrix sitting in Q4-Q7. + fp.FMUL(32, accNEON, Q4, srcQ[0], 0); + fp.FMLA(32, accNEON, Q5, srcQ[0], 1); + fp.FMLA(32, accNEON, Q6, srcQ[0], 2); if (pos) { fp.FADD(32, accNEON, accNEON, Q7); } diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index cc8b6452e..21b3e76a6 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -43,8 +43,6 @@ static const u8 nrmsize[4] = { 0, 3, 6, 12 }, nrmalign[4] = { 0, 1, 2, 4 }; static const u8 possize[4] = { 3, 3, 6, 12 }, posalign[4] = { 1, 1, 2, 4 }; static const u8 wtsize[4] = { 0, 1, 2, 4 }, wtalign[4] = { 0, 1, 2, 4 }; -static constexpr bool validateJit = false; - // When software skinning. This array is only used when non-jitted - when jitted, the matrix // is kept in registers. alignas(16) static float skinMatrix[12]; @@ -60,7 +58,7 @@ int TranslateNumBones(int bones) { return bones; } -static int DecFmtSize(u8 fmt) { +int DecFmtSize(u8 fmt) { switch (fmt) { case DEC_NONE: return 0; case DEC_FLOAT_1: return 4; @@ -83,7 +81,7 @@ static int DecFmtSize(u8 fmt) { } void DecVtxFormat::ComputeID() { - id = w0fmt | (w1fmt << 4) | (uvfmt << 8) | (c0fmt << 12) | (c1fmt << 16) | (nrmfmt << 20); + id = w0fmt | (w1fmt << 4) | (uvfmt << 8) | (c0fmt << 12) | (c1fmt << 16) | (nrmfmt << 20) | (posfmt << 24); } void DecVtxFormat::InitializeFromID(uint32_t id) { @@ -94,6 +92,7 @@ void DecVtxFormat::InitializeFromID(uint32_t id) { c0fmt = ((id >> 12) & 0xF); c1fmt = ((id >> 16) & 0xF); nrmfmt = ((id >> 20) & 0xF); + posfmt = ((id >> 24) & 0xF); w0off = 0; w1off = w0off + DecFmtSize(w0fmt); uvoff = w1off + DecFmtSize(w1fmt); @@ -101,29 +100,16 @@ void DecVtxFormat::InitializeFromID(uint32_t id) { c1off = c0off + DecFmtSize(c0fmt); nrmoff = c1off + DecFmtSize(c1fmt); posoff = nrmoff + DecFmtSize(nrmfmt); - stride = posoff + DecFmtSize(PosFmt()); + stride = posoff + DecFmtSize(posfmt); } void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) { // Find index bounds. Could cache this in display lists. // Also, this could be greatly sped up with SSE2/NEON, although rarely a bottleneck. + int lowerBound = 0x7FFFFFFF; + int upperBound = 0; u32 idx = vertType & GE_VTYPE_IDX_MASK; - if (idx == GE_VTYPE_IDX_16BIT) { - uint16_t upperBound = 0; - uint16_t lowerBound = 0xFFFF; - const u16_le *ind16 = (const u16_le *)inds; - for (int i = 0; i < count; i++) { - u16 value = ind16[i]; - if (value > upperBound) - upperBound = value; - if (value < lowerBound) - lowerBound = value; - } - *indexLowerBound = lowerBound; - *indexUpperBound = upperBound; - } else if (idx == GE_VTYPE_IDX_8BIT) { - uint8_t upperBound = 0; - uint8_t lowerBound = 0xFF; + if (idx == GE_VTYPE_IDX_8BIT) { const u8 *ind8 = (const u8 *)inds; for (int i = 0; i < count; i++) { u8 value = ind8[i]; @@ -132,11 +118,16 @@ void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBo if (value < lowerBound) lowerBound = value; } - *indexLowerBound = lowerBound; - *indexUpperBound = upperBound; + } else if (idx == GE_VTYPE_IDX_16BIT) { + const u16_le *ind16 = (const u16_le *)inds; + for (int i = 0; i < count; i++) { + u16 value = ind16[i]; + if (value > upperBound) + upperBound = value; + if (value < lowerBound) + lowerBound = value; + } } else if (idx == GE_VTYPE_IDX_32BIT) { - int lowerBound = 0x7FFFFFFF; - int upperBound = 0; WARN_LOG_REPORT_ONCE(indexBounds32, G3D, "GetIndexBounds: Decoding 32-bit indexes"); const u32_le *ind32 = (const u32_le *)inds; for (int i = 0; i < count; i++) { @@ -150,12 +141,12 @@ void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBo if (value < lowerBound) lowerBound = value; } - *indexLowerBound = (u16)lowerBound; - *indexUpperBound = (u16)upperBound; } else { - *indexLowerBound = 0; - *indexUpperBound = count - 1; + lowerBound = 0; + upperBound = count - 1; } + *indexLowerBound = (u16)lowerBound; + *indexUpperBound = (u16)upperBound; } void PrintDecodedVertex(const VertexReader &vtx) { @@ -349,29 +340,29 @@ void VertexDecoder::Step_TcFloatThrough() const void VertexDecoder::Step_TcU8Prescale() const { float *uv = (float *)(decoded_ + decFmt.uvoff); const u8 *uvdata = (const u8 *)(ptr_ + tcoff); - uv[0] = (float)uvdata[0] * (1.f / 128.f) * prescaleUV_->uScale + prescaleUV_->uOff; - uv[1] = (float)uvdata[1] * (1.f / 128.f) * prescaleUV_->vScale + prescaleUV_->vOff; + uv[0] = (float)uvdata[0] * (1.f / 128.f) * gstate_c.uv.uScale + gstate_c.uv.uOff; + uv[1] = (float)uvdata[1] * (1.f / 128.f) * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcU16Prescale() const { float *uv = (float *)(decoded_ + decFmt.uvoff); const u16_le *uvdata = (const u16_le *)(ptr_ + tcoff); - uv[0] = (float)uvdata[0] * (1.f / 32768.f) * prescaleUV_->uScale + prescaleUV_->uOff; - uv[1] = (float)uvdata[1] * (1.f / 32768.f) * prescaleUV_->vScale + prescaleUV_->vOff; + uv[0] = (float)uvdata[0] * (1.f / 32768.f) * gstate_c.uv.uScale + gstate_c.uv.uOff; + uv[1] = (float)uvdata[1] * (1.f / 32768.f) * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcU16DoublePrescale() const { float *uv = (float *)(decoded_ + decFmt.uvoff); const u16_le *uvdata = (const u16_le *)(ptr_ + tcoff); - uv[0] = (float)uvdata[0] * (1.f / 16384.f) * prescaleUV_->uScale + prescaleUV_->uOff; - uv[1] = (float)uvdata[1] * (1.f / 16384.f) * prescaleUV_->vScale + prescaleUV_->vOff; + uv[0] = (float)uvdata[0] * (1.f / 16384.f) * gstate_c.uv.uScale + gstate_c.uv.uOff; + uv[1] = (float)uvdata[1] * (1.f / 16384.f) * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcFloatPrescale() const { float *uv = (float *)(decoded_ + decFmt.uvoff); const float_le *uvdata = (const float_le *)(ptr_ + tcoff); - uv[0] = uvdata[0] * prescaleUV_->uScale + prescaleUV_->uOff; - uv[1] = uvdata[1] * prescaleUV_->vScale + prescaleUV_->vOff; + uv[0] = uvdata[0] * gstate_c.uv.uScale + gstate_c.uv.uOff; + uv[1] = uvdata[1] * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcU8MorphToFloat() const { @@ -445,8 +436,8 @@ void VertexDecoder::Step_TcU8PrescaleMorph() const { } float *out = (float *)(decoded_ + decFmt.uvoff); - out[0] = uv[0] * prescaleUV_->uScale + prescaleUV_->uOff; - out[1] = uv[1] * prescaleUV_->vScale + prescaleUV_->vOff; + out[0] = uv[0] * gstate_c.uv.uScale + gstate_c.uv.uOff; + out[1] = uv[1] * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcU16PrescaleMorph() const { @@ -460,8 +451,8 @@ void VertexDecoder::Step_TcU16PrescaleMorph() const { } float *out = (float *)(decoded_ + decFmt.uvoff); - out[0] = uv[0] * prescaleUV_->uScale + prescaleUV_->uOff; - out[1] = uv[1] * prescaleUV_->vScale + prescaleUV_->vOff; + out[0] = uv[0] * gstate_c.uv.uScale + gstate_c.uv.uOff; + out[1] = uv[1] * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcU16DoublePrescaleMorph() const { @@ -475,8 +466,8 @@ void VertexDecoder::Step_TcU16DoublePrescaleMorph() const { } float *out = (float *)(decoded_ + decFmt.uvoff); - out[0] = uv[0] * prescaleUV_->uScale + prescaleUV_->uOff; - out[1] = uv[1] * prescaleUV_->vScale + prescaleUV_->vOff; + out[0] = uv[0] * gstate_c.uv.uScale + gstate_c.uv.uOff; + out[1] = uv[1] * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_TcFloatPrescaleMorph() const { @@ -490,8 +481,8 @@ void VertexDecoder::Step_TcFloatPrescaleMorph() const { } float *out = (float *)(decoded_ + decFmt.uvoff); - out[0] = uv[0] * prescaleUV_->uScale + prescaleUV_->uOff; - out[1] = uv[1] * prescaleUV_->vScale + prescaleUV_->vOff; + out[0] = uv[0] * gstate_c.uv.uScale + gstate_c.uv.uOff; + out[1] = uv[1] * gstate_c.uv.vScale + gstate_c.uv.vOff; } void VertexDecoder::Step_ColorInvalid() const @@ -1185,7 +1176,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, steps_[numSteps_++] = morphcount == 1 ? colstep[col] : colstep_morph[col]; - // All color formats decode to DEC_U8_4. + // All color formats decode to DEC_U8_4 currently. // They can become floats later during transform though. decFmt.c0fmt = DEC_U8_4; decFmt.c0off = decOff; @@ -1247,18 +1238,20 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, if (posalign[pos] > biggest) biggest = posalign[pos]; - // We don't set posfmt because it's always DEC_FLOAT_3. if (throughmode) { steps_[numSteps_++] = posstep_through[pos]; + decFmt.posfmt = DEC_FLOAT_3; } else { if (skinInDecode) { steps_[numSteps_++] = morphcount == 1 ? posstep_skin[pos] : posstep_morph_skin[pos]; + decFmt.posfmt = DEC_FLOAT_3; } else { steps_[numSteps_++] = morphcount == 1 ? posstep[pos] : posstep_morph[pos]; + decFmt.posfmt = DEC_FLOAT_3; } } decFmt.posoff = decOff; - decOff += DecFmtSize(DecVtxFormat::PosFmt()); + decOff += DecFmtSize(decFmt.posfmt); } decFmt.stride = options.alignOutputToWord ? align(decOff, 4) : decOff; @@ -1276,6 +1269,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, ERROR_LOG_REPORT(G3D, "Vertices without position found: (%08x) %s", fmt_, temp); } + _assert_msg_(decFmt.posfmt == DEC_FLOAT_3, "Reader only supports float pos"); _assert_msg_(decFmt.uvfmt == DEC_FLOAT_2 || decFmt.uvfmt == DEC_NONE, "Reader only supports float UV"); // Attempt to JIT as well. But only do that if the main CPU JIT is enabled, in order to aid @@ -1288,13 +1282,11 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, } } -void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const UVScale *uvScaleOffset, int indexLowerBound, int indexUpperBound) const { - // A single 0 is acceptable for point lists. - _dbg_assert_(indexLowerBound <= indexUpperBound); - +void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, int indexLowerBound, int indexUpperBound) const { // Decode the vertices within the found bounds, once each // decoded_ and ptr_ are used in the steps, so can't be turned into locals for speed. - const u8 *startPtr = (const u8*)verts + indexLowerBound * size; + decoded_ = decodedptr; + ptr_ = (const u8*)verts + indexLowerBound * size; int count = indexUpperBound - indexLowerBound + 1; int stride = decFmt.stride; @@ -1306,13 +1298,10 @@ void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const UVScale return; } - if (jitted_ && !validateJit) { + if (jitted_) { // We've compiled the steps into optimized machine code, so just jump! - jitted_(startPtr, decodedptr, count, uvScaleOffset); + jitted_(ptr_, decoded_, count); } else { - ptr_ = startPtr; - decoded_ = decodedptr; - prescaleUV_ = uvScaleOffset; // Interpret the decode steps for (; count; count--) { for (int i = 0; i < numSteps_; i++) { @@ -1321,127 +1310,6 @@ void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const UVScale ptr_ += size; decoded_ += stride; } - - if (jitted_ && validateJit) { - CompareToJit(startPtr, decodedptr, indexUpperBound - indexLowerBound + 1, uvScaleOffset); - } - } -} - -static float LargestAbsDiff(Vec4f a, Vec4f b, int n) { - Vec4f delta = a - b; - float largest = 0; - for (int i = 0; i < n; ++ i) { - largest = std::max(largest, fabsf(delta[i])); - } - return largest; -} - -static bool DecodedVertsAreSimilar(const VertexReader &vtx1, const VertexReader &vtx2) { - Vec4f vec1{}, vec2{}; - if (vtx1.hasNormal()) { - vtx1.ReadNrm(vec1.AsArray()); - vtx2.ReadNrm(vec2.AsArray()); - float diff = LargestAbsDiff(vec1, vec2, 3); - if (diff >= 1.0 / 512.0f) { - WARN_LOG(G3D, "Normal diff %f", diff); - return false; - } - } - if (vtx1.hasUV()) { - vtx1.ReadUV(vec1.AsArray()); - vtx2.ReadUV(vec2.AsArray()); - float diff = LargestAbsDiff(vec1, vec2, 2); - if (diff >= 1.0 / 512.0f) { - WARN_LOG(G3D, "UV diff %f", diff); - return false; - } - } - if (vtx1.hasColor0()) { - vtx1.ReadColor0(vec1.AsArray()); - vtx2.ReadColor0(vec2.AsArray()); - float diff = LargestAbsDiff(vec1, vec2, 4); - if (diff >= 1.0 / 255.0f) { - WARN_LOG(G3D, "Color0 diff %f", diff); - return false; - } - } - if (vtx1.hasColor1()) { - vtx1.ReadColor1(vec1.AsArray()); - vtx2.ReadColor1(vec2.AsArray()); - float diff = LargestAbsDiff(vec1, vec2, 4); - if (diff >= 1.0 / 255.0f) { - WARN_LOG(G3D, "Color1 diff %f", diff); - return false; - } - } - vtx1.ReadPos(vec1.AsArray()); - vtx2.ReadPos(vec2.AsArray()); - float diff = LargestAbsDiff(vec1, vec2, 3); - if (diff >= 1.0 / 512.0f) { - WARN_LOG(G3D, "Pos diff %f", diff); - return false; - } - - return true; -} - -void VertexDecoder::CompareToJit(const u8 *startPtr, u8 *decodedptr, int count, const UVScale *uvScaleOffset) const { - std::vector jittedBuffer(decFmt.stride * count); - jitted_(startPtr, &jittedBuffer[0], count, uvScaleOffset); - - VertexReader controlReader(decodedptr, GetDecVtxFmt(), fmt_); - VertexReader jittedReader(&jittedBuffer[0], GetDecVtxFmt(), fmt_); - for (int i = 0; i < count; ++i) { - int off = decFmt.stride * i; - controlReader.Goto(i); - jittedReader.Goto(i); - if (!DecodedVertsAreSimilar(controlReader, jittedReader)) { - char name[512]{}; - ToString(name); - ERROR_LOG(G3D, "Encountered vertexjit mismatch at %d/%d for %s", i, count, name); - if (morphcount > 1) { - printf("Morph:\n"); - for (int j = 0; j < morphcount; ++j) { - printf(" %f\n", gstate_c.morphWeights[j]); - } - } - if (weighttype) { - printf("Bones:\n"); - for (int j = 0; j < nweights; ++j) { - for (int k = 0; k < 4; ++k) { - if (k == 0) - printf(" *"); - else - printf(" "); - printf(" %f,%f,%f\n", gstate.boneMatrix[j * 12 + k * 3 + 0], gstate.boneMatrix[j * 12 + k * 3 + 1], gstate.boneMatrix[j * 12 + k * 3 + 2]); - } - } - } - printf("Src:\n"); - const u8 *s = startPtr + i * size; - for (int j = 0; j < size; ++j) { - int oneoffset = j % onesize_; - if (oneoffset == weightoff && weighttype) - printf(" W:"); - else if (oneoffset == tcoff && tc) - printf(" T:"); - else if (oneoffset == coloff && col) - printf(" C:"); - else if (oneoffset == nrmoff && nrm) - printf(" N:"); - else if (oneoffset == posoff) - printf(" P:"); - printf("%02x ", s[j]); - if (oneoffset == onesize_ - 1) - printf("\n"); - } - printf("Interpreted vertex:\n"); - PrintDecodedVertex(controlReader); - printf("Jit vertex:\n"); - PrintDecodedVertex(jittedReader); - Crash(); - } } } @@ -1531,7 +1399,7 @@ VertexDecoderJitCache::VertexDecoderJitCache() } void VertexDecoderJitCache::Clear() { - if (g_Config.iCpuCore == (int)CPUCore::JIT || g_Config.iCpuCore == (int)CPUCore::JIT_IR) { + if (g_Config.iCpuCore == (int)CPUCore::JIT) { ClearCodeSpace(0); } } diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 3a0de590b..423dbd918 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -67,6 +67,8 @@ enum { DEC_U16_4, }; +int DecFmtSize(u8 fmt); + struct DecVtxFormat { u8 w0fmt; u8 w0off; // first 4 weights u8 w1fmt; u8 w1off; // second 4 weights @@ -74,14 +76,12 @@ struct DecVtxFormat { u8 c0fmt; u8 c0off; // First color u8 c1fmt; u8 c1off; u8 nrmfmt; u8 nrmoff; - u8 posoff; // Output position format is always DEC_FLOAT_3. + u8 posfmt; u8 posoff; u8 stride; uint32_t id; void ComputeID(); void InitializeFromID(uint32_t id); - - static u8 PosFmt() { return DEC_FLOAT_3; } }; void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); @@ -320,7 +320,7 @@ struct JitLookup { // Collapse to less skinning shaders to reduce shader switching, which is expensive. int TranslateNumBones(int bones); -typedef void (*JittedVertexDecoder)(const u8 *src, u8 *dst, int count, const UVScale *uvScaleOffset); +typedef void(*JittedVertexDecoder)(const u8 *src, u8 *dst, int count); struct VertexDecoderOptions { bool expandAllWeightsToFloat; @@ -336,9 +336,9 @@ public: u32 VertexType() const { return fmt_; } - const DecVtxFormat &GetDecVtxFmt() const { return decFmt; } + const DecVtxFormat &GetDecVtxFmt() { return decFmt; } - void DecodeVerts(u8 *decoded, const void *verts, const UVScale *uvScaleOffset, int indexLowerBound, int indexUpperBound) const; + void DecodeVerts(u8 *decoded, const void *verts, int indexLowerBound, int indexUpperBound) const; int VertexSize() const { return size; } // PSP format size @@ -436,7 +436,6 @@ public: // Mutable decoder state mutable u8 *decoded_ = nullptr; mutable const u8 *ptr_ = nullptr; - mutable const UVScale *prescaleUV_ = nullptr; JittedVertexDecoder jitted_ = 0; int32_t jittedSize_ = 0; @@ -473,9 +472,6 @@ public: u8 biggest; // in practice, alignment. friend class VertexDecoderJitCache; - -private: - void CompareToJit(const u8 *startPtr, u8 *decodedptr, int count, const UVScale *uvScaleOffset) const; }; diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 3dc1cf5c9..accaebcc4 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -33,11 +33,11 @@ static const float const65535 = 65535.0f; using namespace RiscVGen; -static const RiscVReg srcReg = X10; // a0 -static const RiscVReg dstReg = X11; // a1 -static const RiscVReg counterReg = X12; // a2 +static const RiscVReg srcReg = X10; +static const RiscVReg dstReg = X11; +static const RiscVReg counterReg = X12; -static const RiscVReg tempReg1 = X13; // a3 +static const RiscVReg tempReg1 = X13; static const RiscVReg tempReg2 = X14; static const RiscVReg tempReg3 = X15; static const RiscVReg scratchReg = X16; @@ -234,7 +234,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int // Keep the scale/offset in a few fp registers if we need it. if (prescaleStep) { - // tempReg1 happens to be the fourth argument register. + LI(tempReg1, &gstate_c.uv); FL(32, prescaleRegs.scale.u, tempReg1, 0); FL(32, prescaleRegs.scale.v, tempReg1, 4); FL(32, prescaleRegs.offset.u, tempReg1, 8); @@ -265,15 +265,15 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_4)) != 0) { LI(scratchReg, 255.0f / 15.0f); - FMV(FMv::W, FMv::X, fpExtra[0], scratchReg); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); } if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_5)) != 0) { LI(scratchReg, 255.0f / 31.0f); - FMV(FMv::W, FMv::X, fpExtra[1], scratchReg); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); } if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_6)) != 0) { LI(scratchReg, 255.0f / 63.0f); - FMV(FMv::W, FMv::X, fpExtra[2], scratchReg); + FMV(FMv::W, FMv::X, fpScratchReg3, scratchReg); } // Premultiply the values we need and store them so we can reuse. @@ -287,11 +287,11 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int if ((morphFlags & (1 << (int)MorphValuesIndex::AS_FLOAT)) != 0) FS(32, fpScratchReg1, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_4)) != 0) - storePremultiply(fpExtra[0], MorphValuesIndex::COLOR_4, n); + storePremultiply(fpScratchReg1, MorphValuesIndex::COLOR_4, n); if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_5)) != 0) - storePremultiply(fpExtra[1], MorphValuesIndex::COLOR_5, n); + storePremultiply(fpScratchReg2, MorphValuesIndex::COLOR_5, n); if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_6)) != 0) - storePremultiply(fpExtra[2], MorphValuesIndex::COLOR_6, n); + storePremultiply(fpScratchReg3, MorphValuesIndex::COLOR_6, n); } } else if (dec_->skinInDecode) { LI(morphBaseReg, &skinMatrix[0]); @@ -538,7 +538,7 @@ void VertexDecoderJitCache::Jit_TcU16ThroughToFloat() { LHU(tempReg1, srcReg, dec_->tcoff + 0); LHU(tempReg2, srcReg, dec_->tcoff + 2); - if (cpu_info.RiscV_Zbb) { + if (cpu_info.RiscV_B) { MINU(boundsMinUReg, boundsMinUReg, tempReg1); MAXU(boundsMaxUReg, boundsMaxUReg, tempReg1); MINU(boundsMinVReg, boundsMinVReg, tempReg2); @@ -838,20 +838,20 @@ void VertexDecoderJitCache::Jit_PosFloat() { } void VertexDecoderJitCache::Jit_PosS8Skin() { - Jit_AnyS8ToFloat(dec_->posoff); - Jit_WriteMatrixMul(dec_->decFmt.posoff, true); + Jit_AnyS8ToFloat(dec_->nrmoff); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); } void VertexDecoderJitCache::Jit_PosS16Skin() { - Jit_AnyS16ToFloat(dec_->posoff); - Jit_WriteMatrixMul(dec_->decFmt.posoff, true); + Jit_AnyS16ToFloat(dec_->nrmoff); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); } void VertexDecoderJitCache::Jit_PosFloatSkin() { - FL(32, fpSrc[0], srcReg, dec_->posoff + 0); - FL(32, fpSrc[1], srcReg, dec_->posoff + 4); - FL(32, fpSrc[2], srcReg, dec_->posoff + 8); - Jit_WriteMatrixMul(dec_->decFmt.posoff, true); + FL(32, fpSrc[0], srcReg, dec_->nrmoff + 0); + FL(32, fpSrc[1], srcReg, dec_->nrmoff + 4); + FL(32, fpSrc[2], srcReg, dec_->nrmoff + 8); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); } void VertexDecoderJitCache::Jit_PosS8Through() { @@ -867,8 +867,8 @@ void VertexDecoderJitCache::Jit_PosS16Through() { LH(tempReg2, srcReg, dec_->posoff + 2); // This one, Z, has to be unsigned. LHU(tempReg3, srcReg, dec_->posoff + 4); - FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); - FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff + 0); FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); @@ -904,17 +904,17 @@ void VertexDecoderJitCache::Jit_PosFloatMorph() { void VertexDecoderJitCache::Jit_PosS8MorphSkin() { Jit_AnyS8Morph(dec_->posoff, -1); - Jit_WriteMatrixMul(dec_->decFmt.posoff, true); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); } void VertexDecoderJitCache::Jit_PosS16MorphSkin() { Jit_AnyS16Morph(dec_->posoff, -1); - Jit_WriteMatrixMul(dec_->decFmt.posoff, true); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); } void VertexDecoderJitCache::Jit_PosFloatMorphSkin() { Jit_AnyFloatMorph(dec_->posoff, -1); - Jit_WriteMatrixMul(dec_->decFmt.posoff, true); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); } void VertexDecoderJitCache::Jit_Color8888() { @@ -1110,7 +1110,7 @@ void VertexDecoderJitCache::Jit_Color565Morph() { SRLI(tempReg1, tempReg1, 6); FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); - FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg3, Round::TOZERO); for (int n = 1; n < dec_->morphcount; n++) { @@ -1172,7 +1172,7 @@ void VertexDecoderJitCache::Jit_Color5551Morph() { } void VertexDecoderJitCache::Jit_WriteMorphColor(int outOff, bool checkAlpha) { - if (cpu_info.RiscV_Zbb) { + if (cpu_info.RiscV_B) { LI(scratchReg, 0xFF); FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); MAX(tempReg1, tempReg1, R_ZERO); @@ -1389,28 +1389,21 @@ void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) { void VertexDecoderJitCache::Jit_WriteMatrixMul(int dstoff, bool pos) { const RiscVReg fpDst[3] = { fpScratchReg1, fpScratchReg2, fpScratchReg3 }; - // When using morph + skin, we don't keep skinMatrix in a reg. - RiscVReg skinMatrixReg = morphBaseReg; - if (dec_->morphcount > 1) { - LI(scratchReg, &skinMatrix[0]); - skinMatrixReg = scratchReg; - } - // First, take care of the 3x3 portion of the matrix. for (int y = 0; y < 3; ++y) { for (int x = 0; x < 3; ++x) { - FL(32, fpScratchReg4, skinMatrixReg, (y * 3 + x) * 4); + FL(32, fpScratchReg4, morphBaseReg, (y * 3 + x) * 4); if (y == 0) - FMUL(32, fpDst[x], fpSrc[y], fpScratchReg4); + FMUL(32, fpDst[x], fpSrc[x], fpScratchReg4); else - FMADD(32, fpDst[x], fpSrc[y], fpScratchReg4, fpDst[x]); + FMADD(32, fpDst[x], fpSrc[x], fpScratchReg4, fpDst[x]); } } // For normal, z is 0 so we skip. if (pos) { for (int x = 0; x < 3; ++x) - FL(32, fpSrc[x], skinMatrixReg, (9 + x) * 4); + FL(32, fpSrc[x], morphBaseReg, (9 + x) * 4); for (int x = 0; x < 3; ++x) FADD(32, fpDst[x], fpDst[x], fpSrc[x]); } diff --git a/GPU/Common/VertexDecoderX86.cpp b/GPU/Common/VertexDecoderX86.cpp index d92bc964b..3340961f8 100644 --- a/GPU/Common/VertexDecoderX86.cpp +++ b/GPU/Common/VertexDecoderX86.cpp @@ -60,8 +60,6 @@ static const X64Reg tempReg3 = R10; static const X64Reg srcReg = RCX; static const X64Reg dstReg = RDX; static const X64Reg counterReg = R8; -static const X64Reg uvScalePtrReg = R9; // only used during init -static const X64Reg alphaReg = R11; #else static const X64Reg tempReg1 = RAX; static const X64Reg tempReg2 = R9; @@ -69,8 +67,6 @@ static const X64Reg tempReg3 = R10; static const X64Reg srcReg = RDI; static const X64Reg dstReg = RSI; static const X64Reg counterReg = RDX; -static const X64Reg uvScalePtrReg = RCX; // only used during init -static const X64Reg alphaReg = R11; #endif #else static const X64Reg tempReg1 = EAX; @@ -79,7 +75,6 @@ static const X64Reg tempReg3 = EDX; static const X64Reg srcReg = ESI; static const X64Reg dstReg = EDI; static const X64Reg counterReg = ECX; -static const X64Reg uvScalePtrReg = EDX; // only used during init #endif // XMM0-XMM5 are volatile on Windows X64 @@ -171,22 +166,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int BeginWrite(4096); const u8 *start = this->AlignCode16(); - bool prescaleStep = false; - // Look for prescaled texcoord steps - for (int i = 0; i < dec.numSteps_; i++) { - if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || - dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || - dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { - prescaleStep = true; - } - if (dec.steps_[i] == &VertexDecoder::Step_TcU8PrescaleMorph || - dec.steps_[i] == &VertexDecoder::Step_TcU16PrescaleMorph || - dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescaleMorph) { - prescaleStep = true; - } - } - - #if PPSSPP_ARCH(X86) // Store register values PUSH(ESI); @@ -199,7 +178,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int MOV(32, R(srcReg), MDisp(ESP, 16 + offset + 0)); MOV(32, R(dstReg), MDisp(ESP, 16 + offset + 4)); MOV(32, R(counterReg), MDisp(ESP, 16 + offset + 8)); - MOV(32, R(uvScalePtrReg), MDisp(ESP, 16 + offset + 12)); const uint8_t STACK_FIXED_ALLOC = 64; #else @@ -223,18 +201,51 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int MOVUPS(MDisp(ESP, 80), XMM9); #endif - // Initialize alpha reg. -#if PPSSPP_ARCH(AMD64) - if (dec.col) { - MOV(32, R(alphaReg), Imm32(1)); + bool prescaleStep = false; + // Look for prescaled texcoord steps + for (int i = 0; i < dec.numSteps_; i++) { + if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { + prescaleStep = true; + } + if (dec.steps_[i] == &VertexDecoder::Step_TcU8PrescaleMorph || + dec.steps_[i] == &VertexDecoder::Step_TcU16PrescaleMorph || + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescaleMorph) { + prescaleStep = true; + } + } + + // Add code to convert matrices to 4x4. + // Later we might want to do this when the matrices are loaded instead. + if (dec.skinInDecode) { + MOV(PTRBITS, R(tempReg1), ImmPtr(&threeMasks)); + MOVAPS(XMM4, MatR(tempReg1)); + MOV(PTRBITS, R(tempReg1), ImmPtr(&aOne)); + MOVUPS(XMM5, MatR(tempReg1)); + MOV(PTRBITS, R(tempReg1), ImmPtr(gstate.boneMatrix)); + MOV(PTRBITS, R(tempReg2), ImmPtr(bones)); + for (int i = 0; i < dec.nweights; i++) { + MOVUPS(XMM0, MDisp(tempReg1, (12 * i) * 4)); + MOVUPS(XMM1, MDisp(tempReg1, (12 * i + 3) * 4)); + MOVUPS(XMM2, MDisp(tempReg1, (12 * i + 3 * 2) * 4)); + MOVUPS(XMM3, MDisp(tempReg1, (12 * i + 3 * 3) * 4)); + ANDPS(XMM0, R(XMM4)); + ANDPS(XMM1, R(XMM4)); + ANDPS(XMM2, R(XMM4)); + ANDPS(XMM3, R(XMM4)); + ORPS(XMM3, R(XMM5)); + MOVAPS(MDisp(tempReg2, (16 * i) * 4), XMM0); + MOVAPS(MDisp(tempReg2, (16 * i + 4) * 4), XMM1); + MOVAPS(MDisp(tempReg2, (16 * i + 8) * 4), XMM2); + MOVAPS(MDisp(tempReg2, (16 * i + 12) * 4), XMM3); + } } -#endif // Keep the scale/offset in a few fp registers if we need it. - // TODO: Read it from an argument pointer instead of gstate_c.uv. if (prescaleStep) { - // uvScalePtrReg should point to gstate_c.uv, or wherever the UV scale we want to use is located. - MOVUPS(fpScaleOffsetReg, MatR(uvScalePtrReg)); + MOV(PTRBITS, R(tempReg1), ImmPtr(&gstate_c.uv)); + MOVUPS(fpScaleOffsetReg, MatR(tempReg1)); if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { MOV(PTRBITS, R(tempReg2), ImmPtr(&by128_11)); MULPS(fpScaleOffsetReg, MatR(tempReg2)); @@ -244,35 +255,8 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int } } - // Add code to convert matrices to 4x4. - // Later we might want to do this when the matrices are loaded instead. - // Can't touch fpScaleOffsetReg (XMM0) in here! - if (dec.skinInDecode) { - MOV(PTRBITS, R(tempReg1), ImmPtr(&threeMasks)); - MOVAPS(XMM5, MatR(tempReg1)); - MOV(PTRBITS, R(tempReg1), ImmPtr(&aOne)); - MOVUPS(XMM6, MatR(tempReg1)); - MOV(PTRBITS, R(tempReg1), ImmPtr(gstate.boneMatrix)); - MOV(PTRBITS, R(tempReg2), ImmPtr(bones)); - for (int i = 0; i < dec.nweights; i++) { - MOVUPS(XMM1, MDisp(tempReg1, (12 * i) * 4)); - MOVUPS(XMM2, MDisp(tempReg1, (12 * i + 3) * 4)); - MOVUPS(XMM3, MDisp(tempReg1, (12 * i + 3 * 2) * 4)); - MOVUPS(XMM4, MDisp(tempReg1, (12 * i + 3 * 3) * 4)); - ANDPS(XMM1, R(XMM5)); - ANDPS(XMM2, R(XMM5)); - ANDPS(XMM3, R(XMM5)); - ANDPS(XMM4, R(XMM5)); - ORPS(XMM4, R(XMM6)); - MOVAPS(MDisp(tempReg2, (16 * i) * 4), XMM1); - MOVAPS(MDisp(tempReg2, (16 * i + 4) * 4), XMM2); - MOVAPS(MDisp(tempReg2, (16 * i + 8) * 4), XMM3); - MOVAPS(MDisp(tempReg2, (16 * i + 12) * 4), XMM4); - } - } - // Let's not bother with a proper stack frame. We just grab the arguments and go. - JumpTarget loopStart = NopAlignCode16(); + JumpTarget loopStart = GetCodePtr(); for (int i = 0; i < dec.numSteps_; i++) { if (!CompileStep(dec, i)) { EndWrite(); @@ -287,21 +271,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int SUB(32, R(counterReg), Imm8(1)); J_CC(CC_NZ, loopStart, true); - // Writeback alpha reg -#if PPSSPP_ARCH(AMD64) - if (dec.col) { - CMP(32, R(alphaReg), Imm32(1)); - FixupBranch alphaJump = J_CC(CC_E, false); - if (RipAccessible(&gstate_c.vertexFullAlpha)) { - MOV(8, M(&gstate_c.vertexFullAlpha), Imm8(0)); // rip accessible - } else { - MOV(PTRBITS, R(tempReg1), ImmPtr(&gstate_c.vertexFullAlpha)); - MOV(8, MatR(tempReg1), Imm8(0)); // rip accessible - } - SetJumpTarget(alphaJump); - } -#endif - MOVUPS(XMM4, MDisp(ESP, 0)); MOVUPS(XMM5, MDisp(ESP, 16)); MOVUPS(XMM6, MDisp(ESP, 32)); @@ -781,8 +750,6 @@ void VertexDecoderJitCache::Jit_TcU8Prescale() { CVTSI2SS(fpScratchReg, R(tempReg1)); CVTSI2SS(fpScratchReg2, R(tempReg2)); UNPCKLPS(fpScratchReg, R(fpScratchReg2)); - // TODO: These are a lot of nasty consecutive dependencies. Can probably be made faster - // if we can spare another register to avoid the shuffle, like on ARM. MULPS(fpScratchReg, R(fpScaleOffsetReg)); SHUFPS(fpScaleOffsetReg, R(fpScaleOffsetReg), _MM_SHUFFLE(1, 0, 3, 2)); ADDPS(fpScratchReg, R(fpScaleOffsetReg)); @@ -963,17 +930,12 @@ void VertexDecoderJitCache::Jit_Color8888() { CMP(32, R(tempReg1), Imm32(0xFF000000)); FixupBranch skip = J_CC(CC_AE, false); -#if PPSSPP_ARCH(AMD64) - // Would like to use CMOV or SetCC but CMOV doesn't take immediates and SetCC isn't right. So... - XOR(32, R(alphaReg), R(alphaReg)); -#else if (RipAccessible(&gstate_c.vertexFullAlpha)) { MOV(8, M(&gstate_c.vertexFullAlpha), Imm8(0)); // rip accessible } else { MOV(PTRBITS, R(tempReg1), ImmPtr(&gstate_c.vertexFullAlpha)); MOV(8, MatR(tempReg1), Imm8(0)); } -#endif SetJumpTarget(skip); } @@ -1003,16 +965,12 @@ void VertexDecoderJitCache::Jit_Color4444() { CMP(32, R(tempReg1), Imm32(0xFF000000)); FixupBranch skip = J_CC(CC_AE, false); -#if PPSSPP_ARCH(AMD64) - XOR(32, R(alphaReg), R(alphaReg)); -#else if (RipAccessible(&gstate_c.vertexFullAlpha)) { MOV(8, M(&gstate_c.vertexFullAlpha), Imm8(0)); // rip accessible } else { MOV(PTRBITS, R(tempReg1), ImmPtr(&gstate_c.vertexFullAlpha)); MOV(8, MatR(tempReg1), Imm8(0)); } -#endif SetJumpTarget(skip); } @@ -1084,18 +1042,14 @@ void VertexDecoderJitCache::Jit_Color5551() { MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2)); - // Let's AND to avoid a branch, tempReg1 has alpha only in the top 8 bits, and they're all equal. + // Let's AND to avoid a branch, tempReg1 has alpha only in the top 8 bits. SHR(32, R(tempReg1), Imm8(24)); -#if PPSSPP_ARCH(AMD64) - AND(8, R(alphaReg), R(tempReg1)); -#else if (RipAccessible(&gstate_c.vertexFullAlpha)) { AND(8, M(&gstate_c.vertexFullAlpha), R(tempReg1)); // rip accessible } else { MOV(PTRBITS, R(tempReg3), ImmPtr(&gstate_c.vertexFullAlpha)); AND(8, MatR(tempReg3), R(tempReg1)); } -#endif } void VertexDecoderJitCache::Jit_Color8888Morph() { @@ -1304,16 +1258,12 @@ void VertexDecoderJitCache::Jit_WriteMorphColor(int outOff, bool checkAlpha) { if (checkAlpha) { CMP(32, R(tempReg1), Imm32(0xFF000000)); FixupBranch skip = J_CC(CC_AE, false); -#if PPSSPP_ARCH(AMD64) - XOR(32, R(alphaReg), R(alphaReg)); -#else if (RipAccessible(&gstate_c.vertexFullAlpha)) { MOV(8, M(&gstate_c.vertexFullAlpha), Imm8(0)); // rip accessible } else { MOV(PTRBITS, R(tempReg2), ImmPtr(&gstate_c.vertexFullAlpha)); MOV(8, MatR(tempReg2), Imm8(0)); } -#endif SetJumpTarget(skip); } else { // Force alpha to full if we're not checking it. diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 08c0ae6b6..9426074cd 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -53,6 +53,9 @@ const D3D11_PRIMITIVE_TOPOLOGY d3d11prim[8] = { D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // Need expansion - though we could do it with geom shaders in most cases }; +#define VERTEXCACHE_DECIMATION_INTERVAL 17 + +enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; enum { VERTEX_PUSH_SIZE = 1024 * 1024 * 16, INDEX_PUSH_SIZE = 1024 * 1024 * 4, @@ -70,6 +73,7 @@ DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, : draw_(draw), device_(device), context_(context), + vai_(256), inputLayoutMap_(32), blendCache_(32), blendCache1_(32), @@ -80,10 +84,11 @@ DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, decOptions_.expandAllWeightsToFloat = true; decOptions_.expand8BitNormalsToFloat = true; + decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; // Allocate nicely aligned memory. Maybe graphics drivers will // appreciate it. // All this is a LOT of memory, need to see if we can cut down somehow. - indexGen.Setup(decIndex_); + indexGen.Setup(decIndex); InitDeviceObjects(); @@ -106,6 +111,13 @@ void DrawEngineD3D11::InitDeviceObjects() { draw_->SetInvalidationCallback(std::bind(&DrawEngineD3D11::Invalidate, this, std::placeholders::_1)); } +void DrawEngineD3D11::ClearTrackedVertexArrays() { + vai_.Iterate([&](uint32_t hash, VertexArrayInfoD3D11 *vai){ + delete vai; + }); + vai_.Clear(); +} + void DrawEngineD3D11::ClearInputLayoutMap() { inputLayoutMap_.Iterate([&](const InputLayoutKey &key, ID3D11InputLayout *il) { if (il) @@ -120,9 +132,7 @@ void DrawEngineD3D11::NotifyConfigChanged() { } void DrawEngineD3D11::DestroyDeviceObjects() { - if (draw_) { - draw_->SetInvalidationCallback(InvalidationCallback()); - } + draw_->SetInvalidationCallback(InvalidationCallback()); ClearTrackedVertexArrays(); ClearInputLayoutMap(); @@ -187,8 +197,8 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade // TODO: Instead of one for each vshader, we can reduce it to one for each type of shader // that reads TEXCOORD or not, etc. Not sure if worth it. const InputLayoutKey key{ vshader, decFmt.id }; - ID3D11InputLayout *inputLayout; - if (inputLayoutMap_.Get(key, &inputLayout)) { + ID3D11InputLayout *inputLayout = inputLayoutMap_.Get(key); + if (inputLayout) { return inputLayout; } else { D3D11_INPUT_ELEMENT_DESC VertexElements[8]; @@ -231,7 +241,7 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade // POSITION // Always - VertexAttribSetup(VertexElement, DecVtxFormat::PosFmt(), decFmt.posoff, "POSITION", 0); + VertexAttribSetup(VertexElement, decFmt.posfmt, decFmt.posoff, "POSITION", 0); VertexElement++; // Create declaration @@ -247,13 +257,69 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade } } +void DrawEngineD3D11::MarkUnreliable(VertexArrayInfoD3D11 *vai) { + vai->status = VertexArrayInfoD3D11::VAI_UNRELIABLE; + if (vai->vbo) { + vai->vbo->Release(); + vai->vbo = nullptr; + } + if (vai->ebo) { + vai->ebo->Release(); + vai->ebo = nullptr; + } +} + void DrawEngineD3D11::BeginFrame() { pushVerts_->Reset(); pushInds_->Reset(); + gpuStats.numTrackedVertexArrays = (int)vai_.size(); + + if (--decimationCounter_ <= 0) { + decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; + } else { + return; + } + + const int threshold = gpuStats.numFlips - VAI_KILL_AGE; + const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; + int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; + vai_.Iterate([&](uint32_t hash, VertexArrayInfoD3D11 *vai){ + bool kill; + if (vai->status == VertexArrayInfoD3D11::VAI_UNRELIABLE) { + // We limit killing unreliable so we don't rehash too often. + kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0; + } else { + kill = vai->lastFrame < threshold; + } + if (kill) { + delete vai; + vai_.Remove(hash); + } + }); + vai_.Maintain(); + + // Enable if you want to see vertex decoders in the log output. Need a better way. +#if 0 + char buffer[16384]; + for (std::map::iterator dec = decoderMap_.begin(); dec != decoderMap_.end(); ++dec) { + char *ptr = buffer; + ptr += dec->second->ToString(ptr); + // *ptr++ = '\n'; + NOTICE_LOG(G3D, buffer); + } +#endif + lastRenderStepId_ = -1; } +VertexArrayInfoD3D11::~VertexArrayInfoD3D11() { + if (vbo) + vbo->Release(); + if (ebo) + ebo->Release(); +} + // In D3D, we're synchronous and state carries over so all we reset here on a new step is the viewport/scissor. void DrawEngineD3D11::Invalidate(InvalidationCallbackFlags flags) { if (flags & InvalidationCallbackFlags::RENDER_PASS_STATE) { @@ -261,7 +327,7 @@ void DrawEngineD3D11::Invalidate(InvalidationCallbackFlags flags) { } } -// The inline wrapper in the header checks for numDrawCalls_ == 0 +// The inline wrapper in the header checks for numDrawCalls == 0 void DrawEngineD3D11::DoFlush() { bool textureNeedsApply = false; if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { @@ -286,17 +352,168 @@ void DrawEngineD3D11::DoFlush() { ID3D11Buffer *vb_ = nullptr; ID3D11Buffer *ib_ = nullptr; - DecodeVerts(decoded_); - DecodeInds(); + int vertexCount = 0; + int maxIndex = 0; + bool useElements = true; - bool useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; - int vertexCount = indexGen.VertexCount(); - gpuStats.numUncachedVertsDrawn += vertexCount; - int maxIndex = MaxIndex(); - if (!useElements && indexGen.PureCount()) { - vertexCount = indexGen.PureCount(); + // Cannot cache vertex data with morph enabled. + bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); + // Also avoid caching when software skinning. + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + useCache = false; + + if (useCache) { + u32 id = dcid_ ^ gstate.getUVGenMode(); // This can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 + + VertexArrayInfoD3D11 *vai = vai_.Get(id); + if (!vai) { + vai = new VertexArrayInfoD3D11(); + vai_.Insert(id, vai); + } + + switch (vai->status) { + case VertexArrayInfoD3D11::VAI_NEW: + { + // Haven't seen this one before. + uint64_t dataHash = ComputeHash(); + vai->hash = dataHash; + vai->minihash = ComputeMiniHash(); + vai->status = VertexArrayInfoD3D11::VAI_HASHING; + vai->drawsUntilNextFullHash = 0; + DecodeVerts(decoded); // writes to indexGen + vai->numVerts = indexGen.VertexCount(); + vai->prim = indexGen.Prim(); + vai->maxIndex = indexGen.MaxIndex(); + vai->flags = gstate_c.vertexFullAlpha ? VAI11_FLAG_VERTEXFULLALPHA : 0; + goto rotateVBO; + } + + // Hashing - still gaining confidence about the buffer. + // But if we get this far it's likely to be worth creating a vertex buffer. + case VertexArrayInfoD3D11::VAI_HASHING: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + if (vai->drawsUntilNextFullHash == 0) { + // Let's try to skip a full hash if mini would fail. + const u32 newMiniHash = ComputeMiniHash(); + uint64_t newHash = vai->hash; + if (newMiniHash == vai->minihash) { + newHash = ComputeHash(); + } + if (newMiniHash != vai->minihash || newHash != vai->hash) { + MarkUnreliable(vai); + DecodeVerts(decoded); + goto rotateVBO; + } + if (vai->numVerts > 64) { + // exponential backoff up to 16 draws, then every 24 + vai->drawsUntilNextFullHash = std::min(24, vai->numFrames); + } else { + // Lower numbers seem much more likely to change. + vai->drawsUntilNextFullHash = 0; + } + // TODO: tweak + //if (vai->numFrames > 1000) { + // vai->status = VertexArrayInfo::VAI_RELIABLE; + //} + } else { + vai->drawsUntilNextFullHash--; + u32 newMiniHash = ComputeMiniHash(); + if (newMiniHash != vai->minihash) { + MarkUnreliable(vai); + DecodeVerts(decoded); + goto rotateVBO; + } + } + + if (vai->vbo == 0) { + DecodeVerts(decoded); + vai->numVerts = indexGen.VertexCount(); + vai->prim = indexGen.Prim(); + vai->maxIndex = indexGen.MaxIndex(); + vai->flags = gstate_c.vertexFullAlpha ? VAI11_FLAG_VERTEXFULLALPHA : 0; + useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; + if (!useElements && indexGen.PureCount()) { + vai->numVerts = indexGen.PureCount(); + } + + _dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); + + // TODO: Combine these two into one buffer? + u32 size = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex(); + D3D11_BUFFER_DESC desc{ size, D3D11_USAGE_IMMUTABLE, D3D11_BIND_VERTEX_BUFFER, 0 }; + D3D11_SUBRESOURCE_DATA data{ decoded }; + ASSERT_SUCCESS(device_->CreateBuffer(&desc, &data, &vai->vbo)); + if (useElements) { + u32 size = sizeof(short) * indexGen.VertexCount(); + D3D11_BUFFER_DESC desc{ size, D3D11_USAGE_IMMUTABLE, D3D11_BIND_INDEX_BUFFER, 0 }; + D3D11_SUBRESOURCE_DATA data{ decIndex }; + ASSERT_SUCCESS(device_->CreateBuffer(&desc, &data, &vai->ebo)); + } else { + vai->ebo = 0; + } + } else { + gpuStats.numCachedDrawCalls++; + useElements = vai->ebo ? true : false; + gpuStats.numCachedVertsDrawn += vai->numVerts; + gstate_c.vertexFullAlpha = vai->flags & VAI11_FLAG_VERTEXFULLALPHA; + } + vb_ = vai->vbo; + ib_ = vai->ebo; + vertexCount = vai->numVerts; + maxIndex = vai->maxIndex; + prim = static_cast(vai->prim); + break; + } + + // Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time. + case VertexArrayInfoD3D11::VAI_RELIABLE: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + gpuStats.numCachedDrawCalls++; + gpuStats.numCachedVertsDrawn += vai->numVerts; + vb_ = vai->vbo; + ib_ = vai->ebo; + + vertexCount = vai->numVerts; + + maxIndex = vai->maxIndex; + prim = static_cast(vai->prim); + + gstate_c.vertexFullAlpha = vai->flags & VAI11_FLAG_VERTEXFULLALPHA; + break; + } + + case VertexArrayInfoD3D11::VAI_UNRELIABLE: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + DecodeVerts(decoded); + goto rotateVBO; + } + } + + vai->lastFrame = gpuStats.numFlips; + } else { + DecodeVerts(decoded); +rotateVBO: + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); + useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; + vertexCount = indexGen.VertexCount(); + maxIndex = indexGen.MaxIndex(); + if (!useElements && indexGen.PureCount()) { + vertexCount = indexGen.PureCount(); + } + prim = indexGen.Prim(); } - prim = indexGen.Prim(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { @@ -331,7 +548,7 @@ void DrawEngineD3D11::DoFlush() { UINT vOffset; int vSize = (maxIndex + 1) * dec_->GetDecVtxFmt().stride; uint8_t *vptr = pushVerts_->BeginPush(context_, &vOffset, vSize); - memcpy(vptr, decoded_, vSize); + memcpy(vptr, decoded, vSize); pushVerts_->EndPush(context_); ID3D11Buffer *buf = pushVerts_->Buf(); context_->IASetVertexBuffers(0, 1, &buf, &stride, &vOffset); @@ -339,7 +556,7 @@ void DrawEngineD3D11::DoFlush() { UINT iOffset; int iSize = 2 * indexGen.VertexCount(); uint8_t *iptr = pushInds_->BeginPush(context_, &iOffset, iSize); - memcpy(iptr, decIndex_, iSize); + memcpy(iptr, decIndex, iSize); pushInds_->EndPush(context_); context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset); context_->DrawIndexed(vertexCount, 0, 0); @@ -363,8 +580,7 @@ void DrawEngineD3D11::DoFlush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); - DecodeInds(); + DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255); @@ -379,12 +595,12 @@ void DrawEngineD3D11::DoFlush() { prim = GE_PRIM_TRIANGLES; VERBOSE_LOG(G3D, "Flush prim %i SW! %i verts in one go", prim, indexGen.VertexCount()); - u16 *inds = decIndex_; + u16 *inds = decIndex; SoftwareTransformResult result{}; SoftwareTransformParams params{}; - params.decoded = decoded_; - params.transformed = transformed_; - params.transformedExpanded = transformedExpanded_; + params.decoded = decoded; + params.transformed = transformed; + params.transformedExpanded = transformedExpanded; params.fbman = framebufferManager_; params.texCache = textureCache_; params.allowClear = true; @@ -403,7 +619,7 @@ void DrawEngineD3D11::DoFlush() { UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); + int maxIndex = indexGen.MaxIndex(); SoftwareTransform swTransform(params); const Lin::Vec3 trans(gstate_c.vpXOffset, -gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f); @@ -444,8 +660,8 @@ void DrawEngineD3D11::DoFlush() { // We really do need a vertex layout for each vertex shader (or at least check its ID bits for what inputs it uses)! // Some vertex shaders ignore one of the inputs, and then the layout created from it will lack it, which will be a problem for others. InputLayoutKey key{ vshader, 0xFFFFFFFF }; // Let's use 0xFFFFFFFF to signify TransformedVertex - ID3D11InputLayout *layout; - if (!inputLayoutMap_.Get(key, &layout)) { + ID3D11InputLayout *layout = inputLayoutMap_.Get(key); + if (!layout) { ASSERT_SUCCESS(device_->CreateInputLayout(TransformedVertexElements, ARRAY_SIZE(TransformedVertexElements), vshader->bytecode().data(), vshader->bytecode().size(), &layout)); inputLayoutMap_.Insert(key, layout); } @@ -499,8 +715,25 @@ void DrawEngineD3D11::DoFlush() { decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } - ResetAfterDrawInline(); + gpuStats.numFlushes++; + gpuStats.numDrawCalls += numDrawCalls; + gpuStats.numVertsSubmitted += vertexCountInDrawCalls_; + + indexGen.Reset(); + decodedVerts_ = 0; + numDrawCalls = 0; + vertexCountInDrawCalls_ = 0; + decodeCounter_ = 0; + dcid_ = 0; + gstate_c.vertexFullAlpha = true; framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); + + // Now seems as good a time as any to reset the min/max coords, which we may examine later. + gstate_c.vertBounds.minU = 512; + gstate_c.vertBounds.minV = 512; + gstate_c.vertBounds.maxU = 0; + gstate_c.vertBounds.maxV = 0; + GPUDebug::NotifyDraw(); } diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 9f365ab24..80e7b606f 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -38,6 +38,65 @@ class ShaderManagerD3D11; class TextureCacheD3D11; class FramebufferManagerD3D11; +// States transitions: +// On creation: DRAWN_NEW +// DRAWN_NEW -> DRAWN_HASHING +// DRAWN_HASHING -> DRAWN_RELIABLE +// DRAWN_HASHING -> DRAWN_UNRELIABLE +// DRAWN_ONCE -> UNRELIABLE +// DRAWN_RELIABLE -> DRAWN_SAFE +// UNRELIABLE -> death +// DRAWN_ONCE -> death +// DRAWN_RELIABLE -> death + +enum { + VAI11_FLAG_VERTEXFULLALPHA = 1, +}; + +// Try to keep this POD. +class VertexArrayInfoD3D11 { +public: + VertexArrayInfoD3D11() { + status = VAI_NEW; + vbo = 0; + ebo = 0; + prim = GE_PRIM_INVALID; + numDraws = 0; + numFrames = 0; + lastFrame = gpuStats.numFlips; + numVerts = 0; + drawsUntilNextFullHash = 0; + flags = 0; + } + ~VertexArrayInfoD3D11(); + + enum Status : uint8_t { + VAI_NEW, + VAI_HASHING, + VAI_RELIABLE, // cache, don't hash + VAI_UNRELIABLE, // never cache + }; + + uint64_t hash; + u32 minihash; + + ID3D11Buffer *vbo; + ID3D11Buffer *ebo; + + // Precalculated parameter for drawRangeElements + u16 numVerts; + u16 maxIndex; + s8 prim; + Status status; + + // ID information + int numDraws; + int numFrames; + int lastFrame; // So that we can forget. + u16 drawsUntilNextFullHash; + u8 flags; +}; + class TessellationDataTransferD3D11 : public TessellationDataTransfer { private: ID3D11DeviceContext *context_; @@ -79,23 +138,25 @@ public: // So that this can be inlined void Flush() { - if (!numDrawVerts_) + if (!numDrawCalls) return; DoFlush(); } void FinishDeferred() { - if (!numDrawVerts_) + if (!numDrawCalls) return; - DecodeVerts(decoded_); + DecodeVerts(decoded); } void DispatchFlush() override { - if (!numDrawVerts_) + if (!numDrawCalls) return; Flush(); } + void ClearTrackedVertexArrays() override; + void NotifyConfigChanged() override; void ClearInputLayoutMap(); @@ -110,12 +171,16 @@ private: ID3D11InputLayout *SetupDecFmtForDraw(D3D11VertexShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt); + void MarkUnreliable(VertexArrayInfoD3D11 *vai); + Draw::DrawContext *draw_; // Used for framebuffer related things exclusively. ID3D11Device *device_; ID3D11Device1 *device1_; ID3D11DeviceContext *context_; ID3D11DeviceContext1 *context1_; + PrehashMap vai_; + struct InputLayoutKey { D3D11VertexShader *vshader; u32 decFmtId; @@ -128,7 +193,7 @@ private: } }; - DenseHashMap inputLayoutMap_; + DenseHashMap inputLayoutMap_; // Other ShaderManagerD3D11 *shaderManager_ = nullptr; @@ -140,10 +205,10 @@ private: PushBufferD3D11 *pushInds_; // D3D11 state object caches. - DenseHashMap blendCache_; - DenseHashMap blendCache1_; - DenseHashMap depthStencilCache_; - DenseHashMap rasterCache_; + DenseHashMap blendCache_; + DenseHashMap blendCache1_; + DenseHashMap depthStencilCache_; + DenseHashMap rasterCache_; // Keep the depth state between ApplyDrawState and ApplyDrawStateLate ID3D11RasterizerState *rasterState_ = nullptr; diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index aff432ba4..aa1ec6606 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -356,8 +356,8 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { // There might have been interactions between depth and blend above. if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) { if (!device1_) { - ID3D11BlendState *bs = nullptr; - if (!blendCache_.Get(keys_.blend.value, &bs) || !bs) { + ID3D11BlendState *bs = blendCache_.Get(keys_.blend.value); + if (bs == nullptr) { D3D11_BLEND_DESC desc{}; D3D11_RENDER_TARGET_BLEND_DESC &rt = desc.RenderTarget[0]; rt.BlendEnable = keys_.blend.blendEnable; @@ -373,8 +373,8 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { } blendState_ = bs; } else { - ID3D11BlendState1 *bs1 = nullptr; - if (!blendCache1_.Get(keys_.blend.value, &bs1) || !bs1) { + ID3D11BlendState1 *bs1 = blendCache1_.Get(keys_.blend.value); + if (bs1 == nullptr) { D3D11_BLEND_DESC1 desc1{}; D3D11_RENDER_TARGET_BLEND_DESC1 &rt = desc1.RenderTarget[0]; rt.BlendEnable = keys_.blend.blendEnable; @@ -395,8 +395,8 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { } if (gstate_c.IsDirty(DIRTY_RASTER_STATE)) { - ID3D11RasterizerState *rs; - if (!rasterCache_.Get(keys_.raster.value, &rs) || !rs) { + ID3D11RasterizerState *rs = rasterCache_.Get(keys_.raster.value); + if (rs == nullptr) { D3D11_RASTERIZER_DESC desc{}; desc.CullMode = (D3D11_CULL_MODE)(keys_.raster.cullMode); desc.FillMode = D3D11_FILL_SOLID; @@ -410,8 +410,8 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { } if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) { - ID3D11DepthStencilState *ds; - if (!depthStencilCache_.Get(keys_.depthStencil.value, &ds) || !ds) { + ID3D11DepthStencilState *ds = depthStencilCache_.Get(keys_.depthStencil.value); + if (ds == nullptr) { D3D11_DEPTH_STENCIL_DESC desc{}; desc.DepthEnable = keys_.depthStencil.depthTestEnable; desc.DepthWriteMask = keys_.depthStencil.depthWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 465981e67..d658d19a0 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -348,14 +348,6 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (th > 16384) th = 16384; - // NOTE: For block-compressed textures, we'll force the size up to the closest 4x4. This is due to an - // unfortunate restriction in D3D11 (and early D3D12). We'll warn about it in the log to give texture pack - // authors notice to fix it. - if (plan.doReplace && Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) { - tw = (tw + 3) & ~3; - th = (th + 3) & ~3; - } - if (plan.depth == 1) { // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. levels = std::min(plan.levelsToCreate, plan.levelsToLoad); diff --git a/GPU/Debugger/Breakpoints.cpp b/GPU/Debugger/Breakpoints.cpp index e4e521404..d1577d2b6 100644 --- a/GPU/Debugger/Breakpoints.cpp +++ b/GPU/Debugger/Breakpoints.cpp @@ -128,10 +128,9 @@ u32 GetAdjustedRenderTargetAddress(u32 op) { return (u32)-1; } -// Note: this now always returns false, but still needs to be called. -void CheckForTextureChange(u32 op, u32 addr) { +bool IsTextureChangeBreakpoint(u32 op, u32 addr) { if (!textureChangeTemp) { - return; + return false; } const u8 cmd = op >> 24; @@ -143,30 +142,24 @@ void CheckForTextureChange(u32 op, u32 addr) { if (cmd == GE_CMD_TEXTUREMAPENABLE) { enabled = (op & 1) != 0; } else { - return; + return false; } } if (enabled && addr != lastTexture) { textureChangeTemp = false; lastTexture = addr; - - // Silently convert to a primitive breakpoint, so we stop on use. - // Note: this may cause "spurious" breaks if the tex is changed and the changed back. - AddCmdBreakpoint(GE_CMD_PRIM, true); - AddCmdBreakpoint(GE_CMD_BEZIER, true); - AddCmdBreakpoint(GE_CMD_SPLINE, true); - AddCmdBreakpoint(GE_CMD_VAP, true); + return true; + } else { + return false; } } bool IsTextureCmdBreakpoint(u32 op) { const u32 addr = GetAdjustedTextureAddress(op); if (addr != (u32)-1) { - CheckForTextureChange(op, addr); - return IsTextureBreakpoint(addr); + return IsTextureChangeBreakpoint(op, addr) || IsTextureBreakpoint(addr); } else { - CheckForTextureChange(op, gstate.getTextureAddress(0)); - return false; + return IsTextureChangeBreakpoint(op, gstate.getTextureAddress(0)); } } diff --git a/GPU/Debugger/GECommandTable.h b/GPU/Debugger/GECommandTable.h index cced7c243..01d205907 100644 --- a/GPU/Debugger/GECommandTable.h +++ b/GPU/Debugger/GECommandTable.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - #include "GPU/ge_constants.h" enum class GECmdFormat { diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index b0cc4a5a6..d1a1bbf2c 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -49,7 +49,7 @@ namespace GPURecord { static bool active = false; -static std::atomic nextFrame = false; +static bool nextFrame = false; static int flipLastAction = -1; static int flipFinishAt = -1; static uint32_t lastEdramTrans = 0x400; @@ -601,20 +601,18 @@ bool IsActivePending() { return nextFrame || active; } -bool RecordNextFrame(const std::function callback) { +bool Activate() { if (!nextFrame) { + nextFrame = true; flipLastAction = gpuStats.numFlips; flipFinishAt = -1; - writeCallback = callback; - nextFrame = true; return true; } return false; } -void ClearCallback() { - // Not super thread safe.. - writeCallback = nullptr; +void SetCallback(const std::function callback) { + writeCallback = callback; } static void FinishRecording() { diff --git a/GPU/Debugger/Record.h b/GPU/Debugger/Record.h index 454fc4926..5c5d2f6db 100644 --- a/GPU/Debugger/Record.h +++ b/GPU/Debugger/Record.h @@ -27,8 +27,9 @@ namespace GPURecord { bool IsActive(); bool IsActivePending(); -bool RecordNextFrame(const std::function callback); -void ClearCallback(); +bool Activate(); +// Call only if Activate() returns true. +void SetCallback(const std::function callback); void NotifyCommand(u32 pc); void NotifyMemcpy(u32 dest, u32 src, u32 sz); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 506856556..0043250fe 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -72,6 +72,10 @@ enum { TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex) }; +#define VERTEXCACHE_DECIMATION_INTERVAL 17 + +enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; + static const D3DVERTEXELEMENT9 TransformedVertexElements[] = { { 0, offsetof(TransformedVertex, pos), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, offsetof(TransformedVertex, uv), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, @@ -81,12 +85,14 @@ static const D3DVERTEXELEMENT9 TransformedVertexElements[] = { D3DDECL_END() }; -DrawEngineDX9::DrawEngineDX9(Draw::DrawContext *draw) : draw_(draw), vertexDeclMap_(64) { +DrawEngineDX9::DrawEngineDX9(Draw::DrawContext *draw) : draw_(draw), vai_(256), vertexDeclMap_(64) { device_ = (LPDIRECT3DDEVICE9)draw->GetNativeObject(Draw::NativeObject::DEVICE); decOptions_.expandAllWeightsToFloat = true; decOptions_.expand8BitNormalsToFloat = true; - indexGen.Setup(decIndex_); + decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; + + indexGen.Setup(decIndex); InitDeviceObjects(); @@ -155,9 +161,10 @@ static void VertexAttribSetup(D3DVERTEXELEMENT9 * VertexElement, u8 fmt, u8 offs VertexElement->UsageIndex = usage_index; } -IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(const DecVtxFormat &decFmt, u32 pspFmt) { - IDirect3DVertexDeclaration9 *vertexDeclCached; - if (vertexDeclMap_.Get(pspFmt, &vertexDeclCached)) { +IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(VSShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt) { + IDirect3DVertexDeclaration9 *vertexDeclCached = vertexDeclMap_.Get(pspFmt); + + if (vertexDeclCached) { return vertexDeclCached; } else { D3DVERTEXELEMENT9 VertexElements[8]; @@ -200,7 +207,7 @@ IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(const DecVtxForma // POSITION // Always - VertexAttribSetup(VertexElement, DecVtxFormat::PosFmt(), decFmt.posoff, D3DDECLUSAGE_POSITION, 0); + VertexAttribSetup(VertexElement, decFmt.posfmt, decFmt.posoff, D3DDECLUSAGE_POSITION, 0); VertexElement++; // End @@ -221,11 +228,80 @@ IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(const DecVtxForma } } +void DrawEngineDX9::MarkUnreliable(VertexArrayInfoDX9 *vai) { + vai->status = VertexArrayInfoDX9::VAI_UNRELIABLE; + if (vai->vbo) { + vai->vbo->Release(); + vai->vbo = nullptr; + } + if (vai->ebo) { + vai->ebo->Release(); + vai->ebo = nullptr; + } +} + +void DrawEngineDX9::ClearTrackedVertexArrays() { + vai_.Iterate([&](uint32_t hash, VertexArrayInfoDX9 *vai) { + delete vai; + }); + vai_.Clear(); +} + +void DrawEngineDX9::DecimateTrackedVertexArrays() { + if (--decimationCounter_ <= 0) { + decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; + } else { + return; + } + + const int threshold = gpuStats.numFlips - VAI_KILL_AGE; + const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; + int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; + vai_.Iterate([&](uint32_t hash, VertexArrayInfoDX9 *vai) { + bool kill; + if (vai->status == VertexArrayInfoDX9::VAI_UNRELIABLE) { + // We limit killing unreliable so we don't rehash too often. + kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0; + } else { + kill = vai->lastFrame < threshold; + } + if (kill) { + delete vai; + vai_.Remove(hash); + } + }); + vai_.Maintain(); + + // Enable if you want to see vertex decoders in the log output. Need a better way. +#if 0 + char buffer[16384]; + for (std::map::iterator dec = decoderMap_.begin(); dec != decoderMap_.end(); ++dec) { + char *ptr = buffer; + ptr += dec->second->ToString(ptr); + // *ptr++ = '\n'; + NOTICE_LOG(G3D, buffer); + } +#endif +} + +VertexArrayInfoDX9::~VertexArrayInfoDX9() { + if (vbo) { + vbo->Release(); + } + if (ebo) { + ebo->Release(); + } +} + static uint32_t SwapRB(uint32_t c) { return (c & 0xFF00FF00) | ((c >> 16) & 0xFF) | ((c << 16) & 0xFF0000); } void DrawEngineDX9::BeginFrame() { + gpuStats.numTrackedVertexArrays = (int)vai_.size(); + + DecimateTrackedVertexArrays(); + lastRenderStepId_ = -1; } @@ -236,7 +312,7 @@ void DrawEngineDX9::Invalidate(InvalidationCallbackFlags flags) { } } -// The inline wrapper in the header checks for numDrawCalls_ == 0 +// The inline wrapper in the header checks for numDrawCalls == 0 void DrawEngineDX9::DoFlush() { bool textureNeedsApply = false; if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { @@ -255,22 +331,174 @@ void DrawEngineDX9::DoFlush() { bool useHWTransform = CanUseHardwareTransform(prim) && (tess || gstate.getShadeMode() != GE_SHADE_FLAT); if (useHWTransform) { - LPDIRECT3DVERTEXBUFFER9 vb_ = nullptr; - LPDIRECT3DINDEXBUFFER9 ib_ = nullptr; + LPDIRECT3DVERTEXBUFFER9 vb_ = NULL; + LPDIRECT3DINDEXBUFFER9 ib_ = NULL; - DecodeVerts(decoded_); - DecodeInds(); + int vertexCount = 0; + int maxIndex = 0; + bool useElements = true; - bool useElements = !indexGen.SeenOnlyPurePrims(); - int vertexCount = indexGen.VertexCount(); - gpuStats.numUncachedVertsDrawn += vertexCount; - int maxIndex = MaxIndex(); - if (!useElements && indexGen.PureCount()) { - vertexCount = indexGen.PureCount(); + // Cannot cache vertex data with morph enabled. + bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); + // Also avoid caching when software skinning. + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + useCache = false; + + if (useCache) { + u32 id = dcid_ ^ gstate.getUVGenMode(); // This can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 + VertexArrayInfoDX9 *vai = vai_.Get(id); + if (!vai) { + vai = new VertexArrayInfoDX9(); + vai_.Insert(id, vai); + } + + switch (vai->status) { + case VertexArrayInfoDX9::VAI_NEW: + { + // Haven't seen this one before. + uint64_t dataHash = ComputeHash(); + vai->hash = dataHash; + vai->minihash = ComputeMiniHash(); + vai->status = VertexArrayInfoDX9::VAI_HASHING; + vai->drawsUntilNextFullHash = 0; + DecodeVerts(decoded); // writes to indexGen + vai->numVerts = indexGen.VertexCount(); + vai->prim = indexGen.Prim(); + vai->maxIndex = indexGen.MaxIndex(); + vai->flags = gstate_c.vertexFullAlpha ? VAI_FLAG_VERTEXFULLALPHA : 0; + + goto rotateVBO; + } + + // Hashing - still gaining confidence about the buffer. + // But if we get this far it's likely to be worth creating a vertex buffer. + case VertexArrayInfoDX9::VAI_HASHING: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + if (vai->drawsUntilNextFullHash == 0) { + // Let's try to skip a full hash if mini would fail. + const u32 newMiniHash = ComputeMiniHash(); + uint64_t newHash = vai->hash; + if (newMiniHash == vai->minihash) { + newHash = ComputeHash(); + } + if (newMiniHash != vai->minihash || newHash != vai->hash) { + MarkUnreliable(vai); + DecodeVerts(decoded); + goto rotateVBO; + } + if (vai->numVerts > 64) { + // exponential backoff up to 16 draws, then every 24 + vai->drawsUntilNextFullHash = std::min(24, vai->numFrames); + } else { + // Lower numbers seem much more likely to change. + vai->drawsUntilNextFullHash = 0; + } + // TODO: tweak + //if (vai->numFrames > 1000) { + // vai->status = VertexArrayInfo::VAI_RELIABLE; + //} + } else { + vai->drawsUntilNextFullHash--; + u32 newMiniHash = ComputeMiniHash(); + if (newMiniHash != vai->minihash) { + MarkUnreliable(vai); + DecodeVerts(decoded); + goto rotateVBO; + } + } + + if (vai->vbo == 0) { + DecodeVerts(decoded); + vai->numVerts = indexGen.VertexCount(); + vai->prim = indexGen.Prim(); + vai->maxIndex = indexGen.MaxIndex(); + vai->flags = gstate_c.vertexFullAlpha ? VAI_FLAG_VERTEXFULLALPHA : 0; + useElements = !indexGen.SeenOnlyPurePrims(); + if (!useElements && indexGen.PureCount()) { + vai->numVerts = indexGen.PureCount(); + } + + _dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); + + void * pVb; + u32 size = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex(); + device_->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &vai->vbo, NULL); + vai->vbo->Lock(0, size, &pVb, 0); + memcpy(pVb, decoded, size); + vai->vbo->Unlock(); + if (useElements) { + void * pIb; + u32 size = sizeof(short) * indexGen.VertexCount(); + device_->CreateIndexBuffer(size, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &vai->ebo, NULL); + vai->ebo->Lock(0, size, &pIb, 0); + memcpy(pIb, decIndex, size); + vai->ebo->Unlock(); + } else { + vai->ebo = 0; + } + } else { + gpuStats.numCachedDrawCalls++; + useElements = vai->ebo ? true : false; + gpuStats.numCachedVertsDrawn += vai->numVerts; + gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA; + } + vb_ = vai->vbo; + ib_ = vai->ebo; + vertexCount = vai->numVerts; + maxIndex = vai->maxIndex; + prim = static_cast(vai->prim); + break; + } + + // Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time. + case VertexArrayInfoDX9::VAI_RELIABLE: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + gpuStats.numCachedDrawCalls++; + gpuStats.numCachedVertsDrawn += vai->numVerts; + vb_ = vai->vbo; + ib_ = vai->ebo; + + vertexCount = vai->numVerts; + + maxIndex = vai->maxIndex; + prim = static_cast(vai->prim); + + gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA; + break; + } + + case VertexArrayInfoDX9::VAI_UNRELIABLE: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + DecodeVerts(decoded); + goto rotateVBO; + } + } + + vai->lastFrame = gpuStats.numFlips; + } else { + DecodeVerts(decoded); +rotateVBO: + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); + useElements = !indexGen.SeenOnlyPurePrims(); + vertexCount = indexGen.VertexCount(); + maxIndex = indexGen.MaxIndex(); + if (!useElements && indexGen.PureCount()) { + vertexCount = indexGen.PureCount(); + } + prim = indexGen.Prim(); } - prim = indexGen.Prim(); - - _dbg_assert_((int)prim > 0); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { @@ -287,15 +515,15 @@ void DrawEngineDX9::DoFlush() { ApplyDrawStateLate(); VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_); - IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(dec_->GetDecVtxFmt(), dec_->VertexType()); + IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType()); if (pHardwareVertexDecl) { device_->SetVertexDeclaration(pHardwareVertexDecl); if (vb_ == NULL) { if (useElements) { - device_->DrawIndexedPrimitiveUP(d3d_prim[prim], 0, maxIndex + 1, D3DPrimCount(d3d_prim[prim], vertexCount), decIndex_, D3DFMT_INDEX16, decoded_, dec_->GetDecVtxFmt().stride); + device_->DrawIndexedPrimitiveUP(d3d_prim[prim], 0, maxIndex + 1, D3DPrimCount(d3d_prim[prim], vertexCount), decIndex, D3DFMT_INDEX16, decoded, dec_->GetDecVtxFmt().stride); } else { - device_->DrawPrimitiveUP(d3d_prim[prim], D3DPrimCount(d3d_prim[prim], vertexCount), decoded_, dec_->GetDecVtxFmt().stride); + device_->DrawPrimitiveUP(d3d_prim[prim], D3DPrimCount(d3d_prim[prim], vertexCount), decoded, dec_->GetDecVtxFmt().stride); } } else { device_->SetStreamSource(0, vb_, 0, dec_->GetDecVtxFmt().stride); @@ -315,8 +543,7 @@ void DrawEngineDX9::DoFlush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); - DecodeInds(); + DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255); @@ -331,12 +558,12 @@ void DrawEngineDX9::DoFlush() { prim = GE_PRIM_TRIANGLES; VERBOSE_LOG(G3D, "Flush prim %i SW! %i verts in one go", prim, indexGen.VertexCount()); - u16 *inds = decIndex_; + u16 *inds = decIndex; SoftwareTransformResult result{}; SoftwareTransformParams params{}; - params.decoded = decoded_; - params.transformed = transformed_; - params.transformedExpanded = transformedExpanded_; + params.decoded = decoded; + params.transformed = transformed; + params.transformedExpanded = transformedExpanded; params.fbman = framebufferManager_; params.texCache = textureCache_; params.allowClear = true; @@ -355,7 +582,7 @@ void DrawEngineDX9::DoFlush() { UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); + int maxIndex = indexGen.MaxIndex(); SoftwareTransform swTransform(params); // Half pixel offset hack. @@ -430,8 +657,25 @@ void DrawEngineDX9::DoFlush() { decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } - ResetAfterDrawInline(); + gpuStats.numFlushes++; + gpuStats.numDrawCalls += numDrawCalls; + gpuStats.numVertsSubmitted += vertexCountInDrawCalls_; + + indexGen.Reset(); + decodedVerts_ = 0; + numDrawCalls = 0; + vertexCountInDrawCalls_ = 0; + decodeCounter_ = 0; + dcid_ = 0; + gstate_c.vertexFullAlpha = true; framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); + + // Now seems as good a time as any to reset the min/max coords, which we may examine later. + gstate_c.vertBounds.minU = 512; + gstate_c.vertBounds.minV = 512; + gstate_c.vertBounds.maxU = 0; + gstate_c.vertBounds.maxV = 0; + GPUDebug::NotifyDraw(); } diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 14a380398..5d7cbf716 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -35,6 +35,65 @@ class ShaderManagerDX9; class TextureCacheDX9; class FramebufferManagerDX9; +// States transitions: +// On creation: DRAWN_NEW +// DRAWN_NEW -> DRAWN_HASHING +// DRAWN_HASHING -> DRAWN_RELIABLE +// DRAWN_HASHING -> DRAWN_UNRELIABLE +// DRAWN_ONCE -> UNRELIABLE +// DRAWN_RELIABLE -> DRAWN_SAFE +// UNRELIABLE -> death +// DRAWN_ONCE -> death +// DRAWN_RELIABLE -> death + +enum { + VAI_FLAG_VERTEXFULLALPHA = 1, +}; + +// Try to keep this POD. +class VertexArrayInfoDX9 { +public: + VertexArrayInfoDX9() { + status = VAI_NEW; + vbo = 0; + ebo = 0; + prim = GE_PRIM_INVALID; + numDraws = 0; + numFrames = 0; + lastFrame = gpuStats.numFlips; + numVerts = 0; + drawsUntilNextFullHash = 0; + flags = 0; + } + ~VertexArrayInfoDX9(); + + enum Status : uint8_t { + VAI_NEW, + VAI_HASHING, + VAI_RELIABLE, // cache, don't hash + VAI_UNRELIABLE, // never cache + }; + + uint64_t hash; + u32 minihash; + + LPDIRECT3DVERTEXBUFFER9 vbo; + LPDIRECT3DINDEXBUFFER9 ebo; + + // Precalculated parameter for drawRangeElements + u16 numVerts; + u16 maxIndex; + s8 prim; + Status status; + + // ID information + int numDraws; + int numFrames; + int lastFrame; // So that we can forget. + u16 drawsUntilNextFullHash; + u8 flags; +}; + class TessellationDataTransferDX9 : public TessellationDataTransfer { public: TessellationDataTransferDX9() {} @@ -63,30 +122,33 @@ public: void InitDeviceObjects(); void DestroyDeviceObjects(); + void ClearTrackedVertexArrays() override; + void BeginFrame(); // So that this can be inlined void Flush() { - if (!numDrawVerts_) + if (!numDrawCalls) return; DoFlush(); } void FinishDeferred() { - if (!numDrawVerts_) + if (!numDrawCalls) return; - DecodeVerts(decoded_); + DecodeVerts(decoded); } void DispatchFlush() override { - if (!numDrawVerts_) + if (!numDrawCalls) return; Flush(); } protected: // Not currently supported. - bool UpdateUseHWTessellation(bool enable) const override { return false; } + bool UpdateUseHWTessellation(bool enable) override { return false; } + void DecimateTrackedVertexArrays(); private: void Invalidate(InvalidationCallbackFlags flags); @@ -95,12 +157,15 @@ private: void ApplyDrawState(int prim); void ApplyDrawStateLate(); - IDirect3DVertexDeclaration9 *SetupDecFmtForDraw(const DecVtxFormat &decFmt, u32 pspFmt); + IDirect3DVertexDeclaration9 *SetupDecFmtForDraw(VSShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt); + + void MarkUnreliable(VertexArrayInfoDX9 *vai); LPDIRECT3DDEVICE9 device_ = nullptr; Draw::DrawContext *draw_; - DenseHashMap vertexDeclMap_; + PrehashMap vai_; + DenseHashMap vertexDeclMap_; // SimpleVertex IDirect3DVertexDeclaration9* transformedVertexDecl_ = nullptr; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index b8cca50d9..1e099d356 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -19,7 +19,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/GraphicsContext.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Profiler/Profiler.h" #include "Common/Data/Text/I18n.h" #include "Core/Debugger/Breakpoints.h" @@ -88,8 +88,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // Disable hardware tessellation bacause DX9 is still unsupported. ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation"); auto gr = GetI18NCategory(I18NCat::GRAPHICS); - // TODO: Badly formulated - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("Turn off Hardware Tessellation - unsupported")); + System_NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF); } } @@ -123,7 +122,7 @@ void GPU_DX9::BeginFrame() { drawEngine_.BeginFrame(); GPUCommonHW::BeginFrame(); - shaderManagerDX9_->DirtyLastShader(); + shaderManagerDX9_->DirtyShader(); framebufferManager_->BeginFrame(); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 21dccf747..845984e34 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -29,7 +29,7 @@ #include "Common/Math/math_util.h" #include "Common/GPU/D3D9/D3D9ShaderCompiler.h" #include "Common/GPU/thin3d.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/System/Display.h" #include "Common/CommonTypes.h" @@ -291,8 +291,8 @@ void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) { doTextureAlpha = false; } // NOTE: Reversed value, more efficient in shader. - float noAlphaMul[2] = { doTextureAlpha ? 0.0f : 1.0f, gstate.isColorDoublingEnabled() ? 2.0f : 1.0f }; - PSSetFloatArray(CONST_PS_TEX_NO_ALPHA_MUL, noAlphaMul, 2); + PSSetFloat(CONST_PS_TEX_NO_ALPHA, doTextureAlpha ? 0.0f : 1.0f); + PSSetFloat(CONST_PS_TEX_MUL, gstate.isColorDoublingEnabled() ? 2.0f : 1.0f); } if (dirtyUniforms & DIRTY_SHADERBLEND) { PSSetColorUniform3(CONST_PS_BLENDFIXA, gstate.getFixA()); @@ -436,16 +436,12 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { // Texturing if (dirtyUniforms & DIRTY_UVSCALEOFFSET) { - float widthFactor = 1.0f; - float heightFactor = 1.0f; - if (gstate_c.textureIsFramebuffer) { - const float invW = 1.0f / (float)gstate_c.curTextureWidth; - const float invH = 1.0f / (float)gstate_c.curTextureHeight; - const int w = gstate.getTextureWidth(0); - const int h = gstate.getTextureHeight(0); - widthFactor = (float)w * invW; - heightFactor = (float)h * invH; - } + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + const float widthFactor = (float)w * invW; + const float heightFactor = (float)h * invH; float uvscaleoff[4]; uvscaleoff[0] = widthFactor; uvscaleoff[1] = heightFactor; @@ -535,23 +531,27 @@ void ShaderManagerDX9::Clear() { } fsCache_.clear(); vsCache_.clear(); - DirtyLastShader(); + DirtyShader(); } void ShaderManagerDX9::ClearShaders() { Clear(); } -void ShaderManagerDX9::DirtyLastShader() { +void ShaderManagerDX9::DirtyShader() { // Forget the last shader ID lastFSID_.set_invalid(); lastVSID_.set_invalid(); lastVShader_ = nullptr; lastPShader_ = nullptr; - // TODO: Probably not necessary to dirty uniforms here on DX9. gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } +void ShaderManagerDX9::DirtyLastShader() { + lastVShader_ = nullptr; + lastPShader_ = nullptr; +} + VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellation, VertexDecoder *decoder, bool weightsAsFloat, bool useSkinInDecode, const ComputedPipelineState &pipelineState) { VShaderID VSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { @@ -602,7 +602,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat ERROR_LOG(G3D, "Shader compilation failed, falling back to software transform"); } if (!g_Config.bHideSlowWarnings) { - g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("hardware transform error - falling back to software"), 2.5f); + System_NotifyUserMessage(gr->T("hardware transform error - falling back to software"), 2.5f, 0xFF3030FF); } delete vs; diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 5ce429f6f..68337503b 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -79,6 +79,7 @@ public: void ClearShaders() override; VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, VertexDecoder *decoder, bool weightsAsFloat, bool useSkinInDecode, const ComputedPipelineState &pipelineState); + void DirtyShader(); void DirtyLastShader() override; int GetNumVertexShaders() const { return (int)vsCache_.size(); } diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 4d6de3d20..76ec0dd3f 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -44,7 +44,7 @@ #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/GPU_GLES.h" -static const GLuint glprim[8] = { +const GLuint glprim[8] = { // Points, which are expanded to triangles. GL_TRIANGLES, // Lines and line strips, which are also expanded to triangles. @@ -67,7 +67,7 @@ DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : inputLayoutMap_(16), d decOptions_.expandAllWeightsToFloat = false; decOptions_.expand8BitNormalsToFloat = false; - indexGen.Setup(decIndex_); + indexGen.Setup(decIndex); InitDeviceObjects(); @@ -97,18 +97,18 @@ void DrawEngineGLES::InitDeviceObjects() { _assert_msg_(render_ != nullptr, "Render manager must be set"); for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { - frameData_[i].pushVertex = render_->CreatePushBuffer(i, GL_ARRAY_BUFFER, 2048 * 1024, "game_vertex"); - frameData_[i].pushIndex = render_->CreatePushBuffer(i, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024, "game_index"); + frameData_[i].pushVertex = render_->CreatePushBuffer(i, GL_ARRAY_BUFFER, 1024 * 1024); + frameData_[i].pushIndex = render_->CreatePushBuffer(i, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); } - int stride = sizeof(TransformedVertex); + int vertexSize = sizeof(TransformedVertex); std::vector entries; entries.push_back({ ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, offsetof(TransformedVertex, x) }); entries.push_back({ ATTR_TEXCOORD, 3, GL_FLOAT, GL_FALSE, offsetof(TransformedVertex, u) }); entries.push_back({ ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, offsetof(TransformedVertex, color0) }); entries.push_back({ ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, offsetof(TransformedVertex, color1) }); entries.push_back({ ATTR_NORMAL, 1, GL_FLOAT, GL_FALSE, offsetof(TransformedVertex, fog) }); - softwareInputLayout_ = render_->CreateInputLayout(entries, stride); + softwareInputLayout_ = render_->CreateInputLayout(entries, vertexSize); draw_->SetInvalidationCallback(std::bind(&DrawEngineGLES::Invalidate, this, std::placeholders::_1)); } @@ -149,6 +149,8 @@ void DrawEngineGLES::ClearInputLayoutMap() { } void DrawEngineGLES::BeginFrame() { + gpuStats.numTrackedVertexArrays = 0; + FrameData &frameData = frameData_[render_->GetCurFrame()]; render_->BeginPushBuffer(frameData.pushIndex); render_->BeginPushBuffer(frameData.pushVertex); @@ -201,10 +203,10 @@ static inline void VertexAttribSetup(int attrib, int fmt, int offset, std::vecto } // TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets -GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(const DecVtxFormat &decFmt) { +GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt) { uint32_t key = decFmt.id; - GLRInputLayout *inputLayout; - if (inputLayoutMap_.Get(key, &inputLayout)) { + GLRInputLayout *inputLayout = inputLayoutMap_.Get(key); + if (inputLayout) { return inputLayout; } @@ -215,14 +217,25 @@ GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(const DecVtxFormat &decFmt) { VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.c0off, entries); VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.c1off, entries); VertexAttribSetup(ATTR_NORMAL, decFmt.nrmfmt, decFmt.nrmoff, entries); - VertexAttribSetup(ATTR_POSITION, DecVtxFormat::PosFmt(), decFmt.posoff, entries); + VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.posoff, entries); - int stride = decFmt.stride; - inputLayout = render_->CreateInputLayout(entries, stride); + inputLayout = render_->CreateInputLayout(entries, decFmt.stride); inputLayoutMap_.Insert(key, inputLayout); return inputLayout; } +void *DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf) { + u8 *dest = decoded; + + // Figure out how much pushbuffer space we need to allocate. + if (push) { + int vertsToDecode = ComputeNumVertsToDecode(); + dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, buf); + } + DecodeVerts(dest); + return dest; +} + // A new render step means we need to flush any dynamic state. Really, any state that is reset in // GLQueueRunner::PerformRenderPass. void DrawEngineGLES::Invalidate(InvalidationCallbackFlags flags) { @@ -243,11 +256,10 @@ void DrawEngineGLES::DoFlush() { // can't goto bail here, skips too many variable initializations. So let's wipe the most important stuff. indexGen.Reset(); decodedVerts_ = 0; - numDrawVerts_ = 0; - numDrawInds_ = 0; + numDrawCalls = 0; vertexCountInDrawCalls_ = 0; - decodeVertsCounter_ = 0; - decodeIndsCounter_ = 0; + decodeCounter_ = 0; + dcid_ = 0; return; } @@ -271,27 +283,26 @@ void DrawEngineGLES::DoFlush() { uint32_t indexBufferOffset = 0; if (vshader->UseHWTransform()) { + int vertexCount = 0; + bool useElements = true; + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { - // If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content. - DecodeVerts(decoded_); - uint32_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; - u8 *dest = (u8 *)frameData.pushVertex->Allocate(size, 4, &vertexBuffer, &vertexBufferOffset); - memcpy(dest, decoded_, size); + // If software skinning, we've already predecoded into "decoded". So push that content. + size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; + u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer); + memcpy(dest, decoded, size); } else { - // Figure out how much pushbuffer space we need to allocate. - int vertsToDecode = ComputeNumVertsToDecode(); - u8 *dest = (u8 *)frameData.pushVertex->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, &vertexBuffer, &vertexBufferOffset); - DecodeVerts(dest); + // Decode directly into the pushbuffer + u8 *dest = (u8 *)DecodeVertsToPushBuffer(frameData.pushVertex, &vertexBufferOffset, &vertexBuffer); } - DecodeInds(); + + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); // If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS, // there is no need for the index buffer we built. We can then use glDrawArrays instead - // for a very minor speed boost. TODO: We can probably detect this case earlier, like before - // actually doing any vertex decoding (unless we're doing soft skinning and pre-decode on submit). - bool useElements = !indexGen.SeenOnlyPurePrims(); - int vertexCount = indexGen.VertexCount(); - gpuStats.numUncachedVertsDrawn += vertexCount; + // for a very minor speed boost. + useElements = !indexGen.SeenOnlyPurePrims(); + vertexCount = indexGen.VertexCount(); if (!useElements && indexGen.PureCount()) { vertexCount = indexGen.PureCount(); } @@ -313,17 +324,16 @@ void DrawEngineGLES::DoFlush() { ApplyDrawStateLate(false, 0); LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, pipelineState_, framebufferManager_->UseBufferedRendering()); - GLRInputLayout *inputLayout = SetupDecFmtForDraw(dec_->GetDecVtxFmt()); + GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); if (useElements) { - uint32_t esz = sizeof(uint16_t) * indexGen.VertexCount(); - void *dest = frameData.pushIndex->Allocate(esz, 2, &indexBuffer, &indexBufferOffset); - // TODO: When we need to apply an index offset, we can apply it directly when copying the indices here. - // Of course, minding the maximum value of 65535... - memcpy(dest, decIndex_, esz); - render_->DrawIndexed(inputLayout, - vertexBuffer, vertexBufferOffset, - indexBuffer, indexBufferOffset, - glprim[prim], vertexCount, GL_UNSIGNED_SHORT); + if (!indexBuffer) { + size_t esz = sizeof(uint16_t) * indexGen.VertexCount(); + void *dest = frameData.pushIndex->Push(esz, &indexBufferOffset, &indexBuffer); + memcpy(dest, decIndex, esz); + } + render_->DrawIndexed( + inputLayout, vertexBuffer, vertexBufferOffset, indexBuffer, + glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset); } else { render_->Draw( inputLayout, vertexBuffer, vertexBufferOffset, @@ -336,8 +346,7 @@ void DrawEngineGLES::DoFlush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); - DecodeInds(); + DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { @@ -352,13 +361,13 @@ void DrawEngineGLES::DoFlush() { if (prim == GE_PRIM_TRIANGLE_STRIP) prim = GE_PRIM_TRIANGLES; - u16 *inds = decIndex_; + u16 *inds = decIndex; SoftwareTransformResult result{}; // TODO: Keep this static? Faster than repopulating? SoftwareTransformParams params{}; - params.decoded = decoded_; - params.transformed = transformed_; - params.transformedExpanded = transformedExpanded_; + params.decoded = decoded; + params.transformed = transformed; + params.transformedExpanded = transformedExpanded; params.fbman = framebufferManager_; params.texCache = textureCache_; params.allowClear = true; // Clear in OpenGL respects scissor rects, so we'll use it. @@ -372,11 +381,11 @@ void DrawEngineGLES::DoFlush() { ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(), framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), - vpAndScissor_); - UpdateCachedViewportState(vpAndScissor_); + vpAndScissor); + UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); + int maxIndex = indexGen.MaxIndex(); int vertexCount = indexGen.VertexCount(); // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. @@ -424,13 +433,13 @@ void DrawEngineGLES::DoFlush() { if (result.action == SW_DRAW_PRIMITIVES) { if (result.drawIndexed) { - vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vertexBuffer); - indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawNumTrans, 2, &indexBuffer); + vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); + indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawNumTrans, &indexBuffer); render_->DrawIndexed( - softwareInputLayout_, vertexBuffer, vertexBufferOffset, indexBuffer, indexBufferOffset, - glprim[prim], result.drawNumTrans, GL_UNSIGNED_SHORT); + softwareInputLayout_, vertexBuffer, vertexBufferOffset, indexBuffer, + glprim[prim], result.drawNumTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset); } else { - vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), 4, &vertexBuffer); + vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), &vertexBuffer); render_->Draw( softwareInputLayout_, vertexBuffer, vertexBufferOffset, glprim[prim], 0, result.drawNumTrans); } @@ -449,7 +458,7 @@ void DrawEngineGLES::DoFlush() { if (alphaMask) target |= GL_STENCIL_BUFFER_BIT; if (depthMask) target |= GL_DEPTH_BUFFER_BIT; - render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor_.scissorX, vpAndScissor_.scissorY, vpAndScissor_.scissorW, vpAndScissor_.scissorH); + render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH); framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); if (gstate_c.Use(GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate_c.framebufFormat == GE_FORMAT_565)) { @@ -465,8 +474,25 @@ void DrawEngineGLES::DoFlush() { } bail: - ResetAfterDrawInline(); + gpuStats.numFlushes++; + gpuStats.numDrawCalls += numDrawCalls; + gpuStats.numVertsSubmitted += vertexCountInDrawCalls_; + + indexGen.Reset(); + decodedVerts_ = 0; + numDrawCalls = 0; + vertexCountInDrawCalls_ = 0; + decodeCounter_ = 0; + dcid_ = 0; + gstate_c.vertexFullAlpha = true; framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); + + // Now seems as good a time as any to reset the min/max coords, which we may examine later. + gstate_c.vertBounds.minU = 512; + gstate_c.vertBounds.minV = 512; + gstate_c.vertBounds.maxU = 0; + gstate_c.vertBounds.maxV = 0; + GPUDebug::NotifyDraw(); } @@ -476,7 +502,7 @@ bool DrawEngineGLES::SupportsHWTessellation() const { return hasTexelFetch && gstate_c.UseAll(GPU_USE_VERTEX_TEXTURE_FETCH | GPU_USE_TEXTURE_FLOAT | GPU_USE_INSTANCE_RENDERING); } -bool DrawEngineGLES::UpdateUseHWTessellation(bool enable) const { +bool DrawEngineGLES::UpdateUseHWTessellation(bool enable) { return enable && SupportsHWTessellation(); } @@ -496,7 +522,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p if (prevSizeU < size_u || prevSizeV < size_v) { prevSizeU = size_u; prevSizeV = size_v; - if (data_tex[0]) + if (!data_tex[0]) renderManager_->DeleteTexture(data_tex[0]); data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D, size_u * 3, size_v, 1, 1); renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false); @@ -515,7 +541,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p // Weight U if (prevSizeWU < weights.size_u) { prevSizeWU = weights.size_u; - if (data_tex[1]) + if (!data_tex[1]) renderManager_->DeleteTexture(data_tex[1]); data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_u * 2, 1, 1, 1); renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false); @@ -527,7 +553,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p // Weight V if (prevSizeWV < weights.size_v) { prevSizeWV = weights.size_v; - if (data_tex[2]) + if (!data_tex[2]) renderManager_->DeleteTexture(data_tex[2]); data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_v * 2, 1, 1, 1); renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false); diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index e61951c1f..a6c5cc117 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -86,29 +86,36 @@ public: // So that this can be inlined void Flush() { - if (!numDrawVerts_) + if (!numDrawCalls) return; DoFlush(); } void FinishDeferred() { - if (!numDrawVerts_) + if (!numDrawCalls) return; DoFlush(); } void DispatchFlush() override { - if (!numDrawVerts_) + if (!numDrawCalls) return; Flush(); } + GLPushBuffer *GetPushVertexBuffer() { + return frameData_[render_->GetCurFrame()].pushVertex; + } + GLPushBuffer *GetPushIndexBuffer() { + return frameData_[render_->GetCurFrame()].pushIndex; + } + void ClearInputLayoutMap(); bool SupportsHWTessellation() const; protected: - bool UpdateUseHWTessellation(bool enable) const override; + bool UpdateUseHWTessellation(bool enable) override; private: void Invalidate(InvalidationCallbackFlags flags); @@ -120,7 +127,9 @@ private: void ApplyDrawState(int prim); void ApplyDrawStateLate(bool setStencil, int stencilValue); - GLRInputLayout *SetupDecFmtForDraw(const DecVtxFormat &decFmt); + GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt); + + void *DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf); struct FrameData { GLPushBuffer *pushVertex; @@ -128,7 +137,7 @@ private: }; FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]; - DenseHashMap inputLayoutMap_; + DenseHashMap inputLayoutMap_; GLRInputLayout *softwareInputLayout_ = nullptr; GLRenderManager *render_; @@ -141,11 +150,10 @@ private: Draw::DrawContext *draw_; // Need to preserve the scissor for use when clearing. - ViewportAndScissor vpAndScissor_{}; - // Need to preserve writemask, easiest way. - GenericStencilFuncState stencilState_{}; + ViewportAndScissor vpAndScissor; int bufferDecimationCounter_ = 0; + int lastRenderStepId_ = -1; // Hardware tessellation diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index e4eaa274c..963a10018 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -22,7 +22,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/File/FileUtil.h" #include "Common/GraphicsContext.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/VR/PPSSPPVR.h" #include "Core/Config.h" @@ -49,6 +49,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommonHW(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw) { + UpdateVsyncInterval(true); gstate_c.SetUseFlags(CheckGPUFeatures()); shaderManagerGL_ = new ShaderManagerGLES(draw); @@ -85,6 +86,8 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) UpdateCmdInfo(); BuildReportingInfo(); + // Update again after init to be sure of any silly driver problems. + UpdateVsyncInterval(true); textureCache_->NotifyConfigChanged(); @@ -119,7 +122,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) if (!drawEngine_.SupportsHWTessellation()) { ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation"); auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("Turn off Hardware Tessellation - unsupported")); + System_NotifyUserMessage(gr->T("Turn off Hardware Tessellation - unsupported"), 2.5f, 0xFF3030FF); } } } @@ -177,11 +180,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { features |= GPU_USE_SINGLE_PASS_STEREO; } - if (!gl_extensions.GLES3) { - // Heuristic. - features &= ~GPU_USE_FRAGMENT_UBERSHADER; - } - features = CheckGPUFeaturesLate(features); if (draw_->GetBugs().Has(Draw::Bugs::ADRENO_RESOURCE_DEADLOCK) && g_Config.bVendorBugChecksEnabled) { @@ -198,9 +196,18 @@ u32 GPU_GLES::CheckGPUFeatures() const { features |= GPU_ROUND_DEPTH_TO_16BIT; } } + return features; } +bool GPU_GLES::IsReady() { + return shaderManagerGL_->ContinuePrecompile(); +} + +void GPU_GLES::CancelReady() { + shaderManagerGL_->CancelPrecompile(); +} + void GPU_GLES::BuildReportingInfo() { GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); @@ -230,6 +237,7 @@ void GPU_GLES::DeviceLost() { // Simply drop all caches and textures. // FBOs appear to survive? Or no? // TransformDraw has registered as a GfxResourceHolder. + CancelReady(); fragmentTestCache_.DeviceLost(); GPUCommonHW::DeviceLost(); @@ -239,6 +247,7 @@ void GPU_GLES::DeviceRestore(Draw::DrawContext *draw) { GPUCommonHW::DeviceRestore(draw); fragmentTestCache_.DeviceRestore(draw_); + UpdateVsyncInterval(true); } void GPU_GLES::BeginHostFrame() { @@ -268,7 +277,7 @@ void GPU_GLES::BeginFrame() { if (shaderCachePath_.Valid() && (gpuStats.numFlips & 4095) == 0) { shaderManagerGL_->SaveCache(shaderCachePath_, &drawEngine_); } - shaderManagerGL_->DirtyLastShader(); + shaderManagerGL_->DirtyShader(); // Not sure if this is really needed. gstate_c.Dirty(DIRTY_ALL_UNIFORMS); @@ -296,3 +305,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { shaderManagerGL_->GetNumPrograms() ); } + +std::string GPU_GLES::GetGpuProfileString() { + GLRenderManager *rm = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + return rm->GetGpuProfileString(); +} diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index b6ae9492f..5b56504ee 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -40,6 +40,9 @@ public: // This gets called on startup and when we get back from settings. u32 CheckGPUFeatures() const override; + bool IsReady() override; + void CancelReady() override; + void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. @@ -48,6 +51,8 @@ public: void BeginHostFrame() override; void EndHostFrame() override; + std::string GetGpuProfileString() override; + protected: void FinishDeferred() override; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 176b50aa8..248347a07 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -35,7 +35,7 @@ #include "Common/GPU/thin3d.h" #include "Common/GPU/OpenGL/GLRenderManager.h" #include "Common/System/Display.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/VR/PPSSPPVR.h" #include "Common/Log.h" @@ -76,7 +76,6 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, : render_(render), useHWTransform_(useHWTransform) { PROFILE_THIS_SCOPE("shaderlink"); - _assert_(render); _assert_(vs); _assert_(fs); @@ -155,7 +154,8 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, queries.push_back({ &u_uvscaleoffset, "u_uvscaleoffset" }); queries.push_back({ &u_texclamp, "u_texclamp" }); queries.push_back({ &u_texclampoff, "u_texclampoff" }); - queries.push_back({ &u_texNoAlphaMul, "u_texNoAlphaMul" }); + queries.push_back({ &u_texNoAlpha, "u_texNoAlpha" }); + queries.push_back({ &u_texMul, "u_texMul" }); queries.push_back({ &u_lightControl, "u_lightControl" }); for (int i = 0; i < 4; i++) { @@ -357,8 +357,6 @@ static inline bool GuessVRDrawingHUD(bool is2D, bool flatScreen) { else if (gstate.isClearModeDepthMask()) hud = false; //HUD texture has to contain alpha channel else if (!gstate.isTextureAlphaUsed()) hud = false; - //HUD texture cannot be in 5551 format - else if (gstate.getTextureFormat() == GETextureFormat::GE_TFMT_5551) hud = false; //HUD texture cannot be in CLUT16 format else if (gstate.getTextureFormat() == GETextureFormat::GE_TFMT_CLUT16) hud = false; //HUD texture cannot be in CLUT32 format @@ -430,7 +428,9 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin } else { UpdateVRProjection(gstate.projMatrix, leftEyeMatrix.m, rightEyeMatrix.m); } - UpdateVRParams(gstate.projMatrix); + float m4x4[16]; + ConvertMatrix4x3To4x4Transposed(m4x4, gstate.viewMatrix); + UpdateVRParams(gstate.projMatrix, m4x4); FlipProjMatrix(leftEyeMatrix, useBufferedRendering); FlipProjMatrix(rightEyeMatrix, useBufferedRendering); @@ -466,8 +466,8 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) { doTextureAlpha = false; } - float noAlphaMul[2] = { doTextureAlpha ? 0.0f : 1.0f, gstate.isColorDoublingEnabled() ? 2.0f : 1.0f }; - render_->SetUniformF(&u_texNoAlphaMul, 2, noAlphaMul); + render_->SetUniformF1(&u_texNoAlpha, doTextureAlpha ? 0.0f : 1.0f); + render_->SetUniformF1(&u_texMul, gstate.isColorDoublingEnabled() ? 2.0f : 1.0f); } if (dirty & DIRTY_ALPHACOLORREF) { if (shaderLanguage.bitwiseOps) { @@ -505,16 +505,12 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin render_->SetUniformF(&u_fogcoef, 2, fogcoef); } if (dirty & DIRTY_UVSCALEOFFSET) { - float widthFactor = 1.0f; - float heightFactor = 1.0f; - if (gstate_c.textureIsFramebuffer) { - const float invW = 1.0f / (float)gstate_c.curTextureWidth; - const float invH = 1.0f / (float)gstate_c.curTextureHeight; - const int w = gstate.getTextureWidth(0); - const int h = gstate.getTextureHeight(0); - widthFactor = (float)w * invW; - heightFactor = (float)h * invH; - } + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + const float widthFactor = (float)w * invW; + const float heightFactor = (float)h * invH; float uvscaleoff[4]; if (gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE) { // When we are generating UV coordinates through the bezier/spline, we need to apply the scaling. @@ -568,7 +564,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin if (dirty & DIRTY_WORLDMATRIX) { SetMatrix4x3(render_, &u_world, gstate.worldMatrix); } - if (dirty & DIRTY_VIEWMATRIX) { + if ((dirty & DIRTY_VIEWMATRIX) || IsVREnabled()) { if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { float leftEyeView[16]; float rightEyeView[16]; @@ -716,7 +712,7 @@ void ShaderManagerGLES::Clear() { linkedShaderCache_.clear(); fsCache_.Clear(); vsCache_.Clear(); - DirtyLastShader(); + DirtyShader(); } void ShaderManagerGLES::ClearShaders() { @@ -735,24 +731,26 @@ void ShaderManagerGLES::DeviceRestore(Draw::DrawContext *draw) { draw_ = draw; } -void ShaderManagerGLES::DirtyLastShader() { +void ShaderManagerGLES::DirtyShader() { // Forget the last shader ID lastFSID_.set_invalid(); lastVSID_.set_invalid(); + DirtyLastShader(); gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); shaderSwitchDirtyUniforms_ = 0; +} + +void ShaderManagerGLES::DirtyLastShader() { lastShader_ = nullptr; lastVShaderSame_ = false; } -// Can only fail by failing to generate the code (bad FSID). -// Any actual failures driver-side happens later in the render manager. Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { uint64_t uniformMask; std::string errorString; FragmentShaderFlags flags; if (!GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &uniformMask, &flags, &errorString)) { - ERROR_LOG_REPORT(G3D, "FS shader gen error: %s (%s: %08x:%08x)", errorString.c_str(), "GLES", FSID.d[0], FSID.d[1]); + ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str()); return nullptr; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_)); @@ -761,8 +759,6 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { return new Shader(render_, codeBuffer_, desc, params); } -// Can only fail by failing to generate the code (bad VSID). -// Any actual failures driver-side happens later in the render manager. Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { bool useHWTransform = VSID.Bit(VS_BIT_USE_HW_TRANSFORM); uint32_t attrMask; @@ -770,7 +766,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { std::string errorString; VertexShaderFlags flags; if (!GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &attrMask, &uniformMask, &flags, &errorString)) { - ERROR_LOG_REPORT(G3D, "VS shader gen error: %s (%s: %08x:%08x)", errorString.c_str(), "GLES", VSID.d[0], VSID.d[1]); + ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str()); return nullptr; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_)); @@ -796,31 +792,31 @@ Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTess } lastVSID_ = *VSID; - Shader *vs; - if (vsCache_.Get(*VSID, &vs)) { - return vs; - } + Shader *vs = vsCache_.Get(*VSID); + if (!vs) { + // Vertex shader not in cache. Let's compile it. + vs = CompileVertexShader(*VSID); + if (!vs || vs->Failed()) { + auto gr = GetI18NCategory(I18NCat::GRAPHICS); + ERROR_LOG(G3D, "Vertex shader generation failed, falling back to software transform"); + if (!g_Config.bHideSlowWarnings) { + System_NotifyUserMessage(gr->T("hardware transform error - falling back to software"), 2.5f, 0xFF3030FF); + } + delete vs; - // Vertex shader not in cache. Let's compile it. - vs = CompileVertexShader(*VSID); - if (!vs) { - auto gr = GetI18NCategory(I18NCat::GRAPHICS); - ERROR_LOG(G3D, "Vertex shader generation failed, falling back to software transform"); - if (!g_Config.bHideSlowWarnings) { - g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("hardware transform error - falling back to software"), 2.5f); + // TODO: Look for existing shader with the appropriate ID, use that instead of generating a new one - however, need to make sure + // that that shader ID is not used when computing the linked shader ID below, because then IDs won't match + // next time and we'll do this over and over... + + // Can still work with software transform. + VShaderID vsidTemp; + ComputeVertexShaderID(&vsidTemp, decoder, false, false, weightsAsFloat, true); + vs = CompileVertexShader(vsidTemp); } - // TODO: Look for existing shader with the appropriate ID, use that instead of generating a new one - however, need to make sure - // that that shader ID is not used when computing the linked shader ID below, because then IDs won't match - // next time and we'll do this over and over... - - // Can still work with software transform. - VShaderID vsidTemp; - ComputeVertexShaderID(&vsidTemp, decoder, false, false, weightsAsFloat, true); - vs = CompileVertexShader(vsidTemp); + vsCache_.Insert(*VSID, vs); + diskCacheDirty_ = true; } - - vsCache_.Insert(*VSID, vs); return vs; } @@ -848,17 +844,14 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(VShaderID VSID, Shader *vs, lastFSID_ = FSID; - Shader *fs; - if (!fsCache_.Get(FSID, &fs)) { + Shader *fs = fsCache_.Get(FSID); + if (!fs) { // Fragment shader not in cache. Let's compile it. // Can't really tell if we succeeded since the compile is on the GPU thread later. // Could fail to generate, in which case we're kinda screwed. fs = CompileFragmentShader(FSID); - if (!fs) { - ERROR_LOG(G3D, "Failed to generate fragment shader with ID %08x:%08x", FSID.d[0], FSID.d[1]); - // Still insert it so we don't end up spamming generation. - } fsCache_.Insert(FSID, fs); + diskCacheDirty_ = true; } // Okay, we have both shaders. Let's see if there's a linked one. @@ -880,7 +873,7 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(VShaderID VSID, Shader *vs, _dbg_assert_(FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); if (vs == nullptr || fs == nullptr) { - // Can't draw. This shouldn't really happen (but can happen if fragment shader generation fails) + // Can't draw. This shouldn't really happen. return nullptr; } @@ -943,22 +936,14 @@ std::string ShaderManagerGLES::DebugGetShaderString(std::string id, DebugShaderT switch (type) { case SHADER_TYPE_VERTEX: { - Shader *vs; - if (vsCache_.Get(VShaderID(shaderId), &vs) && vs) { - return vs->GetShaderString(stringType, shaderId); - } else { - return ""; - } + Shader *vs = vsCache_.Get(VShaderID(shaderId)); + return vs ? vs->GetShaderString(stringType, shaderId) : ""; } case SHADER_TYPE_FRAGMENT: { - Shader *fs; - if (fsCache_.Get(FShaderID(shaderId), &fs) && fs) { - return fs->GetShaderString(stringType, shaderId); - } else { - return ""; - } + Shader *fs = fsCache_.Get(FShaderID(shaderId)); + return fs->GetShaderString(stringType, shaderId); } default: return "N/A"; @@ -981,7 +966,7 @@ enum class CacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0x83277592 -#define CACHE_VERSION 34 +#define CACHE_VERSION 30 struct CacheHeader { uint32_t magic; @@ -1010,31 +995,6 @@ bool ShaderManagerGLES::LoadCacheFlags(File::IOFile &f, DrawEngineGLES *drawEngi } bool ShaderManagerGLES::LoadCache(File::IOFile &f) { - // TODO: Get rid of this struct. - struct { - std::vector vert; - std::vector frag; - std::vector> link; - - size_t vertPos = 0; - size_t fragPos = 0; - size_t linkPos = 0; - double start; - - void Clear() { - vert.clear(); - frag.clear(); - link.clear(); - vertPos = 0; - fragPos = 0; - linkPos = 0; - } - - bool Done() { - return vertPos >= vert.size() && fragPos >= frag.size() && linkPos >= link.size(); - } - } diskCachePending_; - u64 sz = f.GetSize(); f.Seek(0, SEEK_SET); CacheHeader header; @@ -1089,6 +1049,12 @@ bool ShaderManagerGLES::LoadCache(File::IOFile &f) { diskCachePending_.link.emplace_back(vsid, fsid); } + // Actual compilation happens in ContinuePrecompile(), called by GPU_GLES's IsReady. + diskCacheDirty_ = false; + return true; +} + +bool ShaderManagerGLES::ContinuePrecompile(float sliceTime) { auto &pending = diskCachePending_; if (pending.Done()) { return true; @@ -1097,10 +1063,17 @@ bool ShaderManagerGLES::LoadCache(File::IOFile &f) { PSP_SetLoading("Compiling shaders..."); double start = time_now_d(); + // Let's try to keep it under sliceTime if possible. + double end = start + sliceTime; for (size_t &i = pending.vertPos; i < pending.vert.size(); i++) { + if (time_now_d() >= end) { + // We'll finish later. + return false; + } + const VShaderID &id = pending.vert[i]; - if (!vsCache_.ContainsKey(id)) { + if (!vsCache_.Get(id)) { if (id.Bit(VS_BIT_IS_THROUGH) && id.Bit(VS_BIT_USE_HW_TRANSFORM)) { // Clearly corrupt, bailing. ERROR_LOG_REPORT(G3D, "Corrupt shader cache: Both IS_THROUGH and USE_HW_TRANSFORM set."); @@ -1109,7 +1082,7 @@ bool ShaderManagerGLES::LoadCache(File::IOFile &f) { } Shader *vs = CompileVertexShader(id); - if (!vs) { + if (vs->Failed()) { // Give up on using the cache, just bail. We can't safely create the fallback shaders here // without trying to deduce the vertType from the VSID. ERROR_LOG(G3D, "Failed to compile a vertex shader loading from cache. Skipping rest of shader cache."); @@ -1124,30 +1097,29 @@ bool ShaderManagerGLES::LoadCache(File::IOFile &f) { } for (size_t &i = pending.fragPos; i < pending.frag.size(); i++) { + if (time_now_d() >= end) { + // We'll finish later. + return false; + } + const FShaderID &id = pending.frag[i]; - if (!fsCache_.ContainsKey(id)) { - Shader *fs = CompileFragmentShader(id); - if (!fs) { - // Give up on using the cache - something went wrong. - // We'll still keep the shaders we generated so far around. - ERROR_LOG(G3D, "Failed to compile a fragment shader loading from cache. Skipping rest of shader cache."); - delete fs; - pending.Clear(); - return false; - } - fsCache_.Insert(id, fs); + if (!fsCache_.Get(id)) { + fsCache_.Insert(id, CompileFragmentShader(id)); } else { WARN_LOG(G3D, "Duplicate fragment shader found in GL shader cache, ignoring"); } } for (size_t &i = pending.linkPos; i < pending.link.size(); i++) { + if (time_now_d() >= end) { + // We'll finish later. + return false; + } + const VShaderID &vsid = pending.link[i].first; const FShaderID &fsid = pending.link[i].second; - Shader *vs = nullptr; - Shader *fs = nullptr; - vsCache_.Get(vsid, &vs); - fsCache_.Get(fsid, &fs); + Shader *vs = vsCache_.Get(vsid); + Shader *fs = fsCache_.Get(fsid); if (vs && fs) { LinkedShader *ls = new LinkedShader(render_, vsid, vs, fsid, fs, vs->UseHWTransform(), true); LinkedShaderCacheEntry entry(vs, fs, ls); @@ -1164,7 +1136,14 @@ bool ShaderManagerGLES::LoadCache(File::IOFile &f) { return true; } +void ShaderManagerGLES::CancelPrecompile() { + diskCachePending_.Clear(); +} + void ShaderManagerGLES::SaveCache(const Path &filename, DrawEngineGLES *drawEngine) { + if (!diskCacheDirty_) { + return; + } if (linkedShaderCache_.empty()) { return; } @@ -1172,6 +1151,7 @@ void ShaderManagerGLES::SaveCache(const Path &filename, DrawEngineGLES *drawEngi FILE *f = File::OpenCFile(filename, "wb"); if (!f) { // Can't save, give up for now. + diskCacheDirty_ = false; return; } CacheHeader header; @@ -1205,4 +1185,5 @@ void ShaderManagerGLES::SaveCache(const Path &filename, DrawEngineGLES *drawEngi fwrite(&fsid, 1, sizeof(fsid), f); } fclose(f); + diskCacheDirty_ = false; } diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 5a91bc7f7..ff9478ca2 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -102,7 +102,8 @@ public: int u_uvscaleoffset; int u_texclamp; int u_texclampoff; - int u_texNoAlphaMul; + int u_texNoAlpha; + int u_texMul; // Lighting int u_lightControl; @@ -141,6 +142,7 @@ public: ~Shader(); GLRShader *shader; + bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } // only relevant for vtx shaders std::string GetShaderString(DebugShaderStringType type, ShaderID id) const; @@ -151,6 +153,7 @@ public: private: GLRenderManager *render_; std::string source_; + bool failed_ = false; bool useHWTransform_; bool isFragment_; uint32_t attrMask_; // only used in vertex shaders @@ -172,6 +175,7 @@ public: void DeviceLost() override; void DeviceRestore(Draw::DrawContext *draw) override; + void DirtyShader(); void DirtyLastShader() override; int GetNumVertexShaders() const { return (int)vsCache_.size(); } @@ -183,6 +187,8 @@ public: bool LoadCacheFlags(File::IOFile &f, DrawEngineGLES *drawEngine); bool LoadCache(File::IOFile &f); + bool ContinuePrecompile(float sliceTime = 1.0f / 60.0f); + void CancelPrecompile(); void SaveCache(const Path &filename, DrawEngineGLES *drawEngine); private: @@ -212,9 +218,34 @@ private: u64 shaderSwitchDirtyUniforms_ = 0; char *codeBuffer_; - typedef DenseHashMap FSCache; + typedef DenseHashMap FSCache; FSCache fsCache_; - typedef DenseHashMap VSCache; + typedef DenseHashMap VSCache; VSCache vsCache_; + + bool diskCacheDirty_ = false; + struct { + std::vector vert; + std::vector frag; + std::vector> link; + + size_t vertPos = 0; + size_t fragPos = 0; + size_t linkPos = 0; + double start; + + void Clear() { + vert.clear(); + frag.clear(); + link.clear(); + vertPos = 0; + fragPos = 0; + linkPos = 0; + } + + bool Done() { + return vertPos >= vert.size() && fragPos >= frag.size() && linkPos >= link.size(); + } + } diskCachePending_; }; diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index 7a846711f..ac4b20f3f 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -242,12 +242,13 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) { - ConvertStencilFuncState(stencilState_); + GenericStencilFuncState stencilState; + ConvertStencilFuncState(stencilState); if (gstate.isModeClear()) { - renderManager->SetStencil( - gstate.isClearModeAlphaMask(), GL_ALWAYS, 0xFF, 0xFF, - stencilState_.writeMask, GL_REPLACE, GL_REPLACE, GL_REPLACE); + // Depth Test + renderManager->SetStencilFunc(gstate.isClearModeAlphaMask(), GL_ALWAYS, 0xFF, 0xFF); + renderManager->SetStencilOp(stencilState.writeMask, GL_REPLACE, GL_REPLACE, GL_REPLACE); renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS); } else { // Depth Test @@ -257,18 +258,18 @@ void DrawEngineGLES::ApplyDrawState(int prim) { UpdateEverUsedEqualDepth(gstate.getDepthTestFunction()); // Stencil Test - if (stencilState_.enabled) { - renderManager->SetStencil( - stencilState_.enabled, compareOps[stencilState_.testFunc], stencilState_.testRef, stencilState_.testMask, - stencilState_.writeMask, stencilOps[stencilState_.sFail], stencilOps[stencilState_.zFail], stencilOps[stencilState_.zPass]); + if (stencilState.enabled) { + renderManager->SetStencilFunc(stencilState.enabled, compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask); + renderManager->SetStencilOp(stencilState.writeMask, stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); // Nasty special case for Spongebob and similar where it tries to write zeros to alpha/stencil during // depth-fail. We can't write to alpha then because the pixel is killed. However, we can invert the depth // test and modify the alpha function... - if (SpongebobDepthInverseConditions(stencilState_)) { + if (SpongebobDepthInverseConditions(stencilState)) { renderManager->SetBlendAndMask(0x8, true, GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO, GL_FUNC_ADD, GL_FUNC_ADD); renderManager->SetDepth(true, false, GL_LESS); - renderManager->SetStencil(true, GL_ALWAYS, 0xFF, 0xFF, 0xFF, GL_ZERO, GL_KEEP, GL_ZERO); + renderManager->SetStencilFunc(true, GL_ALWAYS, 0xFF, 0xFF); + renderManager->SetStencilOp(0xFF, GL_ZERO, GL_KEEP, GL_ZERO); dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE; gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE); @@ -283,14 +284,14 @@ void DrawEngineGLES::ApplyDrawState(int prim) { ConvertViewportAndScissor(useBufferedRendering, framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), - vpAndScissor_); - UpdateCachedViewportState(vpAndScissor_); + vpAndScissor); + UpdateCachedViewportState(vpAndScissor); - renderManager->SetScissor(GLRect2D{ vpAndScissor_.scissorX, vpAndScissor_.scissorY, vpAndScissor_.scissorW, vpAndScissor_.scissorH }); + renderManager->SetScissor(GLRect2D{ vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH }); renderManager->SetViewport({ - vpAndScissor_.viewportX, vpAndScissor_.viewportY, - vpAndScissor_.viewportW, vpAndScissor_.viewportH, - vpAndScissor_.depthRangeMin, vpAndScissor_.depthRangeMax }); + vpAndScissor.viewportX, vpAndScissor.viewportY, + vpAndScissor.viewportW, vpAndScissor.viewportH, + vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax }); } gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE); @@ -300,8 +301,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) { void DrawEngineGLES::ApplyDrawStateLate(bool setStencilValue, int stencilValue) { if (setStencilValue) { - render_->SetStencil(stencilState_.writeMask, GL_ALWAYS, stencilValue, 255, 0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE); - gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE); // For the next time. + render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, stencilValue, 255); } // At this point, we know if the vertices are full alpha or not. diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 94dcf0db0..e83ff0a82 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -24,7 +24,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Math/math_util.h" #include "Common/Profiler/Profiler.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/GPU/OpenGL/GLRenderManager.h" #include "Common/TimeUtil.h" @@ -150,9 +150,9 @@ void TextureCacheGLES::StartFrame() { auto err = GetI18NCategory(I18NCat::ERRORS); if (standardScaleFactor_ > 1) { - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Warning: Video memory FULL, reducing upscaling and switching to slow caching mode"), 2.0f); + System_NotifyUserMessage(err->T("Warning: Video memory FULL, reducing upscaling and switching to slow caching mode"), 2.0f); } else { - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); + System_NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); } } } @@ -304,7 +304,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { bc = true; } else { int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); - stride = mipWidth * bpp; + stride = std::max(mipWidth * bpp, 16); dataSize = stride * mipHeight; } } else { @@ -314,7 +314,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { } else { bpp = (int)Draw::DataFormatSizeInBytes(dstFmt); } - stride = mipWidth * bpp; + stride = std::max(mipWidth * bpp, 16); dataSize = stride * mipHeight; } diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index 21ad2d3f0..2a7d47720 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -53,12 +53,14 @@ static void SetGPU(T *obj) { #endif bool GPU_IsReady() { - return gpu != nullptr; + if (gpu) + return gpu->IsReady(); + return false; } bool GPU_IsStarted() { if (gpu) - return gpu->IsStarted(); + return gpu->IsReady() && gpu->IsStarted(); return false; } @@ -110,7 +112,7 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { #endif } - if (gpu && !gpu->IsStarted()) + if (gpu && gpu->IsReady() && !gpu->IsStarted()) SetGPU(nullptr); return gpu != nullptr; @@ -124,6 +126,13 @@ void GPU_Shutdown() { // Reduce the risk for weird races with the Windows GE debugger. gpuDebug = nullptr; + // Wait for IsReady, since it might be running on a thread. + if (gpu) { + gpu->CancelReady(); + while (!gpu->IsReady()) { + sleep_ms(10); + } + } delete gpu; gpu = nullptr; } diff --git a/GPU/GPU.h b/GPU/GPU.h index 7d4d4d1c0..c44749cb6 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -66,7 +66,6 @@ inline unsigned int toFloat24(float f) { return i >> 8; } -// The ToString function lives in GPUCommonHW.cpp. struct GPUStatistics { void Reset() { ResetFrame(); @@ -75,24 +74,25 @@ struct GPUStatistics { void ResetFrame() { numDrawCalls = 0; - numVertexDecodes = 0; numDrawSyncs = 0; numListSyncs = 0; + numCachedDrawCalls = 0; numVertsSubmitted = 0; + numCachedVertsDrawn = 0; numUncachedVertsDrawn = 0; + numTrackedVertexArrays = 0; numTextureInvalidations = 0; numTextureInvalidationsByFramebuffer = 0; numTexturesHashed = 0; + numTextureSwitches = 0; numTextureDataBytesHashed = 0; + numShaderSwitches = 0; numFlushes = 0; - numBBOXJumps = 0; - numPlaneUpdates = 0; numTexturesDecoded = 0; numFramebufferEvaluations = 0; numBlockingReadbacks = 0; numReadbacks = 0; numUploads = 0; - numCachedUploads = 0; numDepal = 0; numClears = 0; numDepthCopies = 0; @@ -100,7 +100,6 @@ struct GPUStatistics { numColorCopies = 0; numCopiesForShaderBlend = 0; numCopiesForSelfTex = 0; - numBlockTransfers = 0; numReplacerTrackedTex = 0; numCachedReplacedTextures = 0; msProcessingDisplayLists = 0; @@ -110,24 +109,25 @@ struct GPUStatistics { // Per frame statistics int numDrawCalls; - int numVertexDecodes; int numDrawSyncs; int numListSyncs; + int numCachedDrawCalls; int numFlushes; - int numBBOXJumps; - int numPlaneUpdates; int numVertsSubmitted; + int numCachedVertsDrawn; int numUncachedVertsDrawn; + int numTrackedVertexArrays; int numTextureInvalidations; int numTextureInvalidationsByFramebuffer; int numTexturesHashed; int numTextureDataBytesHashed; + int numTextureSwitches; + int numShaderSwitches; int numTexturesDecoded; int numFramebufferEvaluations; int numBlockingReadbacks; int numReadbacks; int numUploads; - int numCachedUploads; int numDepal; int numClears; int numDepthCopies; @@ -135,7 +135,6 @@ struct GPUStatistics { int numColorCopies; int numCopiesForShaderBlend; int numCopiesForSelfTex; - int numBlockTransfers; int numReplacerTrackedTex; int numCachedReplacedTextures; double msProcessingDisplayLists; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 0bfb758ee..25eb091cb 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -67,11 +67,13 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : gstate_c.Reset(); gpuStats.Reset(); + UpdateVsyncInterval(true); PPGeSetDrawContext(draw); ResetMatrices(); } void GPUCommon::BeginHostFrame() { + UpdateVsyncInterval(displayResized_); ReapplyGfxState(); // TODO: Assume config may have changed - maybe move to resize. @@ -113,6 +115,38 @@ void GPUCommon::Reinitialize() { framebufferManager_->DestroyAllFBOs(); } +void GPUCommon::UpdateVsyncInterval(bool force) { +#if !(PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS)) + int desiredVSyncInterval = g_Config.bVSync ? 1 : 0; + if (PSP_CoreParameter().fastForward) { + desiredVSyncInterval = 0; + } + if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) { + int limit; + if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) + limit = g_Config.iFpsLimit1; + else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) + limit = g_Config.iFpsLimit2; + else + limit = PSP_CoreParameter().analogFpsLimit; + + // For an alternative speed that is a clean factor of 60, the user probably still wants vsync. + if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) { + desiredVSyncInterval = 0; + } + } + + if (desiredVSyncInterval != lastVsync_ || force) { + // Disabled EXT_swap_control_tear for now, it never seems to settle at the correct timing + // so it just keeps tearing. Not what I hoped for... (gl_extensions.EXT_swap_control_tear) + // See http://developer.download.nvidia.com/opengl/specs/WGL_EXT_swap_control_tear.txt + if (gfxCtx_) + gfxCtx_->SwapInterval(desiredVSyncInterval); + lastVsync_ = desiredVSyncInterval; + } +#endif +} + int GPUCommon::EstimatePerVertexCost() { // TODO: This is transform cost, also account for rasterization cost somehow... although it probably // runs in parallel with transform. @@ -178,6 +212,32 @@ void GPUCommon::NotifyDisplayResized() { displayResized_ = true; } +// Called once per frame. Might also get called during the pause screen +// if "transparent". +void GPUCommon::CheckConfigChanged() { + if (configChanged_) { + ClearCacheNextFrame(); + gstate_c.SetUseFlags(CheckGPUFeatures()); + drawEngineCommon_->NotifyConfigChanged(); + textureCache_->NotifyConfigChanged(); + framebufferManager_->NotifyConfigChanged(); + BuildReportingInfo(); + configChanged_ = false; + } + + // Check needed when running tests. + if (framebufferManager_) { + framebufferManager_->CheckPostShaders(); + } +} + +void GPUCommon::CheckDisplayResized() { + if (displayResized_) { + framebufferManager_->NotifyDisplayResized(); + displayResized_ = false; + } +} + void GPUCommon::DumpNextFrame() { dumpNextFrame_ = true; } @@ -897,7 +957,6 @@ void GPUCommon::Execute_BJump(u32 op, u32 diff) { if (!currentList->bboxResult) { // bounding box jump. const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC); - gpuStats.numBBOXJumps++; if (Memory::IsValidAddress(target)) { UpdatePC(currentList->pc, target - 4); currentList->pc = target - 4; // pc will be increased after we return, counteract that @@ -1665,7 +1724,6 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { int bpp = gstate.getTransferBpp(); DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - gpuStats.numBlockTransfers++; // For VRAM, we wrap around when outside valid memory (mirrors still work.) if ((srcBasePtr & 0x04800000) == 0x04800000) @@ -1705,7 +1763,9 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { memcpy(dstp, srcp, bytesToCopy); if (MemBlockInfoDetailed(bytesToCopy)) { - NotifyMemInfoCopy(dst, src, bytesToCopy, "GPUBlockTransfer/"); + tagSize = FormatMemWriteTagAt(tag, sizeof(tag), "GPUBlockTransfer/", src, bytesToCopy); + NotifyMemInfo(MemBlockFlags::READ, src, bytesToCopy, tag, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, bytesToCopy, tag, tagSize); } } else if ((srcDstOverlap || srcWraps || dstWraps) && (srcValid || srcWraps) && (dstValid || dstWraps)) { // This path means we have either src/dst overlap, OR one or both of src and dst wrap. @@ -1861,11 +1921,12 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size, GPUCopyFlag flags // We use matching values in PerformReadbackToMemory/PerformWriteColorFromMemory. // Since they're identical we don't need to copy. if (dest != src) { - if (Memory::IsValidRange(dest, size) && Memory::IsValidRange(src, size)) { - memcpy(Memory::GetPointerWriteUnchecked(dest), Memory::GetPointerUnchecked(src), size); - } if (MemBlockInfoDetailed(size)) { - NotifyMemInfoCopy(dest, src, size, "GPUMemcpy/"); + char tag[128]; + size_t tagSize = FormatMemWriteTagAt(tag, sizeof(tag), "GPUMemcpy/", src, size); + Memory::Memcpy(dest, src, size, tag, tagSize); + } else { + Memory::Memcpy(dest, src, size, "GPUMemcpy"); } } } @@ -1874,7 +1935,10 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size, GPUCopyFlag flags } if (MemBlockInfoDetailed(size)) { - NotifyMemInfoCopy(dest, src, size, "GPUMemcpy/"); + char tag[128]; + size_t tagSize = FormatMemWriteTagAt(tag, sizeof(tag), "GPUMemcpy/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tag, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dest, size, tag, tagSize); } InvalidateCache(dest, size, GPU_INVALIDATE_HINT); if (!(flags & GPUCopyFlag::DEBUG_NOTIFIED)) @@ -1944,8 +2008,8 @@ bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) { } void GPUCommon::UpdateUVScaleOffset() { -#if defined(_M_SSE) - __m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *)&gstate.texscaleu), 8); +#ifdef _M_SSE + __m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *) & gstate.texscaleu), 8); _mm_storeu_si128((__m128i *)&gstate_c.uv, values); #elif PPSSPP_ARCH(ARM_NEON) const uint32x4_t values = vshlq_n_u32(vld1q_u32((const u32 *)&gstate.texscaleu), 8); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 012f299d3..0e70b2ab9 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -67,18 +67,6 @@ struct TransformedVertex { } }; -inline bool IsTrianglePrim(GEPrimitiveType prim) { - // TODO: KEEP_PREVIOUS is mistakenly treated as TRIANGLE here... This isn't new. - // - // Interesting optimization, but not confident in performance: - // static const bool p[8] = { false, false, false, true, true, true, false, true }; - // 10111000 = 0xB8; - // return (0xB8U >> (u8)prim) & 1; - - return prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES; -} - - class GPUCommon : public GPUInterface, public GPUDebugInterface { public: GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); @@ -88,11 +76,18 @@ public: } virtual u32 CheckGPUFeatures() const = 0; + void CheckDisplayResized() override; + void CheckConfigChanged() override; + virtual void UpdateCmdInfo() = 0; + bool IsReady() override { + return true; + } bool IsStarted() override { return true; } + void CancelReady() override {} void Reinitialize() override; void BeginHostFrame() override; @@ -231,6 +226,10 @@ protected: virtual void CheckRenderResized() {} + inline bool IsTrianglePrim(GEPrimitiveType prim) const { + return prim != GE_PRIM_RECTANGLES && prim > GE_PRIM_LINE_STRIP; + } + void SetDrawType(DrawType type, GEPrimitiveType prim) { if (type != lastDraw_) { // We always flush when drawing splines/beziers so no need to do so here @@ -247,6 +246,7 @@ protected: } void BeginFrame() override; + void UpdateVsyncInterval(bool force); virtual void CheckDepthUsage(VirtualFramebuffer *vfb) {} virtual void FastRunLoop(DisplayList &list) = 0; @@ -258,7 +258,7 @@ protected: void FlushImm(); void DoBlockTransfer(u32 skipDrawReason); - // TODO: Unify this. Vulkan and OpenGL are different due to how they buffer data. + // TODO: Unify this. The only backend that differs is Vulkan. virtual void FinishDeferred() {} void AdvanceVerts(u32 vertType, int count, int bytesRead) { @@ -355,4 +355,6 @@ private: // Debug stats. double timeSteppingStarted_; double timeSpentStepping_; + + int lastVsync_ = -1; }; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 7916a8966..85bbe1e53 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -149,7 +149,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_TEXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, { GE_CMD_TEXLEVEL, FLAG_EXECUTEONCHANGE, DIRTY_TEXTURE_PARAMS, &GPUCommonHW::Execute_TexLevel }, { GE_CMD_TEXLODSLOPE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, + { GE_CMD_TEXADDR0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE | DIRTY_UVSCALEOFFSET }, { GE_CMD_TEXADDR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXADDR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXADDR3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, @@ -191,12 +191,12 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_ANTIALIASENABLE, FLAG_FLUSHBEFOREONCHANGE }, // Viewport. - { GE_CMD_OFFSETX, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_CULL_PLANES }, - { GE_CMD_OFFSETY, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_CULL_PLANES }, - { GE_CMD_VIEWPORTXSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULL_PLANES }, - { GE_CMD_VIEWPORTYSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULL_PLANES }, - { GE_CMD_VIEWPORTXCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULL_PLANES }, - { GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULL_PLANES }, + { GE_CMD_OFFSETX, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_OFFSETY, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_VIEWPORTXSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTYSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTXCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, { GE_CMD_VIEWPORTZSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, { GE_CMD_VIEWPORTZCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, { GE_CMD_DEPTHCLAMPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_RASTER_STATE }, @@ -206,12 +206,12 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_MAXZ, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHRANGE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, // Region - { GE_CMD_REGION1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_CULL_PLANES }, - { GE_CMD_REGION2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_CULL_PLANES }, + { GE_CMD_REGION1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_REGION2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, // Scissor - { GE_CMD_SCISSOR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_CULL_PLANES }, - { GE_CMD_SCISSOR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_CULL_PLANES }, + { GE_CMD_SCISSOR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_SCISSOR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, // Lighting base colors { GE_CMD_AMBIENTCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_AMBIENT }, @@ -401,32 +401,6 @@ GPUCommonHW::~GPUCommonHW() { delete shaderManager_; } -// Called once per frame. Might also get called during the pause screen -// if "transparent". -void GPUCommonHW::CheckConfigChanged() { - if (configChanged_) { - ClearCacheNextFrame(); - gstate_c.SetUseFlags(CheckGPUFeatures()); - drawEngineCommon_->NotifyConfigChanged(); - textureCache_->NotifyConfigChanged(); - framebufferManager_->NotifyConfigChanged(); - BuildReportingInfo(); - configChanged_ = false; - } - - // Check needed when running tests. - if (framebufferManager_) { - framebufferManager_->CheckPostShaders(); - } -} - -void GPUCommonHW::CheckDisplayResized() { - if (displayResized_) { - framebufferManager_->NotifyDisplayResized(); - displayResized_ = false; - } -} - void GPUCommonHW::CheckRenderResized() { if (renderResized_) { framebufferManager_->NotifyRenderResized(msaaLevel_); @@ -447,8 +421,6 @@ void GPUCommonHW::DeviceLost() { // Call at the start of the GPU implementation's DeviceRestore void GPUCommonHW::DeviceRestore(Draw::DrawContext *draw) { draw_ = draw; - displayResized_ = true; // re-check display bounds. - renderResized_ = true; framebufferManager_->DeviceRestore(draw_); textureCache_->DeviceRestore(draw_); shaderManager_->DeviceRestore(draw_); @@ -492,13 +464,6 @@ void GPUCommonHW::UpdateCmdInfo() { cmdInfo_[GE_CMD_MATERIALUPDATE].RemoveDirty(DIRTY_LIGHT_CONTROL); cmdInfo_[GE_CMD_MATERIALUPDATE].AddDirty(DIRTY_VERTEXSHADER_STATE); } - - if (gstate_c.Use(GPU_USE_FRAGMENT_UBERSHADER)) { - // Texfunc controls both texalpha and doubling. The rest is not dynamic yet so can't remove fragment shader dirtying. - cmdInfo_[GE_CMD_TEXFUNC].AddDirty(DIRTY_TEX_ALPHA_MUL); - } else { - cmdInfo_[GE_CMD_TEXFUNC].RemoveDirty(DIRTY_TEX_ALPHA_MUL); - } } void GPUCommonHW::BeginFrame() { @@ -613,7 +578,7 @@ u32 GPUCommonHW::CheckGPUFeatures() const { features |= GPU_USE_FRAMEBUFFER_FETCH; } - if (draw_->GetShaderLanguageDesc().bitwiseOps && g_Config.bUberShaderVertex) { + if (draw_->GetShaderLanguageDesc().bitwiseOps) { features |= GPU_USE_LIGHT_UBERSHADER; } @@ -626,11 +591,6 @@ u32 GPUCommonHW::CheckGPUFeatures() const { features |= GPU_USE_ACCURATE_DEPTH; } - // Some backends will turn this off again in the calling function. - if (g_Config.bUberShaderFragment) { - features |= GPU_USE_FRAGMENT_UBERSHADER; - } - return features; } @@ -727,7 +687,7 @@ bool GPUCommonHW::GetOutputFramebuffer(GPUDebugBuffer &buffer) { return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false; } -std::vector GPUCommonHW::GetFramebufferList() const { +std::vector GPUCommonHW::GetFramebufferList() const { return framebufferManager_->GetFramebufferList(); } @@ -860,14 +820,13 @@ void GPUCommonHW::FastRunLoop(DisplayList &list) { } void GPUCommonHW::Execute_VertexType(u32 op, u32 diff) { - if (diff) { - // TODO: We only need to dirty vshader-state here if the output format will be different. + if (diff) gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); - - if (diff & GE_VTYPE_THROUGH_MASK) { - // Switching between through and non-through, we need to invalidate a bunch of stuff. + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) { + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + // Switching between through and non-through, we need to invalidate a bunch of stuff. + if (diff & GE_VTYPE_THROUGH_MASK) gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_CULLRANGE); - } } } @@ -878,6 +837,8 @@ void GPUCommonHW::Execute_VertexTypeSkinning(u32 op, u32 diff) { gstate.vertType ^= diff; Flush(); gstate.vertType ^= diff; + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); // In this case, we may be doing weights and morphs. // Update any bone matrix uniforms so it uses them correctly. if ((op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { @@ -896,10 +857,14 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { PROFILE_THIS_SCOPE("execprim"); + u32 data = op & 0xFFFFFF; + u32 count = data & 0xFFFF; + if (count == 0) + return; FlushImm(); // Upper bits are ignored. - GEPrimitiveType prim = static_cast((op >> 16) & 7); + GEPrimitiveType prim = static_cast((data >> 16) & 7); SetDrawType(DRAW_PRIM, prim); // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. @@ -948,15 +913,10 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { vfb->usageFlags |= FB_USAGE_BLUE_TO_ALPHA; } - if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { - vertexCost_ = EstimatePerVertexCost(); - } - - u32 count = op & 0xFFFF; // Must check this after SetRenderFrameBuffer so we know SKIPDRAW_NON_DISPLAYED_FB. if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // Rough estimate, not sure what's correct. - cyclesExecuted += vertexCost_ * count; + cyclesExecuted += EstimatePerVertexCost() * count; if (gstate.isModeClear()) { gpuStats.numClears++; } @@ -967,10 +927,6 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { const void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); const void *inds = nullptr; - - bool isTriangle = IsTrianglePrim(prim); - - bool canExtend = isTriangle; u32 vertexType = gstate.vertType; if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { u32 indexAddr = gstate_c.indexAddr; @@ -979,7 +935,10 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { return; } inds = Memory::GetPointerUnchecked(indexAddr); - canExtend = false; + } + + if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { + vertexCost_ = EstimatePerVertexCost(); } int bytesRead = 0; @@ -989,9 +948,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { int cullMode = gstate.getCullMode(); uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); - if (!drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, true, &bytesRead)) { - canExtend = false; - } + drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, cullMode, &bytesRead); // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). // Some games rely on this, they don't bother reloading VADDR and IADDR. // The VADDR/IADDR registers are NOT updated. @@ -999,16 +956,18 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { int totalVertCount = count; // PRIMs are often followed by more PRIMs. Save some work and submit them immediately. - const u32_le *start = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - const u32_le *src = start; + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); const u32_le *stall = currentList->stall ? (const u32_le *)Memory::GetPointerUnchecked(currentList->stall) : 0; + int cmdCount = 0; // Optimized submission of sequences of PRIM. Allows us to avoid going through all the mess // above for each one. This can be expanded to support additional games that intersperse // PRIM commands with other commands. A special case is Earth Defence Force 2 that changes culling mode // between each prim, we just change the triangle winding right here to still be able to join draw calls. - uint32_t vtypeCheckMask = g_Config.bSoftwareSkinning ? (~GE_VTYPE_WEIGHTCOUNT_MASK) : 0xFFFFFFFF; + uint32_t vtypeCheckMask = ~GE_VTYPE_WEIGHTCOUNT_MASK; + if (!g_Config.bSoftwareSkinning) + vtypeCheckMask = 0xFFFFFFFF; if (debugRecording_) goto bail; @@ -1018,38 +977,22 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { switch (data >> 24) { case GE_CMD_PRIM: { - GEPrimitiveType newPrim = static_cast((data >> 16) & 7); - if (IsTrianglePrim(newPrim) != isTriangle) - goto bail; // Can't join over this boundary. Might as well exit and get this on the next time around. - // TODO: more efficient updating of verts/inds - u32 count = data & 0xFFFF; - bool clockwise = !gstate.isCullEnabled() || gstate.getCullMode() == cullMode; - if (canExtend) { - // Non-indexed draws can be cheaply merged if vertexAddr hasn't changed, that means the vertices - // are consecutive in memory. - _dbg_assert_((vertexType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_NONE); - int commandsExecuted = drawEngineCommon_->ExtendNonIndexedPrim(src, stall, vertTypeID, clockwise, &bytesRead, isTriangle); - if (!commandsExecuted) { - goto bail; - } - src += commandsExecuted - 1; - gstate_c.vertexAddr += bytesRead; - totalVertCount += count; + if (count == 0) { + // Ignore. break; } + GEPrimitiveType newPrim = static_cast((data >> 16) & 7); + SetDrawType(DRAW_PRIM, newPrim); + // TODO: more efficient updating of verts/inds verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); inds = nullptr; if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { inds = Memory::GetPointerUnchecked(gstate_c.indexAddr); - } else { - // We can extend again after submitting a normal draw. - canExtend = isTriangle; - } - if (!drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertTypeID, clockwise, &bytesRead)) { - canExtend = false; } + + drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertTypeID, cullMode, &bytesRead); AdvanceVerts(vertexType, count, bytesRead); totalVertCount += count; break; @@ -1058,26 +1001,18 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { { uint32_t diff = data ^ vertexType; // don't mask upper bits, vertexType is unmasked - if (diff) { - if (diff & vtypeCheckMask) - goto bail; - drawEngineCommon_->FlushSkin(); - canExtend = false; // TODO: Might support extending between some vertex types in the future. + if (diff & vtypeCheckMask) { + goto bail; + } else { vertexType = data; vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); } break; } case GE_CMD_VADDR: - { gstate.cmdmem[GE_CMD_VADDR] = data; - uint32_t newAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); - if (gstate_c.vertexAddr != newAddr) { - canExtend = false; - gstate_c.vertexAddr = newAddr; - } + gstate_c.vertexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); break; - } case GE_CMD_IADDR: gstate.cmdmem[GE_CMD_IADDR] = data; gstate_c.indexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); @@ -1139,8 +1074,6 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { (Memory::ReadUnchecked_U32(target + 12 * 4) >> 24) == GE_CMD_RET && (target > currentList->stall || target + 12 * 4 < currentList->stall) && (gstate.boneMatrixNumber & 0x00FFFFFF) <= 96 - 12) { - drawEngineCommon_->FlushSkin(); - canExtend = false; FastLoadBoneMatrix(target); } else { goto bail; @@ -1158,13 +1091,12 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { // All other commands might need a flush or something, stop this inner loop. goto bail; } + cmdCount++; src++; } bail: - drawEngineCommon_->FlushSkin(); gstate.cmdmem[GE_CMD_VERTEXTYPE] = vertexType; - int cmdCount = src - start; // Skip over the commands we just read out manually. if (cmdCount > 0) { UpdatePC(currentList->pc, currentList->pc + cmdCount * 4); @@ -1180,13 +1112,14 @@ bail: } } - int cycles = vertexCost_ * totalVertCount; - gpuStats.vertexGPUCycles += cycles; - cyclesExecuted += cycles; + gpuStats.vertexGPUCycles += vertexCost_ * totalVertCount; + cyclesExecuted += vertexCost_ * totalVertCount; } void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { // We don't dirty on normal changes anymore as we prescale, but it's needed for splines/bezier. + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + gstate_c.framebufFormat = gstate.FrameBufFormat(); // This also make skipping drawing very effective. @@ -1233,8 +1166,7 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); - // We need to dirty UVSCALEOFFSET here because we look at the submit type when setting that uniform. - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { gstate_c.submitType = SubmitType::HW_BEZIER; if (gstate_c.spline_num_points_u != surface.num_points_u) { @@ -1249,7 +1181,7 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); gstate_c.submitType = SubmitType::DRAW; // After drawing, we advance pointers - see SubmitPrim which does the same. @@ -1259,6 +1191,8 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { // We don't dirty on normal changes anymore as we prescale, but it's needed for splines/bezier. + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + gstate_c.framebufFormat = gstate.FrameBufFormat(); // This also make skipping drawing very effective. @@ -1307,8 +1241,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); - // We need to dirty UVSCALEOFFSET here because we look at the submit type when setting that uniform. - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { gstate_c.submitType = SubmitType::HW_SPLINE; if (gstate_c.spline_num_points_u != surface.num_points_u) { @@ -1323,7 +1256,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); gstate_c.submitType = SubmitType::DRAW; // After drawing, we advance pointers - see SubmitPrim which does the same. @@ -1349,6 +1282,7 @@ void GPUCommonHW::Execute_TexSize0(u32 op, u32 diff) { if (diff || gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS)) { gstate_c.curTextureWidth = gstate.getTextureWidth(0); gstate_c.curTextureHeight = gstate.getTextureHeight(0); + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); // We will need to reset the texture now. gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } @@ -1405,7 +1339,7 @@ void GPUCommonHW::Execute_WorldMtxNum(u32 op, u32 diff) { if (dst[i] != newVal) { Flush(); dst[i] = newVal; - gstate_c.Dirty(DIRTY_WORLDMATRIX | DIRTY_CULL_PLANES); + gstate_c.Dirty(DIRTY_WORLDMATRIX); } if (++i >= end) { break; @@ -1428,7 +1362,7 @@ void GPUCommonHW::Execute_WorldMtxData(u32 op, u32 diff) { if (num < 12 && newVal != ((const u32 *)gstate.worldMatrix)[num]) { Flush(); ((u32 *)gstate.worldMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_WORLDMATRIX | DIRTY_CULL_PLANES); + gstate_c.Dirty(DIRTY_WORLDMATRIX); } num++; gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | (num & 0x00FFFFFF); @@ -1458,7 +1392,7 @@ void GPUCommonHW::Execute_ViewMtxNum(u32 op, u32 diff) { if (dst[i] != newVal) { Flush(); dst[i] = newVal; - gstate_c.Dirty(DIRTY_VIEWMATRIX | DIRTY_CULL_PLANES); + gstate_c.Dirty(DIRTY_VIEWMATRIX); } if (++i >= end) { break; @@ -1481,7 +1415,7 @@ void GPUCommonHW::Execute_ViewMtxData(u32 op, u32 diff) { if (num < 12 && newVal != ((const u32 *)gstate.viewMatrix)[num]) { Flush(); ((u32 *)gstate.viewMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_VIEWMATRIX | DIRTY_CULL_PLANES); + gstate_c.Dirty(DIRTY_VIEWMATRIX); } num++; gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | (num & 0x00FFFFFF); @@ -1511,7 +1445,7 @@ void GPUCommonHW::Execute_ProjMtxNum(u32 op, u32 diff) { if (dst[i] != newVal) { Flush(); dst[i] = newVal; - gstate_c.Dirty(DIRTY_PROJMATRIX | DIRTY_CULL_PLANES); + gstate_c.Dirty(DIRTY_PROJMATRIX); } if (++i >= end) { break; @@ -1534,7 +1468,7 @@ void GPUCommonHW::Execute_ProjMtxData(u32 op, u32 diff) { if (num < 16 && newVal != ((const u32 *)gstate.projMatrix)[num]) { Flush(); ((u32 *)gstate.projMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_PROJMATRIX | DIRTY_CULL_PLANES); + gstate_c.Dirty(DIRTY_PROJMATRIX); } num++; if (num <= 16) @@ -1684,25 +1618,25 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; return snprintf(buffer, size, "DL processing time: %0.2f ms, %d drawsync, %d listsync\n" - "Draw: %d (%d dec), flushes %d, clears %d, bbox jumps %d (%d updates)\n" - "Vertices: %d drawn: %d\n" + "Draw calls: %d, flushes %d, clears %d (cached: %d)\n" + "Num Tracked Vertex Arrays: %d\n" + "Vertices: %d cached: %d uncached: %d\n" "FBOs active: %d (evaluations: %d)\n" "Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n" - "readbacks %d (%d non-block), upload %d (cached %d), depal %d\n" - "block transfers: %d\n" + "readbacks %d (%d non-block), uploads %d, depal %d\n" "replacer: tracks %d references, %d unique textures\n" - "Cpy: depth %d, color %d, reint %d, blend %d, self %d\n" - "GPU cycles: %d (%0.1f per vertex)\n%s", + "Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n" + "GPU cycles executed: %d (%f per vertex)\n", gpuStats.msProcessingDisplayLists * 1000.0f, gpuStats.numDrawSyncs, gpuStats.numListSyncs, gpuStats.numDrawCalls, - gpuStats.numVertexDecodes, gpuStats.numFlushes, gpuStats.numClears, - gpuStats.numBBOXJumps, - gpuStats.numPlaneUpdates, + gpuStats.numCachedDrawCalls, + gpuStats.numTrackedVertexArrays, gpuStats.numVertsSubmitted, + gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, (int)framebufferManager_->NumVFBs(), gpuStats.numFramebufferEvaluations, @@ -1713,9 +1647,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { gpuStats.numBlockingReadbacks, gpuStats.numReadbacks, gpuStats.numUploads, - gpuStats.numCachedUploads, gpuStats.numDepal, - gpuStats.numBlockTransfers, gpuStats.numReplacerTrackedTex, gpuStats.numCachedReplacedTextures, gpuStats.numDepthCopies, @@ -1724,7 +1656,6 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { gpuStats.numCopiesForShaderBlend, gpuStats.numCopiesForSelfTex, gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, - vertexAverageCycles, - debugRecording_ ? "(debug-recording)" : "" + vertexAverageCycles ); } diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index fb536893c..6ab7151f5 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -23,7 +23,7 @@ public: bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; - std::vector GetFramebufferList() const override; + std::vector GetFramebufferList() const override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; @@ -83,10 +83,7 @@ protected: void BuildReportingInfo() override; void UpdateMSAALevel(Draw::DrawContext *draw) override; - void CheckDisplayResized() override; void CheckRenderResized() override; - void CheckConfigChanged() override; - u32 CheckGPUFeaturesLate(u32 features) const; int msaaLevel_ = 0; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 496b23057..d48713942 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -31,7 +31,6 @@ struct PspGeListArgs; struct GPUgstate; class PointerWrap; -struct VirtualFramebuffer; enum DisplayListStatus { // The list has been completed @@ -127,6 +126,16 @@ enum class GPUCopyFlag { }; ENUM_CLASS_BITOPS(GPUCopyFlag); +// Used for debug +struct FramebufferInfo { + u32 fb_address; + u32 z_address; + int format; + u32 width; + u32 height; + void* fbo; +}; + struct DisplayListStackEntry { u32 pc; u32 offsetAddr; @@ -181,6 +190,8 @@ public: virtual Draw::DrawContext *GetDrawContext() = 0; // Initialization + virtual bool IsReady() = 0; + virtual void CancelReady() = 0; virtual bool IsStarted() = 0; virtual void Reinitialize() = 0; @@ -262,7 +273,7 @@ public: virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0; virtual const std::list& GetDisplayLists() = 0; // TODO: Currently Qt only, needs to be cleaned up. - virtual std::vector GetFramebufferList() const = 0; + virtual std::vector GetFramebufferList() const = 0; virtual s64 GetListTicks(int listid) const = 0; // For debugging. The IDs returned are opaque, do not poke in them or display them in any way. diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 94bc154c6..28c13b871 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -128,8 +128,6 @@ void GPUgstate::Reset() { memset(gstate.boneMatrix, 0, sizeof(gstate.boneMatrix)); savedContextVersion = 1; - - gstate_c.Dirty(DIRTY_CULL_PLANES); } void GPUgstate::Save(u32_le *ptr) { @@ -260,8 +258,6 @@ void GPUgstate::Restore(const u32_le *ptr) { if (gpu) gpu->ResetMatrices(); - - gstate_c.Dirty(DIRTY_CULL_PLANES); } bool vertTypeIsSkinningEnabled(u32 vertType) { @@ -370,9 +366,6 @@ void GPUStateCache::DoState(PointerWrap &p) { } else { Do(p, savedContextVersion); } - - if (p.GetMode() == PointerWrap::MODE_READ) - gstate_c.Dirty(DIRTY_CULL_PLANES); } static const char *const gpuUseFlagNames[32] = { @@ -382,7 +375,7 @@ static const char *const gpuUseFlagNames[32] = { "GPU_USE_VS_RANGE_CULLING", "GPU_USE_BLEND_MINMAX", "GPU_USE_LOGIC_OP", - "GPU_USE_FRAGMENT_UBERSHADER", + "N/A", "GPU_USE_TEXTURE_NPOT", "GPU_USE_ANISOTROPY", "GPU_USE_CLEAR_RAM_HACK", diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 6b1446c5e..9f7e46432 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -478,7 +478,7 @@ enum { GPU_USE_VS_RANGE_CULLING = FLAG_BIT(3), GPU_USE_BLEND_MINMAX = FLAG_BIT(4), GPU_USE_LOGIC_OP = FLAG_BIT(5), - GPU_USE_FRAGMENT_UBERSHADER = FLAG_BIT(6), + // Bit 6 is free. GPU_USE_TEXTURE_NPOT = FLAG_BIT(7), GPU_USE_ANISOTROPY = FLAG_BIT(8), GPU_USE_CLEAR_RAM_HACK = FLAG_BIT(9), @@ -491,7 +491,7 @@ enum { GPU_USE_DEPTH_TEXTURE = FLAG_BIT(16), GPU_USE_ACCURATE_DEPTH = FLAG_BIT(17), GPU_USE_GS_CULLING = FLAG_BIT(18), // Geometry shader - GPU_USE_FRAMEBUFFER_ARRAYS = FLAG_BIT(19), + // Bit 19 free. GPU_USE_FRAMEBUFFER_FETCH = FLAG_BIT(20), GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT = FLAG_BIT(21), GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT = FLAG_BIT(22), @@ -569,8 +569,8 @@ struct GPUStateCache { } } void SetTextureIsArray(bool isArrayTexture) { // VK only - if (textureIsArray != isArrayTexture) { - textureIsArray = isArrayTexture; + if (arrayTexture != isArrayTexture) { + arrayTexture = isArrayTexture; Dirty(DIRTY_FRAGMENTSHADER_STATE); } } @@ -580,17 +580,6 @@ struct GPUStateCache { Dirty(DIRTY_FRAGMENTSHADER_STATE); } } - void SetTextureIsFramebuffer(bool isFramebuffer) { - if (textureIsFramebuffer != isFramebuffer) { - textureIsFramebuffer = isFramebuffer; - Dirty(DIRTY_UVSCALEOFFSET); - } else if (isFramebuffer) { - // Always dirty if it's a framebuffer, since the uniform value depends both - // on the specified texture size and the bound texture size. Makes things easier. - // TODO: Look at this again later. - Dirty(DIRTY_UVSCALEOFFSET); - } - } void SetUseFlags(u32 newFlags) { if (newFlags != useFlags_) { if (useFlags_ != 0) @@ -625,8 +614,7 @@ public: bool bgraTexture; bool needShaderTexClamp; - bool textureIsArray; - bool textureIsFramebuffer; + bool arrayTexture; bool useFlagsChanged; float morphWeights[8]; diff --git a/GPU/GeDisasm.h b/GPU/GeDisasm.h index aff2d7384..7a7949e21 100644 --- a/GPU/GeDisasm.h +++ b/GPU/GeDisasm.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - #include "Common/CommonTypes.h" void GeDescribeVertexType(u32 op, char *buffer, int len = 256); diff --git a/GPU/Math3D.h b/GPU/Math3D.h index b9af0a7e4..6309801c4 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -43,29 +43,6 @@ #define MATH3D_CALL #endif -// There's probably a better place to define these macros. -#if PPSSPP_ARCH(X86) -// On 32-bit x86, MSVC does not guarantee alignment for -// SSE arguments passed on stack (Compiler Error C2719), see e.g.: -// https://stackoverflow.com/questions/10484422/msvc-cannot-send-function-parameters-of-16byte-alignment-on-x86 -// https://stackoverflow.com/questions/28488986/formal-parameter-with-declspecalign16-wont-be-aligned -// So, as a workaround, "dangerous" cases are loaded via loadu* on 32-bit x86. -// Compilers are decently ok at eliminating these extra loads, at least -// in trivial cases. -// NOTE: not to be outdone, GCC has its own flavor of broken, see e.g.: -// http://www.peterstock.co.uk/games/mingw_sse/ -// https://github.com/nothings/stb/issues/81 -// which is probably worse since it breaks alignment of locals and/or -// spills, but that, hopefully, does not affect PPSSPP (modern GCC+Linux -// is 16-byte aligned on x86, and MinGW is not a supported PPSSPP target). -// NOTE: weird double-casts add a bit of type-safety. -#define SAFE_M128(v) _mm_loadu_ps (reinterpret_cast (static_cast (&(v)))) -#define SAFE_M128I(v) _mm_loadu_si128(reinterpret_cast(static_cast(&(v)))) -#else // x64, FWIW also works for non-x86. -#define SAFE_M128(v) (v) -#define SAFE_M128I(v) (v) -#endif - namespace Math3D { // Helper for Vec classes to clamp values. @@ -219,7 +196,7 @@ public: #if defined(_M_SSE) __m128i ivec; __m128 vec; -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) int32x4_t ivec; float32x4_t vec; #endif @@ -238,7 +215,7 @@ public: Vec3(const Vec3Packed &_xyz) { vec = _mm_loadu_ps(_xyz.AsArray()); } -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) Vec3(const float32x4_t &_vec) : vec(_vec) {} #if !defined(_MSC_VER) Vec3(const int32x4_t &_ivec) : ivec(_ivec) {} @@ -578,7 +555,7 @@ public: #if defined(_M_SSE) __m128i ivec; __m128 vec; -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) int32x4_t ivec; float32x4_t vec; #endif @@ -595,7 +572,7 @@ public: #if defined(_M_SSE) Vec4(const __m128 &_vec) : vec(_vec) {} Vec4(const __m128i &_ivec) : ivec(_ivec) {} -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) Vec4(const float32x4_t &_vec) : vec(_vec) {} #if !defined(_MSC_VER) Vec4(const int32x4_t &_ivec) : ivec(_ivec) {} @@ -603,21 +580,8 @@ public: #endif template - Vec4 Cast() const { - if constexpr (std::is_same::value && std::is_same::value) { -#if defined(_M_SSE) - return _mm_cvtps_epi32(SAFE_M128(vec)); -#elif PPSSPP_ARCH(ARM_NEON) - return vcvtq_s32_f32(vec); -#endif - } - if constexpr (std::is_same::value && std::is_same::value) { -#if defined(_M_SSE) - return _mm_cvtepi32_ps(SAFE_M128I(ivec)); -#elif PPSSPP_ARCH(ARM_NEON) - return vcvtq_f32_s32(ivec); -#endif - } + Vec4 Cast() const + { return Vec4((T2)x, (T2)y, (T2)z, (T2)w); } @@ -665,20 +629,6 @@ public: { return Vec4(x | other.x, y | other.y, z | other.z, w | other.w); } - Vec4 operator & (const Vec4 &other) const - { - return Vec4(x & other.x, y & other.y, z & other.z, w & other.w); - } - Vec4 operator << (const int amount) const - { - // NOTE: x*(1<> (const int amount) const - { - return Vec4(x >> amount, y >> amount, z >> amount, w >> amount); - } template Vec4 operator * (const V& f) const { @@ -922,7 +872,7 @@ inline __m128 MATH3D_CALL Vec3ByMatrix43Internal(__m128 x, __m128 y, __m128 z, c _mm_add_ps(_mm_mul_ps(col2, z), col3)); return sum; } -#elif PPSSPP_ARCH(ARM64_NEON) +#elif PPSSPP_ARCH(ARM_NEON) && PPSSPP_ARCH(ARM64) inline float32x4_t Vec3ByMatrix43Internal(float32x4_t vec, const float m[16]) { float32x4_t col0 = vld1q_f32(m); float32x4_t col1 = vld1q_f32(m + 3); @@ -933,17 +883,6 @@ inline float32x4_t Vec3ByMatrix43Internal(float32x4_t vec, const float m[16]) { vaddq_f32(vmulq_laneq_f32(col2, vec, 2), col3)); return sum; } -#elif PPSSPP_ARCH(ARM_NEON) -inline float32x4_t Vec3ByMatrix43Internal(float32x4_t vec, const float m[16]) { - float32x4_t col0 = vld1q_f32(m); - float32x4_t col1 = vld1q_f32(m + 3); - float32x4_t col2 = vld1q_f32(m + 6); - float32x4_t col3 = vld1q_f32(m + 9); - float32x4_t sum = vaddq_f32( - vaddq_f32(vmulq_lane_f32(col0, vget_low_f32(vec), 0), vmulq_lane_f32(col1, vget_low_f32(vec), 1)), - vaddq_f32(vmulq_lane_f32(col2, vget_high_f32(vec), 0), col3)); - return sum; -} #endif // v and vecOut must point to different memory. @@ -958,7 +897,7 @@ inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) vecOut[0] = _mm_cvtss_f32(sum); vecOut[1] = vectorGetByIndex<1>(sum); vecOut[2] = vectorGetByIndex<2>(sum); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) float vecIn[4] = {v[0], v[1], v[2], 1.0f}; float32x4_t sum = Vec3ByMatrix43Internal(vld1q_f32(vecIn), m); vecOut[0] = vgetq_lane_f32(sum, 0); @@ -972,13 +911,12 @@ inline void Vec3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) } inline Vec3f MATH3D_CALL Vec3ByMatrix43(const Vec3f v, const float m[12]) { -#if defined(_M_SSE) - const __m128 vv = SAFE_M128(v.vec); - __m128 x = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(0, 0, 0, 0)); - __m128 y = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(1, 1, 1, 1)); - __m128 z = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(2, 2, 2, 2)); +#if defined(_M_SSE) && PPSSPP_ARCH(64BIT) + __m128 x = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 y = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 z = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(2, 2, 2, 2)); return Vec3ByMatrix43Internal(x, y, z, m); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) return Vec3ByMatrix43Internal(v.vec, m); #else Vec3f vecOut; @@ -1010,17 +948,6 @@ inline float32x4_t Vec3ByMatrix44Internal(float32x4_t vec, const float m[16]) { vaddq_f32(vmulq_laneq_f32(col2, vec, 2), col3)); return sum; } -#elif PPSSPP_ARCH(ARM_NEON) -inline float32x4_t Vec3ByMatrix44Internal(float32x4_t vec, const float m[16]) { - float32x4_t col0 = vld1q_f32(m); - float32x4_t col1 = vld1q_f32(m + 4); - float32x4_t col2 = vld1q_f32(m + 8); - float32x4_t col3 = vld1q_f32(m + 12); - float32x4_t sum = vaddq_f32( - vaddq_f32(vmulq_lane_f32(col0, vget_low_f32(vec), 0), vmulq_lane_f32(col1, vget_low_f32(vec), 1)), - vaddq_f32(vmulq_lane_f32(col2, vget_high_f32(vec), 0), col3)); - return sum; -} #endif inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16]) { @@ -1030,7 +957,7 @@ inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16]) __m128 z = _mm_set1_ps(v[2]); __m128 sum = Vec3ByMatrix44Internal(x, y, z, m); _mm_storeu_ps(vecOut, sum); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) float vecIn[4] = {v[0], v[1], v[2], 1.0f}; float32x4_t sum = Vec3ByMatrix44Internal(vld1q_f32(vecIn), m); vst1q_f32(vecOut, sum); @@ -1043,13 +970,12 @@ inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16]) } inline Vec4f MATH3D_CALL Vec3ByMatrix44(const Vec3f v, const float m[16]) { -#if defined(_M_SSE) - const __m128 vv = SAFE_M128(v.vec); - __m128 x = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(0, 0, 0, 0)); - __m128 y = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(1, 1, 1, 1)); - __m128 z = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(2, 2, 2, 2)); +#if defined(_M_SSE) && PPSSPP_ARCH(64BIT) + __m128 x = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 y = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 z = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(2, 2, 2, 2)); return Vec3ByMatrix44Internal(x, y, z, m); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) return Vec3ByMatrix44Internal(v.vec, m); #else Vec4f vecOut; @@ -1079,16 +1005,6 @@ inline float32x4_t Norm3ByMatrix43Internal(float32x4_t vec, const float m[16]) { vmulq_laneq_f32(col2, vec, 2)); return sum; } -#elif PPSSPP_ARCH(ARM_NEON) -inline float32x4_t Norm3ByMatrix43Internal(float32x4_t vec, const float m[16]) { - float32x4_t col0 = vld1q_f32(m); - float32x4_t col1 = vld1q_f32(m + 3); - float32x4_t col2 = vld1q_f32(m + 6); - float32x4_t sum = vaddq_f32( - vaddq_f32(vmulq_lane_f32(col0, vget_low_f32(vec), 0), vmulq_lane_f32(col1, vget_low_f32(vec), 1)), - vmulq_lane_f32(col2, vget_high_f32(vec), 0)); - return sum; -} #endif inline void Norm3ByMatrix43(float vecOut[3], const float v[3], const float m[12]) { @@ -1100,7 +1016,7 @@ inline void Norm3ByMatrix43(float vecOut[3], const float v[3], const float m[12] vecOut[0] = _mm_cvtss_f32(sum); vecOut[1] = vectorGetByIndex<1>(sum); vecOut[2] = vectorGetByIndex<2>(sum); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) float32x4_t sum = Norm3ByMatrix43Internal(vld1q_f32(v), m); vecOut[0] = vgetq_lane_f32(sum, 0); vecOut[1] = vgetq_lane_f32(sum, 1); @@ -1113,13 +1029,12 @@ inline void Norm3ByMatrix43(float vecOut[3], const float v[3], const float m[12] } inline Vec3f MATH3D_CALL Norm3ByMatrix43(const Vec3f v, const float m[12]) { -#if defined(_M_SSE) - const __m128 vv = SAFE_M128(v.vec); - __m128 x = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(0, 0, 0, 0)); - __m128 y = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(1, 1, 1, 1)); - __m128 z = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(2, 2, 2, 2)); +#if defined(_M_SSE) && PPSSPP_ARCH(64BIT) + __m128 x = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 y = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 z = _mm_shuffle_ps(v.vec, v.vec, _MM_SHUFFLE(2, 2, 2, 2)); return Norm3ByMatrix43Internal(x, y, z, m); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) return Norm3ByMatrix43Internal(v.vec, m); #else Vec3f vecOut; @@ -1152,13 +1067,6 @@ inline void ConvertMatrix4x3To4x4(float *m4x4, const float *m4x3) { } inline void ConvertMatrix4x3To4x4Transposed(float *m4x4, const float *m4x3) { -#if PPSSPP_ARCH(ARM_NEON) - // vld3q is a perfect match here! - float32x4x3_t packed = vld3q_f32(m4x3); - vst1q_f32(m4x4, packed.val[0]); - vst1q_f32(m4x4 + 4, packed.val[1]); - vst1q_f32(m4x4 + 8, packed.val[2]); -#else m4x4[0] = m4x3[0]; m4x4[1] = m4x3[3]; m4x4[2] = m4x3[6]; @@ -1171,7 +1079,6 @@ inline void ConvertMatrix4x3To4x4Transposed(float *m4x4, const float *m4x3) { m4x4[9] = m4x3[5]; m4x4[10] = m4x3[8]; m4x4[11] = m4x3[11]; -#endif m4x4[12] = 0.0f; m4x4[13] = 0.0f; m4x4[14] = 0.0f; @@ -1187,13 +1094,6 @@ inline void ConvertMatrix4x3To4x4Transposed(float *m4x4, const float *m4x3) { // 89AB // Don't see a way to SIMD that. Should be pretty fast anyway. inline void ConvertMatrix4x3To3x4Transposed(float *m4x4, const float *m4x3) { -#if PPSSPP_ARCH(ARM_NEON) - // vld3q is a perfect match here! - float32x4x3_t packed = vld3q_f32(m4x3); - vst1q_f32(m4x4, packed.val[0]); - vst1q_f32(m4x4 + 4, packed.val[1]); - vst1q_f32(m4x4 + 8, packed.val[2]); -#else m4x4[0] = m4x3[0]; m4x4[1] = m4x3[3]; m4x4[2] = m4x3[6]; @@ -1206,7 +1106,6 @@ inline void ConvertMatrix4x3To3x4Transposed(float *m4x4, const float *m4x3) { m4x4[9] = m4x3[5]; m4x4[10] = m4x3[8]; m4x4[11] = m4x3[11]; -#endif } inline void Transpose4x4(float out[16], const float in[16]) { @@ -1217,6 +1116,11 @@ inline void Transpose4x4(float out[16], const float in[16]) { } } +inline float Vec3Dot(const float v1[3], const float v2[3]) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + namespace Math3D { template @@ -1257,7 +1161,7 @@ inline Vec3 Vec3::FromRGB(unsigned int rgb) __m128i c = _mm_cvtsi32_si128(rgb); c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); return Vec3(_mm_mul_ps(_mm_cvtepi32_ps(c), _mm_set_ps1(1.0f / 255.0f))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint8x8_t c = vreinterpret_u8_u32(vdup_n_u32(rgb)); uint32x4_t u = vmovl_u16(vget_low_u16(vmovl_u8(c))); return Vec3(vmulq_f32(vcvtq_f32_u32(u), vdupq_n_f32(1.0f / 255.0f))); @@ -1276,7 +1180,7 @@ inline Vec3 Vec3::FromRGB(unsigned int rgb) __m128i c = _mm_cvtsi32_si128(rgb); c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); return Vec3(c); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint8x8_t c = vreinterpret_u8_u32(vdup_n_u32(rgb)); uint32x4_t u = vmovl_u16(vget_low_u16(vmovl_u8(c))); return Vec3(vreinterpretq_s32_u32(u)); @@ -1289,10 +1193,14 @@ template<> __forceinline unsigned int Vec3::ToRGB() const { #if defined(_M_SSE) - __m128i c = _mm_cvtps_epi32(_mm_mul_ps(SAFE_M128(vec), _mm_set_ps1(255.0f))); +#if PPSSPP_ARCH(64BIT) + __m128i c = _mm_cvtps_epi32(_mm_mul_ps(vec, _mm_set_ps1(255.0f))); +#else + __m128i c = _mm_cvtps_epi32(_mm_mul_ps(_mm_loadu_ps((float *)&vec), _mm_set_ps1(255.0f))); +#endif __m128i c16 = _mm_packs_epi32(c, c); return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)) & 0x00FFFFFF; -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint16x4_t c16 = vqmovun_s32(vcvtq_s32_f32(vmulq_f32(vsetq_lane_f32(0.0f, vec, 3), vdupq_n_f32(255.0f)))); uint8x8_t c8 = vqmovn_u16(vcombine_u16(c16, c16)); return vget_lane_u32(vreinterpret_u32_u8(c8), 0); @@ -1307,9 +1215,13 @@ template<> __forceinline unsigned int Vec3::ToRGB() const { #if defined(_M_SSE) - __m128i c16 = _mm_packs_epi32(SAFE_M128I(ivec), SAFE_M128I(ivec)); +#if PPSSPP_ARCH(64BIT) + __m128i c16 = _mm_packs_epi32(ivec, ivec); +#else + __m128i c16 = _mm_packs_epi32(_mm_loadu_si128(&ivec), _mm_setzero_si128()); +#endif return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)) & 0x00FFFFFF; -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint16x4_t c16 = vqmovun_s32(vsetq_lane_s32(0, ivec, 3)); uint8x8_t c8 = vqmovn_u16(vcombine_u16(c16, c16)); return vget_lane_u32(vreinterpret_u32_u8(c8), 0); @@ -1326,7 +1238,7 @@ inline Vec4 Vec4::FromRGBA(unsigned int rgba) __m128i c = _mm_cvtsi32_si128(rgba); c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); return Vec4(_mm_mul_ps(_mm_cvtepi32_ps(c), _mm_set_ps1(1.0f / 255.0f))); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint8x8_t c = vreinterpret_u8_u32(vdup_n_u32(rgba)); uint32x4_t u = vmovl_u16(vget_low_u16(vmovl_u8(c))); return Vec4(vmulq_f32(vcvtq_f32_u32(u), vdupq_n_f32(1.0f / 255.0f))); @@ -1352,7 +1264,7 @@ inline Vec4 Vec4::FromRGBA(unsigned int rgba) __m128i c = _mm_cvtsi32_si128(rgba); c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); return Vec4(c); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint8x8_t c = vreinterpret_u8_u32(vdup_n_u32(rgba)); uint32x4_t u = vmovl_u16(vget_low_u16(vmovl_u8(c))); return Vec4(vreinterpretq_s32_u32(u)); @@ -1365,10 +1277,14 @@ template<> __forceinline unsigned int Vec4::ToRGBA() const { #if defined(_M_SSE) - __m128i c = _mm_cvtps_epi32(_mm_mul_ps(SAFE_M128(vec), _mm_set_ps1(255.0f))); +#if PPSSPP_ARCH(64BIT) + __m128i c = _mm_cvtps_epi32(_mm_mul_ps(vec, _mm_set_ps1(255.0f))); +#else + __m128i c = _mm_cvtps_epi32(_mm_mul_ps(_mm_loadu_ps((float *)&vec), _mm_set_ps1(255.0f))); +#endif __m128i c16 = _mm_packs_epi32(c, c); return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint16x4_t c16 = vqmovun_s32(vcvtq_s32_f32(vmulq_f32(vec, vdupq_n_f32(255.0f)))); uint8x8_t c8 = vqmovn_u16(vcombine_u16(c16, c16)); return vget_lane_u32(vreinterpret_u32_u8(c8), 0); @@ -1384,9 +1300,13 @@ template<> __forceinline unsigned int Vec4::ToRGBA() const { #if defined(_M_SSE) - __m128i c16 = _mm_packs_epi32(SAFE_M128I(ivec), SAFE_M128I(ivec)); +#if PPSSPP_ARCH(64BIT) + __m128i c16 = _mm_packs_epi32(ivec, ivec); +#else + __m128i c16 = _mm_packs_epi32(_mm_loadu_si128(&ivec), _mm_setzero_si128()); +#endif return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)); -#elif PPSSPP_ARCH(ARM_NEON) +#elif PPSSPP_ARCH(ARM64_NEON) uint16x4_t c16 = vqmovun_s32(ivec); uint8x8_t c8 = vqmovn_u16(vcombine_u16(c16, c16)); return vget_lane_u32(vreinterpret_u32_u8(c8), 0); @@ -1406,120 +1326,60 @@ __forceinline void Vec4::ToRGBA(u8 *rgba) const // Vec3 operation template<> -inline void Vec3::operator += (const Vec3 &other) { - vec = _mm_add_ps(SAFE_M128(vec), SAFE_M128(other.vec)); +inline void Vec3::operator += (const Vec3 &other) +{ + vec = _mm_add_ps(vec, other.vec); } template<> -inline Vec3 Vec3::operator + (const Vec3 &other) const { - return Vec3(_mm_add_ps(SAFE_M128(vec), SAFE_M128(other.vec))); +inline Vec3 Vec3::operator + (const Vec3 &other) const +{ + return Vec3(_mm_add_ps(vec, other.vec)); } template<> -inline void Vec3::operator -= (const Vec3 &other) { - vec = _mm_sub_ps(SAFE_M128(vec), SAFE_M128(other.vec)); -} - -template<> -inline Vec3 Vec3::operator - (const Vec3 &other) const { - return Vec3(_mm_sub_ps(SAFE_M128(vec), SAFE_M128(other.vec))); -} - -template<> -inline Vec3 Vec3::operator * (const Vec3 &other) const { - return Vec3(_mm_mul_ps(SAFE_M128(vec), SAFE_M128(other.vec))); +inline Vec3 Vec3::operator * (const Vec3 &other) const +{ + return Vec3(_mm_mul_ps(vec, other.vec)); } template<> template<> -inline Vec3 Vec3::operator * (const float &other) const { - return Vec3(_mm_mul_ps(SAFE_M128(vec), _mm_set_ps1(other))); -} - -// Vec4 operation -template<> -inline Vec4 Vec4::operator + (const Vec4 &other) const { - return Vec4(_mm_add_epi32(SAFE_M128I(ivec), SAFE_M128I(other.ivec))); -} - -template<> -inline Vec4 Vec4::operator * (const Vec4 &other) const { - __m128i a = SAFE_M128I(ivec); - __m128i b = SAFE_M128I(other.ivec); - // Intel in its immense wisdom decided that - // SSE2 does not get _mm_mullo_epi32(), - // so we do it this way. This is what clang does, - // which seems about as good as it gets. - __m128i m02 = _mm_mul_epu32(a, b); - __m128i m13 = _mm_mul_epu32( - _mm_shuffle_epi32(a, _MM_SHUFFLE(3, 3, 1, 1)), - _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1))); - __m128i ret = _mm_unpacklo_epi32( - _mm_shuffle_epi32(m02, _MM_SHUFFLE(3, 2, 2, 0)), - _mm_shuffle_epi32(m13, _MM_SHUFFLE(3, 2, 2, 0))); - return Vec4(ret); -} - -template<> template<> -inline Vec4 Vec4::operator * (const int &other) const { - return (*this) * Vec4(_mm_set1_epi32(other)); -} - -template<> -inline Vec4 Vec4::operator | (const Vec4 &other) const { - return Vec4(_mm_or_si128(SAFE_M128I(ivec), SAFE_M128I(other.ivec))); -} - -template<> -inline Vec4 Vec4::operator & (const Vec4 &other) const { - return Vec4(_mm_and_si128(SAFE_M128I(ivec), SAFE_M128I(other.ivec))); -} - -// NOTE: modern GCC, clang, and MSVC are all ok with -// non-compile-time-const amount for _mm_slli_epi32/_mm_srli_epi32. -template<> -inline Vec4 Vec4::operator << (const int amount) const { - return Vec4(_mm_slli_epi32(SAFE_M128I(ivec), amount)); -} - -template<> -inline Vec4 Vec4::operator >> (const int amount) const { - return Vec4(_mm_srli_epi32(SAFE_M128I(ivec), amount)); +inline Vec3 Vec3::operator * (const float &other) const +{ + return Vec3(_mm_mul_ps(vec, _mm_set_ps1(other))); } // Vec4 operation template<> -inline void Vec4::operator += (const Vec4 &other) { - vec = _mm_add_ps(SAFE_M128(vec), SAFE_M128(other.vec)); +inline void Vec4::operator += (const Vec4 &other) +{ + vec = _mm_add_ps(vec, other.vec); } template<> -inline Vec4 Vec4::operator + (const Vec4 &other) const { - return Vec4(_mm_add_ps(SAFE_M128(vec), SAFE_M128(other.vec))); +inline Vec4 Vec4::operator + (const Vec4 &other) const +{ + return Vec4(_mm_add_ps(vec, other.vec)); } template<> -inline Vec4 Vec4::operator * (const Vec4 &other) const { - return Vec4(_mm_mul_ps(SAFE_M128(vec), SAFE_M128(other.vec))); +inline Vec4 Vec4::operator * (const Vec4 &other) const +{ + return Vec4(_mm_mul_ps(vec, other.vec)); } template<> template<> -inline Vec4 Vec4::operator * (const float &other) const { - return Vec4(_mm_mul_ps(SAFE_M128(vec), _mm_set_ps1(other))); +inline Vec4 Vec4::operator * (const float &other) const +{ + return Vec4(_mm_mul_ps(vec, _mm_set_ps1(other))); } // Vec3 cross product template<> inline Vec3 Cross(const Vec3 &a, const Vec3 &b) { -#if PPSSPP_ARCH(X86) - __m128 avec = _mm_loadu_ps(&a.x); - __m128 bvec = _mm_loadu_ps(&b.x); -#else - __m128 avec = a.vec; - __m128 bvec = b.vec; -#endif - const __m128 left = _mm_mul_ps(_mm_shuffle_ps(avec, avec, _MM_SHUFFLE(3, 0, 2, 1)), _mm_shuffle_ps(bvec, bvec, _MM_SHUFFLE(3, 1, 0, 2))); - const __m128 right = _mm_mul_ps(_mm_shuffle_ps(avec, avec, _MM_SHUFFLE(3, 1, 0, 2)), _mm_shuffle_ps(bvec, bvec, _MM_SHUFFLE(3, 0, 2, 1))); + const __m128 left = _mm_mul_ps(_mm_shuffle_ps(a.vec, a.vec, _MM_SHUFFLE(3, 0, 2, 1)), _mm_shuffle_ps(b.vec, b.vec, _MM_SHUFFLE(3, 1, 0, 2))); + const __m128 right = _mm_mul_ps(_mm_shuffle_ps(a.vec, a.vec, _MM_SHUFFLE(3, 1, 0, 2)), _mm_shuffle_ps(b.vec, b.vec, _MM_SHUFFLE(3, 0, 2, 1))); return _mm_sub_ps(left, right); } #endif diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index ad0728599..2d96b1f24 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -405,7 +405,7 @@ void ProcessTriangle(const ClipVertexData &v0, const ClipVertexData &v1, const C ClipVertexData &subv1 = *Vertices[indices[i + 1]]; ClipVertexData &subv2 = *Vertices[indices[i + 2]]; - if (subv0.OutsideRange() || subv1.OutsideRange() || subv2.OutsideRange()) + if (subv0.OutsideRange() || subv1.OutsideRange() | subv2.OutsideRange()) continue; if (gstate.getShadeMode() == GE_SHADE_FLAT) { diff --git a/GPU/Software/DrawPixel.cpp b/GPU/Software/DrawPixel.cpp index ec5b3b707..eda04b0b4 100644 --- a/GPU/Software/DrawPixel.cpp +++ b/GPU/Software/DrawPixel.cpp @@ -844,7 +844,7 @@ void PixelJitCache::Flush() { for (const auto &queued : compileQueue_) { // Might've been compiled after enqueue, but before now. size_t queuedKey = std::hash()(queued); - if (!cache_.ContainsKey(queuedKey)) + if (!cache_.Get(queuedKey)) Compile(queued); } compileQueue_.clear(); @@ -859,10 +859,10 @@ SingleFunc PixelJitCache::GetSingle(const PixelFuncID &id, BinManager *binner) { return lastSingle_.func; std::unique_lock guard(jitCacheLock); - SingleFunc singleFunc; - if (cache_.Get(key, &singleFunc)) { - lastSingle_.Set(key, singleFunc, clearGen_); - return singleFunc; + auto it = cache_.Get(key); + if (it != nullptr) { + lastSingle_.Set(key, it, clearGen_); + return it; } if (!binner) { @@ -878,21 +878,18 @@ SingleFunc PixelJitCache::GetSingle(const PixelFuncID &id, BinManager *binner) { for (const auto &queued : compileQueue_) { // Might've been compiled after enqueue, but before now. size_t queuedKey = std::hash()(queued); - if (!cache_.ContainsKey(queuedKey)) + if (!cache_.Get(queuedKey)) Compile(queued); } compileQueue_.clear(); // Might've been in the queue. - if (!cache_.ContainsKey(key)) + if (!cache_.Get(key)) Compile(id); - if (cache_.Get(key, &singleFunc)) { - lastSingle_.Set(key, singleFunc, clearGen_); - return singleFunc; - } else { - return nullptr; - } + it = cache_.Get(key); + lastSingle_.Set(key, it, clearGen_); + return it; } void PixelJitCache::Compile(const PixelFuncID &id) { diff --git a/GPU/Software/DrawPixel.h b/GPU/Software/DrawPixel.h index e989e17e7..b0eae46ac 100644 --- a/GPU/Software/DrawPixel.h +++ b/GPU/Software/DrawPixel.h @@ -125,7 +125,7 @@ private: } }; - DenseHashMap cache_; + DenseHashMap cache_; std::unordered_map addresses_; std::unordered_set compileQueue_; static int clearGen_; diff --git a/GPU/Software/Lighting.cpp b/GPU/Software/Lighting.cpp index a19630cec..1709db488 100644 --- a/GPU/Software/Lighting.cpp +++ b/GPU/Software/Lighting.cpp @@ -86,13 +86,15 @@ void ComputeState(State *state, bool hasColor0) { bool anyAmbient = false; bool anyDiffuse = false; bool anySpecular = false; - bool anyNonDirectional = false; + bool anyDirectional = false; for (int light = 0; light < 4; ++light) { auto &lstate = state->lights[light]; lstate.enabled = gstate.isLightChanEnabled(light); if (!lstate.enabled) continue; + lstate.spot = gstate.isSpotLight(light); + lstate.directional = gstate.isDirectionalLight(light); lstate.poweredDiffuse = gstate.isUsingPoweredDiffuseLight(light); lstate.specular = gstate.isUsingSpecularLight(light); @@ -110,22 +112,14 @@ void ComputeState(State *state, bool hasColor0) { anySpecular = anySpecular || lstate.specular; } - // Doesn't actually need to be on if nothing will affect it. - if (!lstate.specular && !lstate.ambient && !lstate.diffuse) { - lstate.enabled = false; - continue; - } - lstate.pos = GetLightVec(gstate.lpos, light); - lstate.directional = gstate.isDirectionalLight(light); if (lstate.directional) { lstate.pos.NormalizeOr001(); + anyDirectional = true; } else { lstate.att = GetLightVec(gstate.latt, light); - anyNonDirectional = true; } - lstate.spot = gstate.isSpotLight(light); if (lstate.spot) { lstate.spotDir = GetLightVec(gstate.ldir, light); lstate.spotDir.Normalize(); @@ -183,7 +177,7 @@ void ComputeState(State *state, bool hasColor0) { state->baseAmbientColorFactor = LightColorFactor(gstate.getAmbientRGBA(), ones); state->setColor1 = gstate.isUsingSecondaryColor() && anySpecular; state->addColor1 = !gstate.isUsingSecondaryColor() && anySpecular; - state->usesWorldPos = anyNonDirectional; + state->usesWorldPos = anyDirectional; state->usesWorldNormal = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP || anyDiffuse || anySpecular; } @@ -221,14 +215,13 @@ static inline __m128i LightColorScaleBy512SSE4(__m128i factor, __m128i color, __ __m128i result18 = _mm_madd_epi16(factor, color); // But now with 18 bits, we need a full multiply. __m128i multiplied = _mm_mullo_epi32(result18, scale); - return _mm_srai_epi32(multiplied, 10 + 9); + return _mm_srai_epi32(multiplied, 19); } #endif -template static inline int LightCeil(float f) { #if defined(_M_SSE) - if (useSSE4) + if (cpu_info.bSSE4_1) return LightCeilSSE4(f); #elif PPSSPP_ARCH(ARM64_NEON) return vcvtps_s32_f32(f); @@ -236,19 +229,18 @@ static inline int LightCeil(float f) { return (int)ceilf(f); } -template static Vec4 LightColorScaleBy512(const Vec4 &factor, const Vec4 &color, int scale) { // We multiply s9 * s9 * s9, resulting in s27, then shift off 19 to get 8-bit. // The reason all factors are s9 is to account for rounding. // Also note that all values are positive, so can be treated as unsigned. #if defined(_M_SSE) && !PPSSPP_ARCH(X86) - if (useSSE4) + if (cpu_info.bSSE4_1) return LightColorScaleBy512SSE4(factor.ivec, color.ivec, _mm_set1_epi32(scale)); #elif PPSSPP_ARCH(ARM64_NEON) int32x4_t multiplied = vmulq_n_s32(vmulq_s32(factor.ivec, color.ivec), scale); - return vshrq_n_s32(multiplied, 10 + 9); + return vshrq_n_s32(multiplied, 19); #endif - return (factor * color * scale) >> (10 + 9); + return (factor * color * scale) / (1024 * 512); } static inline void LightColorSum(Vec4 &sum, const Vec4 &src) { @@ -261,25 +253,7 @@ static inline void LightColorSum(Vec4 &sum, const Vec4 &src) { #endif } -static inline float Dot33(const Vec3f &a, const Vec3f &b) { -#if defined(_M_SSE) - __m128 v = _mm_mul_ps(SAFE_M128(a.vec), SAFE_M128(b.vec)); // [X, Y, Z, W] - __m128 shuf = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 2, 0, 1)); // [Y, X, Z, W] - __m128 sums = _mm_add_ps(v, shuf); // [X + Y, X + Y, Z + Z, W + W] - shuf = _mm_movehl_ps(shuf, shuf); // [Z, W, Z, W] - return _mm_cvtss_f32(_mm_add_ss(sums, shuf)); // X + Y + Z -#elif PPSSPP_ARCH(ARM64_NEON) - float32x4_t multipled = vsetq_lane_f32(0.0f, vmulq_f32(a.vec, b.vec), 3); - float32x2_t add1 = vget_low_f32(vpaddq_f32(multipled, multipled)); - float32x2_t add2 = vpadd_f32(add1, add1); - return vget_lane_f32(add2, 0); -#else - return Dot(a, b); -#endif -} - -template -static void ProcessSIMD(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords &worldnormal, const State &state) { +void Process(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords &worldnormal, const State &state) { // Lighting blending rounds using the half offset method (like alpha blend.) const Vec4 ones = Vec4::AssignToAll(1); Vec4 colorFactor; @@ -289,7 +263,7 @@ static void ProcessSIMD(VertexData &vertex, const WorldCoords &worldpos, const W Vec4 mec = Vec4::FromRGBA(gstate.getMaterialEmissive()); Vec4 mac = state.colorForAmbient ? colorFactor : state.material.ambientColorFactor; - Vec4 ambient = (mac * state.baseAmbientColorFactor) >> 10; + Vec4 ambient = (mac * state.baseAmbientColorFactor) / 1024; Vec4 final_color = mec + ambient; Vec4 specular_color = Vec4::AssignToAll(0); @@ -302,26 +276,25 @@ static void ProcessSIMD(VertexData &vertex, const WorldCoords &worldpos, const W // L = vector from vertex to light source // TODO: Should transfer the light positions to world/view space for these calculations? Vec3 L = lstate.pos; - float attspot = 1.0f; + float att = 1.0f; if (!lstate.directional) { L -= worldpos; // TODO: Should this normalize (0, 0, 0) to (0, 0, 1)? float d = L.NormalizeOr001(); - float att = 1.0f / Dot33(lstate.att, Vec3f(1.0f, d, d * d)); + att = 1.0f / Dot(lstate.att, Vec3f(1.0f, d, d * d)); if (!(att > 0.0f)) att = 0.0f; else if (att > 1.0f) att = 1.0f; - attspot = att; } + float spot = 1.0f; if (lstate.spot) { - float rawSpot = Dot33(lstate.spotDir, L); + float rawSpot = Dot(lstate.spotDir, L); if (std::isnan(rawSpot)) rawSpot = std::signbit(rawSpot) ? 0.0f : 1.0f; - float spot = 1.0f; if (rawSpot >= lstate.spotCutoff) { spot = pspLightPow(rawSpot, lstate.spotExp); if (std::isnan(spot)) @@ -329,50 +302,48 @@ static void ProcessSIMD(VertexData &vertex, const WorldCoords &worldpos, const W } else { spot = 0.0f; } - - attspot *= spot; } // ambient lighting if (lstate.ambient) { - int attspot512 = (int)LightCeil(256 * 2 * attspot + 1); - if (attspot512 > 512) - attspot512 = 512; - Vec4 lambient = LightColorScaleBy512(lstate.ambientColorFactor, mac, attspot512); + int attspot = (int)LightCeil(256 * 2 * att * spot + 1); + if (attspot > 512) + attspot = 512; + Vec4 lambient = LightColorScaleBy512(lstate.ambientColorFactor, mac, attspot); LightColorSum(final_color, lambient); } // diffuse lighting float diffuse_factor; if (lstate.diffuse || lstate.specular) { - diffuse_factor = Dot33(L, worldnormal); + diffuse_factor = Dot(L, worldnormal); if (lstate.poweredDiffuse) { diffuse_factor = pspLightPow(diffuse_factor, state.specularExp); } } if (lstate.diffuse && diffuse_factor > 0.0f) { - int diffuse_attspot = (int)LightCeil(256 * 2 * attspot * diffuse_factor + 1); + int diffuse_attspot = (int)LightCeil(256 * 2 * att * spot * diffuse_factor + 1); if (diffuse_attspot > 512) diffuse_attspot = 512; Vec4 mdc = state.colorForDiffuse ? colorFactor : state.material.diffuseColorFactor; - Vec4 ldiffuse = LightColorScaleBy512(lstate.diffuseColorFactor, mdc, diffuse_attspot); + Vec4 ldiffuse = LightColorScaleBy512(lstate.diffuseColorFactor, mdc, diffuse_attspot); LightColorSum(final_color, ldiffuse); } if (lstate.specular && diffuse_factor >= 0.0f) { Vec3 H = L + Vec3(0.f, 0.f, 1.f); - float specular_factor = Dot33(H.NormalizedOr001(useSSE4), worldnormal); + float specular_factor = Dot(H.NormalizedOr001(cpu_info.bSSE4_1), worldnormal); specular_factor = pspLightPow(specular_factor, state.specularExp); if (specular_factor > 0.0f) { - int specular_attspot = (int)LightCeil(256 * 2 * attspot * specular_factor + 1); + int specular_attspot = (int)LightCeil(256 * 2 * att * spot * specular_factor + 1); if (specular_attspot > 512) specular_attspot = 512; Vec4 msc = state.colorForSpecular ? colorFactor : state.material.specularColorFactor; - Vec4 lspecular = LightColorScaleBy512(lstate.specularColorFactor, msc, specular_attspot); + Vec4 lspecular = LightColorScaleBy512(lstate.specularColorFactor, msc, specular_attspot); LightColorSum(specular_color, lspecular); } } @@ -389,14 +360,4 @@ static void ProcessSIMD(VertexData &vertex, const WorldCoords &worldpos, const W } } -void Process(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords &worldnormal, const State &state) { -#ifdef _M_SSE - if (cpu_info.bSSE4_1) { - ProcessSIMD(vertex, worldpos, worldnormal, state); - return; - } -#endif - ProcessSIMD(vertex, worldpos, worldnormal, state); -} - } // namespace diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index b4f924e19..dbb53dea7 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -543,7 +543,9 @@ static inline void GetTextureCoordinatesProj(const VertexData& v0, const VertexD float wq0 = p * q0; float wq1 = (1.0f - p) * q1; - float q_recip = 1.0f / (v0.texturecoords.q() * wq0 + v1.texturecoords.q() * wq1); + float q_recip = 1.0f / (wq0 + wq1); + float q = (v0.texturecoords.q() * wq0 + v1.texturecoords.q() * wq1) * q_recip; + q_recip *= 1.0f / q; s = (v0.texturecoords.s() * wq0 + v1.texturecoords.s() * wq1) * q_recip; t = (v0.texturecoords.t() * wq0 + v1.texturecoords.t() * wq1) * q_recip; @@ -572,9 +574,9 @@ static inline void GetTextureCoordinatesProj(const VertexData &v0, const VertexD Vec4 wq1 = w1.Cast() * q1; Vec4 wq2 = w2.Cast() * q2; - // Here, Interpolate() is a bit suboptimal, since - // there's no need to multiply by 1.0f. - Vec4 q_recip = Interpolate(v0.texturecoords.q(), v1.texturecoords.q(), v2.texturecoords.q(), wq0, wq1, wq2, Vec4::AssignToAll(1.0f)).Reciprocal(); + Vec4 q_recip = (wq0 + wq1 + wq2).Reciprocal(); + Vec4 q = Interpolate(v0.texturecoords.q(), v1.texturecoords.q(), v2.texturecoords.q(), wq0, wq1, wq2, q_recip); + q_recip = q_recip * q.Reciprocal(); s = Interpolate(v0.texturecoords.s(), v1.texturecoords.s(), v2.texturecoords.s(), wq0, wq1, wq2, q_recip); t = Interpolate(v0.texturecoords.t(), v1.texturecoords.t(), v2.texturecoords.t(), wq0, wq1, wq2, q_recip); @@ -685,101 +687,6 @@ static inline void ApplyTexturing(const RasterizerState &state, Vec4 *prim_ } } -static inline Vec4 SOFTRAST_CALL CheckDepthTestPassed4(const Vec4 &mask, GEComparison func, int x, int y, int stride, Vec4 z) { - // Skip the depth buffer read if we're masked already. -#if defined(_M_SSE) - __m128i result = SAFE_M128I(mask.ivec); - int maskbits = _mm_movemask_epi8(result); - if (maskbits >= 0xFFFF) - return mask; -#else - Vec4 result = mask; - if (mask.x < 0 && mask.y < 0 && mask.z < 0 && mask.w < 0) - return result; -#endif - - // Read in the existing depth values. -#if defined(_M_SSE) - // Tried using flags from maskbits to skip dwords... seemed neutral. - __m128i refz = _mm_cvtsi32_si128(*(u32 *)depthbuf.Get16Ptr(x, y, stride)); - refz = _mm_unpacklo_epi32(refz, _mm_cvtsi32_si128(*(u32 *)depthbuf.Get16Ptr(x, y + 1, stride))); - refz = _mm_unpacklo_epi16(refz, _mm_setzero_si128()); -#else - Vec4 refz(depthbuf.Get16(x, y, stride), depthbuf.Get16(x + 1, y, stride), depthbuf.Get16(x, y + 1, stride), depthbuf.Get16(x + 1, y + 1, stride)); -#endif - - switch (func) { - case GE_COMP_NEVER: -#if defined(_M_SSE) - result = _mm_set1_epi32(-1); -#else - result = Vec4::AssignToAll(-1); -#endif - break; - - case GE_COMP_ALWAYS: - break; - - case GE_COMP_EQUAL: -#if defined(_M_SSE) - result = _mm_or_si128(result, _mm_xor_si128(_mm_cmpeq_epi32(z.ivec, refz), _mm_set1_epi32(-1))); -#else - for (int i = 0; i < 4; ++i) - result[i] |= z[i] != refz[i] ? -1 : 0; -#endif - break; - - case GE_COMP_NOTEQUAL: -#if defined(_M_SSE) - result = _mm_or_si128(result, _mm_cmpeq_epi32(z.ivec, refz)); -#else - for (int i = 0; i < 4; ++i) - result[i] |= z[i] == refz[i] ? -1 : 0; -#endif - break; - - case GE_COMP_LESS: -#if defined(_M_SSE) - result = _mm_or_si128(result, _mm_cmpgt_epi32(z.ivec, refz)); - result = _mm_or_si128(result, _mm_cmpeq_epi32(z.ivec, refz)); -#else - for (int i = 0; i < 4; ++i) - result[i] |= z[i] >= refz[i] ? -1 : 0; -#endif - break; - - case GE_COMP_LEQUAL: -#if defined(_M_SSE) - result = _mm_or_si128(result, _mm_cmpgt_epi32(z.ivec, refz)); -#else - for (int i = 0; i < 4; ++i) - result[i] |= z[i] > refz[i] ? -1 : 0; -#endif - break; - - case GE_COMP_GREATER: -#if defined(_M_SSE) - result = _mm_or_si128(result, _mm_cmplt_epi32(z.ivec, refz)); - result = _mm_or_si128(result, _mm_cmpeq_epi32(z.ivec, refz)); -#else - for (int i = 0; i < 4; ++i) - result[i] |= z[i] <= refz[i] ? -1 : 0; -#endif - break; - - case GE_COMP_GEQUAL: -#if defined(_M_SSE) - result = _mm_or_si128(result, _mm_cmplt_epi32(z.ivec, refz)); -#else - for (int i = 0; i < 4; ++i) - result[i] |= z[i] < refz[i] ? -1 : 0; -#endif - break; - } - - return result; -} - template struct TriangleEdge { Vec4 Start(const ScreenCoords &v0, const ScreenCoords &v1, const ScreenCoords &origin); @@ -945,8 +852,11 @@ static inline bool AnyMask(const Vec4 &mask) { return AnyMaskSSE4(mask.ivec); } - // Source: https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/#comment-6676 - return _mm_movemask_ps(_mm_castsi128_ps(mask.ivec)) != 15; + // In other words: !(mask.x < 0 && mask.y < 0 && mask.z < 0 && mask.w < 0) + __m128i low2 = _mm_and_si128(mask.ivec, _mm_shuffle_epi32(mask.ivec, _MM_SHUFFLE(3, 2, 3, 2))); + __m128i low1 = _mm_and_si128(low2, _mm_shuffle_epi32(low2, _MM_SHUFFLE(1, 1, 1, 1))); + // Now we only need to check one sign bit. + return _mm_cvtsi128_si32(low1) >= 0; #elif PPSSPP_ARCH(ARM64_NEON) int64x2_t sig = vreinterpretq_s64_s32(vshrq_n_s32(mask.ivec, 31)); return vgetq_lane_s64(sig, 0) != -1 || vgetq_lane_s64(sig, 1) != -1; @@ -991,9 +901,6 @@ void DrawTriangleSlice( Vec4 w1_base = e1.Start(v2.screenpos, v0.screenpos, pprime); Vec4 w2_base = e2.Start(v0.screenpos, v1.screenpos, pprime); - // The sum of weights should remain constant as we move toward/away from the edges. - const Vec4 wsum_recip = EdgeRecip(w0_base, w1_base, w2_base); - // All the z values are the same, no interpolation required. // This is common, and when we interpolate, we lose accuracy. const bool flatZ = v0.screenpos.z == v1.screenpos.z && v0.screenpos.z == v2.screenpos.z; @@ -1020,12 +927,6 @@ void DrawTriangleSlice( const Vec3 v1_c1 = Vec3::FromRGB(v1.color1); const Vec3 v2_c1 = Vec3::FromRGB(v2.color1); - const Vec4 v0_z4 = Vec4::AssignToAll(v0.screenpos.z).Cast(); - const Vec4 v1_z4 = Vec4::AssignToAll(v1.screenpos.z).Cast(); - const Vec4 v2_z4 = Vec4::AssignToAll(v2.screenpos.z).Cast(); - const Vec4 minz = Vec4::AssignToAll(pixelID.cached.minz); - const Vec4 maxz = Vec4::AssignToAll(pixelID.cached.maxz); - for (int64_t curY = minY; curY <= maxY; curY += SCREEN_SCALE_FACTOR * 2, w0_base = e0.StepY(w0_base), w1_base = e1.StepY(w1_base), @@ -1062,29 +963,32 @@ void DrawTriangleSlice( // If p is on or inside all edges, render pixel Vec4 mask = MakeMask(w0, w1, w2, bias0, bias1, bias2, scissor_mask); if (AnyMask(mask)) { + Vec4 wsum_recip = EdgeRecip(w0, w1, w2); + Vec4 z; if (flatZ) { z = Vec4::AssignToAll(v2.screenpos.z); } else { // Z is interpolated pretty much directly. - Vec4 zfloats = w0.Cast() * v0_z4 + w1.Cast() * v1_z4 + w2.Cast() * v2_z4; + Vec4 zfloats = w0.Cast() * v0.screenpos.z + w1.Cast() * v1.screenpos.z + w2.Cast() * v2.screenpos.z; z = (zfloats * wsum_recip).Cast(); } if (pixelID.earlyZChecks) { - if (pixelID.applyDepthRange) { -#if defined(_M_SSE) - mask.ivec = _mm_or_si128(mask.ivec, _mm_or_si128(_mm_cmplt_epi32(z.ivec, minz.ivec), _mm_cmpgt_epi32(z.ivec, maxz.ivec))); -#else - for (int i = 0; i < 4; ++i) { - if (z[i] < minz[i] || z[i] > maxz[i]) + for (int i = 0; i < 4; ++i) { + if (pixelID.applyDepthRange) { + if (z[i] < pixelID.cached.minz || z[i] > pixelID.cached.maxz) mask[i] = -1; } -#endif + if (mask[i] < 0) + continue; + + int x = p.x + (i & 1); + int y = p.y + (i / 2); + if (!CheckDepthTestPassed(pixelID.DepthTestFunc(), x, y, pixelID.cached.depthbufStride, z[i])) { + mask[i] = -1; + } } - mask = CheckDepthTestPassed4(mask, pixelID.DepthTestFunc(), p.x, p.y, pixelID.cached.depthbufStride, z); - if (!AnyMask(mask)) - continue; } // Color interpolation is not perspective corrected on the PSP. diff --git a/GPU/Software/Sampler.cpp b/GPU/Software/Sampler.cpp index 60afbd39a..6793f9a00 100644 --- a/GPU/Software/Sampler.cpp +++ b/GPU/Software/Sampler.cpp @@ -166,7 +166,7 @@ void SamplerJitCache::Flush() { for (const auto &queued : compileQueue_) { // Might've been compiled after enqueue, but before now. size_t queuedKey = std::hash()(queued); - if (!cache_.ContainsKey(queuedKey)) + if (!cache_.Get(queuedKey)) Compile(queued); } compileQueue_.clear(); @@ -174,11 +174,9 @@ void SamplerJitCache::Flush() { NearestFunc SamplerJitCache::GetByID(const SamplerID &id, size_t key, BinManager *binner) { std::unique_lock guard(jitCacheLock); - - NearestFunc func; - if (cache_.Get(key, &func)) { - return func; - } + auto it = cache_.Get(key); + if (it != nullptr) + return it; if (!binner) { // Can't compile, let's try to do it later when there's an opportunity. @@ -193,20 +191,16 @@ NearestFunc SamplerJitCache::GetByID(const SamplerID &id, size_t key, BinManager for (const auto &queued : compileQueue_) { // Might've been compiled after enqueue, but before now. size_t queuedKey = std::hash()(queued); - if (!cache_.ContainsKey(queuedKey)) + if (!cache_.Get(queuedKey)) Compile(queued); } compileQueue_.clear(); - if (!cache_.ContainsKey(key)) + if (!cache_.Get(key)) Compile(id); // Okay, should be there now. - if (cache_.Get(key, &func)) { - return func; - } else { - return nullptr; - } + return cache_.Get(key); } NearestFunc SamplerJitCache::GetNearest(const SamplerID &id, BinManager *binner) { @@ -282,13 +276,13 @@ static inline int GetPixelDataOffset(uint32_t row_pitch_pixels, uint32_t u, uint if (!swizzled) return (v * (row_pitch_pixels * texel_size_bits >> 3)) + (u * texel_size_bits >> 3); - const uint32_t tile_size_bits = 32; - const uint32_t tiles_in_block_horizontal = 4; - const uint32_t tiles_in_block_vertical = 8; + const int tile_size_bits = 32; + const int tiles_in_block_horizontal = 4; + const int tiles_in_block_vertical = 8; - constexpr uint32_t texels_per_tile = tile_size_bits / texel_size_bits; - uint32_t tile_u = u / texels_per_tile; - uint32_t tile_idx = (v % tiles_in_block_vertical) * (tiles_in_block_horizontal) + + constexpr int texels_per_tile = tile_size_bits / texel_size_bits; + int tile_u = u / texels_per_tile; + int tile_idx = (v % tiles_in_block_vertical) * (tiles_in_block_horizontal) + // TODO: not sure if the *texel_size_bits/8 factor is correct (v / tiles_in_block_vertical) * ((row_pitch_pixels*texel_size_bits/(tile_size_bits))*tiles_in_block_vertical) + (tile_u % tiles_in_block_horizontal) + @@ -414,22 +408,22 @@ inline static Nearest4 SOFTRAST_CALL SampleNearest(const int u[N], const int v[N case GE_TFMT_DXT1: for (int i = 0; i < N; ++i) { - const DXT1Block *block = (const DXT1Block *)srcptr + (v[i] >> 2) * (texbufw >> 2) + (u[i] >> 2); - res.v[i] = GetDXT1Texel(block, u[i] & 3, v[i] & 3); + const DXT1Block *block = (const DXT1Block *)srcptr + (v[i] / 4) * (texbufw / 4) + (u[i] / 4); + res.v[i] = GetDXT1Texel(block, u[i] % 4, v[i] % 4); } return res; case GE_TFMT_DXT3: for (int i = 0; i < N; ++i) { - const DXT3Block *block = (const DXT3Block *)srcptr + (v[i] >> 2) * (texbufw >> 2) + (u[i] >> 2); - res.v[i] = GetDXT3Texel(block, u[i] & 3, v[i] & 3); + const DXT3Block *block = (const DXT3Block *)srcptr + (v[i] / 4) * (texbufw / 4) + (u[i] / 4); + res.v[i] = GetDXT3Texel(block, u[i] % 4, v[i] % 4); } return res; case GE_TFMT_DXT5: for (int i = 0; i < N; ++i) { - const DXT5Block *block = (const DXT5Block *)srcptr + (v[i] >> 2) * (texbufw >> 2) + (u[i] >> 2); - res.v[i] = GetDXT5Texel(block, u[i] & 3, v[i] & 3); + const DXT5Block *block = (const DXT5Block *)srcptr + (v[i] / 4) * (texbufw / 4) + (u[i] / 4); + res.v[i] = GetDXT5Texel(block, u[i] % 4, v[i] % 4); } return res; @@ -619,7 +613,7 @@ static Vec4IntResult SOFTRAST_CALL SampleNearest(float s, float t, Vec4IntArg pr GetTexelCoordinates(level + 1, s, t, u, v, samplerID); Vec4 c1 = Vec4::FromRGBA(SampleNearest<1>(&u, &v, tptr[1], bufw[1], level + 1, samplerID).v[0]); - c0 = (c1 * levelFrac + c0 * (16 - levelFrac)) >> 4; + c0 = (c1 * levelFrac + c0 * (16 - levelFrac)) / 16; } return GetTextureFunctionOutput(prim_color, ToVec4IntArg(c0), samplerID); @@ -726,43 +720,21 @@ static Vec4IntResult SOFTRAST_CALL SampleLinearLevel(float s, float t, const u8 const Vec4 u = GetTexelCoordinatesQuadS(texlevel, s, frac_u, samplerID); const Vec4 v = GetTexelCoordinatesQuadT(texlevel, t, frac_v, samplerID); Nearest4 c = SampleNearest<4>(u.AsArray(), v.AsArray(), tptr[0], bufw[0], texlevel, samplerID); -#ifdef _M_SSE - __m128i zero = _mm_setzero_si128(); - __m128i samples = _mm_loadu_si128((const __m128i*)(c.v)); - __m128i top = _mm_unpacklo_epi8(samples, zero); - __m128i bot = _mm_unpackhi_epi8(samples, zero); - // I just a want reasonably efficient - // __m128i mul_u = _mm_setr_epi16(0x10 - frac_u, 0x10 - frac_u, 0x10 - frac_u, 0x10 - frac_u, frac_u, frac_u, frac_u, frac_u); - // GCC/clang do something decent for that, MSVC - not so much. - // Hence this. (0x10 - frac_u) is expressed as (frac_u ^ 0xF) + 1, - // which REQUIRES 0 <= frac_u < 0x10. - __m128i mul_u = _mm_set1_epi16(frac_u); - mul_u = _mm_xor_si128(mul_u, _mm_setr_epi16(0xF, 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0)); - mul_u = _mm_add_epi16(mul_u, _mm_setr_epi16(0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0)); - top = _mm_mullo_epi16(top, _mm_set1_epi16(0x10 - frac_v)); - bot = _mm_mullo_epi16(bot, _mm_set1_epi16(frac_v)); - __m128i sum = _mm_add_epi16(top, bot); - sum = _mm_mullo_epi16(sum, mul_u); - sum = _mm_add_epi16(sum, _mm_shuffle_epi32(sum, _MM_SHUFFLE(3, 2, 3, 2))); - sum = _mm_srli_epi16(sum, 8); - sum = _mm_unpacklo_epi16(sum, zero); - return sum; -#else + Vec4 texcolor_tl = Vec4::FromRGBA(c.v[0]); Vec4 texcolor_tr = Vec4::FromRGBA(c.v[1]); Vec4 texcolor_bl = Vec4::FromRGBA(c.v[2]); Vec4 texcolor_br = Vec4::FromRGBA(c.v[3]); Vec4 top = texcolor_tl * (0x10 - frac_u) + texcolor_tr * frac_u; Vec4 bot = texcolor_bl * (0x10 - frac_u) + texcolor_br * frac_u; - return ToVec4IntResult((top * (0x10 - frac_v) + bot * frac_v) >> (4 + 4)); -#endif + return ToVec4IntResult((top * (0x10 - frac_v) + bot * frac_v) / (16 * 16)); } static Vec4IntResult SOFTRAST_CALL SampleLinear(float s, float t, Vec4IntArg prim_color, const u8 *const *tptr, const uint16_t *bufw, int texlevel, int levelFrac, const SamplerID &samplerID) { Vec4 c0 = SampleLinearLevel(s, t, tptr, bufw, texlevel, samplerID); if (levelFrac) { const Vec4 c1 = SampleLinearLevel(s, t, tptr + 1, bufw + 1, texlevel + 1, samplerID); - c0 = (c1 * levelFrac + c0 * (16 - levelFrac)) >> 4; + c0 = (c1 * levelFrac + c0 * (16 - levelFrac)) / 16; } return GetTextureFunctionOutput(prim_color, ToVec4IntArg(c0), samplerID); } diff --git a/GPU/Software/Sampler.h b/GPU/Software/Sampler.h index a07ce52a3..ec8d4c263 100644 --- a/GPU/Software/Sampler.h +++ b/GPU/Software/Sampler.h @@ -144,7 +144,7 @@ private: } }; - DenseHashMap cache_; + DenseHashMap cache_; std::unordered_map addresses_; std::unordered_set compileQueue_; static int clearGen_; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2ca6fa8d8..a5cebc319 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -81,7 +81,7 @@ const SoftwareCommandTableEntry softgpuCommandTable[] = { { GE_CMD_VADDR, FLAG_EXECUTE, SoftDirty::NONE, &GPUCommon::Execute_Vaddr }, { GE_CMD_IADDR, FLAG_EXECUTE, SoftDirty::NONE, &GPUCommon::Execute_Iaddr }, { GE_CMD_BJUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, SoftDirty::NONE, &GPUCommon::Execute_BJump }, - { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, SoftDirty::NONE, &SoftGPU::Execute_BoundingBox }, + { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, SoftDirty::NONE, &GPUCommon::Execute_BoundingBox }, { GE_CMD_PRIM, FLAG_EXECUTE, SoftDirty::NONE, &SoftGPU::Execute_Prim }, { GE_CMD_BEZIER, FLAG_EXECUTE, SoftDirty::NONE, &SoftGPU::Execute_Bezier }, @@ -449,13 +449,11 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw) if (gfxCtx && draw) { presentation_ = new PresentationCommon(draw_); presentation_->SetLanguage(draw_->GetShaderLanguageDesc().shaderLanguage); - presentation_->UpdateDisplaySize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); - presentation_->UpdateRenderSize(PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight); } NotifyConfigChanged(); - NotifyDisplayResized(); NotifyRenderResized(); + NotifyDisplayResized(); } void SoftGPU::DeviceLost() { @@ -725,28 +723,14 @@ void SoftGPU::NotifyRenderResized() { } void SoftGPU::NotifyDisplayResized() { - displayResized_ = true; -} - -void SoftGPU::CheckDisplayResized() { - if (displayResized_ && presentation_) { + if (presentation_) { presentation_->UpdateDisplaySize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); presentation_->UpdateRenderSize(PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight); presentation_->UpdatePostShader(); - displayResized_ = false; } } -void SoftGPU::CheckConfigChanged() { - if (configChanged_) { - drawEngineCommon_->NotifyConfigChanged(); - BuildReportingInfo(); - if (presentation_) { - presentation_->UpdatePostShader(); - } - configChanged_ = false; - } -} +void SoftGPU::NotifyConfigChanged() {} void SoftGPU::FastRunLoop(DisplayList &list) { PROFILE_THIS_SCOPE("soft_runloop"); @@ -1031,18 +1015,11 @@ void SoftGPU::Execute_FramebufFormat(u32 op, u32 diff) { drawEngine_->transformUnit.Flush("framebuf"); } -void SoftGPU::Execute_BoundingBox(u32 op, u32 diff) { - gstate_c.Dirty(DIRTY_CULL_PLANES); - GPUCommon::Execute_BoundingBox(op, diff); -} - void SoftGPU::Execute_ZbufPtr(u32 op, u32 diff) { // We assume depthbuf.data won't change while we're drawing. if (diff) { drawEngine_->transformUnit.Flush("depthbuf"); - // For the pointer, ignore memory mirrors. This also gives some buffer for draws that go outside. - // TODO: Confirm how wrapping is handled in drawing. Adjust if we ever handle VRAM mirrors more accurately. - depthbuf.data = Memory::GetPointerWrite(gstate.getDepthBufAddress() & 0x041FFFF0); + depthbuf.data = Memory::GetPointerWrite(gstate.getDepthBufAddress()); } } @@ -1088,7 +1065,6 @@ void SoftGPU::Execute_WorldMtxData(u32 op, u32 diff) { if (newVal != *target) { *target = newVal; dirtyFlags_ |= SoftDirty::TRANSFORM_MATRIX; - gstate_c.Dirty(DIRTY_CULL_PLANES); } } @@ -1109,7 +1085,6 @@ void SoftGPU::Execute_ViewMtxData(u32 op, u32 diff) { if (newVal != *target) { *target = newVal; dirtyFlags_ |= SoftDirty::TRANSFORM_MATRIX; - gstate_c.Dirty(DIRTY_CULL_PLANES); } } @@ -1130,7 +1105,6 @@ void SoftGPU::Execute_ProjMtxData(u32 op, u32 diff) { if (newVal != *target) { *target = newVal; dirtyFlags_ |= SoftDirty::TRANSFORM_MATRIX; - gstate_c.Dirty(DIRTY_CULL_PLANES); } } diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 05ae3bb8e..0377ca7c1 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -138,7 +138,7 @@ public: void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput(bool reallyDirty) override; void GetStats(char *buffer, size_t bufsize) override; - std::vector GetFramebufferList() const override { return std::vector(); } + std::vector GetFramebufferList() const override { return std::vector(); } void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void PerformWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat format) override; bool PerformMemoryCopy(u32 dest, u32 src, int size, GPUCopyFlag flags = GPUCopyFlag::NONE) override; @@ -152,9 +152,7 @@ public: void NotifyRenderResized() override; void NotifyDisplayResized() override; - - void CheckDisplayResized() override; - void CheckConfigChanged() override; + void NotifyConfigChanged() override; void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { primaryInfo = "Software"; @@ -187,9 +185,6 @@ public: // Overridden to change flushing behavior. void Execute_Call(u32 op, u32 diff); - // Overridden for a dirty flag change. - void Execute_BoundingBox(u32 op, u32 diff); - void Execute_WorldMtxNum(u32 op, u32 diff); void Execute_ViewMtxNum(u32 op, u32 diff); void Execute_ProjMtxNum(u32 op, u32 diff); diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 234ef5aca..b7afe1851 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -71,8 +71,8 @@ void SoftwareDrawEngine::DispatchFlush() { transformUnit.Flush("debug"); } -void SoftwareDrawEngine::DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, bool clockwise, int *bytesRead) { - _assert_msg_(clockwise, "Mixed cull mode not supported."); +void SoftwareDrawEngine::DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) { + _assert_msg_(cullMode == gstate.getCullMode(), "Mixed cull mode not supported."); transformUnit.SubmitPrimitive(verts, inds, prim, vertexCount, vertTypeID, bytesRead, this); } @@ -332,31 +332,6 @@ void ComputeTransformState(TransformState *state, const VertexReader &vreader) { state->roundToScreen = &ClipToScreenInternal; } -#if defined(_M_SSE) -#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) -[[gnu::target("sse4.1")]] -#endif -static inline __m128 Dot43SSE4(__m128 a, __m128 b) { - __m128 multiplied = _mm_mul_ps(a, _mm_insert_ps(b, _mm_set1_ps(1.0f), 0x30)); - __m128 lanes3311 = _mm_movehdup_ps(multiplied); - __m128 partial = _mm_add_ps(multiplied, lanes3311); - return _mm_add_ss(partial, _mm_movehl_ps(lanes3311, partial)); -} -#endif - -static inline float Dot43(const Vec4f &a, const Vec3f &b) { -#if defined(_M_SSE) && !PPSSPP_ARCH(X86) - if (cpu_info.bSSE4_1) - return _mm_cvtss_f32(Dot43SSE4(a.vec, b.vec)); -#elif PPSSPP_ARCH(ARM64_NEON) - float32x4_t multipled = vmulq_f32(a.vec, vsetq_lane_f32(1.0f, b.vec, 3)); - float32x2_t add1 = vget_low_f32(vpaddq_f32(multipled, multipled)); - float32x2_t add2 = vpadd_f32(add1, add1); - return vget_lane_f32(add2, 0); -#endif - return Dot(a, Vec4f(b, 1.0f)); -} - ClipVertexData TransformUnit::ReadVertex(const VertexReader &vreader, const TransformState &state) { PROFILE_THIS_SCOPE("read_vert"); // If we ever thread this, we'll have to change this. @@ -421,7 +396,7 @@ ClipVertexData TransformUnit::ReadVertex(const VertexReader &vreader, const Tran } if (state.enableFog) { - vertex.v.fogdepth = Dot43(state.posToFog, pos); + vertex.v.fogdepth = Dot(state.posToFog, Vec4f(pos, 1.0f)); } else { vertex.v.fogdepth = 1.0f; } @@ -494,7 +469,7 @@ public: if (useIndices_) GetIndexBounds(indices, vertex_count, vertex_type, &lowerBound_, &upperBound_); if (vertex_count != 0) - vdecoder.DecodeVerts(base, vertices, &gstate_c.uv, lowerBound_, upperBound_); + vdecoder.DecodeVerts(base, vertices, lowerBound_, upperBound_); // If we're only using a subset of verts, it's better to decode with random access (usually.) // However, if we're reusing a lot of verts, we should read and cache them. diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index 295953a8e..895c023a9 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -178,7 +178,7 @@ public: void NotifyConfigChanged() override; void DispatchFlush() override; - void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, bool clockwise, int *bytesRead) override; + void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int cullMode, int *bytesRead) override; void DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode, bool continuation) override; VertexDecoder *FindVertexDecoder(u32 vtype); @@ -196,5 +196,5 @@ public: #endif protected: - bool UpdateUseHWTessellation(bool enable) const override { return false; } + bool UpdateUseHWTessellation(bool enable) override { return false; } }; diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index f259fafe8..36b869f07 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -30,7 +30,6 @@ #include "ext/vma/vk_mem_alloc.h" #include "DebugVisVulkan.h" -#include "Common/GPU/GPUBackendCommon.h" #include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/Vulkan/VulkanImage.h" #include "Common/Data/Text/Parsers.h" @@ -42,42 +41,43 @@ #undef DrawText -bool comparePushBufferNames(const GPUMemoryManager *a, const GPUMemoryManager *b) { +bool comparePushBufferNames(const VulkanMemoryManager *a, const VulkanMemoryManager *b) { return strcmp(a->Name(), b->Name()) < 0; } -void DrawGPUMemoryVis(UIContext *ui, GPUInterface *gpu) { +void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { // This one will simply display stats. Draw::DrawContext *draw = ui->GetDrawContext(); - std::stringstream str; - VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); - if (vulkan) { - VmaTotalStatistics vmaStats; - vmaCalculateStatistics(vulkan->Allocator(), &vmaStats); - - std::vector budgets; - budgets.resize(vulkan->GetMemoryProperties().memoryHeapCount); - vmaGetHeapBudgets(vulkan->Allocator(), &budgets[0]); - - size_t totalBudget = 0; - size_t totalUsedBytes = 0; - for (auto &budget : budgets) { - totalBudget += budget.budget; - totalUsedBytes += budget.usage; - } - - str << vulkan->GetPhysicalDeviceProperties().properties.deviceName << std::endl; - str << "Allocated " << NiceSizeFormat(vmaStats.total.statistics.allocationBytes) << " in " << vmaStats.total.statistics.allocationCount << " allocs" << std::endl; - // Note: The overall number includes stuff like descriptor sets pools and other things that are not directly visible as allocations. - str << "Overall " << NiceSizeFormat(totalUsedBytes) << " used out of " << NiceSizeFormat(totalBudget) << " available" << std::endl; + if (!vulkan) { + return; } + VmaTotalStatistics vmaStats; + vmaCalculateStatistics(vulkan->Allocator(), &vmaStats); + + std::vector budgets; + budgets.resize(vulkan->GetMemoryProperties().memoryHeapCount); + vmaGetHeapBudgets(vulkan->Allocator(), &budgets[0]); + + size_t totalBudget = 0; + size_t totalUsedBytes = 0; + for (auto &budget : budgets) { + totalBudget += budget.budget; + totalUsedBytes += budget.usage; + } + + std::stringstream str; + str << vulkan->GetPhysicalDeviceProperties().properties.deviceName << std::endl; + str << "Allocated " << NiceSizeFormat(vmaStats.total.statistics.allocationBytes) << " in " << vmaStats.total.statistics.allocationCount << " allocs" << std::endl; + // Note: The overall number includes stuff like descriptor sets pools and other things that are not directly visible as allocations. + str << "Overall " << NiceSizeFormat(totalUsedBytes) << " used out of " << NiceSizeFormat(totalBudget) << " available" << std::endl; + str << "Push buffers:" << std::endl; // Now list the various push buffers. - auto managers = GetActiveGPUMemoryManagers(); + auto managers = GetActiveVulkanMemoryManagers(); std::sort(managers.begin(), managers.end(), comparePushBufferNames); char buffer[512]; @@ -98,6 +98,9 @@ void DrawGPUMemoryVis(UIContext *ui, GPUInterface *gpu) { } void DrawGPUProfilerVis(UIContext *ui, GPUInterface *gpu) { + if (!gpu) { + return; + } using namespace Draw; const int padding = 10 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT); const int starty = 50 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP); @@ -112,7 +115,8 @@ void DrawGPUProfilerVis(UIContext *ui, GPUInterface *gpu) { scale = 0.7f; } - std::string text = ui->GetDrawContext()->GetGpuProfileString(); + GPUCommon *gpuCommon = static_cast(gpu); + std::string text = gpuCommon->GetGpuProfileString(); ui->SetFontScale(0.4f, 0.4f); ui->DrawTextShadow(text.c_str(), x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); diff --git a/GPU/Vulkan/DebugVisVulkan.h b/GPU/Vulkan/DebugVisVulkan.h index 5e2fae38f..210771412 100644 --- a/GPU/Vulkan/DebugVisVulkan.h +++ b/GPU/Vulkan/DebugVisVulkan.h @@ -23,5 +23,5 @@ class GPUInterface; class UIContext; // gpu MUST be an instance of GPU_Vulkan. If not, will definitely crash. -void DrawGPUMemoryVis(UIContext *ui, GPUInterface *gpu); +void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu); void DrawGPUProfilerVis(UIContext *ui, GPUInterface *gpu); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index cd81b7caf..0e72dab08 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -54,46 +54,137 @@ using namespace PPSSPP_VK; +enum { + VERTEX_CACHE_SIZE = 8192 * 1024 +}; + +#define VERTEXCACHE_DECIMATION_INTERVAL 17 +#define DESCRIPTORSET_DECIMATION_INTERVAL 1 // Temporarily cut to 1. Handle reuse breaks this when textures get deleted. + +enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; + enum { TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex) }; DrawEngineVulkan::DrawEngineVulkan(Draw::DrawContext *draw) - : draw_(draw) { + : draw_(draw), vai_(1024) { decOptions_.expandAllWeightsToFloat = false; decOptions_.expand8BitNormalsToFloat = false; #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) decOptions_.alignOutputToWord = true; #endif - indexGen.Setup(decIndex_); + indexGen.Setup(decIndex); } void DrawEngineVulkan::InitDeviceObjects() { // All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated. - BindingType bindingTypes[VKRPipelineLayout::MAX_DESC_SET_BINDINGS] = { - BindingType::COMBINED_IMAGE_SAMPLER, // main - BindingType::COMBINED_IMAGE_SAMPLER, // framebuffer-read - BindingType::COMBINED_IMAGE_SAMPLER, // palette - BindingType::UNIFORM_BUFFER_DYNAMIC_ALL, // uniforms - BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX, // lights - BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX, // bones - BindingType::STORAGE_BUFFER_VERTEX, // tess - BindingType::STORAGE_BUFFER_VERTEX, - BindingType::STORAGE_BUFFER_VERTEX, - }; + // TODO: Make things more flexible, so we at least have specialized layouts for input attachments and tess. + // Note that it becomes a support matrix.. + VkDescriptorSetLayoutBinding bindings[DRAW_BINDING_COUNT]{}; + bindings[0].descriptorCount = 1; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[0].binding = DRAW_BINDING_TEXTURE; + bindings[1].descriptorCount = 1; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[1].binding = DRAW_BINDING_2ND_TEXTURE; + bindings[2].descriptorCount = 1; + bindings[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; // sampler is ignored though. + bindings[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[2].binding = DRAW_BINDING_DEPAL_TEXTURE; + bindings[3].descriptorCount = 1; + bindings[3].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + bindings[3].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + if (gstate_c.Use(GPU_USE_GS_CULLING)) + bindings[3].stageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT; + bindings[3].binding = DRAW_BINDING_DYNUBO_BASE; + bindings[4].descriptorCount = 1; + bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + bindings[4].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[4].binding = DRAW_BINDING_DYNUBO_LIGHT; + bindings[5].descriptorCount = 1; + bindings[5].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + bindings[5].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[5].binding = DRAW_BINDING_DYNUBO_BONE; + // Used only for hardware tessellation. + bindings[6].descriptorCount = 1; + bindings[6].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[6].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[6].binding = DRAW_BINDING_TESS_STORAGE_BUF; + bindings[7].descriptorCount = 1; + bindings[7].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[7].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[7].binding = DRAW_BINDING_TESS_STORAGE_BUF_WU; + bindings[8].descriptorCount = 1; + bindings[8].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[8].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[8].binding = DRAW_BINDING_TESS_STORAGE_BUF_WV; + // Note: This binding is not included if !gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH), using bindingCount below. + bindings[9].descriptorCount = 1; + bindings[9].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + bindings[9].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[9].binding = DRAW_BINDING_INPUT_ATTACHMENT; VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); VkDevice device = vulkan->GetDevice(); - VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - pipelineLayout_ = renderManager->CreatePipelineLayout(bindingTypes, ARRAY_SIZE(bindingTypes), draw_->GetDeviceCaps().geometryShaderSupported, "drawengine_layout"); + VkDescriptorSetLayoutCreateInfo dsl{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + dsl.bindingCount = gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH) ? ARRAY_SIZE(bindings) : ARRAY_SIZE(bindings) - 1; + dsl.pBindings = bindings; + VkResult res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_); + _dbg_assert_(VK_SUCCESS == res); + vulkan->SetDebugName(descriptorSetLayout_, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, "drawengine_d_layout"); + + static constexpr int DEFAULT_DESC_POOL_SIZE = 512; + std::vector dpTypes; + dpTypes.resize(5); + dpTypes[0].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; + dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + dpTypes[1].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // Don't use these for tess anymore, need max three per set. + dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + dpTypes[2].descriptorCount = DEFAULT_DESC_POOL_SIZE * 3; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these. + dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + dpTypes[3].descriptorCount = DEFAULT_DESC_POOL_SIZE; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these. + dpTypes[3].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + dpTypes[4].descriptorCount = DEFAULT_DESC_POOL_SIZE; // For the frame global uniform buffer. Might need to allocate multiple times. + dpTypes[4].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + + VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + // Don't want to mess around with individually freeing these. + // We zap the whole pool every few frames. + dp.flags = 0; + dp.maxSets = DEFAULT_DESC_POOL_SIZE; + + // We are going to use one-shot descriptors in the initial implementation. Might look into caching them + // if creating and updating them turns out to be expensive. + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { + frame_[i].descPool.Create(vulkan, dp, dpTypes); + + // Note that pushUBO_ is also used for tessellation data (search for SetPushBuffer), and to upload + // the null texture. This should be cleaned up... + } pushUBO_ = (VulkanPushPool *)draw_->GetNativeObject(Draw::NativeObject::PUSH_POOL); pushVertex_ = new VulkanPushPool(vulkan, "pushVertex", 4 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); pushIndex_ = new VulkanPushPool(vulkan, "pushIndex", 1 * 512 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; + pl.pPushConstantRanges = nullptr; + pl.pushConstantRangeCount = 0; + VkDescriptorSetLayout layouts[1] = { descriptorSetLayout_}; + pl.setLayoutCount = ARRAY_SIZE(layouts); + pl.pSetLayouts = layouts; + pl.flags = 0; + + res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_); + _dbg_assert_(VK_SUCCESS == res); + + vulkan->SetDebugName(pipelineLayout_, VK_OBJECT_TYPE_PIPELINE_LAYOUT, "drawengine_p_layout"); + VkSamplerCreateInfo samp{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samp.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; @@ -101,7 +192,7 @@ void DrawEngineVulkan::InitDeviceObjects() { samp.magFilter = VK_FILTER_LINEAR; samp.minFilter = VK_FILTER_LINEAR; samp.maxLod = VK_LOD_CLAMP_NONE; // recommended by best practices, has no effect since we don't use mipmaps. - VkResult res = vkCreateSampler(device, &samp, nullptr, &samplerSecondaryLinear_); + res = vkCreateSampler(device, &samp, nullptr, &samplerSecondaryLinear_); samp.magFilter = VK_FILTER_NEAREST; samp.minFilter = VK_FILTER_NEAREST; res = vkCreateSampler(device, &samp, nullptr, &samplerSecondaryNearest_); @@ -109,6 +200,8 @@ void DrawEngineVulkan::InitDeviceObjects() { res = vkCreateSampler(device, &samp, nullptr, &nullSampler_); _dbg_assert_(VK_SUCCESS == res); + vertexCache_ = new VulkanPushBuffer(vulkan, "pushVertexCache", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + tessDataTransferVulkan = new TessellationDataTransferVulkan(vulkan); tessDataTransfer = tessDataTransferVulkan; @@ -119,6 +212,10 @@ DrawEngineVulkan::~DrawEngineVulkan() { DestroyDeviceObjects(); } +void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) { + descPool.Destroy(); +} + void DrawEngineVulkan::DestroyDeviceObjects() { if (!draw_) { // We've already done this from LostDevice. @@ -126,7 +223,6 @@ void DrawEngineVulkan::DestroyDeviceObjects() { } VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); draw_->SetInvalidationCallback(InvalidationCallback()); @@ -134,6 +230,10 @@ void DrawEngineVulkan::DestroyDeviceObjects() { tessDataTransfer = nullptr; tessDataTransferVulkan = nullptr; + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { + frame_[i].Destroy(vulkan); + } + pushUBO_ = nullptr; if (pushVertex_) { @@ -153,8 +253,21 @@ void DrawEngineVulkan::DestroyDeviceObjects() { vulkan->Delete().QueueDeleteSampler(samplerSecondaryLinear_); if (nullSampler_ != VK_NULL_HANDLE) vulkan->Delete().QueueDeleteSampler(nullSampler_); + if (pipelineLayout_ != VK_NULL_HANDLE) + vulkan->Delete().QueueDeletePipelineLayout(pipelineLayout_); + if (descriptorSetLayout_ != VK_NULL_HANDLE) + vulkan->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); + if (vertexCache_) { + vertexCache_->Destroy(vulkan); + delete vertexCache_; + vertexCache_ = nullptr; + } - renderManager->DestroyPipelineLayout(pipelineLayout_); + // Need to clear this to get rid of all remaining references to the dead buffers. + vai_.Iterate([](uint32_t hash, VertexArrayInfoVulkan *vai) { + delete vai; + }); + vai_.Clear(); } void DrawEngineVulkan::DeviceLost() { @@ -169,6 +282,8 @@ void DrawEngineVulkan::DeviceRestore(Draw::DrawContext *draw) { } void DrawEngineVulkan::BeginFrame() { + gpuStats.numTrackedVertexArrays = (int)vai_.size(); + lastPipeline_ = nullptr; // pushUBO is the thin3d push pool, don't need to BeginFrame again. @@ -178,11 +293,230 @@ void DrawEngineVulkan::BeginFrame() { tessDataTransferVulkan->SetPushPool(pushUBO_); DirtyAllUBOs(); + + FrameData *frame = &GetCurFrame(); + + // First reset all buffers, then begin. This is so that Reset can free memory and Begin can allocate it, + // if growing the buffer is needed. Doing it this way will reduce fragmentation if more than one buffer + // needs to grow in the same frame. The state where many buffers are reset can also be used to + // defragment memory. + VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); + + // Wipe the vertex cache if it's grown too large. + if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) { + vertexCache_->Destroy(vulkan); + delete vertexCache_; // orphans the buffers, they'll get deleted once no longer used by an in-flight frame. + vertexCache_ = new VulkanPushBuffer(vulkan, "vertexCacheR", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + vai_.Iterate([&](uint32_t hash, VertexArrayInfoVulkan *vai) { + delete vai; + }); + vai_.Clear(); + } + + vertexCache_->BeginNoReset(); + + if (--descDecimationCounter_ <= 0) { + frame->descPool.Reset(); + descDecimationCounter_ = DESCRIPTORSET_DECIMATION_INTERVAL; + } + + if (--decimationCounter_ <= 0) { + decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; + + const int threshold = gpuStats.numFlips - VAI_KILL_AGE; + const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; + int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; + vai_.Iterate([&](uint32_t hash, VertexArrayInfoVulkan *vai) { + bool kill; + if (vai->status == VertexArrayInfoVulkan::VAI_UNRELIABLE) { + // We limit killing unreliable so we don't rehash too often. + kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0; + } else { + kill = vai->lastFrame < threshold; + } + if (kill) { + // This is actually quite safe. + vai_.Remove(hash); + delete vai; + } + }); + } + vai_.Maintain(); } void DrawEngineVulkan::EndFrame() { + FrameData *frame = &GetCurFrame(); stats_.pushVertexSpaceUsed = (int)pushVertex_->GetUsedThisFrame(); stats_.pushIndexSpaceUsed = (int)pushIndex_->GetUsedThisFrame(); + vertexCache_->End(); +} + +void DrawEngineVulkan::DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf) { + u8 *dest = decoded; + + // Figure out how much pushbuffer space we need to allocate. + if (push) { + int vertsToDecode = ComputeNumVertsToDecode(); + dest = (u8 *)push->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, vkbuf, bindOffset); + } + DecodeVerts(dest); +} + +void DrawEngineVulkan::DecodeVertsToPushPool(VulkanPushPool *push, uint32_t *bindOffset, VkBuffer *vkbuf) { + u8 *dest = decoded; + + // Figure out how much pushbuffer space we need to allocate. + if (push) { + int vertsToDecode = ComputeNumVertsToDecode(); + dest = push->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, vkbuf, bindOffset); + } + DecodeVerts(dest); +} + +VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess) { + _dbg_assert_(base != VK_NULL_HANDLE); + _dbg_assert_(light != VK_NULL_HANDLE); + _dbg_assert_(bone != VK_NULL_HANDLE); + + DescriptorSetKey key{}; + key.imageView_ = imageView; + key.sampler_ = sampler; + key.secondaryImageView_ = boundSecondary_; + key.depalImageView_ = boundDepal_; + key.base_ = base; + key.light_ = light; + key.bone_ = bone; + key.secondaryIsInputAttachment = boundSecondaryIsInputAttachment_; + + FrameData &frame = GetCurFrame(); + // See if we already have this descriptor set cached. + if (!tess) { // Don't cache descriptors for HW tessellation. + VkDescriptorSet d = frame.descSets.Get(key); + if (d != VK_NULL_HANDLE) + return d; + } + + // Didn't find one in the frame descriptor set cache, let's make a new one. + // We wipe the cache on every frame. + VkDescriptorSet desc = frame.descPool.Allocate(1, &descriptorSetLayout_, "game_descset"); + + // Even in release mode, this is bad. + _assert_msg_(desc != VK_NULL_HANDLE, "Ran out of descriptor space in pool. sz=%d", (int)frame.descSets.size()); + + // We just don't write to the slots we don't care about, which is fine. + VkWriteDescriptorSet writes[DRAW_BINDING_COUNT]{}; + // Main texture + int n = 0; + VkDescriptorImageInfo tex[3]{}; + if (imageView) { + _dbg_assert_(sampler != VK_NULL_HANDLE); + + tex[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + tex[0].imageView = imageView; + tex[0].sampler = sampler; + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = DRAW_BINDING_TEXTURE; + writes[n].pImageInfo = &tex[0]; + writes[n].descriptorCount = 1; + writes[n].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[n].dstSet = desc; + n++; + } + + if (boundSecondary_) { + tex[1].imageLayout = key.secondaryIsInputAttachment ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + tex[1].imageView = boundSecondary_; + tex[1].sampler = samplerSecondaryNearest_; + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = key.secondaryIsInputAttachment ? DRAW_BINDING_INPUT_ATTACHMENT : DRAW_BINDING_2ND_TEXTURE; + writes[n].pImageInfo = &tex[1]; + writes[n].descriptorCount = 1; + writes[n].descriptorType = key.secondaryIsInputAttachment ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[n].dstSet = desc; + n++; + } + + if (boundDepal_) { + tex[2].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + tex[2].imageView = boundDepal_; + tex[2].sampler = boundDepalSmoothed_ ? samplerSecondaryLinear_ : samplerSecondaryNearest_; + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = DRAW_BINDING_DEPAL_TEXTURE; + writes[n].pImageInfo = &tex[2]; + writes[n].descriptorCount = 1; + writes[n].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[n].dstSet = desc; + n++; + } + + // Tessellation data buffer. + if (tess) { + const VkDescriptorBufferInfo *bufInfo = tessDataTransferVulkan->GetBufferInfo(); + // Control Points + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = DRAW_BINDING_TESS_STORAGE_BUF; + writes[n].pBufferInfo = &bufInfo[0]; + writes[n].descriptorCount = 1; + writes[n].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + writes[n].dstSet = desc; + n++; + // Weights U + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = DRAW_BINDING_TESS_STORAGE_BUF_WU; + writes[n].pBufferInfo = &bufInfo[1]; + writes[n].descriptorCount = 1; + writes[n].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + writes[n].dstSet = desc; + n++; + // Weights V + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = DRAW_BINDING_TESS_STORAGE_BUF_WV; + writes[n].pBufferInfo = &bufInfo[2]; + writes[n].descriptorCount = 1; + writes[n].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + writes[n].dstSet = desc; + n++; + } + + // Uniform buffer objects + VkDescriptorBufferInfo buf[3]{}; + int count = 0; + buf[count].buffer = base; + buf[count].offset = 0; + buf[count].range = sizeof(UB_VS_FS_Base); + count++; + buf[count].buffer = light; + buf[count].offset = 0; + buf[count].range = sizeof(UB_VS_Lights); + count++; + buf[count].buffer = bone; + buf[count].offset = 0; + buf[count].range = sizeof(UB_VS_Bones); + count++; + for (int i = 0; i < count; i++) { + writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[n].pNext = nullptr; + writes[n].dstBinding = DRAW_BINDING_DYNUBO_BASE + i; + writes[n].dstArrayElement = 0; + writes[n].pBufferInfo = &buf[i]; + writes[n].dstSet = desc; + writes[n].descriptorCount = 1; + writes[n].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + n++; + } + + VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); + vkUpdateDescriptorSets(vulkan->GetDevice(), n, writes, 0, nullptr); + + if (!tess) // Again, avoid caching when HW tessellation. + frame.descSets.Insert(key, desc); + return desc; } void DrawEngineVulkan::DirtyAllUBOs() { @@ -198,6 +532,12 @@ void DrawEngineVulkan::DirtyAllUBOs() { gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } +void MarkUnreliable(VertexArrayInfoVulkan *vai) { + vai->status = VertexArrayInfoVulkan::VAI_UNRELIABLE; + // TODO: If we change to a real allocator, free the data here. + // For now we just leave it in the pushbuffer. +} + void DrawEngineVulkan::Invalidate(InvalidationCallbackFlags flags) { if (flags & InvalidationCallbackFlags::COMMAND_BUFFER_STATE) { // Nothing here anymore (removed the "frame descriptor set" @@ -212,11 +552,12 @@ void DrawEngineVulkan::Invalidate(InvalidationCallbackFlags flags) { } } -// The inline wrapper in the header checks for numDrawCalls_ == 0 +// The inline wrapper in the header checks for numDrawCalls == 0 void DrawEngineVulkan::DoFlush() { VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); PROFILE_THIS_SCOPE("Flush"); + FrameData &frameData = GetCurFrame(); bool tess = gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE; @@ -243,35 +584,184 @@ void DrawEngineVulkan::DoFlush() { const bool forceIndexed = draw_->GetDeviceCaps().verySlowShaderCompiler; if (useHWTransform) { + int vertexCount = 0; + bool useElements = true; + + // Cannot cache vertex data with morph enabled. + bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); + // Also avoid caching when software skinning. VkBuffer vbuf = VK_NULL_HANDLE; VkBuffer ibuf = VK_NULL_HANDLE; if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { - // If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content. - DecodeVerts(decoded_); - VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; - u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); - memcpy(dest, decoded_, size); - } else { - // Figure out how much pushbuffer space we need to allocate. - int vertsToDecode = ComputeNumVertsToDecode(); - // Decode directly into the pushbuffer - u8 *dest = pushVertex_->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, &vbuf, &vbOffset); - DecodeVerts(dest); + useCache = false; } - DecodeInds(); - bool useElements; - int vertexCount = indexGen.VertexCount(); - gpuStats.numUncachedVertsDrawn += vertexCount; - if (forceIndexed) { - useElements = true; - prim = indexGen.GeneralPrim(); - } else { - useElements = !indexGen.SeenOnlyPurePrims(); - if (!useElements && indexGen.PureCount()) { - vertexCount = indexGen.PureCount(); + if (useCache) { + PROFILE_THIS_SCOPE("vcache"); + u32 id = dcid_ ^ gstate.getUVGenMode(); // This can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 + VertexArrayInfoVulkan *vai = vai_.Get(id); + if (!vai) { + vai = new VertexArrayInfoVulkan(); + vai_.Insert(id, vai); + } + + switch (vai->status) { + case VertexArrayInfoVulkan::VAI_NEW: + { + // Haven't seen this one before. We don't actually upload the vertex data yet. + uint64_t dataHash = ComputeHash(); + vai->hash = dataHash; + vai->minihash = ComputeMiniHash(); + vai->status = VertexArrayInfoVulkan::VAI_HASHING; + vai->drawsUntilNextFullHash = 0; + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); // writes to indexGen + vai->numVerts = indexGen.VertexCount(); + vai->prim = indexGen.Prim(); + vai->maxIndex = indexGen.MaxIndex(); + vai->flags = gstate_c.vertexFullAlpha ? VAIVULKAN_FLAG_VERTEXFULLALPHA : 0; + goto rotateVBO; + } + + // Hashing - still gaining confidence about the buffer. + // But if we get this far it's likely to be worth uploading the data. + case VertexArrayInfoVulkan::VAI_HASHING: + { + PROFILE_THIS_SCOPE("vcachehash"); + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + if (vai->drawsUntilNextFullHash == 0) { + // Let's try to skip a full hash if mini would fail. + const u32 newMiniHash = ComputeMiniHash(); + uint64_t newHash = vai->hash; + if (newMiniHash == vai->minihash) { + newHash = ComputeHash(); + } + if (newMiniHash != vai->minihash || newHash != vai->hash) { + MarkUnreliable(vai); + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); + goto rotateVBO; + } + if (vai->numVerts > 64) { + // exponential backoff up to 16 draws, then every 24 + vai->drawsUntilNextFullHash = std::min(24, vai->numFrames); + } else { + // Lower numbers seem much more likely to change. + vai->drawsUntilNextFullHash = 0; + } + // TODO: tweak + //if (vai->numFrames > 1000) { + // vai->status = VertexArrayInfo::VAI_RELIABLE; + //} + } else { + vai->drawsUntilNextFullHash--; + u32 newMiniHash = ComputeMiniHash(); + if (newMiniHash != vai->minihash) { + MarkUnreliable(vai); + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); + goto rotateVBO; + } + } + + if (!vai->vb) { + // Directly push to the vertex cache. + DecodeVertsToPushBuffer(vertexCache_, &vai->vbOffset, &vai->vb); + _dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); + vai->numVerts = indexGen.VertexCount(); + vai->maxIndex = indexGen.MaxIndex(); + vai->flags = gstate_c.vertexFullAlpha ? VAIVULKAN_FLAG_VERTEXFULLALPHA : 0; + if (forceIndexed) { + vai->prim = indexGen.GeneralPrim(); + useElements = true; + } else { + vai->prim = indexGen.Prim(); + useElements = !indexGen.SeenOnlyPurePrims(); + if (!useElements && indexGen.PureCount()) { + vai->numVerts = indexGen.PureCount(); + } + } + + if (useElements) { + u32 size = sizeof(uint16_t) * indexGen.VertexCount(); + void *dest = vertexCache_->Allocate(size, 4, &vai->ib, &vai->ibOffset); + memcpy(dest, decIndex, size); + } else { + vai->ib = VK_NULL_HANDLE; + vai->ibOffset = 0; + } + } else { + gpuStats.numCachedDrawCalls++; + useElements = vai->ib ? true : false; + gpuStats.numCachedVertsDrawn += vai->numVerts; + gstate_c.vertexFullAlpha = vai->flags & VAIVULKAN_FLAG_VERTEXFULLALPHA; + } + vbuf = vai->vb; + ibuf = vai->ib; + vbOffset = vai->vbOffset; + ibOffset = vai->ibOffset; + vertexCount = vai->numVerts; + prim = static_cast(vai->prim); + break; + } + + // Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time. + case VertexArrayInfoVulkan::VAI_RELIABLE: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + gpuStats.numCachedDrawCalls++; + gpuStats.numCachedVertsDrawn += vai->numVerts; + vbuf = vai->vb; + ibuf = vai->ib; + vbOffset = vai->vbOffset; + ibOffset = vai->ibOffset; + vertexCount = vai->numVerts; + prim = static_cast(vai->prim); + + gstate_c.vertexFullAlpha = vai->flags & VAIVULKAN_FLAG_VERTEXFULLALPHA; + break; + } + + case VertexArrayInfoVulkan::VAI_UNRELIABLE: + { + vai->numDraws++; + if (vai->lastFrame != gpuStats.numFlips) { + vai->numFrames++; + } + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); + goto rotateVBO; + } + default: + break; + } + } else { + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + // If software skinning, we've already predecoded into "decoded". So push that content. + VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; + u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); + memcpy(dest, decoded, size); + } else { + // Decode directly into the pushbuffer + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); + } + + rotateVBO: + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); + + vertexCount = indexGen.VertexCount(); + if (forceIndexed) { + useElements = true; + prim = indexGen.GeneralPrim(); + } else { + useElements = !indexGen.SeenOnlyPurePrims(); + if (!useElements && indexGen.PureCount()) { + vertexCount = indexGen.PureCount(); + } + prim = indexGen.Prim(); } - prim = indexGen.Prim(); } bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; @@ -285,7 +775,7 @@ void DrawEngineVulkan::DoFlush() { textureCache_->ApplyTexture(); textureCache_->GetVulkanHandles(imageView, sampler); if (imageView == VK_NULL_HANDLE) - imageView = (VkImageView)draw_->GetNativeObject(gstate_c.textureIsArray ? Draw::NativeObject::NULL_IMAGEVIEW_ARRAY : Draw::NativeObject::NULL_IMAGEVIEW); + imageView = (VkImageView)draw_->GetNativeObject(gstate_c.arrayTexture ? Draw::NativeObject::NULL_IMAGEVIEW_ARRAY : Draw::NativeObject::NULL_IMAGEVIEW); if (sampler == VK_NULL_HANDLE) sampler = nullSampler_; } @@ -300,20 +790,20 @@ void DrawEngineVulkan::DoFlush() { VulkanGeometryShader *gshader = nullptr; shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); + if (!vshader) { + // We're screwed. + return; + } _dbg_assert_msg_(vshader->UseHWTransform(), "Bad vshader"); + VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, true, 0, framebufferManager_->GetMSAALevel(), false); if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. - ResetAfterDraw(); return; } BindShaderBlendTex(); // This might cause copies so important to do before BindPipeline. - if (!renderManager->BindPipeline(pipeline->pipeline, pipeline->pipelineFlags, pipelineLayout_)) { - renderManager->ReportBadStateForDraw(); - ResetAfterDraw(); - return; - } + renderManager->BindPipeline(pipeline->pipeline, pipeline->pipelineFlags, pipelineLayout_); if (pipeline != lastPipeline_) { if (lastPipeline_ && !(lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant())) { gstate_c.Dirty(DIRTY_BLEND_STATE); @@ -329,45 +819,20 @@ void DrawEngineVulkan::DoFlush() { lastPrim_ = prim; dirtyUniforms_ |= shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering()); - UpdateUBOs(); + UpdateUBOs(&frameData); + + VkDescriptorSet ds = GetOrCreateDescriptorSet(imageView, sampler, baseBuf, lightBuf, boneBuf, tess); - int descCount = 6; - if (tess) - descCount = 9; - int descSetIndex; - PackedDescriptor *descriptors = renderManager->PushDescriptorSet(descCount, &descSetIndex); - descriptors[0].image.view = imageView; - descriptors[0].image.sampler = sampler; - descriptors[1].image.view = boundSecondary_; - descriptors[1].image.sampler = samplerSecondaryNearest_; - descriptors[2].image.view = boundDepal_; - descriptors[2].image.sampler = (boundDepal_ && boundDepalSmoothed_) ? samplerSecondaryLinear_ : samplerSecondaryNearest_; - descriptors[3].buffer.buffer = baseBuf; - descriptors[3].buffer.range = sizeof(UB_VS_FS_Base); - descriptors[4].buffer.buffer = lightBuf; - descriptors[4].buffer.range = sizeof(UB_VS_Lights); - descriptors[5].buffer.buffer = boneBuf; - descriptors[5].buffer.range = sizeof(UB_VS_Bones); - if (tess) { - const VkDescriptorBufferInfo *bufInfo = tessDataTransferVulkan->GetBufferInfo(); - for (int j = 0; j < 3; j++) { - descriptors[j + 6].buffer.buffer = bufInfo[j].buffer; - descriptors[j + 6].buffer.offset = bufInfo[j].offset; - descriptors[j + 6].buffer.range = bufInfo[j].range; - } - } - // TODO: Can we avoid binding all three when not needed? Same below for hardware transform. - // Think this will require different descriptor set layouts. const uint32_t dynamicUBOOffsets[3] = { baseUBOOffset, lightUBOOffset, boneUBOOffset, }; if (useElements) { if (!ibuf) { - ibOffset = (uint32_t)pushIndex_->Push(decIndex_, sizeof(uint16_t) * indexGen.VertexCount(), 4, &ibuf); + ibOffset = (uint32_t)pushIndex_->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), 4, &ibuf); } - renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1); + renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16); } else { - renderManager->Draw(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount); + renderManager->Draw(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount); } } else { PROFILE_THIS_SCOPE("soft"); @@ -376,8 +841,7 @@ void DrawEngineVulkan::DoFlush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); - DecodeInds(); + DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255); @@ -390,14 +854,13 @@ void DrawEngineVulkan::DoFlush() { // Undo the strip optimization, not supported by the SW code yet. if (prim == GE_PRIM_TRIANGLE_STRIP) prim = GE_PRIM_TRIANGLES; - _dbg_assert_(prim != GE_PRIM_INVALID); - u16 *inds = decIndex_; + u16 *inds = decIndex; SoftwareTransformResult result{}; SoftwareTransformParams params{}; - params.decoded = decoded_; - params.transformed = transformed_; - params.transformedExpanded = transformedExpanded_; + params.decoded = decoded; + params.transformed = transformed; + params.transformedExpanded = transformedExpanded; params.fbman = framebufferManager_; params.texCache = textureCache_; // In Vulkan, we have to force drawing of primitives if !framebufferManager_->UseBufferedRendering() because Vulkan clears @@ -420,7 +883,7 @@ void DrawEngineVulkan::DoFlush() { UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); + int maxIndex = indexGen.MaxIndex(); SoftwareTransform swTransform(params); const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f); @@ -447,7 +910,7 @@ void DrawEngineVulkan::DoFlush() { textureCache_->ApplyTexture(); textureCache_->GetVulkanHandles(imageView, sampler); if (imageView == VK_NULL_HANDLE) - imageView = (VkImageView)draw_->GetNativeObject(gstate_c.textureIsArray ? Draw::NativeObject::NULL_IMAGEVIEW_ARRAY : Draw::NativeObject::NULL_IMAGEVIEW); + imageView = (VkImageView)draw_->GetNativeObject(gstate_c.arrayTexture ? Draw::NativeObject::NULL_IMAGEVIEW_ARRAY : Draw::NativeObject::NULL_IMAGEVIEW); if (sampler == VK_NULL_HANDLE) sampler = nullSampler_; } @@ -465,16 +928,15 @@ void DrawEngineVulkan::DoFlush() { VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, false, 0, framebufferManager_->GetMSAALevel(), false); if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. - ResetAfterDraw(); + decodedVerts_ = 0; + numDrawCalls = 0; + decodeCounter_ = 0; + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; return; } BindShaderBlendTex(); // This might cause copies so super important to do before BindPipeline. - if (!renderManager->BindPipeline(pipeline->pipeline, pipeline->pipelineFlags, pipelineLayout_)) { - renderManager->ReportBadStateForDraw(); - ResetAfterDraw(); - return; - } + renderManager->BindPipeline(pipeline->pipeline, pipeline->pipelineFlags, pipelineLayout_); if (pipeline != lastPipeline_) { if (lastPipeline_ && !lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant()) { gstate_c.Dirty(DIRTY_BLEND_STATE); @@ -493,24 +955,9 @@ void DrawEngineVulkan::DoFlush() { dirtyUniforms_ |= shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering()); // Even if the first draw is through-mode, make sure we at least have one copy of these uniforms buffered - UpdateUBOs(); - - int descCount = 6; - int descSetIndex; - PackedDescriptor *descriptors = renderManager->PushDescriptorSet(descCount, &descSetIndex); - descriptors[0].image.view = imageView; - descriptors[0].image.sampler = sampler; - descriptors[1].image.view = boundSecondary_; - descriptors[1].image.sampler = samplerSecondaryNearest_; - descriptors[2].image.view = boundDepal_; - descriptors[2].image.sampler = (boundDepal_ && boundDepalSmoothed_) ? samplerSecondaryLinear_ : samplerSecondaryNearest_; - descriptors[3].buffer.buffer = baseBuf; - descriptors[3].buffer.range = sizeof(UB_VS_FS_Base); - descriptors[4].buffer.buffer = lightBuf; - descriptors[4].buffer.range = sizeof(UB_VS_Lights); - descriptors[5].buffer.buffer = boneBuf; - descriptors[5].buffer.range = sizeof(UB_VS_Bones); + UpdateUBOs(&frameData); + VkDescriptorSet ds = GetOrCreateDescriptorSet(imageView, sampler, baseBuf, lightBuf, boneBuf, tess); const uint32_t dynamicUBOOffsets[3] = { baseUBOOffset, lightUBOOffset, boneUBOOffset, }; @@ -521,11 +968,11 @@ void DrawEngineVulkan::DoFlush() { VkBuffer vbuf, ibuf; vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vbuf); ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf); - renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1); + renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1, VK_INDEX_TYPE_UINT16); } else { VkBuffer vbuf; vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), 4, &vbuf); - renderManager->Draw(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, result.drawNumTrans); + renderManager->Draw(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, result.drawNumTrans); } } else if (result.action == SW_CLEAR) { // Note: we won't get here if the clear is alpha but not color, or color but not alpha. @@ -555,26 +1002,29 @@ void DrawEngineVulkan::DoFlush() { decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } - ResetAfterDrawInline(); + gpuStats.numFlushes++; + gpuStats.numDrawCalls += numDrawCalls; + gpuStats.numVertsSubmitted += vertexCountInDrawCalls_; + indexGen.Reset(); + decodedVerts_ = 0; + numDrawCalls = 0; + vertexCountInDrawCalls_ = 0; + decodeCounter_ = 0; + dcid_ = 0; + gstate_c.vertexFullAlpha = true; framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); + // Now seems as good a time as any to reset the min/max coords, which we may examine later. + gstate_c.vertBounds.minU = 512; + gstate_c.vertBounds.minV = 512; + gstate_c.vertBounds.maxU = 0; + gstate_c.vertBounds.maxV = 0; + GPUDebug::NotifyDraw(); } -void DrawEngineVulkan::ResetAfterDraw() { - indexGen.Reset(); - decodedVerts_ = 0; - numDrawVerts_ = 0; - numDrawInds_ = 0; - vertexCountInDrawCalls_ = 0; - decodeIndsCounter_ = 0; - decodeVertsCounter_ = 0; - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; - gstate_c.vertexFullAlpha = true; -} - -void DrawEngineVulkan::UpdateUBOs() { +void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { if ((dirtyUniforms_ & DIRTY_BASE_UNIFORMS) || baseBuf == VK_NULL_HANDLE) { baseUBOOffset = shaderManager_->PushBaseBuffer(pushUBO_, &baseBuf); dirtyUniforms_ &= ~DIRTY_BASE_UNIFORMS; @@ -589,6 +1039,11 @@ void DrawEngineVulkan::UpdateUBOs() { } } +DrawEngineVulkan::FrameData &DrawEngineVulkan::GetCurFrame() { + VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); + return frame_[vulkan->GetCurFrame()]; +} + void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) { // SSBOs that are not simply float1 or float2 need to be padded up to a float4 size. vec3 members // also need to be 16-byte aligned, hence the padding. diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index afc3f24d2..bf7d6940a 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -32,6 +32,7 @@ // won't get any bone data, etc. #include "Common/Data/Collections/Hashmaps.h" +#include "Common/GPU/Vulkan/VulkanMemory.h" #include "GPU/Vulkan/VulkanUtil.h" @@ -44,14 +45,6 @@ #include "GPU/Vulkan/StateMappingVulkan.h" #include "GPU/Vulkan/VulkanRenderManager.h" - -// TODO: Move to some appropriate header. -#ifdef _MSC_VER -#define NO_INLINE __declspec(noinline) -#else -#define NO_INLINE __attribute__((noinline)) -#endif - struct DecVtxFormat; struct UVScale; @@ -61,6 +54,7 @@ class TextureCacheVulkan; class FramebufferManagerVulkan; class VulkanContext; +class VulkanPushBuffer; class VulkanPushPool; struct VulkanPipeline; @@ -69,6 +63,49 @@ struct DrawEngineVulkanStats { int pushIndexSpaceUsed; }; +enum { + VAIVULKAN_FLAG_VERTEXFULLALPHA = 1, +}; + +// Try to keep this POD. +class VertexArrayInfoVulkan { +public: + VertexArrayInfoVulkan() { + lastFrame = gpuStats.numFlips; + } + // No destructor needed - we always fully wipe. + + enum VAIStatus : uint8_t { + VAI_NEW, + VAI_HASHING, + VAI_RELIABLE, // cache, don't hash + VAI_UNRELIABLE, // never cache + }; + + uint64_t hash = 0; + u32 minihash = 0; + + // These will probably always be the same, but whatever. + VkBuffer vb = VK_NULL_HANDLE; + VkBuffer ib = VK_NULL_HANDLE; + // Offsets into the cache buffer. + uint32_t vbOffset = 0; + uint32_t ibOffset = 0; + + // Precalculated parameter for vkDrawIndexed + u16 numVerts = 0; + u16 maxIndex = 0; + s8 prim = GE_PRIM_INVALID; + VAIStatus status = VAI_NEW; + + // ID information + int numDraws = 0; + int numFrames = 0; + int lastFrame; // So that we can forget. + u16 drawsUntilNextFullHash = 0; + u8 flags = 0; +}; + class VulkanRenderManager; class TessellationDataTransferVulkan : public TessellationDataTransfer { @@ -95,7 +132,8 @@ enum { DRAW_BINDING_TESS_STORAGE_BUF = 6, DRAW_BINDING_TESS_STORAGE_BUF_WU = 7, DRAW_BINDING_TESS_STORAGE_BUF_WV = 8, - DRAW_BINDING_COUNT = 9, + DRAW_BINDING_INPUT_ATTACHMENT = 9, + DRAW_BINDING_COUNT = 10, }; // Handles transform, lighting and drawing. @@ -125,13 +163,13 @@ public: // So that this can be inlined void Flush() { - if (!numDrawInds_) + if (!numDrawCalls) return; DoFlush(); } void FinishDeferred() { - if (!numDrawInds_) + if (!numDrawCalls) return; // Decode any pending vertices. And also flush while we're at it, for simplicity. // It might be possible to only decode like in the other backends, but meh, it can't matter. @@ -140,12 +178,12 @@ public: } void DispatchFlush() override { - if (!numDrawInds_) + if (!numDrawCalls) return; - DoFlush(); + Flush(); } - VKRPipelineLayout *GetPipelineLayout() const { + VkPipelineLayout GetPipelineLayout() const { return pipelineLayout_; } @@ -177,26 +215,35 @@ public: private: void Invalidate(InvalidationCallbackFlags flags); + struct FrameData; void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant); void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerVulkan *shaderManager, int prim, VulkanPipelineRasterStateKey &key, VulkanDynamicState &dynState); void BindShaderBlendTex(); void DestroyDeviceObjects(); - void DoFlush(); - void UpdateUBOs(); + void DecodeVertsToPushPool(VulkanPushPool *push, uint32_t *bindOffset, VkBuffer *vkbuf); + void DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf); - NO_INLINE void ResetAfterDraw(); + void DoFlush(); + void UpdateUBOs(FrameData *frame); + FrameData &GetCurFrame(); + + VkDescriptorSet GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess); Draw::DrawContext *draw_; // We use a shared descriptor set layouts for all PSP draws. - VKRPipelineLayout *pipelineLayout_; + // Descriptors created from descriptorSetLayout_ is rebound all the time at set 1. + VkDescriptorSetLayout descriptorSetLayout_; + + VkPipelineLayout pipelineLayout_; VulkanPipeline *lastPipeline_; VkDescriptorSet lastDs_ = VK_NULL_HANDLE; // Secondary texture for shader blending VkImageView boundSecondary_ = VK_NULL_HANDLE; + bool boundSecondaryIsInputAttachment_ = false; // CLUT texture for shader depal VkImageView boundDepal_ = VK_NULL_HANDLE; @@ -204,6 +251,10 @@ private: VkSampler samplerSecondaryLinear_ = VK_NULL_HANDLE; VkSampler samplerSecondaryNearest_ = VK_NULL_HANDLE; + PrehashMap vai_; + VulkanPushBuffer *vertexCache_; + int descDecimationCounter_ = 0; + struct DescriptorSetKey { VkImageView imageView_; VkImageView secondaryImageView_; @@ -211,9 +262,25 @@ private: VkSampler sampler_; VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical // for all draws in a frame, except when the buffer has to grow. + bool secondaryIsInputAttachment; + }; + + // We alternate between these. + struct FrameData { + FrameData() : descSets(512), descPool("DrawEngine", true) { + descPool.Setup([this] { descSets.Clear(); }); + } + + VulkanDescSetPool descPool; + + // We do rolling allocation and reset instead of caching across frames. That we might do later. + DenseHashMap descSets; + + void Destroy(VulkanContext *vulkan); }; GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; + FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; // This one's not accurately named, it's used for all kinds of stuff that's not vertices or indices. VulkanPushPool *pushUBO_ = nullptr; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 2d977f66d..31ddcb091 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -25,7 +25,6 @@ #include "Common/GraphicsContext.h" #include "Common/Serialize/Serializer.h" #include "Common/TimeUtil.h" -#include "Common/Thread/ThreadUtil.h" #include "Core/Config.h" #include "Core/Debugger/Breakpoints.h" @@ -85,6 +84,8 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } BuildReportingInfo(); + // Update again after init to be sure of any silly driver problems. + UpdateVsyncInterval(true); textureCache_->NotifyConfigChanged(); @@ -93,10 +94,26 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) if (discID.size()) { File::CreateFullPath(GetSysDirectory(DIRECTORY_APP_CACHE)); shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) / (discID + ".vkshadercache"); - LoadCache(shaderCachePath_); + shaderCacheLoaded_ = false; + + std::thread th([&] { + LoadCache(shaderCachePath_); + shaderCacheLoaded_ = true; + }); + th.detach(); + } else { + shaderCacheLoaded_ = true; } } +bool GPU_Vulkan::IsReady() { + return shaderCacheLoaded_; +} + +void GPU_Vulkan::CancelReady() { + pipelineManager_->CancelCache(); +} + void GPU_Vulkan::LoadCache(const Path &filename) { if (!g_Config.bShaderCache) { WARN_LOG(G3D, "Shader cache disabled. Not loading."); @@ -167,26 +184,17 @@ void GPU_Vulkan::SaveCache(const Path &filename) { GPU_Vulkan::~GPU_Vulkan() { if (draw_) { VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - // This now also does a hard sync with the render thread, so that we can safely delete our pipeline layout below. - rm->DrainAndBlockCompileQueue(); + rm->DrainCompileQueue(); } SaveCache(shaderCachePath_); - - // Super important to delete pipeline manager FIRST, before clearing shaders, so we wait for all pending pipelines to finish compiling. - delete pipelineManager_; - pipelineManager_ = nullptr; - // Note: We save the cache in DeviceLost DestroyDeviceObjects(); drawEngine_.DeviceLost(); shaderManager_->ClearShaders(); + delete pipelineManager_; // other managers are deleted in ~GPUCommonHW. - if (draw_) { - VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - rm->ReleaseCompileQueue(); - } } u32 GPU_Vulkan::CheckGPUFeatures() const { @@ -272,6 +280,7 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { features |= GPU_USE_SINGLE_PASS_STEREO; features |= GPU_USE_SIMPLE_STEREO_PERSPECTIVE; + features &= ~GPU_USE_FRAMEBUFFER_FETCH; // Need to figure out if this can be supported with multiview rendering if (features & GPU_USE_GS_CULLING) { // Many devices that support stereo and GS don't support GS during stereo. features &= ~GPU_USE_GS_CULLING; @@ -279,12 +288,20 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { } } + // We need to turn off framebuffer fetch through input attachments if MSAA is on for now. + // This is fixable, just needs some shader generator work (subpassInputMS). + // Actually, I've decided to disable framebuffer fetch entirely for now. Perf isn't worth + // the compatibility problems. + + // if (msaaLevel_ != 0) { + features &= ~GPU_USE_FRAMEBUFFER_FETCH; + // } + // Attempt to workaround #17386 if (draw_->GetBugs().Has(Draw::Bugs::UNIFORM_INDEXING_BROKEN)) { features &= ~GPU_USE_LIGHT_UBERSHADER; } - features |= GPU_USE_FRAMEBUFFER_ARRAYS; return CheckGPUFeaturesLate(features); } @@ -299,7 +316,7 @@ void GPU_Vulkan::BeginHostFrame() { framebufferManager_->BeginFrame(); - shaderManagerVulkan_->DirtyLastShader(); + shaderManagerVulkan_->DirtyShader(); gstate_c.Dirty(DIRTY_ALL); if (gstate_c.useFlagsChanged) { @@ -423,14 +440,10 @@ void GPU_Vulkan::CheckRenderResized() { } void GPU_Vulkan::DeviceLost() { - // draw_ is normally actually still valid here in Vulkan. But we null it out in GPUCommonHW::DeviceLost so we don't try to use it again. - // So, we have to save it here to be able to call ReleaseCompileQueue(). - Draw::DrawContext *draw = draw_; - if (draw) { - VulkanRenderManager *rm = (VulkanRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - rm->DrainAndBlockCompileQueue(); + CancelReady(); + while (!IsReady()) { + sleep_ms(10); } - if (shaderCachePath_.Valid()) { SaveCache(shaderCachePath_); } @@ -438,11 +451,6 @@ void GPU_Vulkan::DeviceLost() { pipelineManager_->DeviceLost(); GPUCommonHW::DeviceLost(); - - if (draw) { - VulkanRenderManager *rm = (VulkanRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - rm->ReleaseCompileQueue(); - } } void GPU_Vulkan::DeviceRestore(Draw::DrawContext *draw) { @@ -497,3 +505,8 @@ std::string GPU_Vulkan::DebugGetShaderString(std::string id, DebugShaderType typ return GPUCommonHW::DebugGetShaderString(id, type, stringType); } } + +std::string GPU_Vulkan::GetGpuProfileString() { + VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + return rm->GetGpuProfileString(); +} diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 3d943de1c..1c7f76756 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -19,7 +19,6 @@ #include #include -#include #include "Common/File/Path.h" @@ -41,6 +40,9 @@ public: // This gets called on startup and when we get back from settings. u32 CheckGPUFeatures() const override; + bool IsReady() override; + void CancelReady() override; + // These are where we can reset command buffers etc. void BeginHostFrame() override; void EndHostFrame() override; @@ -57,6 +59,8 @@ public: return textureCacheVulkan_; } + std::string GetGpuProfileString() override; + protected: void FinishDeferred() override; void CheckRenderResized() override; @@ -81,4 +85,5 @@ private: PipelineManagerVulkan *pipelineManager_; Path shaderCachePath_; + std::atomic shaderCacheLoaded_{}; }; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 5325027bc..d5aeb8b2c 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -29,15 +29,6 @@ PipelineManagerVulkan::PipelineManagerVulkan(VulkanContext *vulkan) : pipelines_ } PipelineManagerVulkan::~PipelineManagerVulkan() { - // Block on all pipelines to make sure any background compiles are done. - // This is very important to do before we start trying to tear down the shaders - otherwise, we might - // be deleting shaders before queued pipeline creations that use them are performed. - pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) { - if (value->pipeline) { - value->pipeline->BlockUntilCompiled(); - } - }); - Clear(); if (pipelineCache_ != VK_NULL_HANDLE) vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_); @@ -134,7 +125,7 @@ static int SetupVertexAttribs(VkVertexInputAttributeDescription attrs[], const D VertexAttribSetup(&attrs[count++], decFmt.nrmfmt, decFmt.nrmoff, PspAttributeLocation::NORMAL); } // Position is always there. - VertexAttribSetup(&attrs[count++], DecVtxFormat::PosFmt(), decFmt.posoff, PspAttributeLocation::POSITION); + VertexAttribSetup(&attrs[count++], decFmt.posfmt, decFmt.posoff, PspAttributeLocation::POSITION); return count; } @@ -187,22 +178,17 @@ static std::string CutFromMain(std::string str) { } static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, VkPipelineCache pipelineCache, - VKRPipelineLayout *layout, PipelineFlags pipelineFlags, VkSampleCountFlagBits sampleCount, const VulkanPipelineRasterStateKey &key, + VkPipelineLayout layout, PipelineFlags pipelineFlags, VkSampleCountFlagBits sampleCount, const VulkanPipelineRasterStateKey &key, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask, bool cacheLoad) { - _assert_(fs && vs); - if (!fs || !fs->GetModule()) { + if (!fs->GetModule()) { ERROR_LOG(G3D, "Fragment shader missing in CreateVulkanPipeline"); return nullptr; } - if (!vs || !vs->GetModule()) { + if (!vs->GetModule()) { ERROR_LOG(G3D, "Vertex shader missing in CreateVulkanPipeline"); return nullptr; } - if (gs && !gs->GetModule()) { - ERROR_LOG(G3D, "Geometry shader missing in CreateVulkanPipeline"); - return nullptr; - } VulkanPipeline *vulkanPipeline = new VulkanPipeline(); vulkanPipeline->desc = new VKRGraphicsPipelineDesc(); @@ -291,8 +277,6 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, desc->geometryShaderSource = gs->GetShaderString(SHADER_STRING_SOURCE_CODE); } - _dbg_assert_(key.topology != VK_PRIMITIVE_TOPOLOGY_POINT_LIST); - _dbg_assert_(key.topology != VK_PRIMITIVE_TOPOLOGY_LINE_LIST); desc->topology = (VkPrimitiveTopology)key.topology; int vertexStride = 0; @@ -351,7 +335,7 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, return vulkanPipeline; } -VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager *renderManager, VKRPipelineLayout *layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask, int multiSampleLevel, bool cacheLoad) { +VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager *renderManager, VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask, int multiSampleLevel, bool cacheLoad) { if (!pipelineCache_) { VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); @@ -367,12 +351,14 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * key.gShader = gs ? gs->GetModule() : VK_NULL_HANDLE; key.vtxFmtId = useHwTransform ? decFmt->id : 0; - VulkanPipeline *pipeline; - if (pipelines_.Get(key, &pipeline)) { - return pipeline; - } + auto iter = pipelines_.Get(key); + if (iter) + return iter; PipelineFlags pipelineFlags = (PipelineFlags)0; + if (fs->Flags() & FragmentShaderFlags::INPUT_ATTACHMENT) { + pipelineFlags |= PipelineFlags::USES_INPUT_ATTACHMENT; + } if (fs->Flags() & FragmentShaderFlags::USES_DISCARD) { pipelineFlags |= PipelineFlags::USES_DISCARD; } @@ -382,7 +368,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * VkSampleCountFlagBits sampleCount = MultiSampleLevelToFlagBits(multiSampleLevel); - pipeline = CreateVulkanPipeline( + VulkanPipeline *pipeline = CreateVulkanPipeline( renderManager, pipelineCache_, layout, pipelineFlags, sampleCount, rasterKey, decFmt, vs, fs, gs, useHwTransform, variantBitmask, cacheLoad); @@ -502,11 +488,10 @@ std::string PipelineManagerVulkan::DebugGetObjectString(std::string id, DebugSha VulkanPipelineKey pipelineKey; pipelineKey.FromString(id); - VulkanPipeline *pipeline; - if (!pipelines_.Get(pipelineKey, &pipeline)) { + VulkanPipeline *pipeline = pipelines_.Get(pipelineKey); + if (!pipeline) { return "N/A (missing)"; } - _assert_(pipeline != nullptr); u32 variants = pipeline->GetVariantsBitmask(); std::string keyDescription = pipelineKey.GetDescription(stringType, shaderManager); @@ -676,7 +661,6 @@ void PipelineManagerVulkan::SavePipelineCache(FILE *file, bool saveRawPipelineCa failed = true; return; } - _dbg_assert_(pkey.raster.topology != VK_PRIMITIVE_TOPOLOGY_POINT_LIST && pkey.raster.topology != VK_PRIMITIVE_TOPOLOGY_LINE_LIST); StoredVulkanPipelineKey key{}; key.raster = pkey.raster; key.useHWTransform = pkey.useHWTransform; @@ -718,10 +702,12 @@ void PipelineManagerVulkan::SavePipelineCache(FILE *file, bool saveRawPipelineCa } } -bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VKRPipelineLayout *layout, int multiSampleLevel) { +bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VkPipelineLayout layout, int multiSampleLevel) { VulkanRenderManager *rm = (VulkanRenderManager *)drawContext->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); VulkanQueueRunner *queueRunner = rm->GetQueueRunner(); + cancelCache_ = false; + uint32_t size = 0; if (loadRawPipelineCache) { NOTICE_LOG(G3D, "WARNING: Using the badly tested raw pipeline cache path!!!!"); @@ -780,7 +766,7 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa int pipelineCreateFailCount = 0; int shaderFailCount = 0; for (uint32_t i = 0; i < size; i++) { - if (failed) { + if (failed || cancelCache_) { break; } StoredVulkanPipelineKey key; @@ -789,12 +775,6 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa ERROR_LOG(G3D, "Truncated Vulkan pipeline cache file, stopping."); break; } - - if (key.raster.topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST || key.raster.topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) { - WARN_LOG(G3D, "Bad raster key in cache, ignoring"); - continue; - } - VulkanVertexShader *vs = shaderManager->GetVertexShaderFromID(key.vShaderID); VulkanFragmentShader *fs = shaderManager->GetFragmentShaderFromID(key.fShaderID); VulkanGeometryShader *gs = shaderManager->GetGeometryShaderFromID(key.gShaderID); @@ -831,3 +811,7 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa // We just ignore any failures. return true; } + +void PipelineManagerVulkan::CancelCache() { + cancelCache_ = true; +} diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index cd9311af5..a208c201a 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -73,6 +73,7 @@ struct VulkanPipeline { bool UsesBlendConstant() const { return (pipelineFlags & PipelineFlags::USES_BLEND_CONSTANT) != 0; } bool UsesDepthStencil() const { return (pipelineFlags & PipelineFlags::USES_DEPTH_STENCIL) != 0; } + bool UsesInputAttachment() const { return (pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT) != 0; } bool UsesGeometryShader() const { return (pipelineFlags & PipelineFlags::USES_GEOMETRY_SHADER) != 0; } bool UsesDiscard() const { return (pipelineFlags & PipelineFlags::USES_DISCARD) != 0; } @@ -85,7 +86,7 @@ public: ~PipelineManagerVulkan(); // variantMask is only used when loading pipelines from cache. - VulkanPipeline *GetOrCreatePipeline(VulkanRenderManager *renderManager, VKRPipelineLayout *layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantMask, int multiSampleLevel, bool cacheLoad); + VulkanPipeline *GetOrCreatePipeline(VulkanRenderManager *renderManager, VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantMask, int multiSampleLevel, bool cacheLoad); int GetNumPipelines() const { return (int)pipelines_.size(); } void Clear(); @@ -100,10 +101,12 @@ public: // Saves data for faster creation next time. void SavePipelineCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext); - bool LoadPipelineCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VKRPipelineLayout *layout, int multiSampleLevel); + bool LoadPipelineCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VkPipelineLayout layout, int multiSampleLevel); + void CancelCache(); private: - DenseHashMap pipelines_; + DenseHashMap pipelines_; VkPipelineCache pipelineCache_ = VK_NULL_HANDLE; VulkanContext *vulkan_; + bool cancelCache_ = false; }; diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index debf889f5..dd8442a0b 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -47,7 +47,6 @@ // Most drivers treat vkCreateShaderModule as pretty much a memcpy. What actually // takes time here, and makes this worthy of parallelization, is GLSLtoSPV. // Takes ownership over tag. -// This always returns something, checking the return value for null is not meaningful. static Promise *CompileShaderModuleAsync(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *tag) { auto compile = [=] { PROFILE_THIS_SCOPE("shadercomp"); @@ -113,10 +112,13 @@ static Promise *CompileShaderModuleAsync(VulkanContext *vulkan, VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, FragmentShaderFlags flags, const char *code) : vulkan_(vulkan), id_(id), flags_(flags) { - _assert_(!id.is_invalid()); source_ = code; module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_FRAGMENT_BIT, source_.c_str(), new std::string(FragmentShaderDesc(id))); - VERBOSE_LOG(G3D, "Compiled fragment shader:\n%s\n", (const char *)code); + if (!module_) { + failed_ = true; + } else { + VERBOSE_LOG(G3D, "Compiled fragment shader:\n%s\n", (const char *)code); + } } VulkanFragmentShader::~VulkanFragmentShader() { @@ -145,10 +147,13 @@ std::string VulkanFragmentShader::GetShaderString(DebugShaderStringType type) co VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, VertexShaderFlags flags, const char *code, bool useHWTransform) : vulkan_(vulkan), useHWTransform_(useHWTransform), flags_(flags), id_(id) { - _assert_(!id.is_invalid()); source_ = code; module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_VERTEX_BIT, source_.c_str(), new std::string(VertexShaderDesc(id))); - VERBOSE_LOG(G3D, "Compiled vertex shader:\n%s\n", (const char *)code); + if (!module_) { + failed_ = true; + } else { + VERBOSE_LOG(G3D, "Compiled vertex shader:\n%s\n", (const char *)code); + } } VulkanVertexShader::~VulkanVertexShader() { @@ -177,10 +182,13 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons VulkanGeometryShader::VulkanGeometryShader(VulkanContext *vulkan, GShaderID id, const char *code) : vulkan_(vulkan), id_(id) { - _assert_(!id.is_invalid()); source_ = code; module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_GEOMETRY_BIT, source_.c_str(), new std::string(GeometryShaderDesc(id).c_str())); - VERBOSE_LOG(G3D, "Compiled geometry shader:\n%s\n", (const char *)code); + if (!module_) { + failed_ = true; + } else { + VERBOSE_LOG(G3D, "Compiled geometry shader:\n%s\n", (const char *)code); + } } VulkanGeometryShader::~VulkanGeometryShader() { @@ -224,12 +232,11 @@ ShaderManagerVulkan::ShaderManagerVulkan(Draw::DrawContext *draw) } ShaderManagerVulkan::~ShaderManagerVulkan() { - Clear(); + ClearShaders(); delete[] codeBuffer_; } void ShaderManagerVulkan::DeviceLost() { - Clear(); draw_ = nullptr; } @@ -260,15 +267,19 @@ void ShaderManagerVulkan::Clear() { void ShaderManagerVulkan::ClearShaders() { Clear(); - DirtyLastShader(); + DirtyShader(); gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); } -void ShaderManagerVulkan::DirtyLastShader() { +void ShaderManagerVulkan::DirtyShader() { // Forget the last shader ID lastFSID_.set_invalid(); lastVSID_.set_invalid(); lastGSID_.set_invalid(); + DirtyLastShader(); +} + +void ShaderManagerVulkan::DirtyLastShader() { lastVShader_ = nullptr; lastFShader_ = nullptr; lastGShader_ = nullptr; @@ -290,95 +301,29 @@ uint64_t ShaderManagerVulkan::UpdateUniforms(bool useBufferedRendering) { } void ShaderManagerVulkan::GetShaders(int prim, VertexDecoder *decoder, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode) { - VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - VShaderID VSID; - VulkanVertexShader *vs = nullptr; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); ComputeVertexShaderID(&VSID, decoder, useHWTransform, useHWTessellation, weightsAsFloat, useSkinInDecode); - if (VSID == lastVSID_) { - _dbg_assert_(lastVShader_ != nullptr); - vs = lastVShader_; - } else if (!vsCache_.Get(VSID, &vs)) { - // Vertex shader not in cache. Let's compile it. - std::string genErrorString; - uint64_t uniformMask = 0; // Not used - uint32_t attributeMask = 0; // Not used - VertexShaderFlags flags{}; - bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &flags, &genErrorString); - _assert_msg_(success, "VS gen error: %s", genErrorString.c_str()); - _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_)); - - // Don't need to re-lookup anymore, now that we lock wider. - vs = new VulkanVertexShader(vulkan, VSID, flags, codeBuffer_, useHWTransform); - vsCache_.Insert(VSID, vs); - } - lastVShader_ = vs; - lastVSID_ = VSID; } else { VSID = lastVSID_; - vs = lastVShader_; } - *vshader = vs; FShaderID FSID; - VulkanFragmentShader *fs = nullptr; if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); ComputeFragmentShaderID(&FSID, pipelineState, draw_->GetBugs()); - if (FSID == lastFSID_) { - _dbg_assert_(lastFShader_ != nullptr); - fs = lastFShader_; - } else if (!fsCache_.Get(FSID, &fs)) { - // Fragment shader not in cache. Let's compile it. - std::string genErrorString; - uint64_t uniformMask = 0; // Not used - FragmentShaderFlags flags{}; - bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &flags, &genErrorString); - _assert_msg_(success, "FS gen error: %s", genErrorString.c_str()); - _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_)); - - fs = new VulkanFragmentShader(vulkan, FSID, flags, codeBuffer_); - fsCache_.Insert(FSID, fs); - } - lastFShader_ = fs; - lastFSID_ = FSID; } else { FSID = lastFSID_; - fs = lastFShader_; } - *fshader = fs; GShaderID GSID; - VulkanGeometryShader *gs = nullptr; if (gstate_c.IsDirty(DIRTY_GEOMETRYSHADER_STATE)) { gstate_c.Clean(DIRTY_GEOMETRYSHADER_STATE); ComputeGeometryShaderID(&GSID, draw_->GetBugs(), prim); - if (GSID == lastGSID_) { - // it's ok for this to be null. - gs = lastGShader_; - } else if (GSID.Bit(GS_BIT_ENABLED)) { - if (!gsCache_.Get(GSID, &gs)) { - // Geometry shader not in cache. Let's compile it. - std::string genErrorString; - bool success = GenerateGeometryShader(GSID, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString); - _assert_msg_(success, "GS gen error: %s", genErrorString.c_str()); - _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); - - gs = new VulkanGeometryShader(vulkan, GSID, codeBuffer_); - gsCache_.Insert(GSID, gs); - } - } else { - gs = nullptr; - } - lastGShader_ = gs; - lastGSID_ = GSID; } else { GSID = lastGSID_; - gs = lastGShader_; } - *gshader = gs; _dbg_assert_(FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); _dbg_assert_(FSID.Bit(FS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE)); @@ -386,6 +331,86 @@ void ShaderManagerVulkan::GetShaders(int prim, VertexDecoder *decoder, VulkanVer _dbg_assert_(GSID.Bit(GS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE)); } + // Just update uniforms if this is the same shader as last time. + if (lastVShader_ != nullptr && lastFShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_ && GSID == lastGSID_) { + *vshader = lastVShader_; + *fshader = lastFShader_; + *gshader = lastGShader_; + _dbg_assert_msg_((*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was cached"); + // Already all set, no need to look up in shader maps. + return; + } + + VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); + VulkanVertexShader *vs = vsCache_.Get(VSID); + if (!vs) { + // Vertex shader not in cache. Let's compile it. + std::string genErrorString; + uint64_t uniformMask = 0; // Not used + uint32_t attributeMask = 0; // Not used + VertexShaderFlags flags{}; + bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &flags, &genErrorString); + _assert_msg_(success, "VS gen error: %s", genErrorString.c_str()); + _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_)); + + std::lock_guard guard(cacheLock_); + vs = vsCache_.Get(VSID); + if (!vs) { + vs = new VulkanVertexShader(vulkan, VSID, flags, codeBuffer_, useHWTransform); + vsCache_.Insert(VSID, vs); + } + } + + VulkanFragmentShader *fs = fsCache_.Get(FSID); + if (!fs) { + // Fragment shader not in cache. Let's compile it. + std::string genErrorString; + uint64_t uniformMask = 0; // Not used + FragmentShaderFlags flags{}; + bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &flags, &genErrorString); + _assert_msg_(success, "FS gen error: %s", genErrorString.c_str()); + _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_)); + + std::lock_guard guard(cacheLock_); + fs = fsCache_.Get(FSID); + if (!fs) { + fs = new VulkanFragmentShader(vulkan, FSID, flags, codeBuffer_); + fsCache_.Insert(FSID, fs); + } + } + + VulkanGeometryShader *gs; + if (GSID.Bit(GS_BIT_ENABLED)) { + gs = gsCache_.Get(GSID); + if (!gs) { + // Geometry shader not in cache. Let's compile it. + std::string genErrorString; + bool success = GenerateGeometryShader(GSID, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString); + _assert_msg_(success, "GS gen error: %s", genErrorString.c_str()); + _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); + + std::lock_guard guard(cacheLock_); + gs = gsCache_.Get(GSID); + if (!gs) { + gs = new VulkanGeometryShader(vulkan, GSID, codeBuffer_); + gsCache_.Insert(GSID, gs); + } + } + } else { + gs = nullptr; + } + + lastVSID_ = VSID; + lastFSID_ = FSID; + lastGSID_ = GSID; + + lastVShader_ = vs; + lastFShader_ = fs; + lastGShader_ = gs; + + *vshader = vs; + *fshader = fs; + *gshader = gs; _dbg_assert_msg_((*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was computed"); } @@ -431,30 +456,18 @@ std::string ShaderManagerVulkan::DebugGetShaderString(std::string id, DebugShade switch (type) { case SHADER_TYPE_VERTEX: { - VulkanVertexShader *vs; - if (vsCache_.Get(VShaderID(shaderId), &vs)) { - return vs ? vs->GetShaderString(stringType) : "null (bad)"; - } else { - return ""; - } + VulkanVertexShader *vs = vsCache_.Get(VShaderID(shaderId)); + return vs ? vs->GetShaderString(stringType) : ""; } case SHADER_TYPE_FRAGMENT: { - VulkanFragmentShader *fs; - if (fsCache_.Get(FShaderID(shaderId), &fs)) { - return fs ? fs->GetShaderString(stringType) : "null (bad)"; - } else { - return ""; - } + VulkanFragmentShader *fs = fsCache_.Get(FShaderID(shaderId)); + return fs ? fs->GetShaderString(stringType) : ""; } case SHADER_TYPE_GEOMETRY: { - VulkanGeometryShader *gs; - if (gsCache_.Get(GShaderID(shaderId), &gs)) { - return gs ? gs->GetShaderString(stringType) : "null (bad)"; - } else { - return ""; - } + VulkanGeometryShader *gs = gsCache_.Get(GShaderID(shaderId)); + return gs ? gs->GetShaderString(stringType) : ""; } default: return "N/A"; @@ -507,7 +520,7 @@ enum class VulkanCacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 49 +#define CACHE_VERSION 44 struct VulkanCacheHeader { uint32_t magic; @@ -570,17 +583,21 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { uint64_t uniformMask = 0; VertexShaderFlags flags; if (!GenerateVertexShader(id, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &flags, &genErrorString)) { - ERROR_LOG(G3D, "Failed to generate vertex shader during cache load"); + WARN_LOG(G3D, "Failed to generate vertex shader during cache load"); // We just ignore this one and carry on. failCount++; continue; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_)); - // Don't add the new shader if already compiled - though this should no longer happen. - if (!vsCache_.ContainsKey(id)) { - VulkanVertexShader *vs = new VulkanVertexShader(vulkan, id, flags, codeBuffer_, useHWTransform); - vsCache_.Insert(id, vs); + VulkanVertexShader *vs = new VulkanVertexShader(vulkan, id, flags, codeBuffer_, useHWTransform); + // Remove first, just to be safe (we are loading on a background thread.) + std::lock_guard guard(cacheLock_); + VulkanVertexShader *old = vsCache_.Get(id); + if (old) { + vsCache_.Remove(id); + delete old; } + vsCache_.Insert(id, vs); } uint32_t vendorID = vulkan->GetPhysicalDeviceProperties().properties.vendorID; @@ -594,39 +611,44 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { uint64_t uniformMask = 0; FragmentShaderFlags flags; if (!GenerateFragmentShader(id, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &flags, &genErrorString)) { - ERROR_LOG(G3D, "Failed to generate fragment shader during cache load"); + WARN_LOG(G3D, "Failed to generate fragment shader during cache load"); // We just ignore this one and carry on. failCount++; continue; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_)); - if (!fsCache_.ContainsKey(id)) { - VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan, id, flags, codeBuffer_); - fsCache_.Insert(id, fs); + VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan, id, flags, codeBuffer_); + std::lock_guard guard(cacheLock_); + VulkanFragmentShader *old = fsCache_.Get(id); + if (old) { + fsCache_.Remove(id); + delete old; } + fsCache_.Insert(id, fs); } - // If it's not enabled, don't create shaders cached from earlier runs - creation will likely fail. - if (gstate_c.Use(GPU_USE_GS_CULLING)) { - for (int i = 0; i < header.numGeometryShaders; i++) { - GShaderID id; - if (fread(&id, sizeof(id), 1, f) != 1) { - ERROR_LOG(G3D, "Vulkan shader cache truncated (in GeometryShaders)"); - return false; - } - std::string genErrorString; - if (!GenerateGeometryShader(id, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString)) { - ERROR_LOG(G3D, "Failed to generate geometry shader during cache load"); - // We just ignore this one and carry on. - failCount++; - continue; - } - _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); - if (!gsCache_.ContainsKey(id)) { - VulkanGeometryShader *gs = new VulkanGeometryShader(vulkan, id, codeBuffer_); - gsCache_.Insert(id, gs); - } + for (int i = 0; i < header.numGeometryShaders; i++) { + GShaderID id; + if (fread(&id, sizeof(id), 1, f) != 1) { + ERROR_LOG(G3D, "Vulkan shader cache truncated (in GeometryShaders)"); + return false; } + std::string genErrorString; + if (!GenerateGeometryShader(id, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString)) { + WARN_LOG(G3D, "Failed to generate geometry shader during cache load"); + // We just ignore this one and carry on. + failCount++; + continue; + } + _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); + VulkanGeometryShader *gs = new VulkanGeometryShader(vulkan, id, codeBuffer_); + std::lock_guard guard(cacheLock_); + VulkanGeometryShader *old = gsCache_.Get(id); + if (old) { + gsCache_.Remove(id); + delete old; + } + gsCache_.Insert(id, gs); } NOTICE_LOG(G3D, "ShaderCache: Loaded %d vertex, %d fragment shaders and %d geometry shaders (failed %d)", header.numVertexShaders, header.numFragmentShaders, header.numGeometryShaders, failCount); diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index dc566a426..13013fa49 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -43,6 +43,8 @@ public: const std::string &source() const { return source_; } + bool Failed() const { return failed_; } + std::string GetShaderString(DebugShaderStringType type) const; Promise *GetModule() { return module_; } const FShaderID &GetID() const { return id_; } @@ -66,6 +68,7 @@ public: const std::string &source() const { return source_; } + bool Failed() const { return failed_; } bool UseHWTransform() const { return useHWTransform_; } // TODO: Roll into flags VertexShaderFlags Flags() const { return flags_; } @@ -78,6 +81,7 @@ protected: VulkanContext *vulkan_; std::string source_; + bool failed_ = false; bool useHWTransform_; VShaderID id_; VertexShaderFlags flags_; @@ -90,8 +94,9 @@ public: const std::string &source() const { return source_; } - std::string GetShaderString(DebugShaderStringType type) const; + bool Failed() const { return failed_; } + std::string GetShaderString(DebugShaderStringType type) const; Promise *GetModule() const { return module_; } const GShaderID &GetID() { return id_; } @@ -100,6 +105,7 @@ protected: VulkanContext *vulkan_; std::string source_; + bool failed_ = false; GShaderID id_; }; @@ -113,6 +119,7 @@ public: void GetShaders(int prim, VertexDecoder *decoder, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); void ClearShaders() override; + void DirtyShader(); void DirtyLastShader() override; int GetNumVertexShaders() const { return (int)vsCache_.size(); } @@ -120,10 +127,9 @@ public: int GetNumGeometryShaders() const { return (int)gsCache_.size(); } // Used for saving/loading the cache. Don't need to be particularly fast. - VulkanVertexShader *GetVertexShaderFromID(VShaderID id) { return vsCache_.GetOrNull(id); } - VulkanFragmentShader *GetFragmentShaderFromID(FShaderID id) { return fsCache_.GetOrNull(id); } - VulkanGeometryShader *GetGeometryShaderFromID(GShaderID id) { return gsCache_.GetOrNull(id); } - + VulkanVertexShader *GetVertexShaderFromID(VShaderID id) { return vsCache_.Get(id); } + VulkanFragmentShader *GetFragmentShaderFromID(FShaderID id) { return fsCache_.Get(id); } + VulkanGeometryShader *GetGeometryShaderFromID(GShaderID id) { return gsCache_.Get(id); } VulkanVertexShader *GetVertexShaderFromModule(VkShaderModule module); VulkanFragmentShader *GetFragmentShaderFromModule(VkShaderModule module); VulkanGeometryShader *GetGeometryShaderFromModule(VkShaderModule module); @@ -159,16 +165,17 @@ private: ShaderLanguageDesc compat_; - typedef DenseHashMap FSCache; + typedef DenseHashMap FSCache; FSCache fsCache_; - typedef DenseHashMap VSCache; + typedef DenseHashMap VSCache; VSCache vsCache_; - typedef DenseHashMap GSCache; + typedef DenseHashMap GSCache; GSCache gsCache_; char *codeBuffer_; + std::mutex cacheLock_; uint64_t uboAlignment_; // Uniform block scratchpad. These (the relevant ones) are copied to the current pushbuffer at draw time. diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 8ed78f9d8..18bff9550 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -370,16 +370,21 @@ void DrawEngineVulkan::BindShaderBlendTex() { bool bindResult = framebufferManager_->BindFramebufferAsColorTexture(1, curRenderVfb, BINDFBCOLOR_MAY_COPY | BINDFBCOLOR_UNCACHED, Draw::ALL_LAYERS); _dbg_assert_(bindResult); boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE1_IMAGEVIEW); + boundSecondaryIsInputAttachment_ = false; fboTexBound_ = true; fboTexBindState_ = FBO_TEX_NONE; // Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects. dirtyRequiresRecheck_ |= DIRTY_BLEND_STATE; + } else if (fboTexBindState_ == FBO_TEX_READ_FRAMEBUFFER) { + draw_->BindCurrentFramebufferForColorInput(); + boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_FRAMEBUFFER_COLOR_IMAGEVIEW_RT, (void *)0); + boundSecondaryIsInputAttachment_ = true; + fboTexBindState_ = FBO_TEX_NONE; } else { + boundSecondaryIsInputAttachment_ = false; boundSecondary_ = VK_NULL_HANDLE; } - } else { - boundSecondary_ = VK_NULL_HANDLE; } } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 84898ff3f..3fa809c09 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -27,7 +27,7 @@ #include "Common/Profiler/Profiler.h" #include "Common/GPU/thin3d.h" #include "Common/GPU/Vulkan/VulkanRenderManager.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/Data/Convert/ColorConv.h" #include "Common/StringUtils.h" #include "Common/TimeUtil.h" @@ -121,10 +121,9 @@ SamplerCache::~SamplerCache() { } VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) { - VkSampler sampler; - if (cache_.Get(key, &sampler)) { + VkSampler sampler = cache_.Get(key); + if (sampler != VK_NULL_HANDLE) return sampler; - } VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; samp.addressModeU = key.sClamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT; @@ -443,8 +442,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { dstFmt = VULKAN_CLUT8_FORMAT; } - _dbg_assert_(plan.levelsToLoad <= plan.maxPossibleLevels); - // We don't generate mipmaps for 512x512 textures because they're almost exclusively used for menu backgrounds // and similar, which don't really need it. // Also, if using replacements, check that we really can generate mips for this format - that's not possible for compressed ones. @@ -457,8 +454,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { plan.levelsToCreate = plan.maxPossibleLevels; } - _dbg_assert_(plan.levelsToCreate >= plan.levelsToLoad); - // Any texture scaling is gonna move away from the original 16-bit format, if any. VkFormat actualFmt = plan.scaleFactor > 1 ? VULKAN_8888_FORMAT : dstFmt; bool bcFormat = false; @@ -474,6 +469,19 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { delete entry->vkTex; + char texName[64]{}; + snprintf(texName, sizeof(texName), "tex_%08x_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format, gstate.getClutPaletteFormat())); + entry->vkTex = new VulkanTexture(vulkan, texName); + VulkanTexture *image = entry->vkTex; + + const VkComponentMapping *mapping; + switch (actualFmt) { + case VULKAN_4444_FORMAT: mapping = &VULKAN_4444_SWIZZLE; break; + case VULKAN_1555_FORMAT: mapping = &VULKAN_1555_SWIZZLE; break; + case VULKAN_565_FORMAT: mapping = &VULKAN_565_SWIZZLE; break; + default: mapping = &VULKAN_8888_SWIZZLE; break; // no swizzle + } + VkImageLayout imageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; @@ -494,18 +502,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { actualFmt = VULKAN_8888_FORMAT; } - const VkComponentMapping *mapping; - switch (actualFmt) { - case VULKAN_4444_FORMAT: mapping = &VULKAN_4444_SWIZZLE; break; - case VULKAN_1555_FORMAT: mapping = &VULKAN_1555_SWIZZLE; break; - case VULKAN_565_FORMAT: mapping = &VULKAN_565_SWIZZLE; break; - default: mapping = &VULKAN_8888_SWIZZLE; break; // no swizzle - } - - char texName[64]{}; - snprintf(texName, sizeof(texName), "tex_%08x_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format, gstate.getClutPaletteFormat())); - entry->vkTex = new VulkanTexture(vulkan, texName); - VulkanTexture *image = entry->vkTex; bool allocSuccess = image->CreateDirect(cmdInit, plan.createW, plan.createH, plan.depth, plan.levelsToCreate, actualFmt, imageLayout, usage, mapping); if (!allocSuccess && !lowMemoryMode_) { WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); @@ -517,9 +513,9 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { auto err = GetI18NCategory(I18NCat::ERRORS); if (plan.scaleFactor > 1) { - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Warning: Video memory FULL, reducing upscaling and switching to slow caching mode"), 2.0f); + System_NotifyUserMessage(err->T("Warning: Video memory FULL, reducing upscaling and switching to slow caching mode"), 2.0f); } else { - g_OSD.Show(OSDType::MESSAGE_WARNING, err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); + System_NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); } // Turn off texture replacement for this texture. diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 3dbf725d9..727bd04e3 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -33,6 +33,7 @@ class DrawEngineVulkan; class VulkanContext; class VulkanTexture; +class VulkanPushBuffer; class SamplerCache { public: @@ -48,7 +49,7 @@ public: private: VulkanContext *vulkan_; - DenseHashMap cache_; + DenseHashMap cache_; }; class TextureCacheVulkan : public TextureCacheCommon { diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index f100ad24d..d10749b18 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -60,12 +60,6 @@ void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) { VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); _assert_(VK_SUCCESS == res); - static const BindingType bindingTypes[3] = { - BindingType::STORAGE_IMAGE_COMPUTE, - BindingType::STORAGE_BUFFER_COMPUTE, - BindingType::STORAGE_BUFFER_COMPUTE, - }; - VkDescriptorSetLayoutBinding bindings[3] = {}; bindings[0].descriptorCount = 1; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; @@ -88,8 +82,19 @@ void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) { res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_); _assert_(VK_SUCCESS == res); + std::vector dpTypes; + dpTypes.resize(2); + dpTypes[0].descriptorCount = 8192; + dpTypes[0].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + dpTypes[1].descriptorCount = 4096; + dpTypes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + + VkDescriptorPoolCreateInfo dp = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + dp.flags = 0; // Don't want to mess around with individually freeing these, let's go fixed each frame and zap the whole array. Might try the dynamic approach later. + dp.maxSets = 4096; // GTA can end up creating more than 1000 textures in the first frame! + for (int i = 0; i < ARRAY_SIZE(frameData_); i++) { - frameData_[i].descPool.Create(vulkan_, bindingTypes, ARRAY_SIZE(bindingTypes), 4096); + frameData_[i].descPool.Create(vulkan_, dp, dpTypes); frameData_[i].descPoolUsed = false; } @@ -133,8 +138,7 @@ VkDescriptorSet VulkanComputeShaderManager::GetDescriptorSet(VkImageView image, int curFrame = vulkan_->GetCurFrame(); FrameData &frameData = frameData_[curFrame]; frameData.descPoolUsed = true; - VkDescriptorSet desc; - frameData.descPool.Allocate(&desc, 1, &descriptorSetLayout_); + VkDescriptorSet desc = frameData.descPool.Allocate(1, &descriptorSetLayout_, "compute_descset"); _assert_(desc != VK_NULL_HANDLE); VkWriteDescriptorSet writes[3]{}; @@ -181,10 +185,9 @@ VkDescriptorSet VulkanComputeShaderManager::GetDescriptorSet(VkImageView image, VkPipeline VulkanComputeShaderManager::GetPipeline(VkShaderModule cs) { PipelineKey key{ cs }; - VkPipeline pipeline; - if (pipelines_.Get(key, &pipeline)) { + VkPipeline pipeline = pipelines_.Get(key); + if (pipeline) return pipeline; - } VkComputePipelineCreateInfo pci{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; pci.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; diff --git a/GPU/Vulkan/VulkanUtil.h b/GPU/Vulkan/VulkanUtil.h index 7cadc957f..75ed153ad 100644 --- a/GPU/Vulkan/VulkanUtil.h +++ b/GPU/Vulkan/VulkanUtil.h @@ -24,7 +24,7 @@ #include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/GPU/Vulkan/VulkanImage.h" #include "Common/GPU/Vulkan/VulkanLoader.h" -#include "Common/GPU/Vulkan/VulkanDescSet.h" +#include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/thin3d.h" extern const VkComponentMapping VULKAN_4444_SWIZZLE; @@ -72,7 +72,9 @@ private: VkPipelineCache pipelineCache_ = VK_NULL_HANDLE; struct FrameData { - FrameData() : descPool("VulkanComputeShaderManager", true) {} + FrameData() : descPool("VulkanComputeShaderManager", true) { + descPool.Setup([] { }); + } VulkanDescSetPool descPool; bool descPoolUsed = false; @@ -83,7 +85,7 @@ private: VkShaderModule module; }; - DenseHashMap pipelines_; + DenseHashMap pipelines_; }; diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index e425dbeef..cdb7cbce5 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -460,10 +460,10 @@ inline bool IsTextureFormat16Bit(GETextureFormat tfmt) { inline int BufferFormatBytesPerPixel(GEBufferFormat format) { switch (format) { - case GE_FORMAT_8888: return 4; + case GE_FORMAT_8888: return 4; // applies to depth as well. case GE_FORMAT_CLUT8: return 1; default: - return 2; // works for depth as well as the 16-bit color formats. + return 2; } } diff --git a/Qt/NKCodeFromQt.h b/Qt/NKCodeFromQt.h index dfc67beb0..b53b09fff 100644 --- a/Qt/NKCodeFromQt.h +++ b/Qt/NKCodeFromQt.h @@ -1,11 +1,10 @@ #pragma once #include "Common/Data/Collections/ConstMap.h" -#include "Common/Input/KeyCodes.h" #include // TODO: Add any missing keys -static const std::map KeyMapRawQttoNative = InitConstMap +static const std::map KeyMapRawQttoNative = InitConstMap (Qt::Key_P, NKCODE_P) (Qt::Key_O, NKCODE_O) (Qt::Key_I, NKCODE_I) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 0ba01e48d..5d65a83a0 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -161,8 +161,6 @@ std::string System_GetProperty(SystemProperty prop) { return result; } #endif - case SYSPROP_BUILD_VERSION: - return PPSSPP_GIT_VERSION; default: return ""; } @@ -251,8 +249,6 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_HAS_FILE_BROWSER: case SYSPROP_HAS_FOLDER_BROWSER: case SYSPROP_HAS_OPEN_DIRECTORY: - case SYSPROP_HAS_TEXT_INPUT_DIALOG: - case SYSPROP_CAN_SHOW_FILE: return true; case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor @@ -304,7 +300,7 @@ bool MainUI::HandleCustomEvent(QEvent *e) { const char *filter = "All files (*.*)"; switch (fileType) { case BrowseFileType::BOOTABLE: - filter = "PSP ROMs (*.iso *.cso *.chd *.pbp *.elf *.zip *.ppdmp)"; + filter = "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)"; break; case BrowseFileType::IMAGE: filter = "Pictures (*.jpg *.png)"; @@ -315,9 +311,6 @@ bool MainUI::HandleCustomEvent(QEvent *e) { case BrowseFileType::DB: filter = "DB files (*.db)"; break; - case BrowseFileType::SOUND_EFFECT: - filter = "WAVE files (*.wav)"; - break; case BrowseFileType::ANY: break; } @@ -408,9 +401,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string emit(qtcamera->onStopCamera()); } return true; - case SystemRequestType::SHOW_FILE_IN_FOLDER: - QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromUtf8(param1.c_str()))); - return true; default: return false; } @@ -428,6 +418,10 @@ void System_Vibrate(int length_ms) { length_ms = 25; } +void System_ShowFileInFolder(const char *path) { + QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromUtf8(path))); +} + void System_LaunchUrl(LaunchUrlType urlType, const char *url) { QDesktopServices::openUrl(QUrl(url)); @@ -475,7 +469,7 @@ void MainUI::EmuThreadFunc() { emuThreadState = (int)EmuThreadState::RUNNING; while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { updateAccelerometer(); - UpdateRunLoop(graphicsContext); + UpdateRunLoop(); } emuThreadState = (int)EmuThreadState::STOPPED; @@ -542,7 +536,7 @@ QString MainUI::InputBoxGetQString(QString title, QString defaultValue) { void MainUI::resizeGL(int w, int h) { if (UpdateScreenScale(w, h)) { - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_displayResized", ""); } xscale = w / this->width(); yscale = h / this->height(); @@ -639,7 +633,7 @@ bool MainUI::event(QEvent *e) { { auto qtKeycode = ((QKeyEvent*)e)->key(); auto iter = KeyMapRawQttoNative.find(qtKeycode); - InputKeyCode nativeKeycode = NKCODE_UNKNOWN; + int nativeKeycode = 0; if (iter != KeyMapRawQttoNative.end()) { nativeKeycode = iter->second; NativeKey(KeyInput(DEVICE_ID_KEYBOARD, nativeKeycode, KEY_DOWN)); @@ -658,8 +652,8 @@ bool MainUI::event(QEvent *e) { default: if (str.size()) { int pos = 0; - int unicode = u8_nextchar(str.c_str(), &pos); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, unicode)); + int code = u8_nextchar(str.c_str(), &pos); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, code, KEY_CHAR)); } break; } @@ -719,7 +713,7 @@ void MainUI::paintGL() { #endif updateAccelerometer(); if (emuThreadState == (int)EmuThreadState::DISABLED) { - UpdateRunLoop(graphicsContext); + UpdateRunLoop(); } else { graphicsContext->ThreadFrame(); // Do the rest in EmuThreadFunc @@ -731,7 +725,20 @@ void MainUI::updateAccelerometer() { // TODO: Toggle it depending on whether it is enabled QAccelerometerReading *reading = acc->reading(); if (reading) { - NativeAccelerometer(reading->x(), reading->y(), reading->z()); + AxisInput axis; + axis.deviceId = DEVICE_ID_ACCELEROMETER; + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; + axis.value = reading->x(); + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; + axis.value = reading->y(); + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; + axis.value = reading->z(); + NativeAxis(axis); } #endif } diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 16bcc6d62..39cce11f7 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -49,7 +49,7 @@ class QtGLGraphicsContext : public GraphicsContext { public: QtGLGraphicsContext() { CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(false); + draw_ = Draw::T3DCreateGLContext(); SetGPUBackend(GPUBackend::OPENGL); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); @@ -66,6 +66,11 @@ public: } void Shutdown() override {} + void SwapInterval(int interval) override { + // See TODO in constructor. + // renderManager_->SwapInterval(interval); + } + void SwapBuffers() override {} void Resize() override {} Draw::DrawContext *GetDrawContext() override { diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index a0a67456e..64a9b4ead 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -125,12 +125,12 @@ void MainWindow::bootDone() /* SIGNALS */ void MainWindow::loadAct() { - QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.chd *.prx)"); + QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)"); if (QFile::exists(filename)) { QFileInfo info(filename); g_Config.currentDirectory = Path(info.absolutePath().toStdString()); - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, filename.toStdString().c_str()); + NativeMessageReceived("boot", filename.toStdString().c_str()); } } @@ -138,7 +138,7 @@ void MainWindow::closeAct() { updateMenus(); - System_PostUIMessage(UIMessage::REQUEST_GAME_STOP); + NativeMessageReceived("stop", ""); SetGameTitle(""); } @@ -232,29 +232,30 @@ void MainWindow::exitAct() void MainWindow::runAct() { - System_PostUIMessage(UIMessage::REQUEST_GAME_RUN); + NativeMessageReceived("run", ""); } void MainWindow::pauseAct() { - System_PostUIMessage(UIMessage::REQUEST_GAME_PAUSE); + NativeMessageReceived("pause", ""); } void MainWindow::stopAct() { Core_Stop(); - System_PostUIMessage(UIMessage::REQUEST_GAME_STOP); + NativeMessageReceived("stop", ""); } void MainWindow::resetAct() { updateMenus(); - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); + + NativeMessageReceived("reset", ""); } void MainWindow::switchUMDAct() { - QString filename = QFileDialog::getOpenFileName(NULL, "Switch UMD", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.chd *.prx)"); + QString filename = QFileDialog::getOpenFileName(NULL, "Switch UMD", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)"); if (QFile::exists(filename)) { QFileInfo info(filename); @@ -586,6 +587,8 @@ void MainWindow::createMenus() ->addDisableState(UISTATE_MENU); debugMenu->add(new MenuAction(this, SLOT(dumpNextAct()), QT_TR_NOOP("D&ump next frame to log"))) ->addDisableState(UISTATE_MENU); + debugMenu->add(new MenuAction(this, SLOT(statsAct()), QT_TR_NOOP("Show debu&g statistics"))) + ->addEventChecked(&g_Config.bShowDebugStats); debugMenu->addSeparator(); debugMenu->add(new MenuAction(this, SLOT(consoleAct()), QT_TR_NOOP("&Log console"), Qt::CTRL + Qt::Key_L)) ->addDisableState(UISTATE_MENU); @@ -650,6 +653,8 @@ void MainWindow::createMenus() gameSettingsMenu->add(new MenuAction(this, SLOT(transformAct()), QT_TR_NOOP("&Hardware transform"))) ->addEventChecked(&g_Config.bHardwareTransform); + gameSettingsMenu->add(new MenuAction(this, SLOT(vertexCacheAct()), QT_TR_NOOP("&Vertex cache"))) + ->addEventChecked(&g_Config.bVertexCache); gameSettingsMenu->addSeparator(); gameSettingsMenu->add(new MenuAction(this, SLOT(audioAct()), QT_TR_NOOP("Enable s&ound"))) ->addEventChecked(&g_Config.bEnableSound); diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index b9da7ee90..1123f6d57 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -113,20 +113,20 @@ private slots: void consoleAct(); // Game settings - void languageAct() { System_PostUIMessage(UIMessage::SHOW_LANGUAGE_SCREEN); } - void controlMappingAct() { System_PostUIMessage(UIMessage::SHOW_CONTROL_MAPPING); } - void displayLayoutEditorAct() { System_PostUIMessage(UIMessage::SHOW_DISPLAY_LAYOUT_EDITOR); } - void moreSettingsAct() { System_PostUIMessage(UIMessage::SHOW_SETTINGS); } + void languageAct() { NativeMessageReceived("language screen", ""); } + void controlMappingAct() { NativeMessageReceived("control mapping", ""); } + void displayLayoutEditorAct() { NativeMessageReceived("display layout editor", ""); } + void moreSettingsAct() { NativeMessageReceived("settings", ""); } void bufferRenderAct() { - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_renderResized", ""); + NativeMessageReceived("gpu_configChanged", ""); } void linearAct() { g_Config.iTexFiltering = (g_Config.iTexFiltering != 0) ? 0 : 3; } void renderingResolutionGroup_triggered(QAction *action) { g_Config.iInternalResolution = action->data().toInt(); - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_renderResized", ""); } void windowGroup_triggered(QAction *action) { SetWindowScale(action->data().toInt()); } @@ -134,7 +134,7 @@ private slots: g_Config.bAutoFrameSkip = !g_Config.bAutoFrameSkip; if (g_Config.bSkipBufferEffects) { g_Config.bSkipBufferEffects = false; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } } void frameSkippingGroup_triggered(QAction *action) { g_Config.iFrameSkip = action->data().toInt(); } @@ -143,20 +143,21 @@ private slots: void screenScalingFilterGroup_triggered(QAction *action) { g_Config.iDisplayFilter = action->data().toInt(); } void textureScalingLevelGroup_triggered(QAction *action) { g_Config.iTexScalingLevel = action->data().toInt(); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } void textureScalingTypeGroup_triggered(QAction *action) { g_Config.iTexScalingType = action->data().toInt(); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } void deposterizeAct() { g_Config.bTexDeposterize = !g_Config.bTexDeposterize; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } void transformAct() { g_Config.bHardwareTransform = !g_Config.bHardwareTransform; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } + void vertexCacheAct() { g_Config.bVertexCache = !g_Config.bVertexCache; } void frameskipAct() { g_Config.iFrameSkip = !g_Config.iFrameSkip; } void frameskipTypeAct() { g_Config.iFrameSkipType = !g_Config.iFrameSkipType; } @@ -171,12 +172,16 @@ private slots: // Chat void chatAct() { if (GetUIState() == UISTATE_INGAME) { - System_PostUIMessage(UIMessage::SHOW_CHAT_SCREEN); + NativeMessageReceived("chat screen", ""); } } void fullscrAct(); void raiseTopMost(); + void statsAct() { + g_Config.bShowDebugStats = !g_Config.bShowDebugStats; + NativeMessageReceived("clear jit", ""); + } // Help void websiteAct(); diff --git a/README.md b/README.md index 270c0970d..dde15de29 100644 --- a/README.md +++ b/README.md @@ -25,120 +25,6 @@ If you want to download regularly updated builds for Android, Windows x86 and x6 For game compatibility, see [community compatibility feedback](https://report.ppsspp.org/games). -What's new in 1.16.6 -==================== -- Fix performance issue with Vulkan descriptor set allocation ([#18332]) -- Smoother loading of replacement textures -- Fix the store on iOS ([#18323]) -- Fix problem with waves background ([#18310]) -- Some translation updates -- Other minor fixes - -What's new in 1.16.5 -==================== -- Additional crash and memory-leak fixes ([#18243], [#18244], [#18247]) -- Revert bad change that broke things with hardware transform turned off ([#18261]) -- Fix menu texture problem in Naruto Kizuna Drive in OpenGL ([#18255]) -- Apply flicker fix to WWE SvR 2007 -- More efficient handling of accelerometer events ([#18250]) -- Fix for jumpy graphics in Harvest Moon ([#18249]) - -What's new in 1.16.4 -==================== -- Simplify shader cache lookups on Vulkan, hopefully fixing some crashes ([#18218]) -- Assorted improvements to the IR JITs ([#18228], [#18235], [#18211], more) -- Other crash and stability fixes ([#18221], [#18220], [#18230], [#18216]) -- Some translation updates ([#18237], more) -- Cleanups and assert fixes ([#18205], [#18201], [#18206]) - -What's new in 1.16.3 -==================== -- Fix crash bug and performance issue in Vulkan shader cache ([#18183], [#18189]) -- Fix crash in icon loading in homebrew store ([#18185]) -- Add some memory safety check ([#18184], [#18194]) -- Fix problem when changing backend from the Windows menu ([#18182]) - -What's new in 1.16.2 -==================== -- Fix for HTTP support on Linux on networks with shaky or incomplete IPv6 support -- Assorted fixes for leaks and crashes ([#18169], [#18151]) -- Fix hang when switching UMD with RetroAchievements enabled ([#18143]) -- Fix math bug in new IR JIT for x86 ([#18165]) -- Minor math optimization -fno-math-errno ([#18158]) -- Fix for software renderer crash - -What's new in 1.16.1 -==================== - -- Move RetroAchievements to the Tools tab in settings ([#18127]) -- Fix graphics regressions in Hot Shots Golf 2 / Everybody's Golf 2 and Final Fantasy Tactics ([#18142]) -- Fix hang on startup with OpenGL, that happened often if "buffer commands" was set to off. -- Fix problem with the sc instruction that broke Beats ([#18133], [#18140]) -- Fix problem with the chat window accidentally closing on typing X ([#18135]) -- Fix some crashes, add some asserts and reporting hooks ([#18129]) -- Fix some text rendering in the software renderer ([#18126]) - -What's new in 1.16 -================== -Special thanks to unknownbrackets for the new JIT compilers, and fp64 for finally cracking the vrnd instruction. - -- RetroAchievements support ([#17589], [#17631], many more). See [RetroAchievements on ppsspp.org](https://www.ppsspp.org/docs/reference/retro-achievements). -- New JIT backends: - - RISC-V, based on IR - - x86 JIT based on IR. Often faster than the existing one. -- Input fixes - - Improve behavior when analog and digital inputs clash ([#17960]) - - Combo mapping is now disabled by default ([#17673]) - - Android: Better tracking of devices names ([#17562], auto config) - - Fix mapping custom touch buttons to analog inputs ([#17433]) -- Rendering performance and fixes - - Fix flicker in WWE Smackdown vs Raw 2006 ([#18009]), video flicker in Naruto 2 ([#18008]) - - Fix bad colors in Syphon Filter: Logan's Shadow menu ([#17965]) - - On lower-end devices, avoid "uber" shaders due to performance and driver bugs ([#17449], [#17922]) - - Allow disabling V-sync on Android with Vulkan, more SDL platforms ([#17903], [#18087]) - - On Vulkan, reduce input lag when "Buffer graphics commands" is set to off ([#17831]) - - Assorted minor perf ([#17810], [#17505], [#17478], [#17471], [#17452], [#17446], [#17442]) - - Fix shadows in MotorStorm ([#17602]) (not actually a rendering problem) - - Fix rendering issue in Lunar Silver Star ([#17451]) - - Add a cache for MakePixelsTexture, improving perf in God of War ([#17534]) - - Lots of software renderer improvements ([#17571], [#17569], [#17619], [#17621], [#17618], [#17609], ...) -- Networking - - HTTPS support now enabled in store and for RA on Windows, Android, Mac, iOS ([#17744], ...) - - Ad-hoc: Fix for Metal Gear Acid issue with Link Battle ([#17947]) -- Texture replacement fixes - - Fix Tactics Ogre texture issues ([#18001], [#18011]) - - Fix problem with anisotropic filtering ([#17930]) - - Fix glitches on D3D11 with KTX2 textures ([#17749]) -- UI changes - - Color emoji support on some platforms ([#17854], [#17856]) - - Use TTF fonts on SDL where available (macOS, Linux/Steam Deck) ([#17844]), support HiDPI ([#17651]) - - Allow setting the PSP's MAC address directly ([#17755]) - - Better looking notifications ([#17606], [#17674], [#17672]) -- Cheats - - Fix loading cheat dbs on Android devices with scoped storage ([#17834]) -- VR (Quest, other Android VR devices) - - Cinema screen mode improvements ([#17704], [#17752]) - - Quest-only passthrough mode ([#17591]) - - Cleanups, compatibility fixes, make VR settings per-game ([#17636], [#17656], [#17598], [#17518]) -- Other - - Fix horrible audio glitch in After Burner ([#18076]) - - Emulate the vrnd instruction accurately ([#17506], [#17549]) - - Fix timing issue causing slowdowns in MLB games ([#17676], [#17677]) - - UWP keyboard support, many other updates ([#17952], [#17974]) - - Allow choosing the display resolution on Android again ([#17473]) - - Fix issue running some file types out of the Download folder on Android ([#17466]) - -What's new in 1.15.4 -==================== -- Tilt controls: Restore "Low end radius" control ([#17489]) -- Android: Restore the ability to choose "display" (hardware scaler) resolution ([#17473]) -- Improve the workarounds for the DJ Max games ([#17467]) -- Android: Fix running some file formats directly from the Downloads folder ([#17466]) -- OpenGL: Restore most of the lost performance on low-end hardware from the shader variant reduction ([#17440, [#17439]]) -- Add a simple profiling tool to check CPU usage by the GL backend ([#17475]) -- Loader: Fix bug preventing WWE 2009 from starting ([#17435]) -- Misc minor fixes and optimizations ([#17442], [#17457], [#17486], [#17446], more) - What's new in 1.15.3 ==================== - Assorted minor crash- and other fixes ([#17406], [#17414], [#17415], [#17422]) @@ -218,6 +104,143 @@ What's new in 1.15 - Rockman 2 audio glitch fix ([#16810], [#16798]) - UI fixes: Vertical use of space ([#16795]), scrollbars ([#16785]), touchpad scroll on Windows ([#16699]) +What's new in 1.14.4 +==================== +* Multiple shader compatibility fixes for older devices/drivers: ([#16710], [#16709], [#16708]) +* A few other minor fixes: ([#16703], [#16706]) + +What's new in 1.14.3 +==================== +* Several crash/hang fixes ([#16690], [#16689], [#16683], [#16685], [#16680], [#16697], [#16681], more) +* Minor UI fixes ([#16698], [#16684], [#16674], [#16677]) +* Fix confirm/cancel button reversal ([#16692]) + +What's new in 1.14.2 +==================== +* Fix Toca/DTM and others (culling) on Mali again ([#16645]) +* Fix line rendering bugs in the homebrew Tempest clone Webfest ([#16656]) +* Assorted cleanup and bugfixes ([#16673], [#16662], [#16655], [#16644], [#16636], [#16639] etc) + +What's new in 1.14.1 +==================== +* Fix black screen in Vulkan on some older Android devices (Android version 7) ([#16599]) +* Fix error message in Medal of Honor ([#16614]) +* Various minor bugfixes ([#16617], [#16609], [#16608], [#16615], [#16619]) +* Add an option to turn off the new transparent menu background ([#16595]) + +What's new in 1.14 +================== +* Massive number of rendering fixes + - Water in Outrun 2006 and DiRT 2 now renders correctly (logic op fixes) ([#15960], [#16208], [#16032], [#16024], [#15967]) + - Split/Second now renders all effects correctly + - Multiple fixes workarounds for clipping/culling, both through clip planes and geometry shaders, fixing + graphical issues in many, many games and getting rid of hacks ([#16142], [#16504], [#16442], [#16383], [#16165], [#16162], [#16049], others) + - Killzone color effect now renders efficiently and correctly (in-game only, not title screen) ([#15934]) + - Ridge Racer speedometers and lens flares fixed ([#16084], [#16188], [#16115]) + - Lens flare effect fixed in Burnout Dominator, Ridge Racer, Colin McRae, several others ([#16014], [#16081], [#16076], [#16073]) + - Shadows in Colin McRae are no longer flickering (side effect of other fixes) + - Spongebob: Yellow Avenger renders correctly (previously very broken) ([#15907], [#15903]) + - Cars: Race-o-Rama, and MX vs ATV Reflex render correctly (at 1x resolution only) ([#15898], [#15907]) + - Asphalt 2 depth occlusion problems fixed ([#15854], [#15853]) + - Fix performance regression in Juiced 2 while also fixing the graphics ([#15888]) + - Silent Hill games are less broken ([#16127]) + - Depth occlusion and other problems fixed in Kurohyou (both games) and Ratchet & Clank ([#16454], [#15772], [#15728], [#15859]) + - Misshitsu no Sacrifice intro animation and Macross water rendering fixed (3D texture) ([#15727]) + - Tekken 6 Nancy laser beam fixed, plus line rendering fixes in rRootage and other games ([#16067]) + - Tiger & Bunny, Yu-Gi-Oh, GEB, and PlayView games - JPEG image display issues ([#16179], [#16184], [#15924]) + - Many, many others like Hunter x Hunter, Crash: Mind over Mutant, Boundless Trails, etc. ([#16265], [#16043], [#16379], [#15822], [#16358]) +* Software renderer performance and accuracy improvements + - Better performance ([#15998], [#16001], [#16011], [#16039], [#16054], [#16080], [#16085], [#16094], [#16102], [#16387], [#16486], [#16502], [#16518]) + - Improved accuracy, clipping ([#15999], [#16005], [#16042], [#16086], [#16117], [#16231], [#16241], [#16265], [#16274], [#16469], [#16470], [#16478], [#16480], [#16485]) +* New features + - Initial VR support added (Quest and PICO only for now, PC in the future) ([#15659], [#15901], [#16246], [#16262], [#16273]) + - MSAA antialiasing added to the Vulkan backend (desktop only) ([#16458]) + - New API for plugins to access aspect ratio, scaling and fast-forward ([#16441]), other new APIs & improvements ([#15748], [#16121], [#16187], [#16198], [#16389]) + - Read texture replacement packs directly from ZIP files ([#16304]) +* UI improvements + - New interactive Display Layout & Effects screen, replacing the old Display Layout Editor ([#16409], [#16415], [#16417], [#16445]) + - Add default shader for LCD persistence simulation ([#16531]) + - Game being played can now be seen as a background in most menus ([#16404], more) + - Reorganize speed hack settings ([#16346], [#16347], [#16348], [#16432]) +* Stability fixes + - Workaround for hangs on older Adreno GPUs ([#16422]) + - Input handling fixes for deadzones and touch controls ([#16419], [#16450]) + - Avoid game bugs in Twinbee Portable ([#16388]) and Shining Ark ([#16449]) + - Fixes to D3D9 backend issues ([#15723], [#15815], [#15926], [#16100], [#16232], [#16550]) +* IR interpreter (iOS, etc.) bug fixes + - Metal Gear Solid - Peace Walker no longer bugged out ([#16396]) + - VFPU fixes for Dissidia, others ([#16302], [#16305], [#16306]) +* Performance improvements + - Vulkan bandwidth and synchronization optimizations ([#16434], [#16099], [#16090], [#16072], [#16061], [#16060], [#16035], [#15917]) + - Lighting "ubershader" optimization to prevent hitches ([#16104], [#16111]) + - Assorted minor other improvements ([#15589], [#15843], [#16190]) + - Improve texture replacement memory usage ([#15884], [#16304], [#16314]) + - Texture upscaling speedup and fixes ([#15803], [#16125]) +* Other + - HLE/CPU accuracy improvements helping Brooktown High, Frontier Gate, Madoka Magicka, some language patches ([#16413], [#16070], [#16052], [#15952], [#15957], more) + - Many GE debugger improvements ([#15839], [#15851], [#15894], [#15925], [#15974], [#16007], [#16047], [#16096], [#16201]) + - Optional memory alignment validation in IR mode ([#15879], [#15880]) + - Fix netplay assertion in Cars ([#16089]) + +What's new in 1.13.2 +==================== +* Crashfix on Android 12 when playing certain background music ([#15990]) +* Fix Star Ocean battles in D3D backends ([#15889]) +* Minor fixes that might fix some other crashes + +What's new in 1.13.1 +==================== + +* Confirmation dialog added before change of MAC address ([#15738]) +* IR interpreter regression fixed ([#15739]) +* Fix clearing of replacement texture cache ([#15740]) +* Improved Portuguese-pt translation ([#15734]) +* Fix graphical regression in Split/Second ([#15733]) +* Couple of minor crash fixes + +What's new in 1.13 +================== + +General + +* Fix assorted Android "scoped storage"-related bugs and performance issues ([#15237], [#15487]), etc. +* Analog mapping for fast-forward ([#15645]) +* Major softgpu accuracy fixes and speedups, including a JIT ([#15163], [#15345], [#15389], [#15529], [#15440], [#15410], [#15405], [#15400]) and many, many more +* Fixed some NEON code paths ([#15481]) +* Fix performance of texture uploads with Vulkan ([#15474]) +* Don't include the large font atlas when we don't need it +* Improved upscaling shaders ([#15566]) +* Vulkan texture upscaling performance improvements ([#15238]), etc. +* Vulkan correctness fixes ([#15217], [#15211]), use the VMA allocator ([#15162]), etc. +* Fixes to depth culling ([#15106]), many more +* Background loading of texture replacement ([#15025]) +* Threading manager improvements and fixes ([#15470]), etc. +* Added search in settings ([#14414]) +* Added fast button repeats on custom touch buttons ([#15613]) +* Two new bicubic upscaling shader: Catmull-Rom and Mitchell-Netravali ([#15569]) +* Allow to change screen rotation per game and to bind a key to change it ([#15494], [#15510]) +* Re-enabled software rendering option on Android ([#12958]) + +Game fixes + +* Add more workarounds for Mali driver bugs ([#15016]) +* Vortex in God of War: Ghost of Sparta can now be passed ([#15640]) +* Various proAdhoc fixes ([#15213], [#15215]), and many more +* Correct flickering text in Sol Trigger and Last Ranker. ([#15549]) +* Fix and improve line drawing in Echochrome ([#15583]), after line refactoring ([#15073], [#15075]) +* Fix HUD graphics in Split/Second ([#15500], [#15501]) +* Fix bad screen overlay issues in Clone Wars and Force Unleashed ([#15691], [#15696], [#12949], [#9572]) +* Zettai Zetsumei Toshi 3 no longer hangs on character select screen ([#15687]) +* Juiced 2: Bloom effect no longer covering the screen ([#7295], [#15717]) +* Fix keyboard shift issue in a few games ([#15698]) + +UI + +* Windows/Xbox UWP directory navigation improvements ([#15652]) +* Color change and basic theme support ([#15396], [#15394]) +* Fix input focus bug ([#15560]) +* New GE debugger features and other UI fixes ([#15393], [#15324], [#15377], [#15424], [#15402], [#15378], [#15338]), etc. + Looking for [older news](history.md)? @@ -234,9 +257,240 @@ Credit goes to: [comment]: # (LINK_LIST_BEGIN_HERE) +[#15237]: https://github.com/hrydgard/ppsspp/issues/15237 "Path: Check for PSP case insensitively" +[#15487]: https://github.com/hrydgard/ppsspp/issues/15487 "Save textures on background tasks when texture dumping is enabled." +[#15645]: https://github.com/hrydgard/ppsspp/issues/15645 "UI: Add analog speed limit mapping" +[#15566]: https://github.com/hrydgard/ppsspp/issues/15566 "Screen upscaling shaders improvements" +[#15163]: https://github.com/hrydgard/ppsspp/issues/15163 "Implement a jit for drawing pixels in the software renderer" +[#15345]: https://github.com/hrydgard/ppsspp/issues/15345 "Fix some minor softgpu blending bugs" +[#15389]: https://github.com/hrydgard/ppsspp/issues/15389 "Draw rectangles always using a specialized path in softgpu" +[#15529]: https://github.com/hrydgard/ppsspp/issues/15529 "softgpu: Fix viewport flag clean/dirty" +[#15440]: https://github.com/hrydgard/ppsspp/issues/15440 "softgpu: Plug bad leak of bin queue data" +[#15410]: https://github.com/hrydgard/ppsspp/issues/15410 "softgpu: Remove offset from screenpos, adjust filtering coords" +[#15405]: https://github.com/hrydgard/ppsspp/issues/15405 "Fix some samplerjit issues without SSE4 or AVX" +[#15400]: https://github.com/hrydgard/ppsspp/issues/15400 "softgpu: Track dirty vs really dirty per buffer" +[#15481]: https://github.com/hrydgard/ppsspp/issues/15481 "Fix some NEON code that had bad compile-time checks" +[#15474]: https://github.com/hrydgard/ppsspp/issues/15474 "Merge CheckAlpha into texture decoding" +[#15238]: https://github.com/hrydgard/ppsspp/issues/15238 "Vulkan: Be more restrictive about hardware texture upscaling on \"slow\" GPUs" +[#15217]: https://github.com/hrydgard/ppsspp/issues/15217 "Vulkan is strict about scissor rect, so let's clamp centrally." +[#15211]: https://github.com/hrydgard/ppsspp/issues/15211 "Vulkan: Specify Vulkan version, fix mip level generation calculation" +[#15162]: https://github.com/hrydgard/ppsspp/issues/15162 "Integrate VMA (Vulkan Memory Allocator)" +[#15106]: https://github.com/hrydgard/ppsspp/issues/15106 "GLES: Explicitly enable ARB_cull_distance" +[#15075]: https://github.com/hrydgard/ppsspp/issues/15075 "Draw points using triangles" +[#15470]: https://github.com/hrydgard/ppsspp/issues/15470 "Threading manager stresstest and fixes" +[#14414]: https://github.com/hrydgard/ppsspp/issues/14414 "Add search for settings" +[#15613]: https://github.com/hrydgard/ppsspp/issues/15613 "Allow to repeat a \"single\" button" +[#15569]: https://github.com/hrydgard/ppsspp/issues/15569 "Upscaling shaders" +[#15494]: https://github.com/hrydgard/ppsspp/issues/15494 "Add key bind to hotswap internal screen rotation" +[#15510]: https://github.com/hrydgard/ppsspp/issues/15510 "Allow to set InternalScreenRotation per game" +[#12958]: https://github.com/hrydgard/ppsspp/issues/12958 "Feature Request: restore software rendering ui setting on android" +[#15016]: https://github.com/hrydgard/ppsspp/issues/15016 "[Android][Mali GPU] Vulkan backend workaround issue in some games with graphics glitch." +[#15640]: https://github.com/hrydgard/ppsspp/issues/15640 "Disable ForceMax60FPS for GOW games and replace it with fixed 60 fps" +[#15213]: https://github.com/hrydgard/ppsspp/issues/15213 "[Adhoc] Updated PdpCreate, PdpSend, PdpRecv, GetPdpStat, GetPtpStat" +[#15215]: https://github.com/hrydgard/ppsspp/issues/15215 "[Adhocctl] Fix Tekken 5 Dark Resurrection Multiplayer" +[#15549]: https://github.com/hrydgard/ppsspp/issues/15549 "GPU: Hook Sol Trigger func to flush texture" +[#15583]: https://github.com/hrydgard/ppsspp/issues/15583 "Fix and further improve line drawing in Echochrome" +[#15073]: https://github.com/hrydgard/ppsspp/issues/15073 "Cleanup line/point handling and refactor a bit" +[#15500]: https://github.com/hrydgard/ppsspp/issues/15500 "Add BlueToAlpha compat.ini workaround, fixes Split/Second graphics" +[#15501]: https://github.com/hrydgard/ppsspp/issues/15501 "Make the existing ReinterpretFramebuffers/ShaderColorBitmask path work for Split/Second" +[#15652]: https://github.com/hrydgard/ppsspp/issues/15652 "Replace Win32 file IO with UWP safe variants and add support for getting drives to UWP build" +[#15396]: https://github.com/hrydgard/ppsspp/issues/15396 "Add UI Tint/Saturation settings" +[#15394]: https://github.com/hrydgard/ppsspp/issues/15394 "Allow custom UI themes" +[#15560]: https://github.com/hrydgard/ppsspp/issues/15560 "UI: Abandon focus movement on returning from pause" +[#15393]: https://github.com/hrydgard/ppsspp/issues/15393 "GE Debugger: Avoid crash on Step Draw with flush" +[#15324]: https://github.com/hrydgard/ppsspp/issues/15324 "UI: Reset ZIP install errors for new ZIPs" +[#15377]: https://github.com/hrydgard/ppsspp/issues/15377 "Debugger: Avoid mem write tag lookup on small alloc" +[#15424]: https://github.com/hrydgard/ppsspp/issues/15424 "Windows: Create SYSTEM directory early" +[#15402]: https://github.com/hrydgard/ppsspp/issues/15402 "GE Debugger: Highlight changed state values" +[#15378]: https://github.com/hrydgard/ppsspp/issues/15378 "GE Debugger: Add filter to skip prim calls" +[#15338]: https://github.com/hrydgard/ppsspp/issues/15338 "Alow flushing at will via the GE debugger" +[#15025]: https://github.com/hrydgard/ppsspp/issues/15025 "Allow delayed loading of texture replacements" +[#15691]: https://github.com/hrydgard/ppsspp/issues/15691 "Add a simple compat flag to workaround the Clone Wars issue, #12949" +[#15696]: https://github.com/hrydgard/ppsspp/issues/15696 "Use the recent Clone Wars fix for Star Wars: Force Unleashed too" +[#12949]: https://github.com/hrydgard/ppsspp/issues/12949 "Star Wars: The Clone Wars - Graphic glitch [Android/Windows]" +[#9572]: https://github.com/hrydgard/ppsspp/issues/9572 "Star Wars force unleashed [Screen Overlay problem]" +[#15687]: https://github.com/hrydgard/ppsspp/issues/15687 "Add Zettai Zetsumei Toshi 3" +[#7295]: https://github.com/hrydgard/ppsspp/issues/7295 "Juiced 2: Hot Import Nights, screen artifacts and missing half of race tracks" +[#15717]: https://github.com/hrydgard/ppsspp/issues/15717 "Allows \"merging\" render targets that overlap on the Y axis. Fixes Juiced 2" +[#15698]: https://github.com/hrydgard/ppsspp/issues/15698 "Osk: Allow upper/lower for all keyboards" +[#15738]: https://github.com/hrydgard/ppsspp/issues/15738 "Add confirmation dialog when generating a new Mac address" +[#15739]: https://github.com/hrydgard/ppsspp/issues/15739 "irjit: Correct another PurgeTemps case" +[#15740]: https://github.com/hrydgard/ppsspp/issues/15740 "Replacement: Clear cache on disable" +[#15734]: https://github.com/hrydgard/ppsspp/issues/15734 "Better pt-pt translation" +[#15733]: https://github.com/hrydgard/ppsspp/issues/15733 "Fix bug in blue-to-alpha - alpha blending could be on when it shouldn't be." +[#15960]: https://github.com/hrydgard/ppsspp/issues/15960 "Enable logic op emulation in-shader" +[#16208]: https://github.com/hrydgard/ppsspp/issues/16208 "GPU: Respect stencil state in shader blend" +[#16032]: https://github.com/hrydgard/ppsspp/issues/16032 "Fix the water in Outrun when no logic ops" +[#16024]: https://github.com/hrydgard/ppsspp/issues/16024 "GPU: Fix simulating logicop with blend and shader" +[#15967]: https://github.com/hrydgard/ppsspp/issues/15967 "Fix BlueToAlpha mode, re-enable it for Outrun and DiRT" +[#16142]: https://github.com/hrydgard/ppsspp/issues/16142 "Implement geometry shader for range culling" +[#16504]: https://github.com/hrydgard/ppsspp/issues/16504 "GPU: Use accurate depth for depth range hack" +[#16442]: https://github.com/hrydgard/ppsspp/issues/16442 "Vulkan: Only use geometry shaders with accurate depth" +[#16383]: https://github.com/hrydgard/ppsspp/issues/16383 "GPU: Automatically reduce depth range on == test" +[#16165]: https://github.com/hrydgard/ppsspp/issues/16165 "Vulkan: Clip clamped depth in geometry shader" +[#16162]: https://github.com/hrydgard/ppsspp/issues/16162 "Implement negative Z clipping in geometry shader" +[#16049]: https://github.com/hrydgard/ppsspp/issues/16049 "GPU: Clip depth properly when also clamping" +[#15934]: https://github.com/hrydgard/ppsspp/issues/15934 "Split the main framebuffer in Killzone, to avoid texturing-from-current-rendertarget" +[#16084]: https://github.com/hrydgard/ppsspp/issues/16084 "Fix Ridge Racer lens flares - ignore stride if texHeight == 1, when matching tex/fb" +[#16188]: https://github.com/hrydgard/ppsspp/issues/16188 "Fix depal bounds with dynamic CLUT. Fixes lens flare glitches in Ridge Racer" +[#16115]: https://github.com/hrydgard/ppsspp/issues/16115 "Add compatibility flag for loading pixels on framebuffer create using nearest filtering" +[#16014]: https://github.com/hrydgard/ppsspp/issues/16014 "Texture depal using CLUT loaded from framebuffers, and more. Fixes Burnout Dominator lens flare" +[#16081]: https://github.com/hrydgard/ppsspp/issues/16081 "Fix green flashes with Burnout Dominator lens flare" +[#16076]: https://github.com/hrydgard/ppsspp/issues/16076 "Don't try to replace or scale CLUT8-on-GPU textures." +[#16073]: https://github.com/hrydgard/ppsspp/issues/16073 "CLUTs can be loaded from small rectangular textures. Need to linearize." +[#15907]: https://github.com/hrydgard/ppsspp/issues/15907 "Reinterpret between 32 and 16 bit texture formats" +[#15903]: https://github.com/hrydgard/ppsspp/issues/15903 "Remove support for framebuffers changing stride (already unreachable)." +[#15898]: https://github.com/hrydgard/ppsspp/issues/15898 "Rendering issues in Tantalus Media games (Spongebob, MX ATV, etc)" +[#15854]: https://github.com/hrydgard/ppsspp/issues/15854 "Use sequence numbers instead of a tracking array for depth buffers" +[#15853]: https://github.com/hrydgard/ppsspp/issues/15853 "Framebuffer-bind sequence numbers" +[#15888]: https://github.com/hrydgard/ppsspp/issues/15888 "Copy color from overlapping framebuffers on bind, under certain conditions" +[#16127]: https://github.com/hrydgard/ppsspp/issues/16127 "Fixes for Silent Hill: Origins (depth buffer reassignment, eliminate readback)" +[#16454]: https://github.com/hrydgard/ppsspp/issues/16454 "GPU: Support framebuf depal from rendered CLUT" +[#15772]: https://github.com/hrydgard/ppsspp/issues/15772 "Add support for binding the depth buffer as a color target. Fixes Kurohyo depth sorting" +[#15728]: https://github.com/hrydgard/ppsspp/issues/15728 "Better ways to deal with overlapping render targets" +[#15859]: https://github.com/hrydgard/ppsspp/issues/15859 "Allow binding depth as 565" +[#15727]: https://github.com/hrydgard/ppsspp/issues/15727 "Implement the PSP's equal-size mips \"3D texturing\"" +[#16067]: https://github.com/hrydgard/ppsspp/issues/16067 "GPU: Account for w properly in lines, fixing width" +[#16179]: https://github.com/hrydgard/ppsspp/issues/16179 "Correct size and YUV order for jpeg decoding" +[#16184]: https://github.com/hrydgard/ppsspp/issues/16184 "GPU: Hook Gods Eater Burst avatar read" +[#15924]: https://github.com/hrydgard/ppsspp/issues/15924 "Add support for reading depth buffers to the PackFramebufferSync function" +[#16265]: https://github.com/hrydgard/ppsspp/issues/16265 "GPU: Respect world matrix and reverse flag w/o normals" +[#16043]: https://github.com/hrydgard/ppsspp/issues/16043 "Consider the Adreno and Mali stencil-discard bugs the same." +[#16379]: https://github.com/hrydgard/ppsspp/issues/16379 "Fix alpha/stencil replace on Adreno when color masked" +[#15822]: https://github.com/hrydgard/ppsspp/issues/15822 "GPU: Write stencil fail to alpha is RGB masked" +[#16358]: https://github.com/hrydgard/ppsspp/issues/16358 "TexCache: Fix 16->32 colors with CLUT start pos" +[#15998]: https://github.com/hrydgard/ppsspp/issues/15998 "softgpu: Allow almost flat rectangles to go fast" +[#16001]: https://github.com/hrydgard/ppsspp/issues/16001 "softgpu: Check depth test early on simple stencil" +[#16011]: https://github.com/hrydgard/ppsspp/issues/16011 "Detect more triangles as rectangles in softgpu" +[#16039]: https://github.com/hrydgard/ppsspp/issues/16039 "softgpu: Run early Z tests in fast rect path" +[#16054]: https://github.com/hrydgard/ppsspp/issues/16054 "softgpu: Reduce some flushing / flushing cost" +[#16080]: https://github.com/hrydgard/ppsspp/issues/16080 "softgpu: Avoid unnecessary flushing for curves" +[#16085]: https://github.com/hrydgard/ppsspp/issues/16085 "softgpu: Cache reused indexed verts" +[#16094]: https://github.com/hrydgard/ppsspp/issues/16094 "softgpu: Optimize rectangle sampling/blending used in bloom" +[#16102]: https://github.com/hrydgard/ppsspp/issues/16102 "softgpu: Avoid waiting for a thread to drain" +[#16387]: https://github.com/hrydgard/ppsspp/issues/16387 "softgpu: Use threads on self-render if safe" +[#16486]: https://github.com/hrydgard/ppsspp/issues/16486 "softgpu: Apply optimizations to states generically" +[#16502]: https://github.com/hrydgard/ppsspp/issues/16502 "A few more softgpu optimizations for alpha blend/test" +[#16518]: https://github.com/hrydgard/ppsspp/issues/16518 "softgpu: Expand fast path to all fb formats" +[#15999]: https://github.com/hrydgard/ppsspp/issues/15999 "softgpu: Clamp/wrap textures at 512 pixels" +[#16005]: https://github.com/hrydgard/ppsspp/issues/16005 "softgpu: Correct accuracy of fog calculation" +[#16042]: https://github.com/hrydgard/ppsspp/issues/16042 "softgpu: Refactor imm prim handling to support fog/color1" +[#16086]: https://github.com/hrydgard/ppsspp/issues/16086 "softgpu: Fix self-render detect in Ridge Racer" +[#16117]: https://github.com/hrydgard/ppsspp/issues/16117 "Correct texture projection issues, mainly in softgpu" +[#16231]: https://github.com/hrydgard/ppsspp/issues/16231 "softgpu: Cull a triangle with all negative w" +[#16241]: https://github.com/hrydgard/ppsspp/issues/16241 "softgpu: Correct linear interp for uneven positions" +[#16274]: https://github.com/hrydgard/ppsspp/issues/16274 "Correct accuracy of bounding box test" +[#16469]: https://github.com/hrydgard/ppsspp/issues/16469 "Correct block transfer overlap and wrapping behavior" +[#16470]: https://github.com/hrydgard/ppsspp/issues/16470 "softgpu: Correctly fix inversions, matching tests" +[#16478]: https://github.com/hrydgard/ppsspp/issues/16478 "softgpu: Interpolate Z for 3D lines" +[#16480]: https://github.com/hrydgard/ppsspp/issues/16480 "softgpu: Cull verts outside post-viewport Z" +[#16485]: https://github.com/hrydgard/ppsspp/issues/16485 "softgpu: Handle infnan fog coefficients better" +[#15659]: https://github.com/hrydgard/ppsspp/issues/15659 "Oculus Quest native support" +[#15901]: https://github.com/hrydgard/ppsspp/issues/15901 "OpenXR - Stereoscopic rendering" +[#16246]: https://github.com/hrydgard/ppsspp/issues/16246 "VR: Add the VR code to all builds. Remove IsVRBuild calls from the renderer." +[#16262]: https://github.com/hrydgard/ppsspp/issues/16262 "OpenXR - Add an option to adjust camera distance" +[#16273]: https://github.com/hrydgard/ppsspp/issues/16273 "Vulkan multiview rendering" +[#16458]: https://github.com/hrydgard/ppsspp/issues/16458 "Implement MSAA support for desktop GPUs in Vulkan" +[#16441]: https://github.com/hrydgard/ppsspp/issues/16441 "Exposed more emulator things to devctl api" +[#15748]: https://github.com/hrydgard/ppsspp/issues/15748 "Windows: Add a simple window message to get the base pointer." +[#16121]: https://github.com/hrydgard/ppsspp/issues/16121 "Debugger: Add API to scan memory for funcs" +[#16187]: https://github.com/hrydgard/ppsspp/issues/16187 "Remote API: hle.func.removeRange added" +[#16198]: https://github.com/hrydgard/ppsspp/issues/16198 "Readback stencil buffer for debugger on GLES" +[#16389]: https://github.com/hrydgard/ppsspp/issues/16389 "Make breakpoints work better in interpreter" +[#16304]: https://github.com/hrydgard/ppsspp/issues/16304 "Improve texture replacement cache and allow read from zip" +[#16409]: https://github.com/hrydgard/ppsspp/issues/16409 "Preserve framebuffer on pause screen even if render resolution is changed" +[#16415]: https://github.com/hrydgard/ppsspp/issues/16415 "Display layout editor - Remove editing widget, just use the background directly" +[#16417]: https://github.com/hrydgard/ppsspp/issues/16417 "Move post processing settings to the Display Layout Editor" +[#16445]: https://github.com/hrydgard/ppsspp/issues/16445 "New screen size controls on Display Layout & Effects screen" +[#16531]: https://github.com/hrydgard/ppsspp/issues/16531 "iota97's \"Motion blur\" - LCD persistence shader, plus fixes to make it work with OpenGL" +[#16404]: https://github.com/hrydgard/ppsspp/issues/16404 "Make the pause screen \"transparent\"" +[#16346]: https://github.com/hrydgard/ppsspp/issues/16346 "Change the \"Retain changed textures\" option into a compat.ini option." +[#16347]: https://github.com/hrydgard/ppsspp/issues/16347 "Always skin in decode for software transform and rendering" +[#16348]: https://github.com/hrydgard/ppsspp/issues/16348 "Speed hack setting reorganization" +[#16432]: https://github.com/hrydgard/ppsspp/issues/16432 "Cleanup graphics settings list" +[#16422]: https://github.com/hrydgard/ppsspp/issues/16422 "Add compat flag / bug check for games on old Adreno/GL affected" +[#16419]: https://github.com/hrydgard/ppsspp/issues/16419 "Stick input: Fix issue where deadzone noise from one device could drown out signal from another." +[#16450]: https://github.com/hrydgard/ppsspp/issues/16450 "UI: Fix right analog with single button" +[#16388]: https://github.com/hrydgard/ppsspp/issues/16388 "Twinbee Portable: Add compat flag to avoid game bug with some languages" +[#16449]: https://github.com/hrydgard/ppsspp/issues/16449 "Blind workaround for Shining Ark circle button problem" +[#15723]: https://github.com/hrydgard/ppsspp/issues/15723 "D3D9 state cache cleanup" +[#15815]: https://github.com/hrydgard/ppsspp/issues/15815 "Depth blit using raster" +[#15926]: https://github.com/hrydgard/ppsspp/issues/15926 "Implement shader blending for D3D9" +[#16100]: https://github.com/hrydgard/ppsspp/issues/16100 "D3D9: Allow INTZ depth buffers more correctly" +[#16232]: https://github.com/hrydgard/ppsspp/issues/16232 "D3D9: Correct scissor state cache in Draw" +[#16550]: https://github.com/hrydgard/ppsspp/issues/16550 "Hide the D3D9 option on Intel Xe graphics." +[#16396]: https://github.com/hrydgard/ppsspp/issues/16396 "Correct misbehavior on uninitialized values in IR" +[#16302]: https://github.com/hrydgard/ppsspp/issues/16302 "Handle vrot overlap and vscl/vmscl prefixes more accurately" +[#16305]: https://github.com/hrydgard/ppsspp/issues/16305 "irjit: Fix unordered float compares" +[#16306]: https://github.com/hrydgard/ppsspp/issues/16306 "irjit: Correct prefix validation" +[#16434]: https://github.com/hrydgard/ppsspp/issues/16434 "Vulkan: Use stencil export when available" +[#16099]: https://github.com/hrydgard/ppsspp/issues/16099 "Vulkan: Avoid allocating depth images for stuff like temp copies, depal buffers etc." +[#16090]: https://github.com/hrydgard/ppsspp/issues/16090 "Simplify synchronization in VulkanRenderManager" +[#16072]: https://github.com/hrydgard/ppsspp/issues/16072 "Vulkan: Don't have renderpasses store/load depth buffers when we don't use them" +[#16061]: https://github.com/hrydgard/ppsspp/issues/16061 "Vulkan: Submit main command buffer before acquiring the swapchain image" +[#16060]: https://github.com/hrydgard/ppsspp/issues/16060 "Vulkan FrameData refactor" +[#16035]: https://github.com/hrydgard/ppsspp/issues/16035 "Vulkan: \"Acquire\" the image from the swapchain as late as possible in the frame" +[#15917]: https://github.com/hrydgard/ppsspp/issues/15917 "Vulkan bandwidth optimizations (configure renderpass load/store better)" +[#16104]: https://github.com/hrydgard/ppsspp/issues/16104 "Generate \"Ubershaders\" that can handle all lighting configurations" +[#16111]: https://github.com/hrydgard/ppsspp/issues/16111 "Always do the vertex shader part of the fog computation." +[#15589]: https://github.com/hrydgard/ppsspp/issues/15589 "Vulkan: Parallelize GLSL compilation" +[#15843]: https://github.com/hrydgard/ppsspp/issues/15843 "GPU: Skip fb create upload when clearing" +[#16190]: https://github.com/hrydgard/ppsspp/issues/16190 "Reduce IO primarily during save operations" +[#15884]: https://github.com/hrydgard/ppsspp/issues/15884 "Replacement: Read files only within time budget" +[#16314]: https://github.com/hrydgard/ppsspp/issues/16314 "UI: Install textures as a zip if supported" +[#15803]: https://github.com/hrydgard/ppsspp/issues/15803 "Reimplement bicubic upscaling." +[#16125]: https://github.com/hrydgard/ppsspp/issues/16125 "Remove alpha ignore in xbrz texture shaders." +[#16413]: https://github.com/hrydgard/ppsspp/issues/16413 "Kernel: Respect partition param in heap funcs" +[#16070]: https://github.com/hrydgard/ppsspp/issues/16070 "Kernel: Match index lookup behavior for tls" +[#16052]: https://github.com/hrydgard/ppsspp/issues/16052 "HLE: sceKernelAllocPartitionMemory volatile memory support (partition 5)" +[#15952]: https://github.com/hrydgard/ppsspp/issues/15952 "interp: Handle jumps in branch delay slots better" +[#15957]: https://github.com/hrydgard/ppsspp/issues/15957 "Handle branch/jump in branch delay slots more accurately" +[#15839]: https://github.com/hrydgard/ppsspp/issues/15839 "GE debugger: Allow displaying two tabs at once, separate DL view" +[#15851]: https://github.com/hrydgard/ppsspp/issues/15851 "After recording a GE dump, open an explorer window pointing at the file" +[#15894]: https://github.com/hrydgard/ppsspp/issues/15894 "GE Debugger: Record only one flip if display framebuf not changed, step on vsync" +[#15925]: https://github.com/hrydgard/ppsspp/issues/15925 "GE Debugger: Improve display list disasm" +[#15974]: https://github.com/hrydgard/ppsspp/issues/15974 "Add breakpoint conditions to GE debugger" +[#16007]: https://github.com/hrydgard/ppsspp/issues/16007 "GE Debugger: Add fields to register expressions" +[#16047]: https://github.com/hrydgard/ppsspp/issues/16047 "GE Debugger: Allow search" +[#16096]: https://github.com/hrydgard/ppsspp/issues/16096 "GE Debugger: Add option to track pixel in preview" +[#16201]: https://github.com/hrydgard/ppsspp/issues/16201 "GE Debugger: Normalize framebuffer texture preview" +[#15879]: https://github.com/hrydgard/ppsspp/issues/15879 "irjit: Validate alignment in slow memory mode" +[#15880]: https://github.com/hrydgard/ppsspp/issues/15880 "Core: Show exception on misaligned jump" +[#16089]: https://github.com/hrydgard/ppsspp/issues/16089 "[AdhocMatching] Fix assertion issue when playing Cars over public adhoc server." +[#15990]: https://github.com/hrydgard/ppsspp/issues/15990 "Atrac3+: Allocate some extra" +[#15889]: https://github.com/hrydgard/ppsspp/issues/15889 "Correct D3D viewport offset sign in sw transform" +[#16599]: https://github.com/hrydgard/ppsspp/issues/16599 "Vulkan: Remove the new 0th descriptor set, move everything else back to desc set 0" +[#16614]: https://github.com/hrydgard/ppsspp/issues/16614 "GPU: Keep prevPrim_ set on flush" +[#16617]: https://github.com/hrydgard/ppsspp/issues/16617 "GE Debugger: Prevent double init" +[#16609]: https://github.com/hrydgard/ppsspp/issues/16609 "OpenXR - Rendering fixes for a few games" +[#16608]: https://github.com/hrydgard/ppsspp/issues/16608 "Cleanup value corrections in config load/save" +[#16615]: https://github.com/hrydgard/ppsspp/issues/16615 "D3D9: Support old-style user clip planes" +[#16619]: https://github.com/hrydgard/ppsspp/issues/16619 "Debugger: Don't hang memory dump if stepping in GE" +[#16595]: https://github.com/hrydgard/ppsspp/issues/16595 "Transparent background option" +[#16645]: https://github.com/hrydgard/ppsspp/issues/16645 "Fix vertex shader range culling - the driver bug check was wrong." +[#16656]: https://github.com/hrydgard/ppsspp/issues/16656 "Fix rendering of lines with the same x/y but different z." +[#16673]: https://github.com/hrydgard/ppsspp/issues/16673 "Show bluescreen properly on memory errors that we failed to ignore." +[#16662]: https://github.com/hrydgard/ppsspp/issues/16662 "Correct some reversed dependencies, minor other cleanup" +[#16655]: https://github.com/hrydgard/ppsspp/issues/16655 "OpenXR - Force flat mode for Madden NFL games" +[#16644]: https://github.com/hrydgard/ppsspp/issues/16644 "Additional Android cleanup" +[#16636]: https://github.com/hrydgard/ppsspp/issues/16636 "Crash: Ensure we never handle faults in faults" +[#16639]: https://github.com/hrydgard/ppsspp/issues/16639 "Minor initialization cleanup, setup for Vulkan validation layers on Android" [#16690]: https://github.com/hrydgard/ppsspp/issues/16690 "softgpu: Detect binner alloc fail and bail" +[#16689]: https://github.com/hrydgard/ppsspp/issues/16689 "Vulkan: Avoid race in compile thread exit" +[#16683]: https://github.com/hrydgard/ppsspp/issues/16683 "Assorted fixes after looking at crash data" +[#16685]: https://github.com/hrydgard/ppsspp/issues/16685 "Replacement: Verify out stride" +[#16680]: https://github.com/hrydgard/ppsspp/issues/16680 "Make sure we don't multithread libzip access" +[#16697]: https://github.com/hrydgard/ppsspp/issues/16697 "Check for valid memory range when doing fast bone matrix loads" +[#16681]: https://github.com/hrydgard/ppsspp/issues/16681 "Cleanup some mic data reading" +[#16698]: https://github.com/hrydgard/ppsspp/issues/16698 "Screen background fixes" +[#16684]: https://github.com/hrydgard/ppsspp/issues/16684 "Enabled CPU breakpoints unchecked" +[#16674]: https://github.com/hrydgard/ppsspp/issues/16674 "Broken menus after using Break on Load" +[#16677]: https://github.com/hrydgard/ppsspp/issues/16677 "D3D11: Fix Draw state issues on pause screen" +[#16692]: https://github.com/hrydgard/ppsspp/issues/16692 "Dialog: Fix confirm/cancel button reversal" [#16710]: https://github.com/hrydgard/ppsspp/issues/16710 "GLES: Use uint for uint shift amounts" [#16709]: https://github.com/hrydgard/ppsspp/issues/16709 "Correct some shader errors in reporting" +[#16708]: https://github.com/hrydgard/ppsspp/issues/16708 "Additional fixes from both our reports and Play reports" +[#16703]: https://github.com/hrydgard/ppsspp/issues/16703 "Minor fixes based on the latest Google Play report" [#16706]: https://github.com/hrydgard/ppsspp/issues/16706 "softgpu: Fix lighting with 0 exp" [#16873]: https://github.com/hrydgard/ppsspp/issues/16873 "Add facility to run tasks on dedicated threads using the ThreadManager interface" [#16802]: https://github.com/hrydgard/ppsspp/issues/16802 "Vulkan: Parallel pipeline creation" @@ -345,120 +599,10 @@ Credit goes to: [#17396]: https://github.com/hrydgard/ppsspp/issues/17396 "Vulkan: Turn off the ubershader on Mali T880, T860 and T830 on old driver versions" [#17401]: https://github.com/hrydgard/ppsspp/issues/17401 "Additional crash fixes" [#17399]: https://github.com/hrydgard/ppsspp/issues/17399 "More crash fixes" -[#17398]: https://github.com/hrydgard/ppsspp/issues/17398 "OpenXR - Cleanup unsupported features, support Android 12" -[#17406]: https://github.com/hrydgard/ppsspp/issues/17406 "Even more crash fixes" +[#17398]: https://github.com/hrydgard/ppsspp/issues/17398 "OpenXR - Cleanup unsupported features, support Android 12"[#17406]: https://github.com/hrydgard/ppsspp/issues/17406 "Even more crash fixes" [#17414]: https://github.com/hrydgard/ppsspp/issues/17414 "GPU: Remove JumpFast/CallFast" [#17415]: https://github.com/hrydgard/ppsspp/issues/17415 "Misc fixes and checks" [#17422]: https://github.com/hrydgard/ppsspp/issues/17422 "Windows: Fix initial window show for all displays" [#17425]: https://github.com/hrydgard/ppsspp/issues/17425 "Android: Explicitly allow content URI intents" [#17412]: https://github.com/hrydgard/ppsspp/issues/17412 "Controller mapping fixes" -[#17420]: https://github.com/hrydgard/ppsspp/issues/17420 "Fix glitch when mapping analog inputs, caused" -[#17489]: https://github.com/hrydgard/ppsspp/issues/17489 "Restore \"low end radius\" (inverse deadzone) for tilt input" -[#17473]: https://github.com/hrydgard/ppsspp/issues/17473 "Revert \"Remove the Android display resolution selector\"" -[#17467]: https://github.com/hrydgard/ppsspp/issues/17467 "Make the DJ Max workaround more aggressive about hiding stuff." -[#17466]: https://github.com/hrydgard/ppsspp/issues/17466 "Fix running some file formats from the Downloads folder" -[#17440]: https://github.com/hrydgard/ppsspp/issues/17440 "Revert lmode variant reduction" -[#17439]: https://github.com/hrydgard/ppsspp/issues/17439 "Revert \"Merge pull request #16628 from hrydgard/remove-fog-fshader-flag\"" -[#17475]: https://github.com/hrydgard/ppsspp/issues/17475 "Add a trivial profiling tool to the OpenGL backend" -[#17435]: https://github.com/hrydgard/ppsspp/issues/17435 "ElfLoader: Don't scan for functions in zero-length sections" -[#17442]: https://github.com/hrydgard/ppsspp/issues/17442 "Shrink the GLRRenderCommand struct from 152 to 88" -[#17457]: https://github.com/hrydgard/ppsspp/issues/17457 "UI: Fix thread error on zip open failure" -[#17486]: https://github.com/hrydgard/ppsspp/issues/17486 "Build fixes for OpenBSD" -[#17446]: https://github.com/hrydgard/ppsspp/issues/17446 "OpenGL: Combine some render commands" -[#17589]: https://github.com/hrydgard/ppsspp/issues/17589 "Retroachievements support (work-in-progress)" -[#17631]: https://github.com/hrydgard/ppsspp/issues/17631 "RetroAchievements: Remaining features to implement" -[#17960]: https://github.com/hrydgard/ppsspp/issues/17960 "Controls: Make the analog/digital mapping clash resolution more gentle." -[#17673]: https://github.com/hrydgard/ppsspp/issues/17673 "Add checkbox controlling if new mappings can be combo mappings." -[#17562]: https://github.com/hrydgard/ppsspp/issues/17562 "Android: Correct pad name tracking" -[#17433]: https://github.com/hrydgard/ppsspp/issues/17433 "Custom button analog fix" -[#18009]: https://github.com/hrydgard/ppsspp/issues/18009 "Enable [DisallowFramebufferAtOffset] for WWE SvR 2006." -[#18008]: https://github.com/hrydgard/ppsspp/issues/18008 "Add heuristic for memory->framebuffer copies, fixing video flicker in Naruto UNH 2" -[#17965]: https://github.com/hrydgard/ppsspp/issues/17965 "Add compat flag to not load CLUTs from old framebuffers" -[#17449]: https://github.com/hrydgard/ppsspp/issues/17449 "Fragment \"ubershader\" option" -[#17922]: https://github.com/hrydgard/ppsspp/issues/17922 "Add checkboxes in developer tools to allow disabling ubershaders" -[#17903]: https://github.com/hrydgard/ppsspp/issues/17903 "Present modes refactor" -[#18087]: https://github.com/hrydgard/ppsspp/issues/18087 "Vulkan: Fix disabling VSync on SDL platforms that support IMMEDIATE but not MAILBOX" -[#17831]: https://github.com/hrydgard/ppsspp/issues/17831 "Vulkan: Don't use multithreaded rendering if buffer commands (frames in flight) is set to 1" -[#17810]: https://github.com/hrydgard/ppsspp/issues/17810 "Cache computed planes used for BBOX culling" -[#17505]: https://github.com/hrydgard/ppsspp/issues/17505 "Only dirty the uniform UVSCALEOFFSET when really needed" -[#17478]: https://github.com/hrydgard/ppsspp/issues/17478 "OpenGL: Efficiency improvements for stencil commands" -[#17471]: https://github.com/hrydgard/ppsspp/issues/17471 "Reduce zero initialization and copying overhead of render commands" -[#17452]: https://github.com/hrydgard/ppsspp/issues/17452 "Don't cache render target copies for shader blending, only cache copies for overlap" -[#17602]: https://github.com/hrydgard/ppsspp/issues/17602 "Loader: Support HI16/16 pairs, not just LO16" -[#17451]: https://github.com/hrydgard/ppsspp/issues/17451 "Rendering issue with tornado in Lunar Silver Star" -[#17534]: https://github.com/hrydgard/ppsspp/issues/17534 "Add a cache for MakePixelsTexture" -[#17571]: https://github.com/hrydgard/ppsspp/issues/17571 "softgpu: Use SIMD more for dot products" -[#17569]: https://github.com/hrydgard/ppsspp/issues/17569 "ARM64: Optimize saved registers in vertex decoder." -[#17619]: https://github.com/hrydgard/ppsspp/issues/17619 "softgpu: Improve Z interpolation SIMD" -[#17621]: https://github.com/hrydgard/ppsspp/issues/17621 "softgpu: Ensure early depth test uses SIMD" -[#17618]: https://github.com/hrydgard/ppsspp/issues/17618 "Optimize casts in softgpu" -[#17609]: https://github.com/hrydgard/ppsspp/issues/17609 "softgpu: Optimize (bi-)linear texture filtering" -[#17744]: https://github.com/hrydgard/ppsspp/issues/17744 "Initial HTTPS support via Naett (partial platform support)" -[#17947]: https://github.com/hrydgard/ppsspp/issues/17947 "[Adhocctl] Fix for Metal Gear Acid issue" -[#18001]: https://github.com/hrydgard/ppsspp/issues/18001 "Enable the FakeMipmapChange flag for US/EU Tactics Ogre, fixing replacement problem." -[#18011]: https://github.com/hrydgard/ppsspp/issues/18011 "Detect the simplest Tactics Ogre case (US/EU) early" -[#17930]: https://github.com/hrydgard/ppsspp/issues/17930 "Enable anisotropic filtering for replacement textures with mipmaps" -[#17749]: https://github.com/hrydgard/ppsspp/issues/17749 "In D3D11, force block compressed textures to have dimensions divisible" -[#17854]: https://github.com/hrydgard/ppsspp/issues/17854 "Implement color emoji support for Android" -[#17856]: https://github.com/hrydgard/ppsspp/issues/17856 "Windows UWP: Enable color emoji rendering through DirectWrite" -[#17844]: https://github.com/hrydgard/ppsspp/issues/17844 "SDL: text renderer fixes, and CI" -[#17651]: https://github.com/hrydgard/ppsspp/issues/17651 "SDL: support HiDPI on wayland" -[#17755]: https://github.com/hrydgard/ppsspp/issues/17755 "Allow entering an exact Mac address, while keeping the randomization ability" -[#17606]: https://github.com/hrydgard/ppsspp/issues/17606 "OSD: Add colored backgrounds to OSD messages, according to type." -[#17674]: https://github.com/hrydgard/ppsspp/issues/17674 "New UI view: Notice" -[#17672]: https://github.com/hrydgard/ppsspp/issues/17672 "Android: Show some Java exceptions as they happen" -[#17834]: https://github.com/hrydgard/ppsspp/issues/17834 "OpenCFile: Fix Android content-uri append mode" -[#17704]: https://github.com/hrydgard/ppsspp/issues/17704 "OpenXR - Enhancements of cinema-style screen" -[#17752]: https://github.com/hrydgard/ppsspp/issues/17752 "OpenXR - Enable 6DoF in cinema mode" -[#17591]: https://github.com/hrydgard/ppsspp/issues/17591 "OpenXR - Add passthrough option (Quest only)" -[#17636]: https://github.com/hrydgard/ppsspp/issues/17636 "OpenXR - Major review" -[#17656]: https://github.com/hrydgard/ppsspp/issues/17656 "OpenXR - Game compatibility fixes" -[#17598]: https://github.com/hrydgard/ppsspp/issues/17598 "OpenXR - Disable stereo for Ultimate Ghosts and Goblins" -[#17518]: https://github.com/hrydgard/ppsspp/issues/17518 "OpenXR - Enable VR settings per game" -[#18076]: https://github.com/hrydgard/ppsspp/issues/18076 "SasAudio: Always reinitialize the VAG decoder on sceSasSetVoice, even if already playing" -[#17506]: https://github.com/hrydgard/ppsspp/issues/17506 "Emulating HW vrnd" -[#17549]: https://github.com/hrydgard/ppsspp/issues/17549 "Fix vrnd to the current understanding" -[#17676]: https://github.com/hrydgard/ppsspp/issues/17676 "Reduce delays in sceKernelReferThreadProfiler/ReferGlobalProfiler." -[#17677]: https://github.com/hrydgard/ppsspp/issues/17677 "Kernel: Use lower profiler func timing" -[#17952]: https://github.com/hrydgard/ppsspp/issues/17952 "[UWP] Improvements 2 (Configs, Render, Input)" -[#17974]: https://github.com/hrydgard/ppsspp/issues/17974 "(UWP) Another Round of Code Cleanups" -[#18127]: https://github.com/hrydgard/ppsspp/issues/18127 "Move RetroAchievements to the tools tab, fix leaderboard submitted notification positioning" -[#18142]: https://github.com/hrydgard/ppsspp/issues/18142 "Revert \"Merge pull request #18008 from hrydgard/naruto-video-flicker-heuristic\"" -[#18143]: https://github.com/hrydgard/ppsspp/issues/18143 "Fix UMD disc swap with Retroachievements enabled" -[#18133]: https://github.com/hrydgard/ppsspp/issues/18133 "More sensible approach to the sc problem that broke Beats" -[#18140]: https://github.com/hrydgard/ppsspp/issues/18140 "x86jit: Fix spill on sc in longer block" -[#18135]: https://github.com/hrydgard/ppsspp/issues/18135 "Fix closing the chat window with ESC, add some asserts" -[#18129]: https://github.com/hrydgard/ppsspp/issues/18129 "Fix the semantics of DenseHashMap to be consistent even when inserting nulls" -[#18126]: https://github.com/hrydgard/ppsspp/issues/18126 "PPGe: Use texture windows for atlas text" -[#18169]: https://github.com/hrydgard/ppsspp/issues/18169 "Better handling of shadergen failures, other minor things" -[#18151]: https://github.com/hrydgard/ppsspp/issues/18151 "GPU, VFS, UI: Fixed minor memleaks" -[#18165]: https://github.com/hrydgard/ppsspp/issues/18165 "x86jit: Fix flush for special-purpose reg" -[#18158]: https://github.com/hrydgard/ppsspp/issues/18158 "Add -fno-math-errno" -[#18183]: https://github.com/hrydgard/ppsspp/issues/18183 "Pipeline/shader race-condition-during-shutdown crash fix" -[#18189]: https://github.com/hrydgard/ppsspp/issues/18189 "Be a bit smarter when loading the shader cache, avoid duplicating work" -[#18185]: https://github.com/hrydgard/ppsspp/issues/18185 "Store: Fix race condition causing crashes if looking at another game before an icon finishes downloading" -[#18184]: https://github.com/hrydgard/ppsspp/issues/18184 "Add memory bounds-check when expanding points, rects and lines to triangles" -[#18194]: https://github.com/hrydgard/ppsspp/issues/18194 "Cleanups and comment clarifications" -[#18182]: https://github.com/hrydgard/ppsspp/issues/18182 "Backend change from Win32 menu: Add quick workaround for instance counter misbehavior" -[#18218]: https://github.com/hrydgard/ppsspp/issues/18218 "Vulkan: Simplify GetShaders and DirtyLastShader, making them internally consistent." -[#18228]: https://github.com/hrydgard/ppsspp/issues/18228 "unittest: Add jit compare for jit IR" -[#18235]: https://github.com/hrydgard/ppsspp/issues/18235 "irjit: Handle VDet" -[#18211]: https://github.com/hrydgard/ppsspp/issues/18211 "More crash fix attempts" -[#18221]: https://github.com/hrydgard/ppsspp/issues/18221 "Some cleanups and fixes to obscure crashes" -[#18220]: https://github.com/hrydgard/ppsspp/issues/18220 "Add some missing locking in KeyMap.cpp." -[#18230]: https://github.com/hrydgard/ppsspp/issues/18230 "Android: Minor activity lifecycle stuff" -[#18216]: https://github.com/hrydgard/ppsspp/issues/18216 "Don't load the shader cache on a separate thread - all it does is already async" -[#18237]: https://github.com/hrydgard/ppsspp/issues/18237 "UI/localization: Italian translation update" -[#18205]: https://github.com/hrydgard/ppsspp/issues/18205 "http: Fix errors on connect" -[#18201]: https://github.com/hrydgard/ppsspp/issues/18201 "Asserts and checks" -[#18206]: https://github.com/hrydgard/ppsspp/issues/18206 "GPU: Handle invalid blendeq more accurately" -[#18243]: https://github.com/hrydgard/ppsspp/issues/18243 "More crashfix/leakfix attempts" -[#18244]: https://github.com/hrydgard/ppsspp/issues/18244 "Core: Stop leaking file loaders" -[#18247]: https://github.com/hrydgard/ppsspp/issues/18247 "Jit: Assert on bad exit numbers, allow two more exits per block" -[#18261]: https://github.com/hrydgard/ppsspp/issues/18261 "Revert \"Merge pull request #18184 from hrydgard/expand-lines-mem-fix\"" -[#18255]: https://github.com/hrydgard/ppsspp/issues/18255 "Fix issue uploading narrow textures in OpenGL." -[#18250]: https://github.com/hrydgard/ppsspp/issues/18250 "Separate out accelerometer events from joystick axis events" -[#18249]: https://github.com/hrydgard/ppsspp/issues/18249 "arm64jit: Avoid fused multiplies in vcrsp.t" -[#18332]: https://github.com/hrydgard/ppsspp/issues/18332 "We somehow lost the usage_ counter increment in VulkanDescSetPool, fix that" -[#18323]: https://github.com/hrydgard/ppsspp/issues/18323 "Turn off HTTPS support for iOS." -[#18310]: https://github.com/hrydgard/ppsspp/issues/18310 "Fix waves background" \ No newline at end of file +[#17420]: https://github.com/hrydgard/ppsspp/issues/17420 "Fix glitch when mapping analog inputs, caused" \ No newline at end of file diff --git a/SDL/CocoaBarItems.mm b/SDL/CocoaBarItems.mm index e518c2ab1..733a5954b 100644 --- a/SDL/CocoaBarItems.mm +++ b/SDL/CocoaBarItems.mm @@ -24,12 +24,12 @@ #include "Common/Data/Text/I18n.h" #include "Common/StringUtils.h" +void TakeScreenshot(); + #ifdef __cplusplus extern "C" { #endif -extern bool g_TakeScreenshot; - #define MENU_ITEM(variableName, localizedTitleName, SEL, ConfigurationValueName, Tag) \ NSMenuItem *variableName = [[NSMenuItem alloc] initWithTitle:localizedTitleName action:SEL keyEquivalent:@""]; \ variableName.target = self; \ @@ -217,7 +217,7 @@ void OSXOpenURL(const char *url) { item.state = [self controlStateForBool:g_Config.bIgnoreBadMemAccess]; break; case 12: - item.state = [self controlStateForBool:(DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS]; + item.state = [self controlStateForBool:g_Config.bShowDebugStats]; break; default: item.enabled = state == UISTATE_INGAME ? YES : NO; @@ -405,7 +405,7 @@ void OSXOpenURL(const char *url) { copyBaseAddr.target = self; copyBaseAddr.tag = 11; - MENU_ITEM(showDebugStatsAction, DESKTOPUI_LOCALIZED("Show Debug Statistics"), @selector(toggleShowDebugStats:), ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS), 12) + MENU_ITEM(showDebugStatsAction, DESKTOPUI_LOCALIZED("Show Debug Statistics"), @selector(toggleShowDebugStats:), g_Config.bShowDebugStats, 12) [parent addItem:loadSymbolMapAction]; [parent addItem:saveMapFileAction]; @@ -442,17 +442,17 @@ void OSXOpenURL(const char *url) { } -(void)pauseAction: (NSMenuItem *)item { - System_PostUIMessage(UIMessage::REQUEST_GAME_PAUSE); + NativeMessageReceived("pause", ""); } -(void)resetAction: (NSMenuItem *)item { - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); + NativeMessageReceived("reset", ""); Core_EnableStepping(false); } -(void)chatAction: (NSMenuItem *)item { if (GetUIState() == UISTATE_INGAME) { - System_PostUIMessage(UIMessage::SHOW_CHAT_SCREEN); + NativeMessageReceived("chat screen", ""); } } @@ -488,7 +488,7 @@ void OSXOpenURL(const char *url) { } -(void)takeScreenshot { - g_TakeScreenshot = true; + TakeScreenshot(); } -(void)resetSymbolTable { @@ -541,18 +541,9 @@ TOGGLE_METHOD(AutoFrameSkip, g_Config.bAutoFrameSkip, g_Config.UpdateAfterSettin TOGGLE_METHOD(SoftwareRendering, g_Config.bSoftwareRendering) TOGGLE_METHOD(FullScreen, g_Config.bFullScreen, System_MakeRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, 0, g_Config.UseFullScreen() ? "1" : "0", "", 3)) // TOGGLE_METHOD(VSync, g_Config.bVSync) +TOGGLE_METHOD(ShowDebugStats, g_Config.bShowDebugStats, NativeMessageReceived("clear jit", "")) #undef TOGGLE_METHOD --(void)toggleShowDebugStats: (NSMenuItem *)item { \ - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS) { - g_Config.iDebugOverlay = (int)DebugOverlay::OFF; - } else { - g_Config.iDebugOverlay = (int)DebugOverlay::DEBUG_STATS; - } - System_PostUIMessage(UIMessage::REQUEST_CLEAR_JIT); - item.state = [self controlStateForBool: (DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS]; \ -} - -(void)setToggleShowCounterItem: (NSMenuItem *)item { [self addOrRemoveInteger:(int)(item.tag - 100) to:&g_Config.iShowStatusFlags]; item.state = [self controlStateForBool:g_Config.iShowStatusFlags & item.tag]; @@ -631,14 +622,14 @@ TOGGLE_METHOD(FullScreen, g_Config.bFullScreen, System_MakeRequest(SystemRequest } -(void)openRecentItem: (NSMenuItem *)item { - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, g_Config.RecentIsos()[item.tag].c_str()); + NativeMessageReceived("boot", g_Config.RecentIsos()[item.tag].c_str()); } -(void)openSystemFileBrowser { int g = 0; DarwinDirectoryPanelCallback callback = [g] (bool succ, Path thePathChosen) { if (succ) - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, thePathChosen.c_str()); + NativeMessageReceived("boot", thePathChosen.c_str()); }; DarwinFileSystemServices services; diff --git a/SDL/NKCodeFromSDL.h b/SDL/NKCodeFromSDL.h index bcc13ff36..bd184eef0 100644 --- a/SDL/NKCodeFromSDL.h +++ b/SDL/NKCodeFromSDL.h @@ -1,11 +1,10 @@ #pragma once #include "Common/Data/Collections/ConstMap.h" -#include "Common/Input/KeyCodes.h" #include // TODO: Add any missing keys -static const std::map KeyMapRawSDLtoNative = InitConstMap +static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_UNKNOWN, NKCODE_UNKNOWN) (SDLK_p, NKCODE_P) (SDLK_o, NKCODE_O) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 7c05a1ad9..b3c580d3b 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -414,7 +414,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h, // Finally we can do the regular initialization. CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(true); + draw_ = Draw::T3DCreateGLContext(); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); @@ -429,7 +429,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h, #else SDL_GL_SwapWindow(window_); #endif - }); + }, false); renderManager_->SetSwapIntervalFunction([&](int interval) { INFO_LOG(G3D, "SDL SwapInterval: %d", interval); @@ -439,15 +439,19 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h, return 0; } +void SDLGLGraphicsContext::SwapInterval(int interval) { + renderManager_->SwapInterval(interval); +} + +void SDLGLGraphicsContext::Shutdown() { +} + void SDLGLGraphicsContext::ShutdownFromRenderThread() { delete draw_; draw_ = nullptr; - renderManager_ = nullptr; #ifdef USING_EGL EGL_Close(); #endif SDL_GL_DeleteContext(glContext); - glContext = nullptr; - window_ = nullptr; } diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index a54e8b512..95d627ded 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -16,9 +16,16 @@ public: // Returns 0 on success. int Init(SDL_Window *&window, int x, int y, int w, int h, int mode, std::string *error_message); - void Shutdown() override {} + void Shutdown() override; void ShutdownFromRenderThread() override; + void SwapBuffers() override { + // Do nothing, the render thread takes care of this. + } + + // Gets forwarded to the render thread. + void SwapInterval(int interval) override; + void Resize() override {} Draw::DrawContext *GetDrawContext() override { diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp index d9d064434..2f6b47171 100644 --- a/SDL/SDLJoystick.cpp +++ b/SDL/SDLJoystick.cpp @@ -88,8 +88,7 @@ void SDLJoystick::setUpController(int deviceIndex) { controllers.push_back(controller); controllerDeviceMap[SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller))] = deviceIndex; cout << "found control pad: " << SDL_GameControllerName(controller) << ", loading mapping: "; - // NOTE: The case to InputDeviceID here is wrong, we should do some kind of lookup. - KeyMap::NotifyPadConnected((InputDeviceID)deviceIndex, std::string(pszGUID) + ": " + SDL_GameControllerName(controller)); + KeyMap::NotifyPadConnected(deviceIndex, std::string(pszGUID) + ": " + SDL_GameControllerName(controller)); auto mapping = SDL_GameControllerMapping(controller); if (mapping == NULL) { //cout << "FAILED" << endl; @@ -117,7 +116,7 @@ void SDLJoystick::registerEventHandler() { registeredAsEventHandler = true; } -InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { +keycode_t SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { switch (button) { case SDL_CONTROLLER_BUTTON_DPAD_UP: return NKCODE_DPAD_UP; @@ -155,7 +154,7 @@ InputKeyCode SDLJoystick::getKeycodeForButton(SDL_GameControllerButton button) { } } -void SDLJoystick::ProcessInput(const SDL_Event &event){ +void SDLJoystick::ProcessInput(SDL_Event &event){ switch (event.type) { case SDL_CONTROLLERBUTTONDOWN: if (event.cbutton.state == SDL_PRESSED) { @@ -182,28 +181,14 @@ void SDLJoystick::ProcessInput(const SDL_Event &event){ } break; case SDL_CONTROLLERAXISMOTION: - { - InputDeviceID deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.caxis.which); - // TODO: Can we really cast axis IDs like that? Do they match? - InputAxis axisId = (InputAxis)event.caxis.axis; - float value = event.caxis.value * (1.f / 32767.f); - if (value > 1.0f) value = 1.0f; - if (value < -1.0f) value = -1.0f; - // Filter duplicate axis values. - auto key = std::pair(deviceId, axisId); - auto iter = prevAxisValue_.find(key); - if (iter == prevAxisValue_.end()) { - prevAxisValue_[key] = value; - } else if (iter->second != value) { - iter->second = value; - AxisInput axis; - axis.axisId = axisId; - axis.value = value; - axis.deviceId = deviceId; - NativeAxis(&axis, 1); - } // else ignore event. + AxisInput axis; + axis.axisId = event.caxis.axis; + axis.value = event.caxis.value / 32767.0f; + if (axis.value > 1.0f) axis.value = 1.0f; + if (axis.value < -1.0f) axis.value = -1.0f; + axis.deviceId = DEVICE_ID_PAD_0 + getDeviceIndex(event.caxis.which); + NativeAxis(axis); break; - } case SDL_CONTROLLERDEVICEREMOVED: // for removal events, "which" is the instance ID for SDL_CONTROLLERDEVICEREMOVED for (auto it = controllers.begin(); it != controllers.end(); ++it) { diff --git a/SDL/SDLJoystick.h b/SDL/SDLJoystick.h index 50cc43c4c..d7494f829 100644 --- a/SDL/SDLJoystick.h +++ b/SDL/SDLJoystick.h @@ -20,18 +20,14 @@ public: ~SDLJoystick(); void registerEventHandler(); - void ProcessInput(const SDL_Event &event); + void ProcessInput(SDL_Event &event); private: void setUpController(int deviceIndex); void setUpControllers(); - InputKeyCode getKeycodeForButton(SDL_GameControllerButton button); + keycode_t getKeycodeForButton(SDL_GameControllerButton button); int getDeviceIndex(int instanceId); - bool registeredAsEventHandler; std::vector controllers; std::map controllerDeviceMap; - - // Deduplicate axis events. Pair is device, axis. - std::map, float> prevAxisValue_; }; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index b7e0572d9..d81157d83 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -64,12 +64,6 @@ SDLJoystick *joystick = NULL; #include "SDLGLGraphicsContext.h" #include "SDLVulkanGraphicsContext.h" -#if PPSSPP_PLATFORM(MAC) -#include "SDL2/SDL_vulkan.h" -#else -#include "SDL_vulkan.h" -#endif - #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) #include "UI/DarwinFileSystemServices.h" #endif @@ -78,11 +72,6 @@ SDLJoystick *joystick = NULL; #include "CocoaBarItems.h" #endif -#if PPSSPP_PLATFORM(SWITCH) -#define LIBNX_SWKBD_LIMIT 500 // enforced by HOS -extern u32 __nx_applet_type; // Not exposed through a header? -#endif - GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); @@ -91,13 +80,9 @@ static bool g_RestartRequested = false; static int g_DesktopWidth = 0; static int g_DesktopHeight = 0; -static float g_DesktopDPI = 1.0f; -static float g_ForcedDPI = 0.0f; // if this is 0.0f, use g_DesktopDPI static float g_RefreshRate = 60.f; static int g_sampleRate = 44100; -static bool g_rebootEmuThread = false; - static SDL_AudioSpec g_retFmt; // Window state to be transferred to the main SDL thread. @@ -183,27 +168,6 @@ static void StopSDLAudioDevice() { } } -static void UpdateScreenDPI(SDL_Window *window) { - int drawable_width, window_width; - SDL_GetWindowSize(window, &window_width, NULL); - - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) - SDL_GL_GetDrawableSize(window, &drawable_width, NULL); - else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) - SDL_Vulkan_GetDrawableSize(window, &drawable_width, NULL); - - // Round up a little otherwise there would be a gap sometimes - // in fractional scaling - g_DesktopDPI = ((float) drawable_width + 1.0f) / window_width; - - // Temporary hack -#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - g_DesktopDPI = 1.0f; - } -#endif -} - // Simple implementations of System functions @@ -234,36 +198,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string // Do a clean exit g_QuitRequested = true; return true; -#if PPSSPP_PLATFORM(SWITCH) - case SystemRequestType::INPUT_TEXT_MODAL: { - // swkbd only works on "real" titles - if (__nx_applet_type != AppletType_Application && __nx_applet_type != AppletType_SystemApplication) { - g_requestManager.PostSystemFailure(requestId); - return true; - } - - SwkbdConfig kbd; - Result rc = swkbdCreate(&kbd, 0); - - if (R_SUCCEEDED(rc)) { - char buf[LIBNX_SWKBD_LIMIT] = {'\0'}; - swkbdConfigMakePresetDefault(&kbd); - - swkbdConfigSetHeaderText(&kbd, param1.c_str()); - swkbdConfigSetInitialText(&kbd, param2.c_str()); - - rc = swkbdShow(&kbd, buf, sizeof(buf)); - - swkbdClose(&kbd); - - g_requestManager.PostSystemSuccess(requestId, buf); - return true; - } - - g_requestManager.PostSystemFailure(requestId); - return true; - } -#endif // PPSSPP_PLATFORM(SWITCH) #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) case SystemRequestType::BROWSE_FOR_FILE: { @@ -275,8 +209,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } }; DarwinFileSystemServices services; - BrowseFileType fileType = (BrowseFileType)param3; - services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ false, fileType); + services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ false); return true; } case SystemRequestType::BROWSE_FOR_FOLDER: @@ -324,31 +257,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string g_windowState.update = true; return true; } - case SystemRequestType::SHOW_FILE_IN_FOLDER: - { -#if PPSSPP_PLATFORM(WINDOWS) - SFGAOF flags; - PIDLIST_ABSOLUTE pidl = nullptr; - HRESULT hr = SHParseDisplayName(ConvertUTF8ToWString(ReplaceAll(path, "/", "\\")).c_str(), nullptr, &pidl, 0, &flags); - if (pidl) { - if (SUCCEEDED(hr)) - SHOpenFolderAndSelectItems(pidl, 0, NULL, 0); - CoTaskMemFree(pidl); - } -#elif PPSSPP_PLATFORM(MAC) - OSXShowInFinder(param1.c_str()); -#elif (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)) - pid_t pid = fork(); - if (pid < 0) - return true; - - if (pid == 0) { - execlp("xdg-open", "xdg-open", param1.c_str(), nullptr); - exit(1); - } -#endif /* PPSSPP_PLATFORM(WINDOWS) */ - return true; - } default: return false; } @@ -357,6 +265,30 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } +void System_ShowFileInFolder(const char *path) { +#if PPSSPP_PLATFORM(WINDOWS) + SFGAOF flags; + PIDLIST_ABSOLUTE pidl = nullptr; + HRESULT hr = SHParseDisplayName(ConvertUTF8ToWString(ReplaceAll(path, "/", "\\")).c_str(), nullptr, &pidl, 0, &flags); + if (pidl) { + if (SUCCEEDED(hr)) + SHOpenFolderAndSelectItems(pidl, 0, NULL, 0); + CoTaskMemFree(pidl); + } +#elif PPSSPP_PLATFORM(MAC) + OSXShowInFinder(path); +#elif (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)) + pid_t pid = fork(); + if (pid < 0) + return; + + if (pid == 0) { + execlp("xdg-open", "xdg-open", path, nullptr); + exit(1); + } +#endif /* PPSSPP_PLATFORM(WINDOWS) */ +} + void System_LaunchUrl(LaunchUrlType urlType, const char *url) { switch (urlType) { case LaunchUrlType::BROWSER_URL: @@ -463,13 +395,6 @@ std::string System_GetProperty(SystemProperty prop) { } return result; } - case SYSPROP_BUILD_VERSION: - return PPSSPP_GIT_VERSION; - case SYSPROP_USER_DOCUMENTS_DIR: - { - const char *home = getenv("HOME"); - return home ? std::string(home) : "/"; - } default: return ""; } @@ -532,8 +457,6 @@ float System_GetPropertyFloat(SystemProperty prop) { switch (prop) { case SYSPROP_DISPLAY_REFRESH_RATE: return g_RefreshRate; - case SYSPROP_DISPLAY_DPI: - return (g_ForcedDPI == 0.0f ? g_DesktopDPI : g_ForcedDPI) * 96.0; case SYSPROP_DISPLAY_SAFE_INSET_LEFT: case SYSPROP_DISPLAY_SAFE_INSET_RIGHT: case SYSPROP_DISPLAY_SAFE_INSET_TOP: @@ -546,12 +469,6 @@ float System_GetPropertyFloat(SystemProperty prop) { bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { - case SYSPROP_CAN_SHOW_FILE: -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC) || (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)) - return true; -#else - return false; -#endif case SYSPROP_HAS_OPEN_DIRECTORY: #if PPSSPP_PLATFORM(WINDOWS) return true; @@ -560,12 +477,6 @@ bool System_GetPropertyBool(SystemProperty prop) { #endif case SYSPROP_HAS_BACK_BUTTON: return true; -#if PPSSPP_PLATFORM(SWITCH) - case SYSPROP_HAS_TEXT_INPUT_DIALOG: - return __nx_applet_type == AppletType_Application || __nx_applet_type != AppletType_SystemApplication; - case SYSPROP_HAS_KEYBOARD: - return true; -#endif case SYSPROP_APP_GOLD: #ifdef GOLD return true; @@ -574,22 +485,12 @@ bool System_GetPropertyBool(SystemProperty prop) { #endif case SYSPROP_CAN_JIT: return true; - case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: + case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor -#ifndef HTTPS_NOT_AVAILABLE - case SYSPROP_SUPPORTS_HTTPS: - return !g_Config.bDisableHTTPS; -#endif #if PPSSPP_PLATFORM(MAC) case SYSPROP_HAS_FOLDER_BROWSER: case SYSPROP_HAS_FILE_BROWSER: return true; -#endif - case SYSPROP_HAS_ACCELEROMETER: -#if defined(MOBILE_DEVICE) - return true; -#else - return false; #endif default: return false; @@ -675,17 +576,7 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext) { NativeInitGraphics(graphicsContext); while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { - double startTime = time_now_d(); - - UpdateRunLoop(graphicsContext); - - // Simple throttling to not burn the GPU in the menu. - if (GetUIState() != UISTATE_INGAME || !PSP_IsInited()) { - double diffTime = time_now_d() - startTime; - int sleepTime = (int)(1000.0 / 60.0) - (int)(diffTime * 1000.0); - if (sleepTime > 0) - sleep_ms(sleepTime); - } + UpdateRunLoop(); } emuThreadState = (int)EmuThreadState::STOPPED; graphicsContext->StopThread(); @@ -698,7 +589,7 @@ static void EmuThreadStart(GraphicsContext *context) { emuThread = std::thread(&EmuThreadFunc, context); } -static void EmuThreadStop(const char *reason) { +static void EmuThreadStop() { emuThreadState = (int)EmuThreadState::QUIT_REQUESTED; } @@ -707,449 +598,6 @@ static void EmuThreadJoin() { emuThread = std::thread(); } -struct InputStateTracker { - void TranslateMouseWheel() { - // SDL2 doesn't consider the mousewheel a button anymore - // so let's send the KEY_UP if it was moved after some frames - if (mouseWheelMovedUpFrames > 0) { - mouseWheelMovedUpFrames--; - if (mouseWheelMovedUpFrames == 0) { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - key.flags = KEY_UP; - NativeKey(key); - } - } - if (mouseWheelMovedDownFrames > 0) { - mouseWheelMovedDownFrames--; - if (mouseWheelMovedDownFrames == 0) { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - key.flags = KEY_UP; - NativeKey(key); - } - } - } - - void MouseControl() { - // Disabled by default, needs a workaround to map to psp keys. - if (g_Config.bMouseControl) { - float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; - float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; - - AxisInput axis[2]; - axis[0].axisId = JOYSTICK_AXIS_MOUSE_REL_X; - axis[0].deviceId = DEVICE_ID_MOUSE; - axis[0].value = std::max(-1.0f, std::min(1.0f, mouseDeltaX * scaleFactor_x)); - axis[1].axisId = JOYSTICK_AXIS_MOUSE_REL_Y; - axis[1].deviceId = DEVICE_ID_MOUSE; - axis[1].value = std::max(-1.0f, std::min(1.0f, mouseDeltaY * scaleFactor_y)); - - if (GetUIState() == UISTATE_INGAME || g_Config.bMapMouse) { - NativeAxis(axis, 2); - } - mouseDeltaX *= g_Config.fMouseSmoothing; - mouseDeltaY *= g_Config.fMouseSmoothing; - } - } - - void MouseCaptureControl() { - bool captureMouseCondition = g_Config.bMouseControl && ((GetUIState() == UISTATE_INGAME && g_Config.bMouseConfine) || g_Config.bMapMouse); - if (mouseCaptured != captureMouseCondition) { - mouseCaptured = captureMouseCondition; - if (captureMouseCondition) - SDL_SetRelativeMouseMode(SDL_TRUE); - else - SDL_SetRelativeMouseMode(SDL_FALSE); - } - } - - bool mouseDown; - float mouseDeltaX; - float mouseDeltaY; - int mouseWheelMovedUpFrames; - int mouseWheelMovedDownFrames; - bool mouseCaptured; -}; - -static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputStateTracker *inputTracker) { - // We have to juggle around 3 kinds of "DPI spaces" if a logical DPI is - // provided (through --dpi, it is equal to system DPI if unspecified): - // - SDL gives us motion events in "system DPI" points - // - UpdateScreenScale expects pixels, so in a way "96 DPI" points - // - The UI code expects motion events in "logical DPI" points - float mx = event.motion.x * g_DesktopDPI * g_display.dpi_scale_x; - float my = event.motion.y * g_DesktopDPI * g_display.dpi_scale_x; - - switch (event.type) { - case SDL_QUIT: - g_QuitRequested = 1; - break; - -#if !defined(MOBILE_DEVICE) - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_WINDOWEVENT_SIZE_CHANGED: // better than RESIZED, more general - { - int new_width = event.window.data1; - int new_height = event.window.data2; - - // The size given by SDL is in point-units, convert these to - // pixels before passing to UpdateScreenScale() - int new_width_px = new_width * g_DesktopDPI; - int new_height_px = new_height * g_DesktopDPI; - - Core_NotifyWindowHidden(false); - - Uint32 window_flags = SDL_GetWindowFlags(window); - bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); - - // This one calls NativeResized if the size changed. - UpdateScreenScale(new_width_px, new_height_px); - - // Set variable here in case fullscreen was toggled by hotkey - if (g_Config.UseFullScreen() != fullscreen) { - g_Config.bFullScreen = fullscreen; - g_Config.iForceFullScreen = -1; - } else { - // It is possible for the monitor to change DPI, so recalculate - // DPI on each resize event. - UpdateScreenDPI(window); - } - - if (!g_Config.bFullScreen) { - g_Config.iWindowWidth = new_width; - g_Config.iWindowHeight = new_height; - } - // Hide/Show cursor correctly toggling fullscreen - if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) { - SDL_ShowCursor(SDL_DISABLE); - } else if (lastUIState != UISTATE_INGAME || !fullscreen) { - SDL_ShowCursor(SDL_ENABLE); - } - break; - } - - case SDL_WINDOWEVENT_MOVED: - { - Uint32 window_flags = SDL_GetWindowFlags(window); - bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); - if (!fullscreen) { - g_Config.iWindowX = (int)event.window.data1; - g_Config.iWindowY = (int)event.window.data2; - } - break; - } - - case SDL_WINDOWEVENT_MINIMIZED: - case SDL_WINDOWEVENT_HIDDEN: - Core_NotifyWindowHidden(true); - break; - case SDL_WINDOWEVENT_EXPOSED: - case SDL_WINDOWEVENT_SHOWN: - Core_NotifyWindowHidden(false); - break; - default: - break; - } - break; -#endif - case SDL_KEYDOWN: - { - if (event.key.repeat > 0) { break;} - int k = event.key.keysym.sym; - KeyInput key; - key.flags = KEY_DOWN; - auto mapped = KeyMapRawSDLtoNative.find(k); - if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { - break; - } - key.keyCode = mapped->second; - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - -#ifdef _DEBUG - if (k == SDLK_F7) { - printf("f7 pressed - rebooting emuthread\n"); - g_rebootEmuThread = true; - } -#endif - // Convenience subset of what - // "Enable standard shortcut keys" - // does on Windows. - if(g_Config.bSystemControls) { - bool ctrl = bool(event.key.keysym.mod & KMOD_CTRL); - if (ctrl && (k == SDLK_w)) - { - if (Core_IsStepping()) - Core_EnableStepping(false); - Core_Stop(); - System_PostUIMessage(UIMessage::REQUEST_GAME_STOP); - // NOTE: Unlike Windows version, this - // does not need Core_WaitInactive(); - // since SDL does not have a separate - // UI thread. - } - if (ctrl && (k == SDLK_b)) - { - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); - Core_EnableStepping(false); - } - } - break; - } - case SDL_KEYUP: - { - if (event.key.repeat > 0) { break;} - int k = event.key.keysym.sym; - KeyInput key; - key.flags = KEY_UP; - auto mapped = KeyMapRawSDLtoNative.find(k); - if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { - break; - } - key.keyCode = mapped->second; - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - break; - } - case SDL_TEXTINPUT: - { - int pos = 0; - int c = u8_nextchar(event.text.text, &pos); - KeyInput key; - key.flags = KEY_CHAR; - key.unicodeChar = c; - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - break; - } -// This behavior doesn't feel right on a macbook with a touchpad. -#if !PPSSPP_PLATFORM(MAC) - case SDL_FINGERMOTION: - { - int w, h; - SDL_GetWindowSize(window, &w, &h); - TouchInput input; - input.id = event.tfinger.fingerId; - input.x = event.tfinger.x * w * g_DesktopDPI * g_display.dpi_scale_x; - input.y = event.tfinger.y * h * g_DesktopDPI * g_display.dpi_scale_x; - input.flags = TOUCH_MOVE; - input.timestamp = event.tfinger.timestamp; - NativeTouch(input); - break; - } - case SDL_FINGERDOWN: - { - int w, h; - SDL_GetWindowSize(window, &w, &h); - TouchInput input; - input.id = event.tfinger.fingerId; - input.x = event.tfinger.x * w * g_DesktopDPI * g_display.dpi_scale_x; - input.y = event.tfinger.y * h * g_DesktopDPI * g_display.dpi_scale_x; - input.flags = TOUCH_DOWN; - input.timestamp = event.tfinger.timestamp; - NativeTouch(input); - - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEBUTTON_1; - key.flags = KEY_DOWN; - NativeKey(key); - break; - } - case SDL_FINGERUP: - { - int w, h; - SDL_GetWindowSize(window, &w, &h); - TouchInput input; - input.id = event.tfinger.fingerId; - input.x = event.tfinger.x * w * g_DesktopDPI * g_display.dpi_scale_x; - input.y = event.tfinger.y * h * g_DesktopDPI * g_display.dpi_scale_x; - input.flags = TOUCH_UP; - input.timestamp = event.tfinger.timestamp; - NativeTouch(input); - - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEBUTTON_1; - key.flags = KEY_UP; - NativeKey(key); - break; - } -#endif - case SDL_MOUSEBUTTONDOWN: - switch (event.button.button) { - case SDL_BUTTON_LEFT: - { - inputTracker->mouseDown = true; - TouchInput input{}; - input.x = mx; - input.y = my; - input.flags = TOUCH_DOWN | TOUCH_MOUSE; - input.id = 0; - NativeTouch(input); - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); - NativeKey(key); - } - break; - case SDL_BUTTON_RIGHT: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); - NativeKey(key); - } - break; - case SDL_BUTTON_MIDDLE: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_3, KEY_DOWN); - NativeKey(key); - } - break; - case SDL_BUTTON_X1: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_4, KEY_DOWN); - NativeKey(key); - } - break; - case SDL_BUTTON_X2: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_5, KEY_DOWN); - NativeKey(key); - } - break; - } - break; - case SDL_MOUSEWHEEL: - { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.flags = KEY_DOWN; -#if SDL_VERSION_ATLEAST(2, 0, 18) - if (event.wheel.preciseY != 0.0f) { - // Should the scale be DPI-driven? - const float scale = 30.0f; - key.keyCode = event.wheel.preciseY > 0 ? NKCODE_EXT_MOUSEWHEEL_UP : NKCODE_EXT_MOUSEWHEEL_DOWN; - key.flags |= KEY_HASWHEELDELTA; - int wheelDelta = event.wheel.preciseY * scale; - if (event.wheel.preciseY < 0) { - wheelDelta = -wheelDelta; - } - key.flags |= wheelDelta << 16; - NativeKey(key); - break; - } -#endif - if (event.wheel.y > 0) { - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - inputTracker->mouseWheelMovedUpFrames = 5; - NativeKey(key); - } else if (event.wheel.y < 0) { - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - inputTracker->mouseWheelMovedDownFrames = 5; - NativeKey(key); - } - break; - } - case SDL_MOUSEMOTION: - if (inputTracker->mouseDown) { - TouchInput input{}; - input.x = mx; - input.y = my; - input.flags = TOUCH_MOVE | TOUCH_MOUSE; - input.id = 0; - NativeTouch(input); - } - inputTracker->mouseDeltaX += event.motion.xrel; - inputTracker->mouseDeltaY += event.motion.yrel; - break; - case SDL_MOUSEBUTTONUP: - switch (event.button.button) { - case SDL_BUTTON_LEFT: - { - inputTracker->mouseDown = false; - TouchInput input{}; - input.x = mx; - input.y = my; - input.flags = TOUCH_UP | TOUCH_MOUSE; - input.id = 0; - NativeTouch(input); - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); - NativeKey(key); - } - break; - case SDL_BUTTON_RIGHT: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); - NativeKey(key); - } - break; - case SDL_BUTTON_MIDDLE: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_3, KEY_UP); - NativeKey(key); - } - break; - case SDL_BUTTON_X1: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_4, KEY_UP); - NativeKey(key); - } - break; - case SDL_BUTTON_X2: - { - KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_5, KEY_UP); - NativeKey(key); - } - break; - } - break; - -#if SDL_VERSION_ATLEAST(2, 0, 4) - case SDL_AUDIODEVICEADDED: - // Automatically switch to the new device. - if (event.adevice.iscapture == 0) { - const char *name = SDL_GetAudioDeviceName(event.adevice.which, 0); - if (!name) { - break; - } - // Don't start auto switching for a second, because some devices init on start. - bool doAutoSwitch = g_Config.bAutoAudioDevice && time_now_d() > 1.0f; - if (doAutoSwitch || g_Config.sAudioDevice == name) { - StopSDLAudioDevice(); - InitSDLAudioDevice(name ? name : ""); - } - } - break; - case SDL_AUDIODEVICEREMOVED: - if (event.adevice.iscapture == 0 && event.adevice.which == audioDev) { - StopSDLAudioDevice(); - InitSDLAudioDevice(); - } - break; -#endif - - default: - if (joystick) { - joystick->ProcessInput(event); - } - break; - } -} - -void UpdateSDLCursor() { -#if !defined(MOBILE_DEVICE) - if (lastUIState != GetUIState()) { - lastUIState = GetUIState(); - if (lastUIState == UISTATE_INGAME && g_Config.UseFullScreen() && !g_Config.bShowTouchControls) - SDL_ShowCursor(SDL_DISABLE); - if (lastUIState != UISTATE_INGAME || !g_Config.UseFullScreen()) - SDL_ShowCursor(SDL_ENABLE); - } -#endif -} - #ifdef _WIN32 #undef main #endif @@ -1196,7 +644,7 @@ int main(int argc, char *argv[]) { int set_yres = -1; bool portrait = false; bool set_ipad = false; - float set_dpi = 0.0f; + float set_dpi = 1.0f; float set_scale = 1.0f; // Produce a new set of arguments with the ones we skip. @@ -1288,7 +736,7 @@ int main(int argc, char *argv[]) { #elif defined(USING_FBDEV) || PPSSPP_PLATFORM(SWITCH) mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; #else - mode |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; + mode |= SDL_WINDOW_RESIZABLE; #endif if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { @@ -1307,6 +755,8 @@ int main(int argc, char *argv[]) { g_Config.bFullScreen = false; } + set_dpi = 1.0f / set_dpi; + if (set_ipad) { g_display.pixel_xres = 1024; g_display.pixel_yres = 768; @@ -1321,8 +771,9 @@ int main(int argc, char *argv[]) { if (set_yres > 0) { g_display.pixel_yres = set_yres; } + float dpi_scale = 1.0f; if (set_dpi > 0) { - g_ForcedDPI = set_dpi; + dpi_scale = set_dpi; } // Mac / Linux @@ -1373,6 +824,18 @@ int main(int argc, char *argv[]) { if (g_Config.iWindowHeight > 0) h = g_Config.iWindowHeight; } + g_display.pixel_xres = w; + g_display.pixel_yres = h; + g_display.dp_xres = (float)g_display.pixel_xres * dpi_scale; + g_display.dp_yres = (float)g_display.pixel_yres * dpi_scale; + + g_display.pixel_in_dps_x = (float)g_display.pixel_xres / g_display.dp_xres; + g_display.pixel_in_dps_y = (float)g_display.pixel_yres / g_display.dp_yres; + g_display.dpi_scale_x = g_display.dp_xres / (float)g_display.pixel_xres; + g_display.dpi_scale_y = g_display.dp_yres / (float)g_display.pixel_yres; + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; + // g_display.Print(); GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; @@ -1400,19 +863,8 @@ int main(int argc, char *argv[]) { } #endif } -#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - g_ForcedDPI = 1.0f; - } -#endif - UpdateScreenDPI(window); - - float dpi_scale = 1.0f / (g_ForcedDPI == 0.0f ? g_DesktopDPI : g_ForcedDPI); - - UpdateScreenScale(w * g_DesktopDPI, h * g_DesktopDPI); - - bool mainThreadIsRender = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; + bool useEmuThread = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); @@ -1445,6 +897,11 @@ int main(int argc, char *argv[]) { SDL_ShowCursor(SDL_DISABLE); #endif + if (!useEmuThread) { + NativeInitGraphics(graphicsContext); + NativeResized(); + } + // Ensure that the swap interval is set after context creation (needed for kmsdrm) SDL_GL_SetSwapInterval(1); @@ -1457,72 +914,435 @@ int main(int argc, char *argv[]) { } EnableFZ(); - EmuThreadStart(graphicsContext); + int framecount = 0; + bool mouseDown = false; + if (useEmuThread) { + EmuThreadStart(graphicsContext); + } graphicsContext->ThreadStart(); - InputStateTracker inputTracker{}; + float mouseDeltaX = 0; + float mouseDeltaY = 0; + int mouseWheelMovedUpFrames = 0; + int mouseWheelMovedDownFrames = 0; + bool mouseCaptured = false; + bool windowHidden = false; #if PPSSPP_PLATFORM(MAC) // setup menu items for macOS - initializeOSXExtras(); + initializeOSXExtras(); #endif + + while (true) { + double startTime = time_now_d(); - bool waitOnExit = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; - - if (!mainThreadIsRender) { - // We should only be a message pump - while (true) { - inputTracker.TranslateMouseWheel(); - - SDL_Event event; - while (SDL_PollEvent(&event)) { - ProcessSDLEvent(window, event, &inputTracker); + // SDL2 doesn't consider the mousewheel a button anymore + // so let's send the KEY_UP if it was moved after some frames + if (mouseWheelMovedUpFrames > 0) { + mouseWheelMovedUpFrames--; + if (mouseWheelMovedUpFrames == 0) { + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; + key.flags = KEY_UP; + NativeKey(key); } - if (g_QuitRequested || g_RestartRequested) + } + if (mouseWheelMovedDownFrames > 0) { + mouseWheelMovedDownFrames--; + if (mouseWheelMovedDownFrames == 0) { + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; + key.flags = KEY_UP; + NativeKey(key); + } + } + SDL_Event event, touchEvent; + while (SDL_PollEvent(&event)) { + float mx = event.motion.x * g_display.dpi_scale_x; + float my = event.motion.y * g_display.dpi_scale_y; + + switch (event.type) { + case SDL_QUIT: + g_QuitRequested = 1; break; - UpdateSDLCursor(); +#if !defined(MOBILE_DEVICE) + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_SIZE_CHANGED: // better than RESIZED, more general + { + int new_width = event.window.data1; + int new_height = event.window.data2; - inputTracker.MouseControl(); - inputTracker.MouseCaptureControl(); + windowHidden = false; + Core_NotifyWindowHidden(windowHidden); + Uint32 window_flags = SDL_GetWindowFlags(window); + bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); - { - std::lock_guard guard(g_mutexWindow); - if (g_windowState.update) { - UpdateWindowState(window); + // This one calls NativeResized if the size changed. + UpdateScreenScale(new_width, new_height); + + // Set variable here in case fullscreen was toggled by hotkey + if (g_Config.UseFullScreen() != fullscreen) { + g_Config.bFullScreen = fullscreen; + g_Config.iForceFullScreen = -1; + } + + if (!g_Config.bFullScreen) { + g_Config.iWindowWidth = new_width; + g_Config.iWindowHeight = new_height; + } + // Hide/Show cursor correctly toggling fullscreen + if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) { + SDL_ShowCursor(SDL_DISABLE); + } else if (lastUIState != UISTATE_INGAME || !fullscreen) { + SDL_ShowCursor(SDL_ENABLE); + } + break; } - } - } - } else while (true) { - inputTracker.TranslateMouseWheel(); - { - SDL_Event event; - while (SDL_PollEvent(&event)) { - ProcessSDLEvent(window, event, &inputTracker); + case SDL_WINDOWEVENT_MOVED: + { + int x = event.window.data1; + int y = event.window.data2; + Uint32 window_flags = SDL_GetWindowFlags(window); + bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); + if (!fullscreen) { + g_Config.iWindowX = x; + g_Config.iWindowY = y; + } + break; + } + + case SDL_WINDOWEVENT_MINIMIZED: + case SDL_WINDOWEVENT_HIDDEN: + windowHidden = true; + Core_NotifyWindowHidden(windowHidden); + break; + case SDL_WINDOWEVENT_EXPOSED: + case SDL_WINDOWEVENT_SHOWN: + windowHidden = false; + Core_NotifyWindowHidden(windowHidden); + break; + default: + break; + } + break; +#endif + case SDL_KEYDOWN: + { + if (event.key.repeat > 0) { break;} + int k = event.key.keysym.sym; + KeyInput key; + key.flags = KEY_DOWN; + auto mapped = KeyMapRawSDLtoNative.find(k); + if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { + break; + } + key.keyCode = mapped->second; + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + break; + } + case SDL_KEYUP: + { + if (event.key.repeat > 0) { break;} + int k = event.key.keysym.sym; + KeyInput key; + key.flags = KEY_UP; + auto mapped = KeyMapRawSDLtoNative.find(k); + if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { + break; + } + key.keyCode = mapped->second; + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + break; + } + case SDL_TEXTINPUT: + { + int pos = 0; + int c = u8_nextchar(event.text.text, &pos); + KeyInput key; + key.flags = KEY_CHAR; + key.keyCode = c; + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + break; + } +// This behavior doesn't feel right on a macbook with a touchpad. +#if !PPSSPP_PLATFORM(MAC) + case SDL_FINGERMOTION: + { + SDL_GetWindowSize(window, &w, &h); + TouchInput input; + input.id = event.tfinger.fingerId; + input.x = event.tfinger.x * w; + input.y = event.tfinger.y * h; + input.flags = TOUCH_MOVE; + input.timestamp = event.tfinger.timestamp; + NativeTouch(input); + break; + } + case SDL_FINGERDOWN: + { + SDL_GetWindowSize(window, &w, &h); + TouchInput input; + input.id = event.tfinger.fingerId; + input.x = event.tfinger.x * w; + input.y = event.tfinger.y * h; + input.flags = TOUCH_DOWN; + input.timestamp = event.tfinger.timestamp; + NativeTouch(input); + + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + key.keyCode = NKCODE_EXT_MOUSEBUTTON_1; + key.flags = KEY_DOWN; + NativeKey(key); + break; + } + case SDL_FINGERUP: + { + SDL_GetWindowSize(window, &w, &h); + TouchInput input; + input.id = event.tfinger.fingerId; + input.x = event.tfinger.x * w; + input.y = event.tfinger.y * h; + input.flags = TOUCH_UP; + input.timestamp = event.tfinger.timestamp; + NativeTouch(input); + + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + key.keyCode = NKCODE_EXT_MOUSEBUTTON_1; + key.flags = KEY_UP; + NativeKey(key); + break; + } +#endif + case SDL_MOUSEBUTTONDOWN: + switch (event.button.button) { + case SDL_BUTTON_LEFT: + { + mouseDown = true; + TouchInput input{}; + input.x = mx; + input.y = my; + input.flags = TOUCH_DOWN | TOUCH_MOUSE; + input.id = 0; + NativeTouch(input); + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); + NativeKey(key); + } + break; + case SDL_BUTTON_RIGHT: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); + NativeKey(key); + } + break; + case SDL_BUTTON_MIDDLE: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_3, KEY_DOWN); + NativeKey(key); + } + break; + case SDL_BUTTON_X1: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_4, KEY_DOWN); + NativeKey(key); + } + break; + case SDL_BUTTON_X2: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_5, KEY_DOWN); + NativeKey(key); + } + break; + } + break; + case SDL_MOUSEWHEEL: + { + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + key.flags = KEY_DOWN; +#if SDL_VERSION_ATLEAST(2, 0, 18) + if (event.wheel.preciseY != 0.0f) { + // Should the scale be DPI-driven? + const float scale = 30.0f; + key.keyCode = event.wheel.preciseY > 0 ? NKCODE_EXT_MOUSEWHEEL_UP : NKCODE_EXT_MOUSEWHEEL_DOWN; + key.flags |= KEY_HASWHEELDELTA; + int wheelDelta = event.wheel.preciseY * scale; + if (event.wheel.preciseY < 0) { + wheelDelta = -wheelDelta; + } + key.flags |= wheelDelta << 16; + NativeKey(key); + break; + } +#endif + // TODO: Should we even keep the "non-precise" events? + if (event.wheel.y > 0) { + key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; + mouseWheelMovedUpFrames = 5; + NativeKey(key); + } else if (event.wheel.y < 0) { + key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; + mouseWheelMovedDownFrames = 5; + NativeKey(key); + } + break; + } + case SDL_MOUSEMOTION: + if (mouseDown) { + TouchInput input{}; + input.x = mx; + input.y = my; + input.flags = TOUCH_MOVE | TOUCH_MOUSE; + input.id = 0; + NativeTouch(input); + } + mouseDeltaX += event.motion.xrel; + mouseDeltaY += event.motion.yrel; + break; + case SDL_MOUSEBUTTONUP: + switch (event.button.button) { + case SDL_BUTTON_LEFT: + { + mouseDown = false; + TouchInput input{}; + input.x = mx; + input.y = my; + input.flags = TOUCH_UP | TOUCH_MOUSE; + input.id = 0; + NativeTouch(input); + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); + NativeKey(key); + } + break; + case SDL_BUTTON_RIGHT: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); + NativeKey(key); + } + break; + case SDL_BUTTON_MIDDLE: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_3, KEY_UP); + NativeKey(key); + } + break; + case SDL_BUTTON_X1: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_4, KEY_UP); + NativeKey(key); + } + break; + case SDL_BUTTON_X2: + { + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_5, KEY_UP); + NativeKey(key); + } + break; + } + break; + +#if SDL_VERSION_ATLEAST(2, 0, 4) + case SDL_AUDIODEVICEADDED: + // Automatically switch to the new device. + if (event.adevice.iscapture == 0) { + const char *name = SDL_GetAudioDeviceName(event.adevice.which, 0); + if (!name) { + break; + } + // Don't start auto switching for a second, because some devices init on start. + bool doAutoSwitch = g_Config.bAutoAudioDevice && framecount > 60; + if (doAutoSwitch || g_Config.sAudioDevice == name) { + StopSDLAudioDevice(); + InitSDLAudioDevice(name ? name : ""); + } + } + break; + case SDL_AUDIODEVICEREMOVED: + if (event.adevice.iscapture == 0 && event.adevice.which == audioDev) { + StopSDLAudioDevice(); + InitSDLAudioDevice(); + } + break; +#endif + + default: + if (joystick) { + joystick->ProcessInput(event); + } + break; } } if (g_QuitRequested || g_RestartRequested) break; + const uint8_t *keys = SDL_GetKeyboardState(NULL); if (emuThreadState == (int)EmuThreadState::DISABLED) { - UpdateRunLoop(graphicsContext); + UpdateRunLoop(); } if (g_QuitRequested || g_RestartRequested) break; - UpdateSDLCursor(); +#if !defined(MOBILE_DEVICE) + if (lastUIState != GetUIState()) { + lastUIState = GetUIState(); + if (lastUIState == UISTATE_INGAME && g_Config.UseFullScreen() && !g_Config.bShowTouchControls) + SDL_ShowCursor(SDL_DISABLE); + if (lastUIState != UISTATE_INGAME || !g_Config.UseFullScreen()) + SDL_ShowCursor(SDL_ENABLE); + } +#endif - inputTracker.MouseControl(); - inputTracker.MouseCaptureControl(); + // Disabled by default, needs a workaround to map to psp keys. + if (g_Config.bMouseControl) { + float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; + float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; - bool renderThreadPaused = Core_IsWindowHidden() && g_Config.bPauseWhenMinimized && emuThreadState != (int)EmuThreadState::DISABLED; + AxisInput axisX, axisY; + axisX.axisId = JOYSTICK_AXIS_MOUSE_REL_X; + axisX.deviceId = DEVICE_ID_MOUSE; + axisX.value = std::max(-1.0f, std::min(1.0f, mouseDeltaX * scaleFactor_x)); + axisY.axisId = JOYSTICK_AXIS_MOUSE_REL_Y; + axisY.deviceId = DEVICE_ID_MOUSE; + axisY.value = std::max(-1.0f, std::min(1.0f, mouseDeltaY * scaleFactor_y)); + + if (GetUIState() == UISTATE_INGAME || g_Config.bMapMouse) { + NativeAxis(axisX); + NativeAxis(axisY); + } + mouseDeltaX *= g_Config.fMouseSmoothing; + mouseDeltaY *= g_Config.fMouseSmoothing; + } + bool captureMouseCondition = g_Config.bMouseControl && ((GetUIState() == UISTATE_INGAME && g_Config.bMouseConfine) || g_Config.bMapMouse); + if (mouseCaptured != captureMouseCondition) { + mouseCaptured = captureMouseCondition; + if (captureMouseCondition) + SDL_SetRelativeMouseMode(SDL_TRUE); + else + SDL_SetRelativeMouseMode(SDL_FALSE); + } + + if (framecount % 60 == 0) { + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. + } + + bool renderThreadPaused = windowHidden && g_Config.bPauseWhenMinimized && emuThreadState != (int)EmuThreadState::DISABLED; if (emuThreadState != (int)EmuThreadState::DISABLED && !renderThreadPaused) { if (!graphicsContext->ThreadFrame()) break; } + graphicsContext->SwapBuffers(); + { std::lock_guard guard(g_mutexWindow); if (g_windowState.update) { @@ -1530,50 +1350,31 @@ int main(int argc, char *argv[]) { } } - if (g_rebootEmuThread) { - printf("rebooting emu thread"); - g_rebootEmuThread = false; - EmuThreadStop("shutdown"); - // Skipping GL calls, the old context is gone. - while (graphicsContext->ThreadFrame()) { - INFO_LOG(SYSTEM, "graphicsContext->ThreadFrame executed to clear buffers"); - } - EmuThreadJoin(); - graphicsContext->ThreadEnd(); - graphicsContext->ShutdownFromRenderThread(); - - printf("OK, shutdown complete. starting up graphics again.\n"); - - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { - SDLGLGraphicsContext *ctx = (SDLGLGraphicsContext *)graphicsContext; - if (!ctx->Init(window, x, y, w, h, mode, &error_message)) { - printf("Failed to reinit graphics.\n"); - } - } - - if (!graphicsContext->InitFromRenderThread(&error_message)) { - System_Toast("Graphics initialization failed. Quitting."); - return 1; - } - - EmuThreadStart(graphicsContext); - graphicsContext->ThreadStart(); + // Simple throttling to not burn the GPU in the menu. + if (GetUIState() != UISTATE_INGAME || !PSP_IsInited() || renderThreadPaused) { + double diffTime = time_now_d() - startTime; + int sleepTime = (int)(1000.0 / 60.0) - (int)(diffTime * 1000.0); + if (sleepTime > 0) + sleep_ms(sleepTime); } + + framecount++; } - EmuThreadStop("shutdown"); - - if (waitOnExit) { + if (useEmuThread) { + EmuThreadStop(); while (graphicsContext->ThreadFrame()) { // Need to keep eating frames to allow the EmuThread to exit correctly. continue; } + EmuThreadJoin(); } - EmuThreadJoin(); - delete joystick; + if (!useEmuThread) { + NativeShutdownGraphics(); + } graphicsContext->ThreadEnd(); NativeShutdown(); diff --git a/SDL/SDLVulkanGraphicsContext.cpp b/SDL/SDLVulkanGraphicsContext.cpp index c15eb2824..b46858068 100644 --- a/SDL/SDLVulkanGraphicsContext.cpp +++ b/SDL/SDLVulkanGraphicsContext.cpp @@ -27,14 +27,9 @@ static const bool g_Validate = true; static const bool g_Validate = false; #endif -// TODO: Share this between backends. static uint32_t FlagsFromConfig() { - uint32_t flags; - if (g_Config.bVSync) { - flags = VULKAN_FLAG_PRESENT_FIFO; - } else { - flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_IMMEDIATE; - } + uint32_t flags = 0; + flags = g_Config.bVSync ? VULKAN_FLAG_PRESENT_FIFO : VULKAN_FLAG_PRESENT_MAILBOX; if (g_Validate) { flags |= VULKAN_FLAG_VALIDATE; } @@ -74,15 +69,7 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, in vulkan_ = nullptr; return false; } - - int deviceNum = vulkan_->GetPhysicalDeviceByName(g_Config.sVulkanDevice); - if (deviceNum < 0) { - deviceNum = vulkan_->GetBestPhysicalDevice(); - if (!g_Config.sVulkanDevice.empty()) - g_Config.sVulkanDevice = vulkan_->GetPhysicalDeviceProperties(deviceNum).properties.deviceName; - } - - vulkan_->ChooseDevice(deviceNum); + vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice()); if (vulkan_->CreateDevice() != VK_SUCCESS) { *error_message = vulkan_->InitError(); delete vulkan_; @@ -149,11 +136,7 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, in return false; } - bool useMultiThreading = g_Config.bRenderMultiThreading; - if (g_Config.iInflightFrames == 1) { - useMultiThreading = false; - } - draw_ = Draw::T3DCreateVulkanContext(vulkan_, useMultiThreading); + draw_ = Draw::T3DCreateVulkanContext(vulkan_); SetGPUBackend(GPUBackend::VULKAN); bool success = draw_->CreatePresets(); _assert_(success); @@ -161,6 +144,7 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, in renderManager_ = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); + return true; } diff --git a/SDL/SDLVulkanGraphicsContext.h b/SDL/SDLVulkanGraphicsContext.h index f10edf8d2..d309e685d 100644 --- a/SDL/SDLVulkanGraphicsContext.h +++ b/SDL/SDLVulkanGraphicsContext.h @@ -26,10 +26,16 @@ public: void Shutdown() override; + void SwapBuffers() override { + // We don't do it this way. + } + void Resize() override; void Poll() override; + void SwapInterval(int interval) override { + } void *GetAPIContext() override { return vulkan_; } diff --git a/SDL/macbundle.sh b/SDL/macbundle.sh index b51e804ce..9c67205ef 100755 --- a/SDL/macbundle.sh +++ b/SDL/macbundle.sh @@ -1,11 +1,10 @@ #!/bin/bash -echo "Hello from macbundle.sh" +echo "Hello" PPSSPP="${1}" PPSSPP_SHORTNAME="${2}" PPSSPPSDL="${PPSSPP}/Contents/MacOS/${PPSSPP_SHORTNAME}" -MOLTENVK="${PPSSPP}/Contents/Frameworks/libMoltenVK.dylib" ls ${PPSSPPSDL} @@ -36,7 +35,11 @@ install_name_tool -rpath "${RPATH}" "@executable_path/../Frameworks" "${PPSSPPSD echo "Done." -GIT_VERSION_LINE=$(grep "PPSSPP_GIT_VERSION = " "$(dirname "${0}")/../build/git-version.cpp") +GIT_VERSION_LINE=$(grep "PPSSPP_GIT_VERSION = " "$(dirname "${0}")/../git-version.cpp") +# Hack, need to do something better here. +if [ -z "$GIT_VERSION_LINE" ]; then + GIT_VERSION_LINE=$(grep "PPSSPP_GIT_VERSION = " "$(dirname "${0}")/../build/git-version.cpp") +fi echo "Setting version to '${GIT_VERSION_LINE}'..." SHORT_VERSION_MATCH='.*"v([0-9\.]+(-[0-9]+)?).*";' @@ -51,7 +54,5 @@ fi # AdHoc codesign is required for Apple Silicon. echo "Signing..." - -codesign -fs - --entitlements ../macOS/Entitlements.plist --timestamp "${MOLTENVK}" || echo "Failed signing MoltenVK" -codesign -fs - --entitlements ../macOS/Entitlements.plist --timestamp "${PPSSPPSDL}" || echo "Failed signing PPSSPPSDL" -codesign -fs - --entitlements ../macOS/Entitlements.plist --timestamp "${PPSSPP}" || echo "Failed signing PPSSPP" +codesign -fs - --entitlements ../macOS/Entitlements.plist --timestamp "${PPSSPPSDL}" || echo "Failed signing" +codesign -fs - --entitlements ../macOS/Entitlements.plist --timestamp "${PPSSPP}" || echo "Failed signing" diff --git a/Tools/langtool/Cargo.lock b/Tools/langtool/Cargo.lock index e8dd042a5..97d4ce158 100644 --- a/Tools/langtool/Cargo.lock +++ b/Tools/langtool/Cargo.lock @@ -76,9 +76,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "proc-macro-error" @@ -106,18 +106,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-segmentation" @@ -186,9 +186,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "vec_map" diff --git a/Tools/langtool/src/inifile.rs b/Tools/langtool/src/inifile.rs index f0c23bd29..c70f4636e 100644 --- a/Tools/langtool/src/inifile.rs +++ b/Tools/langtool/src/inifile.rs @@ -120,9 +120,12 @@ impl IniFile { } pub fn get_section_mut(&mut self, section_name: &str) -> Option<&mut Section> { - self.sections - .iter_mut() - .find(|section| section.name == section_name) + for section in &mut self.sections { + if section.name == section_name { + return Some(section); + } + } + None } } diff --git a/Tools/langtool/src/main.rs b/Tools/langtool/src/main.rs index 6e2a0a372..f18060959 100644 --- a/Tools/langtool/src/main.rs +++ b/Tools/langtool/src/main.rs @@ -17,10 +17,7 @@ struct Opt { #[derive(StructOpt, Debug)] enum Command { - CopyMissingLines { - #[structopt(short, long)] - dont_comment_missing: bool, - }, + CopyMissingLines {}, CommentUnknownLines {}, RemoveUnknownLines {}, AddNewKey { @@ -46,11 +43,7 @@ enum Command { }, } -fn copy_missing_lines( - reference_ini: &IniFile, - target_ini: &mut IniFile, - comment_missing: bool, -) -> io::Result<()> { +fn copy_missing_lines(reference_ini: &IniFile, target_ini: &mut IniFile) -> io::Result<()> { for reference_section in &reference_ini.sections { // Insert any missing full sections. if !target_ini.insert_section_if_missing(reference_section) { @@ -60,9 +53,7 @@ fn copy_missing_lines( } //target_section.remove_lines_if_not_in(reference_section); - if comment_missing { - target_section.comment_out_lines_if_not_in(reference_section); - } + target_section.comment_out_lines_if_not_in(reference_section); } } else { // Note: insert_section_if_missing will copy the entire section, @@ -186,10 +177,8 @@ fn main() { let mut target_ini = IniFile::parse(&target_ini_filename).unwrap(); match opt.cmd { - Command::CopyMissingLines { - dont_comment_missing, - } => { - copy_missing_lines(reference_ini, &mut target_ini, !dont_comment_missing).unwrap(); + Command::CopyMissingLines {} => { + copy_missing_lines(reference_ini, &mut target_ini).unwrap(); } Command::CommentUnknownLines {} => { deal_with_unknown_lines(reference_ini, &mut target_ini, false).unwrap(); @@ -242,12 +231,7 @@ fn main() { ref section, ref old, ref new, - } => { - if old == new { - println!("WARNING: old == new"); - } - rename_key(&mut reference_ini, section, old, new).unwrap(); - } + } => rename_key(&mut reference_ini, section, old, new).unwrap(), Command::MoveKey { ref old, ref new, diff --git a/Tools/langtool/src/section.rs b/Tools/langtool/src/section.rs index 34120de60..ec07dfcc7 100644 --- a/Tools/langtool/src/section.rs +++ b/Tools/langtool/src/section.rs @@ -92,12 +92,7 @@ impl Section { } if let Some(index) = found_index { let line = self.lines.remove(index); - let mut right_part = line.strip_prefix(&prefix).unwrap().to_string(); - if right_part.trim() == old.trim() { - // Was still untranslated - replace the translation too. - right_part = format!(" {}", new); - } - let line = new.to_owned() + " =" + &right_part; + let line = new.to_owned() + " =" + line.strip_prefix(&prefix).unwrap(); self.insert_line_if_missing(&line); } else { let name = &self.name; @@ -122,10 +117,12 @@ impl Section { if prefix.starts_with("Font") || prefix.starts_with('#') { continue; } - if !other.lines.iter().any(|line| line.starts_with(prefix)) && !prefix.contains("URL") { - println!("Commenting out from {}: {line}", other.name); - // Comment out the line. - *line = "#".to_owned() + line; + if !other.lines.iter().any(|line| line.starts_with(prefix)) { + if !prefix.contains("URL") { + println!("Commenting out from {}: {line}", other.name); + // Comment out the line. + *line = "#".to_owned() + line; + } } } } diff --git a/Tools/tag_release.sh b/Tools/tag_release.sh deleted file mode 100755 index 3d05e6b05..000000000 --- a/Tools/tag_release.sh +++ /dev/null @@ -1,14 +0,0 @@ -# Only for use during the process of making official releases - -if [ -z "$1" ]; then - echo "No argument supplied" - exit 1 -fi - -VER=$1 - -git tag -a ${VER} -m '${VER}'; git push --tags origin ${VER}; git push origin master - -echo Now run the internal tool: -echo ppsspp-build --commit ${VER} --gold --sign-code - diff --git a/UI/AudioCommon.cpp b/UI/AudioCommon.cpp index 082d80410..5cbe809f2 100644 --- a/UI/AudioCommon.cpp +++ b/UI/AudioCommon.cpp @@ -1,19 +1,13 @@ #include "Common/System/System.h" #include "Core/HW/StereoResampler.h" // TODO: doesn't belong in Core/HW... #include "UI/AudioCommon.h" -#include "UI/BackgroundAudio.h" StereoResampler g_resampler; // numFrames is number of stereo frames. // This is called from *outside* the emulator thread. -int __AudioMix(int16_t *outStereo, int numFrames, int sampleRateHz) { - int validFrames = g_resampler.Mix(outStereo, numFrames, false, sampleRateHz); - - // Mix sound effects on top. - g_BackgroundAudio.SFX().Mix(outStereo, validFrames, sampleRateHz); - - return validFrames; +int __AudioMix(int16_t *outstereo, int numFrames, int sampleRate) { + return g_resampler.Mix(outstereo, numFrames, false, sampleRate); } void System_AudioGetDebugStats(char *buf, size_t bufSize) { diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index c990da8a6..bc3fc19e0 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -4,20 +4,18 @@ #include "Common/File/VFS/VFS.h" #include "Common/UI/Root.h" -#include "Common/Data/Text/I18n.h" #include "Common/CommonTypes.h" #include "Common/Data/Format/RIFF.h" #include "Common/Log.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/TimeUtil.h" #include "Common/Data/Collections/FixedSizeQueue.h" #include "Core/HW/SimpleAudioDec.h" #include "Core/HLE/__sceAudio.h" #include "Core/System.h" +#include "GameInfoCache.h" #include "Core/Config.h" -#include "UI/GameInfoCache.h" #include "UI/BackgroundAudio.h" struct WavData { @@ -42,11 +40,6 @@ struct WavData { free(raw_data); raw_data = nullptr; } - - bool IsSimpleWAV() const { - bool isBad = raw_bytes_per_frame > sizeof(int16_t) * num_channels; - return !isBad && num_channels > 0 && sample_rate >= 8000 && codec == 0; - } }; void WavData::Read(RIFFReader &file_) { @@ -148,7 +141,6 @@ void WavData::Read(RIFFReader &file_) { raw_data = (uint8_t *)malloc(numBytes); raw_data_size = numBytes; - if (num_channels == 1 || num_channels == 2) { file_.ReadData(raw_data, numBytes); } else { @@ -262,10 +254,52 @@ BackgroundAudio::BackgroundAudio() { } BackgroundAudio::~BackgroundAudio() { - delete at3Reader_; delete[] buffer; } +BackgroundAudio::Sample *BackgroundAudio::LoadSample(const std::string &path) { + size_t bytes; + uint8_t *data = g_VFS.ReadFile(path.c_str(), &bytes); + if (!data) { + return nullptr; + } + + RIFFReader reader(data, (int)bytes); + + WavData wave; + wave.Read(reader); + + delete [] data; + + if (wave.num_channels != 2 || wave.sample_rate != 44100 || wave.raw_bytes_per_frame != 4) { + ERROR_LOG(AUDIO, "Wave format not supported for mixer playback. Must be 16-bit raw stereo. '%s'", path.c_str()); + return nullptr; + } + + int16_t *samples = new int16_t[2 * wave.numFrames]; + memcpy(samples, wave.raw_data, wave.numFrames * wave.raw_bytes_per_frame); + + return new BackgroundAudio::Sample(samples, wave.numFrames); +} + +void BackgroundAudio::LoadSamples() { + samples_.resize((size_t)UI::UISound::COUNT); + samples_[(size_t)UI::UISound::BACK] = std::unique_ptr(LoadSample("sfx_back.wav")); + samples_[(size_t)UI::UISound::SELECT] = std::unique_ptr(LoadSample("sfx_select.wav")); + samples_[(size_t)UI::UISound::CONFIRM] = std::unique_ptr(LoadSample("sfx_confirm.wav")); + samples_[(size_t)UI::UISound::TOGGLE_ON] = std::unique_ptr(LoadSample("sfx_toggle_on.wav")); + samples_[(size_t)UI::UISound::TOGGLE_OFF] = std::unique_ptr(LoadSample("sfx_toggle_off.wav")); + + UI::SetSoundCallback([](UI::UISound sound) { + g_BackgroundAudio.PlaySFX(sound); + }); +} + +void BackgroundAudio::PlaySFX(UI::UISound sfx) { + std::lock_guard lock(mutex_); + plays_.push_back(PlayInstance{ sfx, 0, 64, false }); +} + void BackgroundAudio::Clear(bool hard) { if (!hard) { fadingOut_ = true; @@ -338,6 +372,28 @@ bool BackgroundAudio::Play() { } } + // Mix in menu sound effects. Terribly slow mixer but meh. + if (!plays_.empty()) { + for (int i = 0; i < sz * 2; i += 2) { + std::vector::iterator iter = plays_.begin(); + while (iter != plays_.end()) { + PlayInstance inst = *iter; + auto sample = samples_[(int)inst.sound].get(); + if (!sample || iter->offset >= sample->length_) { + iter->done = true; + iter = plays_.erase(iter); + } else { + if (!iter->done) { + buffer[i] += sample->data_[inst.offset * 2] * inst.volume >> 8; + buffer[i + 1] += sample->data_[inst.offset * 2 + 1] * inst.volume >> 8; + } + iter->offset++; + iter++; + } + } + } + } + System_AudioPushSamples(buffer, sz); if (at3Reader_ && fadingOut_ && volume_ <= 0.0f) { @@ -375,175 +431,3 @@ void BackgroundAudio::Update() { sndLoadPending_ = false; } } - -inline int16_t ConvertU8ToI16(uint8_t value) { - int ivalue = value - 128; - return ivalue * 255; -} - -Sample *Sample::Load(const std::string &path) { - size_t bytes; - uint8_t *data = g_VFS.ReadFile(path.c_str(), &bytes); - if (!data) { - WARN_LOG(AUDIO, "Failed to load sample '%s'", path.c_str()); - return nullptr; - } - - RIFFReader reader(data, (int)bytes); - - WavData wave; - wave.Read(reader); - - delete[] data; - - if (!wave.IsSimpleWAV()) { - ERROR_LOG(AUDIO, "Wave format not supported for mixer playback. Must be 8-bit or 16-bit raw mono or stereo. '%s'", path.c_str()); - return nullptr; - } - - int16_t *samples = new int16_t[wave.num_channels * wave.numFrames]; - if (wave.raw_bytes_per_frame == wave.num_channels * 2) { - // 16-bit - memcpy(samples, wave.raw_data, wave.numFrames * wave.raw_bytes_per_frame); - } else if (wave.raw_bytes_per_frame == wave.num_channels) { - // 8-bit. Convert. - for (int i = 0; i < wave.num_channels * wave.numFrames; i++) { - samples[i] = ConvertU8ToI16(wave.raw_data[i]); - } - } - - // Protect against bad metadata. - int actualFrames = std::min(wave.numFrames, wave.raw_data_size / wave.raw_bytes_per_frame); - - return new Sample(samples, wave.num_channels, actualFrames, wave.sample_rate); -} - -static inline int16_t Clamp16(int32_t sample) { - if (sample < -32767) return -32767; - if (sample > 32767) return 32767; - return sample; -} - -void SoundEffectMixer::Mix(int16_t *buffer, int sz, int sampleRateHz) { - { - std::lock_guard guard(mutex_); - if (!queue_.empty()) { - for (const auto &entry : queue_) { - plays_.push_back(entry); - } - queue_.clear(); - } - if (plays_.empty()) { - return; - } - } - - for (std::vector::iterator iter = plays_.begin(); iter != plays_.end(); ) { - auto sample = samples_[(int)iter->sound].get(); - if (!sample) { - // Remove playback instance if sample invalid. - iter = plays_.erase(iter); - continue; - } - - int64_t rateOfSample = sample->rateInHz_; - int64_t stride = (rateOfSample << 32) / sampleRateHz; - - for (int i = 0; i < sz * 2; i += 2) { - if ((iter->offset >> 32) >= sample->length_ - 2) { - iter->done = true; - break; - } - - int wholeOffset = iter->offset >> 32; - int frac = (iter->offset >> 20) & 0xFFF; // Use a 12 bit fraction to get away with 32-bit multiplies - - if (sample->channels_ == 2) { - int interpolatedLeft = (sample->data_[wholeOffset * 2] * (0x1000 - frac) + sample->data_[(wholeOffset + 1) * 2] * frac) >> 12; - int interpolatedRight = (sample->data_[wholeOffset * 2 + 1] * (0x1000 - frac) + sample->data_[(wholeOffset + 1) * 2 + 1] * frac) >> 12; - - // Clamping add on top per sample. Not great, we should be mixing at higher bitrate instead. Oh well. - int left = Clamp16(buffer[i] + (interpolatedLeft * iter->volume >> 8)); - int right = Clamp16(buffer[i + 1] + (interpolatedRight * iter->volume >> 8)); - - buffer[i] = left; - buffer[i + 1] = right; - } else if (sample->channels_ == 1) { - int interpolated = (sample->data_[wholeOffset] * (0x1000 - frac) + sample->data_[wholeOffset + 1] * frac) >> 12; - - // Clamping add on top per sample. Not great, we should be mixing at higher bitrate instead. Oh well. - int value = Clamp16(buffer[i] + (interpolated * iter->volume >> 8)); - - buffer[i] = value; - buffer[i + 1] = value; - } - - iter->offset += stride; - } - - if (iter->done) { - iter = plays_.erase(iter); - } else { - iter++; - } - } -} - -void SoundEffectMixer::Play(UI::UISound sfx, float volume) { - std::lock_guard guard(mutex_); - queue_.push_back(PlayInstance{ sfx, 0, (int)(255.0f * volume), false }); -} - -void SoundEffectMixer::UpdateSample(UI::UISound sound, Sample *sample) { - if (sample) { - std::lock_guard guard(mutex_); - samples_[(size_t)sound] = std::unique_ptr(sample); - } else { - LoadDefaultSample(sound); - } -} - -void SoundEffectMixer::LoadDefaultSample(UI::UISound sound) { - const char *filename = nullptr; - switch (sound) { - case UI::UISound::BACK: filename = "sfx_back.wav"; break; - case UI::UISound::SELECT: filename = "sfx_select.wav"; break; - case UI::UISound::CONFIRM: filename = "sfx_confirm.wav"; break; - case UI::UISound::TOGGLE_ON: filename = "sfx_toggle_on.wav"; break; - case UI::UISound::TOGGLE_OFF: filename = "sfx_toggle_off.wav"; break; - case UI::UISound::ACHIEVEMENT_UNLOCKED: filename = "sfx_achievement_unlocked.wav"; break; - case UI::UISound::LEADERBOARD_SUBMITTED: filename = "sfx_leaderbord_submitted.wav"; break; - default: - return; - } - Sample *sample = Sample::Load(filename); - if (!sample) { - ERROR_LOG(SYSTEM, "Failed to load the default sample for UI sound %d", (int)sound); - } - std::lock_guard guard(mutex_); - samples_[(size_t)sound] = std::unique_ptr(sample); -} - -void SoundEffectMixer::LoadSamples() { - samples_.resize((size_t)UI::UISound::COUNT); - LoadDefaultSample(UI::UISound::BACK); - LoadDefaultSample(UI::UISound::SELECT); - LoadDefaultSample(UI::UISound::CONFIRM); - LoadDefaultSample(UI::UISound::TOGGLE_ON); - LoadDefaultSample(UI::UISound::TOGGLE_OFF); - - if (!g_Config.sAchievementsUnlockAudioFile.empty()) { - UpdateSample(UI::UISound::ACHIEVEMENT_UNLOCKED, Sample::Load(g_Config.sAchievementsUnlockAudioFile)); - } else { - LoadDefaultSample(UI::UISound::ACHIEVEMENT_UNLOCKED); - } - if (!g_Config.sAchievementsLeaderboardSubmitAudioFile.empty()) { - UpdateSample(UI::UISound::LEADERBOARD_SUBMITTED, Sample::Load(g_Config.sAchievementsLeaderboardSubmitAudioFile)); - } else { - LoadDefaultSample(UI::UISound::LEADERBOARD_SUBMITTED); - } - - UI::SetSoundCallback([](UI::UISound sound, float volume) { - g_BackgroundAudio.SFX().Play(sound, volume); - }); -} diff --git a/UI/BackgroundAudio.h b/UI/BackgroundAudio.h index 178ea2e1d..818b063a3 100644 --- a/UI/BackgroundAudio.h +++ b/UI/BackgroundAudio.h @@ -10,46 +10,6 @@ class AT3PlusReader; -struct Sample { - // data must be new-ed. - Sample(int16_t *data, int channels, int length, int rateInHz) : channels_(channels), data_(data), length_(length), rateInHz_(rateInHz) {} - ~Sample() { - delete[] data_; - } - int16_t *data_; - int length_; // stereo or mono samples. - int rateInHz_; // sampleRate - int channels_; - - static Sample *Load(const std::string &path); -}; - -// Mixer for things played on top of everything. -class SoundEffectMixer { -public: - void LoadSamples(); - - void Mix(int16_t *buffer, int sz, int sampleRateHz); - void Play(UI::UISound sfx, float volume); - - void UpdateSample(UI::UISound sound, Sample *sample); - void LoadDefaultSample(UI::UISound sound); - - std::vector> samples_; - - struct PlayInstance { - UI::UISound sound; - int64_t offset; // 32.32 fixed point - int volume; // 0..255 - bool done; - }; - -private: - std::mutex mutex_; - std::vector queue_; - std::vector plays_; -}; - class BackgroundAudio { public: BackgroundAudio(); @@ -59,9 +19,8 @@ public: void Update(); bool Play(); - SoundEffectMixer &SFX() { - return sfxMixer_; - } + void LoadSamples(); + void PlaySFX(UI::UISound sfx); private: void Clear(bool hard); @@ -74,14 +33,35 @@ private: Path bgGamePath_; std::atomic sndLoadPending_; int playbackOffset_ = 0; - AT3PlusReader *at3Reader_ = nullptr; + AT3PlusReader *at3Reader_; double gameLastChanged_ = 0.0; double lastPlaybackTime_ = 0.0; int *buffer = nullptr; bool fadingOut_ = true; float volume_ = 0.0f; float delta_ = -0.0001f; - SoundEffectMixer sfxMixer_; + + struct PlayInstance { + UI::UISound sound; + int offset; + int volume; // 0..255 + bool done; + }; + + struct Sample { + // data must be new-ed. + Sample(int16_t *data, int length) : data_(data), length_(length) {} + ~Sample() { + delete[] data_; + } + int16_t *data_; + int length_; // stereo samples. + }; + + static Sample *LoadSample(const std::string &path); + + std::vector plays_; + std::vector> samples_; }; extern BackgroundAudio g_BackgroundAudio; diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp index 9d5b8536d..08538a547 100644 --- a/UI/ChatScreen.cpp +++ b/UI/ChatScreen.cpp @@ -90,12 +90,12 @@ void ChatMenu::CreateSubviews(const Bounds &screenBounds) { } UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || (defined(SDL) && !PPSSPP_PLATFORM(SWITCH)) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(SDL) std::string chat = chatEdit_->GetText(); chatEdit_->SetText(""); chatEdit_->SetFocus(); sendChat(chat); -#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#elif PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Chat"), "", [](const std::string &value, int) { sendChat(value); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 48a11adb6..0747181e1 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -46,7 +46,6 @@ #include "UI/ControlMappingScreen.h" #include "UI/GameSettingsScreen.h" #include "UI/JoystickHistoryView.h" -#include "UI/OnScreenDisplay.h" #if PPSSPP_PLATFORM(ANDROID) #include "android/jni/app-android.h" @@ -243,25 +242,16 @@ void ControlMappingScreen::CreateViews() { root_ = new LinearLayout(ORIENT_HORIZONTAL); LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(200, FILL_PARENT, Margins(10, 0, 0, 10))); - leftColumn->Add(new Choice(km->T("Clear All")))->OnClick.Add([](UI::EventParams &) { - KeyMap::ClearAllMappings(); - return UI::EVENT_DONE; - }); - leftColumn->Add(new Choice(km->T("Default All")))->OnClick.Add([](UI::EventParams &) { - KeyMap::RestoreDefault(); - return UI::EVENT_DONE; - }); + leftColumn->Add(new Choice(km->T("Clear All")))->OnClick.Handle(this, &ControlMappingScreen::OnClearMapping); + leftColumn->Add(new Choice(km->T("Default All")))->OnClick.Handle(this, &ControlMappingScreen::OnDefaultMapping); + std::string sysName = System_GetProperty(SYSPROP_NAME); // If there's a builtin controller, restore to default should suffice. No need to conf the controller on top. if (!KeyMap::HasBuiltinController(sysName) && KeyMap::GetSeenPads().size()) { leftColumn->Add(new Choice(km->T("Autoconfigure")))->OnClick.Handle(this, &ControlMappingScreen::OnAutoConfigure); } - leftColumn->Add(new Choice(km->T("Show PSP")))->OnClick.Add([=](UI::EventParams &) { - screenManager()->push(new VisualMappingScreen(gamePath_)); - return UI::EVENT_DONE; - }); - leftColumn->Add(new CheckBox(&g_Config.bAllowMappingCombos, km->T("Allow combo mappings"))); + leftColumn->Add(new Choice(km->T("Show PSP")))->OnClick.Handle(this, &ControlMappingScreen::OnVisualizeMapping); leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f))); AddStandardBack(leftColumn); @@ -295,6 +285,16 @@ void ControlMappingScreen::update() { SetVRAppMode(VRAppMode::VR_MENU_MODE); } +UI::EventReturn ControlMappingScreen::OnClearMapping(UI::EventParams ¶ms) { + KeyMap::ClearAllMappings(); + return UI::EVENT_DONE; +} + +UI::EventReturn ControlMappingScreen::OnDefaultMapping(UI::EventParams ¶ms) { + KeyMap::RestoreDefault(); + return UI::EVENT_DONE; +} + UI::EventReturn ControlMappingScreen::OnAutoConfigure(UI::EventParams ¶ms) { std::vector items; const auto seenPads = KeyMap::GetSeenPads(); @@ -309,6 +309,12 @@ UI::EventReturn ControlMappingScreen::OnAutoConfigure(UI::EventParams ¶ms) { return UI::EVENT_DONE; } +UI::EventReturn ControlMappingScreen::OnVisualizeMapping(UI::EventParams ¶ms) { + VisualMappingScreen *visualMapping = new VisualMappingScreen(gamePath_); + screenManager()->push(visualMapping); + return UI::EVENT_DONE; +} + void ControlMappingScreen::dialogFinished(const Screen *dialog, DialogResult result) { if (result == DR_OK && std::string(dialog->tag()) == "listpopup") { UI::ListPopupScreen *popup = (UI::ListPopupScreen *)dialog; @@ -327,9 +333,6 @@ void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) { parent->Add(new TextView(std::string(km->T("Map a new key for")) + " " + mc->T(pspButtonName), new LinearLayoutParams(Margins(10, 0)))); parent->Add(new TextView(std::string(mapping_.ToVisualString()), new LinearLayoutParams(Margins(10, 0)))); - comboMappingsNotEnabled_ = parent->Add(new NoticeView(NoticeLevel::WARN, km->T("Combo mappings are not enabled"), "", new LinearLayoutParams(Margins(10, 0)))); - comboMappingsNotEnabled_->SetVisibility(UI::V_GONE); - SetVRAppMode(VRAppMode::VR_CONTROLLER_MAPPING_MODE); } @@ -338,7 +341,6 @@ bool KeyMappingNewKeyDialog::key(const KeyInput &key) { return true; if (time_now_d() < delayUntil_) return true; - if (key.flags & KEY_DOWN) { if (key.keyCode == NKCODE_EXT_MOUSEBUTTON_1) { // Don't map @@ -353,9 +355,7 @@ bool KeyMappingNewKeyDialog::key(const KeyInput &key) { InputMapping newMapping(key.deviceId, key.keyCode); if (!(key.flags & KEY_IS_REPEAT)) { - if (!g_Config.bAllowMappingCombos && !mapping_.mappings.empty()) { - comboMappingsNotEnabled_->SetVisibility(UI::V_VISIBLE); - } else if (!mapping_.mappings.contains(newMapping)) { + if (!mapping_.mappings.contains(newMapping)) { mapping_.mappings.push_back(newMapping); RecreateViews(); } @@ -438,18 +438,14 @@ void KeyMappingNewKeyDialog::axis(const AxisInput &axis) { if (axis.value > AXIS_BIND_THRESHOLD) { InputMapping mapping(axis.deviceId, axis.axisId, 1); triggeredAxes_.insert(mapping); - if (!g_Config.bAllowMappingCombos && !mapping_.mappings.empty()) { - comboMappingsNotEnabled_->SetVisibility(UI::V_VISIBLE); - } else if (!mapping_.mappings.contains(mapping)) { + if (!mapping_.mappings.contains(mapping)) { mapping_.mappings.push_back(mapping); RecreateViews(); } } else if (axis.value < -AXIS_BIND_THRESHOLD) { InputMapping mapping(axis.deviceId, axis.axisId, -1); triggeredAxes_.insert(mapping); - if (!g_Config.bAllowMappingCombos && !mapping_.mappings.empty()) { - comboMappingsNotEnabled_->SetVisibility(UI::V_VISIBLE); - } else if (!mapping_.mappings.contains(mapping)) { + if (!mapping_.mappings.contains(mapping)) { mapping_.mappings.push_back(mapping); RecreateViews(); } @@ -504,7 +500,7 @@ AnalogSetupScreen::AnalogSetupScreen(const Path &gamePath) : UIDialogScreenWithG } void AnalogSetupScreen::update() { - mapper_.Update(time_now_d()); + mapper_.Update(); // We ignore the secondary stick for now and just use the two views // for raw and psp input. if (stickView_[0]) { @@ -535,7 +531,7 @@ void AnalogSetupScreen::axis(const AxisInput &axis) { // UIScreen::axis(axis); // Instead we just send the input directly to the mapper, that we'll visualize. - mapper_.Axis(&axis, 1); + mapper_.Axis(axis); } void AnalogSetupScreen::CreateViews() { @@ -634,7 +630,6 @@ void TouchTestScreen::touch(const TouchInput &touch) { } } -// TODO: Move this screen out into its own file. void TouchTestScreen::CreateViews() { using namespace UI; @@ -643,7 +638,9 @@ void TouchTestScreen::CreateViews() { root_ = new LinearLayout(ORIENT_VERTICAL); LinearLayout *theTwo = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)); - lastKeyEvents_ = theTwo->Add(new TextView("-", new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + lastLastKeyEvent_ = theTwo->Add(new TextView("-", new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + lastLastKeyEvent_->SetTextColor(0x80FFFFFF); // semi-transparent + lastKeyEvent_ = theTwo->Add(new TextView("-", new LayoutParams(FILL_PARENT, WRAP_CONTENT))); root_->Add(theTwo); @@ -669,48 +666,43 @@ void TouchTestScreen::CreateViews() { root_->Add(new Button(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); } -void TouchTestScreen::UpdateLogView() { - while (keyEventLog_.size() > 8) { - keyEventLog_.erase(keyEventLog_.begin()); - } - - std::string text; - for (auto &iter : keyEventLog_) { - text += iter + "\n"; - } - - if (lastKeyEvents_) { - lastKeyEvents_->SetText(text); - } -} +#if PPSSPP_PLATFORM(ANDROID) +extern int display_xres; +extern int display_yres; +#endif bool TouchTestScreen::key(const KeyInput &key) { - UIScreen::key(key); char buf[512]; - snprintf(buf, sizeof(buf), "%s (%d) Device ID: %d [%s%s%s%s]", KeyMap::GetKeyName(key.keyCode).c_str(), key.keyCode, key.deviceId, + snprintf(buf, sizeof(buf), "Keycode: %d Device ID: %d [%s%s%s%s]", key.keyCode, key.deviceId, (key.flags & KEY_IS_REPEAT) ? "REP" : "", (key.flags & KEY_UP) ? "UP" : "", (key.flags & KEY_DOWN) ? "DOWN" : "", (key.flags & KEY_CHAR) ? "CHAR" : ""); - keyEventLog_.push_back(buf); - UpdateLogView(); + if (lastLastKeyEvent_ && lastKeyEvent_) { + lastLastKeyEvent_->SetText(lastKeyEvent_->GetText()); + lastKeyEvent_->SetText(buf); + } return true; } void TouchTestScreen::axis(const AxisInput &axis) { - // This just filters out accelerometer events. We show everything else. + // This is mainly to catch axis events that would otherwise get translated + // into arrow keys, since seeing keyboard arrow key events appear when using + // a controller would be confusing for the user. if (IgnoreAxisForMapping(axis.axisId)) return; - char buf[512]; - snprintf(buf, sizeof(buf), "Axis: %s (%d) (value %1.3f) Device ID: %d", - KeyMap::GetAxisName(axis.axisId).c_str(), axis.axisId, axis.value, axis.deviceId); - - keyEventLog_.push_back(buf); - if (keyEventLog_.size() > 8) { - keyEventLog_.erase(keyEventLog_.begin()); + const float AXIS_LOG_THRESHOLD = AXIS_BIND_THRESHOLD * 0.5f; + if (axis.value > AXIS_LOG_THRESHOLD || axis.value < -AXIS_LOG_THRESHOLD) { + char buf[512]; + snprintf(buf, sizeof(buf), "Axis: %d (value %1.3f) Device ID: %d", + axis.axisId, axis.value, axis.deviceId); + // Null-check just in case they weren't created yet. + if (lastLastKeyEvent_ && lastKeyEvent_) { + lastLastKeyEvent_->SetText(lastKeyEvent_->GetText()); + lastKeyEvent_->SetText(buf); + } } - UpdateLogView(); } void TouchTestScreen::render() { @@ -751,7 +743,7 @@ void TouchTestScreen::render() { "g_dpi: %0.3f g_dpi_scale: %0.3fx%0.3f\n" "g_dpi_scale_real: %0.3fx%0.3f\n%s", #if PPSSPP_PLATFORM(ANDROID) - System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES), + display_xres, display_yres, #endif g_display.dp_xres, g_display.dp_yres, g_display.pixel_xres, g_display.pixel_yres, diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index cffdac5f6..1885473da 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -22,7 +22,6 @@ #include #include #include -#include #include "Common/UI/View.h" #include "Common/UI/UIScreen.h" @@ -44,7 +43,10 @@ protected: void update() override; private: + UI::EventReturn OnDefaultMapping(UI::EventParams ¶ms); + UI::EventReturn OnClearMapping(UI::EventParams ¶ms); UI::EventReturn OnAutoConfigure(UI::EventParams ¶ms); + UI::EventReturn OnVisualizeMapping(UI::EventParams ¶ms); void dialogFinished(const Screen *dialog, DialogResult result) override; @@ -78,8 +80,6 @@ private: KeyMap::MultiInputMapping mapping_; - UI::View *comboMappingsNotEnabled_ = nullptr; - // We need to do our own detection for axis "keyup" here. std::set triggeredAxes_; @@ -165,12 +165,10 @@ protected: }; TrackedTouch touches_[MAX_TOUCH_POINTS]{}; - std::vector keyEventLog_; - - UI::TextView *lastKeyEvents_ = nullptr; + UI::TextView *lastKeyEvent_ = nullptr; + UI::TextView *lastLastKeyEvent_ = nullptr; void CreateViews() override; - void UpdateLogView(); UI::EventReturn OnImmersiveModeChange(UI::EventParams &e); UI::EventReturn OnRenderingBackend(UI::EventParams &e); diff --git a/UI/CustomButtonMappingScreen.cpp b/UI/CustomButtonMappingScreen.cpp index 09ebaa293..31edd6d22 100644 --- a/UI/CustomButtonMappingScreen.cpp +++ b/UI/CustomButtonMappingScreen.cpp @@ -131,10 +131,73 @@ void CustomButtonMappingScreen::CreateViews() { ConfigCustomButton* cfg = nullptr; bool* show = nullptr; memset(array, 0, sizeof(array)); - cfg = &g_Config.CustomButton[id_]; - show = &g_Config.touchCustom[id_].show; - for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) - array[i] = (0x01 == ((g_Config.CustomButton[id_].key >> i) & 0x01)); + switch (id_) { + case 0: + cfg = &g_Config.CustomButton0; + show = &g_Config.touchCustom0.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton0.key >> i) & 0x01)); + break; + case 1: + cfg = &g_Config.CustomButton1; + show = &g_Config.touchCustom1.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton1.key >> i) & 0x01)); + break; + case 2: + cfg = &g_Config.CustomButton2; + show = &g_Config.touchCustom2.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton2.key >> i) & 0x01)); + break; + case 3: + cfg = &g_Config.CustomButton3; + show = &g_Config.touchCustom3.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton3.key >> i) & 0x01)); + break; + case 4: + cfg = &g_Config.CustomButton4; + show = &g_Config.touchCustom4.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton4.key >> i) & 0x01)); + break; + case 5: + cfg = &g_Config.CustomButton5; + show = &g_Config.touchCustom5.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton5.key >> i) & 0x01)); + break; + case 6: + cfg = &g_Config.CustomButton6; + show = &g_Config.touchCustom6.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton6.key >> i) & 0x01)); + break; + case 7: + cfg = &g_Config.CustomButton7; + show = &g_Config.touchCustom7.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton7.key >> i) & 0x01)); + break; + case 8: + cfg = &g_Config.CustomButton8; + show = &g_Config.touchCustom8.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton8.key >> i) & 0x01)); + break; + case 9: + cfg = &g_Config.CustomButton9; + show = &g_Config.touchCustom9.show; + for (int i = 0; i < ARRAY_SIZE(customKeyList); i++) + array[i] = (0x01 == ((g_Config.CustomButton9.key >> i) & 0x01)); + break; + default: + // This shouldn't happen, let's just not crash. + cfg = &g_Config.CustomButton0; + show = &g_Config.touchCustom0.show; + break; + } leftColumn->Add(new ButtonPreview(g_Config.iTouchButtonStyle == 0 ? customKeyShapes[cfg->shape].i : customKeyShapes[cfg->shape].l, customKeyImages[cfg->image].i, customKeyImages[cfg->image].r, customKeyShapes[cfg->shape].f, customKeyShapes[cfg->shape].r, 62, 82)); @@ -219,8 +282,37 @@ static uint64_t arrayToInt(const bool ary[ARRAY_SIZE(CustomKeyData::customKeyLis } void CustomButtonMappingScreen::saveArray() { - if (id_ >= 0 && id_ < Config::CUSTOM_BUTTON_COUNT) { - g_Config.CustomButton[id_].key = arrayToInt(array); + switch (id_) { + case 0: + g_Config.CustomButton0.key = arrayToInt(array); + break; + case 1: + g_Config.CustomButton1.key = arrayToInt(array); + break; + case 2: + g_Config.CustomButton2.key = arrayToInt(array); + break; + case 3: + g_Config.CustomButton3.key = arrayToInt(array); + break; + case 4: + g_Config.CustomButton4.key = arrayToInt(array); + break; + case 5: + g_Config.CustomButton5.key = arrayToInt(array); + break; + case 6: + g_Config.CustomButton6.key = arrayToInt(array); + break; + case 7: + g_Config.CustomButton7.key = arrayToInt(array); + break; + case 8: + g_Config.CustomButton8.key = arrayToInt(array); + break; + case 9: + g_Config.CustomButton9.key = arrayToInt(array); + break; } } diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index 1b63895c9..17cf9165e 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -188,7 +188,11 @@ UI::EventReturn CwCheatScreen::OnEditCheatFile(UI::EventParams ¶ms) { MIPSComp::jit->ClearCache(); } if (engine_) { +#if PPSSPP_PLATFORM(UWP) + System_LaunchUrl(LaunchUrlType::BROWSER_URL, engine_->CheatFilename().c_str()); +#else File::OpenFileInEditor(engine_->CheatFilename()); +#endif } return UI::EVENT_DONE; } diff --git a/UI/CwCheatScreen.h b/UI/CwCheatScreen.h index ec6414598..7a7578c76 100644 --- a/UI/CwCheatScreen.h +++ b/UI/CwCheatScreen.h @@ -15,8 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#pragma once - #include #include diff --git a/UI/DarwinFileSystemServices.h b/UI/DarwinFileSystemServices.h index 2b22d12ac..6a76c3e8d 100644 --- a/UI/DarwinFileSystemServices.h +++ b/UI/DarwinFileSystemServices.h @@ -9,7 +9,6 @@ #include "ppsspp_config.h" #include "Common/File/Path.h" -#include "Common/System/Request.h" #define PreferredMemoryStickUserDefaultsKey "UserPreferredMemoryStickDirectoryPath" @@ -19,20 +18,18 @@ typedef std::function DarwinDirectoryPanelCallback; /// on Darwin platforms. class DarwinFileSystemServices { public: - /// Present a panel to choose a file or directory. - void presentDirectoryPanel( - DarwinDirectoryPanelCallback, - bool allowFiles = false, - bool allowDirectories = true, - BrowseFileType fileType = BrowseFileType::ANY); - - static Path appropriateMemoryStickDirectoryToUse(); - static void setUserPreferredMemoryStickDirectory(Path); + /// Present a pannel to choose the directory as the memory stick manager. + void presentDirectoryPanel(DarwinDirectoryPanelCallback, + bool allowFiles = false, + bool allowDirectories = true); + + static Path appropriateMemoryStickDirectoryToUse(); + static void setUserPreferredMemoryStickDirectory(Path); private: - static Path __defaultMemoryStickPath(); + static Path __defaultMemoryStickPath(); #if PPSSPP_PLATFORM(IOS) - // iOS only, needed for UIDocumentPickerViewController - void *__pickerDelegate = NULL; + // iOS only, needed for UIDocumentPickerViewController + void *__pickerDelegate = NULL; #endif // PPSSPP_PLATFORM(IOS) }; diff --git a/UI/DarwinFileSystemServices.mm b/UI/DarwinFileSystemServices.mm index 2afeabfa9..09daa933b 100644 --- a/UI/DarwinFileSystemServices.mm +++ b/UI/DarwinFileSystemServices.mm @@ -44,35 +44,15 @@ #include #endif // __has_include() -void DarwinFileSystemServices::presentDirectoryPanel( - DarwinDirectoryPanelCallback callback, - bool allowFiles, bool allowDirectories, - BrowseFileType fileType) { - dispatch_async(dispatch_get_main_queue(), ^{ +void DarwinFileSystemServices::presentDirectoryPanel(DarwinDirectoryPanelCallback callback, + bool allowFiles, + bool allowDirectories) { + dispatch_async(dispatch_get_main_queue(), ^{ #if PPSSPP_PLATFORM(MAC) - NSOpenPanel *panel = [[NSOpenPanel alloc] init]; - panel.allowsMultipleSelection = NO; - panel.canChooseFiles = allowFiles; - panel.canChooseDirectories = allowDirectories; - switch (fileType) { - case BrowseFileType::BOOTABLE: - [panel setAllowedFileTypes:[NSArray arrayWithObjects:@"iso", @"cso", @"pbp", @"elf", @"zip", @"ppdmp", nil]]; - break; - case BrowseFileType::IMAGE: - [panel setAllowedFileTypes:[NSArray arrayWithObjects:@"jpg", @"png", nil]]; - break; - case BrowseFileType::INI: - [panel setAllowedFileTypes:[NSArray arrayWithObject:@"ini"]]; - break; - case BrowseFileType::DB: - [panel setAllowedFileTypes:[NSArray arrayWithObject:@"db"]]; - break; - case BrowseFileType::SOUND_EFFECT: - [panel setAllowedFileTypes:[NSArray arrayWithObject:@"wav"]]; - break; - default: - break; - } + NSOpenPanel *panel = [[NSOpenPanel alloc] init]; + panel.allowsMultipleSelection = NO; + panel.canChooseFiles = allowFiles; + panel.canChooseDirectories = allowDirectories; // if (!allowFiles && allowDirectories) // panel.allowedFileTypes = @[(__bridge NSString *)kUTTypeFolder]; diff --git a/UI/DebugOverlay.cpp b/UI/DebugOverlay.cpp deleted file mode 100644 index aa4b94cf2..000000000 --- a/UI/DebugOverlay.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "Common/Render/DrawBuffer.h" -#include "Common/GPU/thin3d.h" -#include "Common/System/System.h" -#include "UI/DebugOverlay.h" -#include "Core/HW/Display.h" -#include "Core/FrameTiming.h" -#include "Core/HLE/sceSas.h" -#include "Core/ControlMapper.h" -#include "Core/Config.h" -#include "Core/System.h" -#include "GPU/GPU.h" -#include "GPU/GPUInterface.h" -// TODO: This should be moved here or to Common, doesn't belong in /GPU -#include "GPU/Vulkan/DebugVisVulkan.h" -#include "GPU/Common/FramebufferManagerCommon.h" - -// For std::max -#include - -static void DrawDebugStats(UIContext *ctx, const Bounds &bounds) { - FontID ubuntu24("UBUNTU24"); - - float left = std::max(bounds.w / 2 - 20.0f, 550.0f); - float right = bounds.w - left - 20.0f; - - char statbuf[4096]; - - ctx->Flush(); - ctx->BindFontTexture(); - ctx->Draw()->SetFontScale(.7f, .7f); - - __DisplayGetDebugStats(statbuf, sizeof(statbuf)); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, left, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, left, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - - ctx->Draw()->SetFontScale(1.0f, 1.0f); - ctx->Flush(); - ctx->RebindTexture(); -} - -static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) { - FontID ubuntu24("UBUNTU24"); - - char statbuf[4096] = { 0 }; - System_AudioGetDebugStats(statbuf, sizeof(statbuf)); - - ctx->Flush(); - ctx->BindFontTexture(); - ctx->Draw()->SetFontScale(0.5f, 0.5f); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - - float left = std::max(bounds.w / 2 - 20.0f, 500.0f); - - __SasGetDebugStats(statbuf, sizeof(statbuf)); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + left + 21, bounds.y + 31, bounds.w - left, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + left + 20, bounds.y + 30, bounds.w - left, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - - ctx->Draw()->SetFontScale(1.0f, 1.0f); - - ctx->Flush(); - ctx->RebindTexture(); -} - -static void DrawControlDebug(UIContext *ctx, const ControlMapper &mapper, const Bounds &bounds) { - FontID ubuntu24("UBUNTU24"); - - char statbuf[4096] = { 0 }; - mapper.GetDebugString(statbuf, sizeof(statbuf)); - - ctx->Flush(); - ctx->BindFontTexture(); - ctx->Draw()->SetFontScale(0.5f, 0.5f); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII); - ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - ctx->Draw()->SetFontScale(1.0f, 1.0f); - ctx->Flush(); - ctx->RebindTexture(); -} - -static void DrawFrameTimes(UIContext *ctx, const Bounds &bounds) { - FontID ubuntu24("UBUNTU24"); - double *sleepHistory; - int valid, pos; - double *history = __DisplayGetFrameTimes(&valid, &pos, &sleepHistory); - int scale = 7000; - int width = 600; - - ctx->Flush(); - ctx->BeginNoTex(); - int bottom = bounds.y2(); - for (int i = 0; i < valid; ++i) { - double activeTime = history[i] - sleepHistory[i]; - ctx->Draw()->vLine(bounds.x + i, bottom, bottom - activeTime * scale, 0xFF3FFF3F); - ctx->Draw()->vLine(bounds.x + i, bottom - activeTime * scale, bottom - history[i] * scale, 0x7F3FFF3F); - } - ctx->Draw()->vLine(bounds.x + pos, bottom, bottom - 512, 0xFFff3F3f); - - ctx->Draw()->hLine(bounds.x, bottom - 0.0333 * scale, bounds.x + width, 0xFF3f3Fff); - ctx->Draw()->hLine(bounds.x, bottom - 0.0167 * scale, bounds.x + width, 0xFF3f3Fff); - - ctx->Flush(); - ctx->Begin(); - ctx->BindFontTexture(); - ctx->Draw()->SetFontScale(0.5f, 0.5f); - ctx->Draw()->DrawText(ubuntu24, "33.3ms", bounds.x + width, bottom - 0.0333 * scale, 0xFF3f3Fff, ALIGN_BOTTOMLEFT | FLAG_DYNAMIC_ASCII); - ctx->Draw()->DrawText(ubuntu24, "16.7ms", bounds.x + width, bottom - 0.0167 * scale, 0xFF3f3Fff, ALIGN_BOTTOMLEFT | FLAG_DYNAMIC_ASCII); - ctx->Draw()->SetFontScale(1.0f, 1.0f); - ctx->Flush(); - ctx->RebindTexture(); -} - -static void DrawFrameTiming(UIContext *ctx, const Bounds &bounds) { - FontID ubuntu24("UBUNTU24"); - - char statBuf[1024]{}; - - ctx->Flush(); - ctx->BindFontTexture(); - ctx->Draw()->SetFontScale(0.5f, 0.5f); - - snprintf(statBuf, sizeof(statBuf), - "Mode (interval): %s (%d)", - Draw::PresentModeToString(g_frameTiming.presentMode), - g_frameTiming.presentInterval); - - ctx->Draw()->DrawTextRect(ubuntu24, statBuf, bounds.x + 10, bounds.y + 50, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - - for (int i = 0; i < 5; i++) { - size_t curIndex = i + 6; - size_t prevIndex = i + 7; - - FrameTimeData data = ctx->GetDrawContext()->FrameTimeHistory().Back(curIndex); - FrameTimeData prevData = ctx->GetDrawContext()->FrameTimeHistory().Back(prevIndex); - if (data.frameBegin == 0.0) { - snprintf(statBuf, sizeof(statBuf), "(No frame time data)"); - } else { - double stride = data.frameBegin - prevData.frameBegin; - double fenceLatency_s = data.afterFenceWait - data.frameBegin; - double submitLatency_s = data.firstSubmit - data.frameBegin; - double queuePresentLatency_s = data.queuePresent - data.frameBegin; - double actualPresentLatency_s = data.actualPresent - data.frameBegin; - double presentMargin = data.presentMargin; - double computedMargin = data.actualPresent - data.queuePresent; - - char presentStats[256] = ""; - if (data.actualPresent != 0.0) { - snprintf(presentStats, sizeof(presentStats), - "* Present: %0.1f ms\n" - "* Margin: %0.1f ms\n" - "* Margin(c): %0.1f ms\n", - actualPresentLatency_s * 1000.0, - presentMargin * 1000.0, - computedMargin * 1000.0); - } - snprintf(statBuf, sizeof(statBuf), - "* Stride: %0.1f (waits: %d)\n" - "%llu: From start:\n" - "* Past fence: %0.1f ms\n" - "* Submit #1: %0.1f ms\n" - "* Queue-p: %0.1f ms\n" - "%s", - stride * 1000.0, - data.waitCount, - (long long)data.frameId, - fenceLatency_s * 1000.0, - submitLatency_s * 1000.0, - queuePresentLatency_s * 1000.0, - presentStats - ); - } - ctx->Draw()->DrawTextRect(ubuntu24, statBuf, bounds.x + 10 + i * 150, bounds.y + 150, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - } - ctx->Draw()->SetFontScale(1.0f, 1.0f); - ctx->Flush(); - ctx->RebindTexture(); -} - -void DrawFramebufferList(UIContext *ctx, GPUInterface *gpu, const Bounds &bounds) { - if (!gpu) { - return; - } - FontID ubuntu24("UBUNTU24"); - auto list = gpu->GetFramebufferList(); - ctx->Flush(); - ctx->BindFontTexture(); - ctx->Draw()->SetFontScale(0.7f, 0.7f); - - int i = 0; - for (const VirtualFramebuffer *vfb : list) { - char buf[512]; - snprintf(buf, sizeof(buf), "%08x (Z %08x): %dx%d (stride %d, %d)", - vfb->fb_address, vfb->z_address, vfb->width, vfb->height, vfb->fb_stride, vfb->z_stride); - ctx->Draw()->DrawTextRect(ubuntu24, buf, bounds.x + 10, bounds.y + 20 + i * 50, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - i++; - } - ctx->Flush(); -} - -void DrawControlMapperOverlay(UIContext *ctx, const Bounds &bounds, const ControlMapper &controlMapper) { - DrawControlDebug(ctx, controlMapper, ctx->GetLayoutBounds()); -} - -void DrawDebugOverlay(UIContext *ctx, const Bounds &bounds, DebugOverlay overlay) { - bool inGame = GetUIState() == UISTATE_INGAME; - - switch (overlay) { - case DebugOverlay::DEBUG_STATS: - if (inGame) - DrawDebugStats(ctx, ctx->GetLayoutBounds()); - break; - case DebugOverlay::FRAME_GRAPH: - if (inGame) - DrawFrameTimes(ctx, ctx->GetLayoutBounds()); - break; - case DebugOverlay::FRAME_TIMING: - DrawFrameTiming(ctx, ctx->GetLayoutBounds()); - break; - case DebugOverlay::AUDIO: - DrawAudioDebugStats(ctx, ctx->GetLayoutBounds()); - break; -#if !PPSSPP_PLATFORM(UWP) && !PPSSPP_PLATFORM(SWITCH) - case DebugOverlay::GPU_PROFILE: - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { - DrawGPUProfilerVis(ctx, gpu); - } - break; - case DebugOverlay::GPU_ALLOCATOR: - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { - DrawGPUMemoryVis(ctx, gpu); - } - break; -#endif - case DebugOverlay::FRAMEBUFFER_LIST: - if (inGame) - DrawFramebufferList(ctx, gpu, bounds); - break; - default: - break; - } -} diff --git a/UI/DebugOverlay.h b/UI/DebugOverlay.h deleted file mode 100644 index 119f220fc..000000000 --- a/UI/DebugOverlay.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "Common/UI/Context.h" -#include "Core/ConfigValues.h" -#include "Core/ControlMapper.h" - -void DrawControlMapperOverlay(UIContext *ctx, const Bounds &bounds, const ControlMapper &controlMapper); -void DrawDebugOverlay(UIContext *ctx, const Bounds &bounds, DebugOverlay overlay); diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 329ed9e67..61c7d1ec7 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -31,7 +31,6 @@ #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/GPU/OpenGL/GLFeatures.h" #if !PPSSPP_PLATFORM(UWP) @@ -39,14 +38,11 @@ #endif #include "Common/File/AndroidStorage.h" #include "Common/Data/Text/I18n.h" -#include "Common/Data/Encoding/Utf8.h" #include "Common/Net/HTTPClient.h" #include "Common/UI/Context.h" #include "Common/UI/View.h" #include "Common/UI/ViewGroup.h" #include "Common/UI/UI.h" -#include "Common/UI/IconCache.h" -#include "Common/Data/Text/Parsers.h" #include "Common/Profiler/Profiler.h" #include "Common/LogManager.h" @@ -63,7 +59,6 @@ #include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/JitCommon/JitState.h" -#include "GPU/Debugger/Record.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" #include "UI/MiscScreens.h" @@ -90,31 +85,6 @@ static const char *logLevelList[] = { "Verb." }; -static const char *g_debugOverlayList[] = { - "Off", - "Debug stats", - "Draw Frametimes Graph", - "Frame timing", -#ifdef USE_PROFILER - "Frame profile", -#endif - "Control Debug", - "Audio Debug", - "GPU Profile", - "GPU Allocator Viewer", - "Framebuffer List", -}; - -void AddOverlayList(UI::ViewGroup *items, ScreenManager *screenManager) { - using namespace UI; - auto dev = GetI18NCategory(I18NCat::DEVELOPER); - int numOverlays = ARRAY_SIZE(g_debugOverlayList); - if (!(g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL)) { - numOverlays -= 2; // skip the last 2. - } - items->Add(new PopupMultiChoice((int *)&g_Config.iDebugOverlay, dev->T("Debug overlay"), g_debugOverlayList, 0, numOverlays, I18NCat::DEVELOPER, screenManager)); -} - void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; auto dev = GetI18NCategory(I18NCat::DEVELOPER); @@ -130,38 +100,28 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) { items->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &DevMenuScreen::OnDeveloperTools); items->Add(new Choice(dev->T("Jit Compare")))->OnClick.Handle(this, &DevMenuScreen::OnJitCompare); items->Add(new Choice(dev->T("Shader Viewer")))->OnClick.Handle(this, &DevMenuScreen::OnShaderView); - - AddOverlayList(items, screenManager()); - items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Add([](UI::EventParams &e) { - if (PSP_CoreParameter().frozen) { - PSP_CoreParameter().frozen = false; - } else { - PSP_CoreParameter().freezeNext = true; - } - return UI::EVENT_DONE; - }); - - items->Add(new Choice(dev->T("Reset limited logging")))->OnClick.Handle(this, &DevMenuScreen::OnResetLimitedLogging); - - items->Add(new Choice(dev->T("Create frame dump")))->OnClick.Add([](UI::EventParams &e) { - GPURecord::RecordNextFrame([](const Path &dumpPath) { - NOTICE_LOG(SYSTEM, "Frame dump created at '%s'", dumpPath.c_str()); - if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { - System_ShowFileInFolder(dumpPath); - } else { - g_OSD.Show(OSDType::MESSAGE_SUCCESS, dumpPath.ToVisualString(), 7.0f); - } - }); - return UI::EVENT_DONE; - }); - - // This one is not very useful these days, and only really on desktop. Hide it on other platforms. - if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_DESKTOP) { - items->Add(new Choice(dev->T("Dump next frame to log")))->OnClick.Add([](UI::EventParams &e) { - gpu->DumpNextFrame(); - return UI::EVENT_DONE; - }); + if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { + items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer"))); } + if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { + items->Add(new CheckBox(&g_Config.bShowGpuProfile, dev->T("GPU Profile"))); + } + items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenuScreen::OnFreezeFrame); + + items->Add(new Choice(dev->T("Dump next frame to log")))->OnClick.Handle(this, &DevMenuScreen::OnDumpFrame); + items->Add(new Choice(dev->T("Toggle Audio Debug")))->OnClick.Add([](UI::EventParams &) { + g_Config.bShowAudioDebug = !g_Config.bShowAudioDebug; + return UI::EVENT_DONE; + }); + items->Add(new Choice(dev->T("Toggle Control Debug")))->OnClick.Add([](UI::EventParams &) { + g_Config.bShowControlDebug = !g_Config.bShowControlDebug; + return UI::EVENT_DONE; + }); +#ifdef USE_PROFILER + items->Add(new CheckBox(&g_Config.bShowFrameProfiler, dev->T("Frame Profiler"), "")); +#endif + items->Add(new CheckBox(&g_Config.bDrawFrameGraph, dev->T("Draw Frametimes Graph"))); + items->Add(new Choice(dev->T("Reset limited logging")))->OnClick.Handle(this, &DevMenuScreen::OnResetLimitedLogging); scroll->Add(items); parent->Add(scroll); @@ -208,6 +168,20 @@ UI::EventReturn DevMenuScreen::OnShaderView(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn DevMenuScreen::OnFreezeFrame(UI::EventParams &e) { + if (PSP_CoreParameter().frozen) { + PSP_CoreParameter().frozen = false; + } else { + PSP_CoreParameter().freezeNext = true; + } + return UI::EVENT_DONE; +} + +UI::EventReturn DevMenuScreen::OnDumpFrame(UI::EventParams &e) { + gpu->DumpNextFrame(); + return UI::EVENT_DONE; +} + void DevMenuScreen::dialogFinished(const Screen *dialog, DialogResult result) { UpdateUIState(UISTATE_INGAME); // Close when a subscreen got closed. @@ -225,12 +199,12 @@ void LogScreen::UpdateLog() { TextView *v = vert_->Add(new TextView(ring->TextAt(i), FLAG_DYNAMIC_ASCII, false)); uint32_t color = 0xFFFFFF; switch (ring->LevelAt(i)) { - case LogLevel::LDEBUG: color = 0xE0E0E0; break; - case LogLevel::LWARNING: color = 0x50FFFF; break; - case LogLevel::LERROR: color = 0x5050FF; break; - case LogLevel::LNOTICE: color = 0x30FF30; break; - case LogLevel::LINFO: color = 0xFFFFFF; break; - case LogLevel::LVERBOSE: color = 0xC0C0C0; break; + case LogTypes::LDEBUG: color = 0xE0E0E0; break; + case LogTypes::LWARNING: color = 0x50FFFF; break; + case LogTypes::LERROR: color = 0x5050FF; break; + case LogTypes::LNOTICE: color = 0x30FF30; break; + case LogTypes::LINFO: color = 0xFFFFFF; break; + case LogTypes::LVERBOSE: color = 0xC0C0C0; break; } v->SetTextColor(0xFF000000 | color); } @@ -309,7 +283,7 @@ void LogConfigScreen::CreateViews() { GridLayout *grid = vert->Add(new GridLayoutList(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); for (int i = 0; i < LogManager::GetNumChannels(); i++) { - LogType type = (LogType)i; + LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; LogChannel *chan = logMan->GetLogChannel(type); LinearLayout *row = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(cellSize - 50, WRAP_CONTENT)); row->SetSpacing(0); @@ -322,7 +296,7 @@ void LogConfigScreen::CreateViews() { UI::EventReturn LogConfigScreen::OnToggleAll(UI::EventParams &e) { LogManager *logMan = LogManager::GetInstance(); for (int i = 0; i < LogManager::GetNumChannels(); i++) { - LogChannel *chan = logMan->GetLogChannel((LogType)i); + LogChannel *chan = logMan->GetLogChannel((LogTypes::LOG_TYPE)i); chan->enabled = !chan->enabled; } return UI::EVENT_DONE; @@ -331,7 +305,7 @@ UI::EventReturn LogConfigScreen::OnToggleAll(UI::EventParams &e) { UI::EventReturn LogConfigScreen::OnEnableAll(UI::EventParams &e) { LogManager *logMan = LogManager::GetInstance(); for (int i = 0; i < LogManager::GetNumChannels(); i++) { - LogChannel *chan = logMan->GetLogChannel((LogType)i); + LogChannel *chan = logMan->GetLogChannel((LogTypes::LOG_TYPE)i); chan->enabled = true; } return UI::EVENT_DONE; @@ -340,7 +314,7 @@ UI::EventReturn LogConfigScreen::OnEnableAll(UI::EventParams &e) { UI::EventReturn LogConfigScreen::OnDisableAll(UI::EventParams &e) { LogManager *logMan = LogManager::GetInstance(); for (int i = 0; i < LogManager::GetNumChannels(); i++) { - LogChannel *chan = logMan->GetLogChannel((LogType)i); + LogChannel *chan = logMan->GetLogChannel((LogTypes::LOG_TYPE)i); chan->enabled = false; } return UI::EVENT_DONE; @@ -378,10 +352,10 @@ void LogLevelScreen::OnCompleted(DialogResult result) { LogManager *logMan = LogManager::GetInstance(); for (int i = 0; i < LogManager::GetNumChannels(); ++i) { - LogType type = (LogType)i; + LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; LogChannel *chan = logMan->GetLogChannel(type); if (chan->enabled) - chan->level = (LogLevel)(selected + 1); + chan->level = (LogTypes::LOG_LEVELS)(selected + 1); } } @@ -482,60 +456,68 @@ const char *GetCompilerABI() { #endif } -void SystemInfoScreen::update() { - TabbedUIDialogScreenWithGameBackground::update(); - g_OSD.NudgeSidebar(); -} - -void SystemInfoScreen::CreateTabs() { +void SystemInfoScreen::CreateViews() { using namespace Draw; using namespace UI; + // NOTE: Do not translate this section. It will change a lot and will be impossible to keep up. auto di = GetI18NCategory(I18NCat::DIALOG); auto si = GetI18NCategory(I18NCat::SYSINFO); - auto sy = GetI18NCategory(I18NCat::SYSTEM); auto gr = GetI18NCategory(I18NCat::GRAPHICS); + root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); + + ViewGroup *leftColumn = new AnchorLayout(new LinearLayoutParams(1.0f)); + root_->Add(leftColumn); + + AddStandardBack(root_); TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 225, new AnchorLayoutParams(10, 0, 10, 0, false)); tabHolder->SetTag("DevSystemInfo"); - LinearLayout *deviceSpecs = AddTab("Device Info", si->T("Device Info")); + root_->Add(tabHolder); + ViewGroup *deviceSpecsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + deviceSpecsScroll->SetTag("DevSystemInfoDeviceSpecs"); + LinearLayout *deviceSpecs = new LinearLayoutList(ORIENT_VERTICAL); + deviceSpecs->SetSpacing(0); + deviceSpecsScroll->Add(deviceSpecs); + tabHolder->AddTab(si->T("Device Info"), deviceSpecsScroll); - CollapsibleSection *systemInfo = deviceSpecs->Add(new CollapsibleSection(si->T("System Information"))); - systemInfo->Add(new InfoItem(si->T("System Name", "Name"), System_GetProperty(SYSPROP_NAME))); + deviceSpecs->Add(new ItemHeader(si->T("System Information"))); + deviceSpecs->Add(new InfoItem(si->T("System Name", "Name"), System_GetProperty(SYSPROP_NAME))); #if PPSSPP_PLATFORM(ANDROID) - systemInfo->Add(new InfoItem(si->T("System Version"), StringFromInt(System_GetPropertyInt(SYSPROP_SYSTEMVERSION)))); + deviceSpecs->Add(new InfoItem(si->T("System Version"), StringFromInt(System_GetPropertyInt(SYSPROP_SYSTEMVERSION)))); #endif - systemInfo->Add(new InfoItem(si->T("Lang/Region"), System_GetProperty(SYSPROP_LANGREGION))); + deviceSpecs->Add(new InfoItem(si->T("Lang/Region"), System_GetProperty(SYSPROP_LANGREGION))); std::string board = System_GetProperty(SYSPROP_BOARDNAME); if (!board.empty()) - systemInfo->Add(new InfoItem(si->T("Board"), board)); - systemInfo->Add(new InfoItem(si->T("ABI"), GetCompilerABI())); - if (System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) { - systemInfo->Add(new InfoItem(si->T("Debugger Present"), di->T("Yes"))); + deviceSpecs->Add(new InfoItem(si->T("Board"), board)); + deviceSpecs->Add(new InfoItem(si->T("ABI"), GetCompilerABI())); +#ifdef _WIN32 + if (IsDebuggerPresent()) { + deviceSpecs->Add(new InfoItem(si->T("Debugger Present"), di->T("Yes"))); } +#endif - CollapsibleSection *cpuInfo = deviceSpecs->Add(new CollapsibleSection(si->T("CPU Information"))); + deviceSpecs->Add(new ItemHeader(si->T("CPU Information"))); // Don't bother showing the CPU name if we don't have one. if (strcmp(cpu_info.brand_string, "Unknown") != 0) { - cpuInfo->Add(new InfoItem(si->T("CPU Name", "Name"), cpu_info.brand_string)); + deviceSpecs->Add(new InfoItem(si->T("CPU Name", "Name"), cpu_info.brand_string)); } int totalThreads = cpu_info.num_cores * cpu_info.logical_cpu_count; std::string cores = StringFromFormat(si->T("%d (%d per core, %d cores)"), totalThreads, cpu_info.logical_cpu_count, cpu_info.num_cores); - cpuInfo->Add(new InfoItem(si->T("Threads"), cores)); + deviceSpecs->Add(new InfoItem(si->T("Threads"), cores)); #if PPSSPP_PLATFORM(IOS) - cpuInfo->Add(new InfoItem(si->T("JIT available"), System_GetPropertyBool(SYSPROP_CAN_JIT) ? di->T("Yes") : di->T("No"))); + deviceSpecs->Add(new InfoItem(si->T("JIT available"), System_GetPropertyBool(SYSPROP_CAN_JIT) ? di->T("Yes") : di->T("No"))); #endif - - CollapsibleSection *gpuInfo = deviceSpecs->Add(new CollapsibleSection(si->T("GPU Information"))); + deviceSpecs->Add(new ItemHeader(si->T("GPU Information"))); DrawContext *draw = screenManager()->getDrawContext(); const std::string apiNameKey = draw->GetInfoString(InfoField::APINAME); const char *apiName = gr->T(apiNameKey); - gpuInfo->Add(new InfoItem(si->T("3D API"), apiName)); + deviceSpecs->Add(new InfoItem(si->T("3D API"), apiName)); // TODO: Not really vendor, on most APIs it's a device name (GL calls it vendor though). std::string vendorString; @@ -544,38 +526,38 @@ void SystemInfoScreen::CreateTabs() { } else { vendorString = draw->GetInfoString(InfoField::VENDORSTRING); } - gpuInfo->Add(new InfoItem(si->T("Vendor"), vendorString)); + deviceSpecs->Add(new InfoItem(si->T("Vendor"), vendorString)); std::string vendor = draw->GetInfoString(InfoField::VENDOR); if (vendor.size()) - gpuInfo->Add(new InfoItem(si->T("Vendor (detected)"), vendor)); - gpuInfo->Add(new InfoItem(si->T("Driver Version"), draw->GetInfoString(InfoField::DRIVER))); + deviceSpecs->Add(new InfoItem(si->T("Vendor (detected)"), vendor)); + deviceSpecs->Add(new InfoItem(si->T("Driver Version"), draw->GetInfoString(InfoField::DRIVER))); #ifdef _WIN32 if (GetGPUBackend() != GPUBackend::VULKAN) - gpuInfo->Add(new InfoItem(si->T("Driver Version"), System_GetProperty(SYSPROP_GPUDRIVER_VERSION))); + deviceSpecs->Add(new InfoItem(si->T("Driver Version"), System_GetProperty(SYSPROP_GPUDRIVER_VERSION))); #if !PPSSPP_PLATFORM(UWP) if (GetGPUBackend() == GPUBackend::DIRECT3D9) { - gpuInfo->Add(new InfoItem(si->T("D3DCompiler Version"), StringFromFormat("%d", GetD3DCompilerVersion()))); + deviceSpecs->Add(new InfoItem(si->T("D3DCompiler Version"), StringFromFormat("%d", GetD3DCompilerVersion()))); } #endif #endif if (GetGPUBackend() == GPUBackend::OPENGL) { - gpuInfo->Add(new InfoItem(si->T("Core Context"), gl_extensions.IsCoreContext ? di->T("Active") : di->T("Inactive"))); + deviceSpecs->Add(new InfoItem(si->T("Core Context"), gl_extensions.IsCoreContext ? di->T("Active") : di->T("Inactive"))); int highp_int_min = gl_extensions.range[1][5][0]; int highp_int_max = gl_extensions.range[1][5][1]; int highp_float_min = gl_extensions.range[1][2][0]; int highp_float_max = gl_extensions.range[1][2][1]; if (highp_int_max != 0) { - char temp[128]; - snprintf(temp, sizeof(temp), "%d-%d", highp_int_min, highp_int_max); - gpuInfo->Add(new InfoItem(si->T("High precision int range"), temp)); + char temp[512]; + snprintf(temp, sizeof(temp), "Highp int range: %d-%d", highp_int_min, highp_int_max); + deviceSpecs->Add(new InfoItem(si->T("High precision int range"), temp)); } if (highp_float_max != 0) { - char temp[128]; - snprintf(temp, sizeof(temp), "%d-%d", highp_int_min, highp_int_max); - gpuInfo->Add(new InfoItem(si->T("High precision float range"), temp)); + char temp[512]; + snprintf(temp, sizeof(temp), "Highp float range: %d-%d", highp_int_min, highp_int_max); + deviceSpecs->Add(new InfoItem(si->T("High precision float range"), temp)); } } - gpuInfo->Add(new InfoItem(si->T("Depth buffer format"), DataFormatToString(draw->GetDeviceCaps().preferredDepthBufferFormat))); + deviceSpecs->Add(new InfoItem(si->T("Depth buffer format"), DataFormatToString(draw->GetDeviceCaps().preferredDepthBufferFormat))); std::string texCompressionFormats; // Simple non-detailed summary of supported tex compression formats. @@ -584,70 +566,50 @@ void SystemInfoScreen::CreateTabs() { if (draw->GetDataFormatSupport(Draw::DataFormat::BC1_RGBA_UNORM_BLOCK)) texCompressionFormats += "BC1-3 "; if (draw->GetDataFormatSupport(Draw::DataFormat::BC4_UNORM_BLOCK)) texCompressionFormats += "BC4-5 "; if (draw->GetDataFormatSupport(Draw::DataFormat::BC7_UNORM_BLOCK)) texCompressionFormats += "BC7 "; - gpuInfo->Add(new InfoItem(si->T("Compressed texture formats"), texCompressionFormats)); + deviceSpecs->Add(new InfoItem(si->T("Compressed texture formats"), texCompressionFormats)); - CollapsibleSection *osInformation = deviceSpecs->Add(new CollapsibleSection(si->T("OS Information"))); - osInformation->Add(new InfoItem(si->T("Memory Page Size"), StringFromFormat(si->T("%d bytes"), GetMemoryProtectPageSize()))); - osInformation->Add(new InfoItem(si->T("RW/RX exclusive"), PlatformIsWXExclusive() ? di->T("Active") : di->T("Inactive"))); + deviceSpecs->Add(new ItemHeader(si->T("OS Information"))); + deviceSpecs->Add(new InfoItem(si->T("Memory Page Size"), StringFromFormat(si->T("%d bytes"), GetMemoryProtectPageSize()))); + deviceSpecs->Add(new InfoItem(si->T("RW/RX exclusive"), PlatformIsWXExclusive() ? di->T("Active") : di->T("Inactive"))); #if PPSSPP_PLATFORM(ANDROID) - osInformation->Add(new InfoItem(si->T("Sustained perf mode"), System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE) ? di->T("Supported") : di->T("Unsupported"))); + deviceSpecs->Add(new InfoItem(si->T("Sustained perf mode"), System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE) ? di->T("Supported") : di->T("Unsupported"))); #endif const char *build = si->T("Release"); #ifdef _DEBUG build = si->T("Debug"); #endif - osInformation->Add(new InfoItem(si->T("PPSSPP build"), build)); + deviceSpecs->Add(new InfoItem(si->T("PPSSPP build"), build)); - CollapsibleSection *audioInformation = deviceSpecs->Add(new CollapsibleSection(si->T("Audio Information"))); - audioInformation->Add(new InfoItem(si->T("Sample rate"), StringFromFormat(si->T("%d Hz"), System_GetPropertyInt(SYSPROP_AUDIO_SAMPLE_RATE)))); + deviceSpecs->Add(new ItemHeader(si->T("Audio Information"))); + deviceSpecs->Add(new InfoItem(si->T("Sample rate"), StringFromFormat(si->T("%d Hz"), System_GetPropertyInt(SYSPROP_AUDIO_SAMPLE_RATE)))); int framesPerBuffer = System_GetPropertyInt(SYSPROP_AUDIO_FRAMES_PER_BUFFER); if (framesPerBuffer > 0) { - audioInformation->Add(new InfoItem(si->T("Frames per buffer"), StringFromFormat("%d", framesPerBuffer))); + deviceSpecs->Add(new InfoItem(si->T("Frames per buffer"), StringFromFormat("%d", framesPerBuffer))); } #if PPSSPP_PLATFORM(ANDROID) - audioInformation->Add(new InfoItem(si->T("Optimal sample rate"), StringFromFormat(si->T("%d Hz"), System_GetPropertyInt(SYSPROP_AUDIO_OPTIMAL_SAMPLE_RATE)))); - audioInformation->Add(new InfoItem(si->T("Optimal frames per buffer"), StringFromFormat("%d", System_GetPropertyInt(SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER)))); + deviceSpecs->Add(new InfoItem(si->T("Optimal sample rate"), StringFromFormat(si->T("%d Hz"), System_GetPropertyInt(SYSPROP_AUDIO_OPTIMAL_SAMPLE_RATE)))); + deviceSpecs->Add(new InfoItem(si->T("Optimal frames per buffer"), StringFromFormat("%d", System_GetPropertyInt(SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER)))); #endif - CollapsibleSection *displayInfo = deviceSpecs->Add(new CollapsibleSection(si->T("Display Information"))); -#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(UWP) - displayInfo->Add(new InfoItem(si->T("Native resolution"), StringFromFormat("%dx%d", + deviceSpecs->Add(new ItemHeader(si->T("Display Information"))); +#if PPSSPP_PLATFORM(ANDROID) + deviceSpecs->Add(new InfoItem(si->T("Native Resolution"), StringFromFormat("%dx%d", System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES)))); -#endif - displayInfo->Add(new InfoItem(si->T("UI resolution"), StringFromFormat("%dx%d (%s: %0.2f)", + deviceSpecs->Add(new InfoItem(si->T("UI Resolution"), StringFromFormat("%dx%d (%s: %0.2f)", g_display.dp_xres, g_display.dp_yres, si->T("DPI"), g_display.dpi))); - displayInfo->Add(new InfoItem(si->T("Pixel resolution"), StringFromFormat("%dx%d", - g_display.pixel_xres, - g_display.pixel_yres))); - - const float insets[4] = { - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT), - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP), - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT), - System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM), - }; - if (insets[0] != 0.0f || insets[1] != 0.0f || insets[2] != 0.0f || insets[3] != 0.0f) { - displayInfo->Add(new InfoItem(si->T("Screen notch insets"), StringFromFormat("%0.1f %0.1f %0.1f %0.1f", insets[0], insets[1], insets[2], insets[3]))); - } +#endif +#if !PPSSPP_PLATFORM(WINDOWS) // Don't show on Windows, since it's always treated as 60 there. - displayInfo->Add(new InfoItem(si->T("Refresh rate"), StringFromFormat(si->T("%0.2f Hz"), (float)System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE)))); - std::string presentModes; - if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::FIFO) presentModes += "FIFO, "; - if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::IMMEDIATE) presentModes += "IMMEDIATE, "; - if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::MAILBOX) presentModes += "MAILBOX, "; - if (!presentModes.empty()) { - presentModes.pop_back(); - presentModes.pop_back(); - } - displayInfo->Add(new InfoItem(si->T("Present modes"), presentModes)); + deviceSpecs->Add(new InfoItem(si->T("Refresh rate"), StringFromFormat(si->T("%0.2f Hz"), (float)System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE)))); +#endif - CollapsibleSection *versionInfo = deviceSpecs->Add(new CollapsibleSection(si->T("Version Information"))); + deviceSpecs->Add(new ItemHeader(si->T("Version Information"))); std::string apiVersion; if (GetGPUBackend() == GPUBackend::OPENGL) { if (gl_extensions.IsGLES) { @@ -660,31 +622,36 @@ void SystemInfoScreen::CreateTabs() { if (apiVersion.size() > 30) apiVersion.resize(30); } - versionInfo->Add(new InfoItem(si->T("API Version"), apiVersion)); - versionInfo->Add(new InfoItem(si->T("Shading Language"), draw->GetInfoString(InfoField::SHADELANGVERSION))); + deviceSpecs->Add(new InfoItem(si->T("API Version"), apiVersion)); + deviceSpecs->Add(new InfoItem(si->T("Shading Language"), draw->GetInfoString(InfoField::SHADELANGVERSION))); #if PPSSPP_PLATFORM(ANDROID) std::string moga = System_GetProperty(SYSPROP_MOGA_VERSION); if (moga.empty()) { moga = si->T("(none detected)"); } - versionInfo->Add(new InfoItem("Moga", moga)); + deviceSpecs->Add(new InfoItem("Moga", moga)); #endif if (gstate_c.GetUseFlags()) { // We're in-game, and can determine these. // TODO: Call a static version of GPUCommon::CheckGPUFeatures() and derive them here directly. - CollapsibleSection *gpuFlags = deviceSpecs->Add(new CollapsibleSection(si->T("GPU Flags"))); + deviceSpecs->Add(new ItemHeader(si->T("GPU Flags"))); for (int i = 0; i < 32; i++) { if (gstate_c.Use((1 << i))) { - gpuFlags->Add(new TextView(GpuUseFlagToString(i), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); + deviceSpecs->Add(new TextView(GpuUseFlagToString(i), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } } } - LinearLayout *storage = AddTab("Storage", si->T("Storage")); + ViewGroup *storageScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + storageScroll->SetTag("DevSystemInfoBuildConfig"); + LinearLayout *storage = new LinearLayout(ORIENT_VERTICAL); + storage->SetSpacing(0); + storageScroll->Add(storage); + tabHolder->AddTab(si->T("Storage"), storageScroll); storage->Add(new ItemHeader(si->T("Directories"))); // Intentionally non-translated @@ -703,7 +670,12 @@ void SystemInfoScreen::CreateTabs() { } #endif - LinearLayout *buildConfig = AddTab("DevSystemInfoBuildConfig", si->T("Build Config")); + ViewGroup *buildConfigScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + buildConfigScroll->SetTag("DevSystemInfoBuildConfig"); + LinearLayout *buildConfig = new LinearLayoutList(ORIENT_VERTICAL); + buildConfig->SetSpacing(0); + buildConfigScroll->Add(buildConfig); + tabHolder->AddTab(si->T("Build Config"), buildConfigScroll); buildConfig->Add(new ItemHeader(si->T("Build Configuration"))); #ifdef JENKINS @@ -736,14 +708,27 @@ void SystemInfoScreen::CreateTabs() { buildConfig->Add(new InfoItem("GOLD", "")); } - LinearLayout *cpuExtensions = AddTab("DevSystemInfoCPUExt", si->T("CPU Extensions")); + ViewGroup *cpuExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + cpuExtensionsScroll->SetTag("DevSystemInfoCPUExt"); + LinearLayout *cpuExtensions = new LinearLayoutList(ORIENT_VERTICAL); + cpuExtensions->SetSpacing(0); + cpuExtensionsScroll->Add(cpuExtensions); + + tabHolder->AddTab(si->T("CPU Extensions"), cpuExtensionsScroll); + cpuExtensions->Add(new ItemHeader(si->T("CPU Extensions"))); std::vector exts = cpu_info.Features(); for (std::string &ext : exts) { cpuExtensions->Add(new TextView(ext, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } - LinearLayout *driverBugs = AddTab("DevSystemInfoDriverBugs", si->T("Driver bugs")); + ViewGroup *driverBugsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + driverBugsScroll->SetTag("DevSystemInfoDriverBugs"); + LinearLayout *driverBugs = new LinearLayoutList(ORIENT_VERTICAL); + driverBugs->SetSpacing(0); + driverBugsScroll->Add(driverBugs); + + tabHolder->AddTab(si->T("Driver bugs"), driverBugsScroll); bool anyDriverBugs = false; for (int i = 0; i < (int)draw->GetBugs().MaxBugIndex(); i++) { @@ -757,8 +742,14 @@ void SystemInfoScreen::CreateTabs() { driverBugs->Add(new TextView(si->T("No GPU driver bugs detected"), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } + ViewGroup *gpuExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + gpuExtensionsScroll->SetTag("DevSystemInfoOGLExt"); + LinearLayout *gpuExtensions = new LinearLayoutList(ORIENT_VERTICAL); + gpuExtensions->SetSpacing(0); + gpuExtensionsScroll->Add(gpuExtensions); + if (GetGPUBackend() == GPUBackend::OPENGL) { - LinearLayout *gpuExtensions = AddTab("DevSystemInfoOGLExt", si->T("OGL Extensions")); + tabHolder->AddTab(si->T("OGL Extensions"), gpuExtensionsScroll); if (!gl_extensions.IsGLES) { gpuExtensions->Add(new ItemHeader(si->T("OpenGL Extensions"))); @@ -795,161 +786,44 @@ void SystemInfoScreen::CreateTabs() { } } } else if (GetGPUBackend() == GPUBackend::VULKAN) { - LinearLayout *gpuExtensions = AddTab("DevSystemInfoOGLExt", si->T("Vulkan Features")); #if !PPSSPP_PLATFORM(UWP) // Vulkan specific code here, can't be bothered to abstract. // OK because of above check. + tabHolder->AddTab(si->T("Vulkan Features"), gpuExtensionsScroll); VulkanContext *vk = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); - CollapsibleSection *vulkanFeatures = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Features"))); + gpuExtensions->Add(new ItemHeader(si->T("Vulkan Features"))); std::vector features = draw->GetFeatureList(); for (auto &feature : features) { - vulkanFeatures->Add(new TextView(feature, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); + gpuExtensions->Add(new TextView(feature, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } - CollapsibleSection *presentModes = gpuExtensions->Add(new CollapsibleSection(si->T("Present Modes"))); + gpuExtensions->Add(new ItemHeader(si->T("Present Modes"))); for (auto mode : vk->GetAvailablePresentModes()) { std::string str = VulkanPresentModeToString(mode); if (mode == vk->GetPresentMode()) { str += std::string(" (") + di->T("Current") + ")"; } - presentModes->Add(new TextView(str, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); + gpuExtensions->Add(new TextView(VulkanPresentModeToString(mode), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } - CollapsibleSection *colorFormats = gpuExtensions->Add(new CollapsibleSection(si->T("Display Color Formats"))); + gpuExtensions->Add(new ItemHeader(si->T("Display Color Formats"))); if (vk) { for (auto &format : vk->SurfaceFormats()) { std::string line = StringFromFormat("%s : %s", VulkanFormatToString(format.format), VulkanColorSpaceToString(format.colorSpace)); - colorFormats->Add(new TextView(line, + gpuExtensions->Add(new TextView(line, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } } #endif - CollapsibleSection *enabledExtensions = gpuExtensions->Add(new CollapsibleSection(std::string(si->T("Vulkan Extensions")) + " (" + di->T("Enabled") + ")")); - std::vector extensions = draw->GetExtensionList(true, true); - std::sort(extensions.begin(), extensions.end()); + gpuExtensions->Add(new ItemHeader(si->T("Vulkan Extensions"))); + std::vector extensions = draw->GetExtensionList(); for (auto &extension : extensions) { - enabledExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); - } - // Also get instance extensions - enabledExtensions->Add(new ItemHeader("Instance")); - extensions = draw->GetExtensionList(false, true); - std::sort(extensions.begin(), extensions.end()); - for (auto &extension : extensions) { - enabledExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); - } - - CollapsibleSection *vulkanExtensions = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Extensions"))); - extensions = draw->GetExtensionList(true, false); - std::sort(extensions.begin(), extensions.end()); - for (auto &extension : extensions) { - vulkanExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); - } - - vulkanExtensions->Add(new ItemHeader("Instance")); - // Also get instance extensions - extensions = draw->GetExtensionList(false, false); - std::sort(extensions.begin(), extensions.end()); - for (auto &extension : extensions) { - vulkanExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); + gpuExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true); } } - -#ifdef _DEBUG - LinearLayout *internals = AddTab("DevSystemInfoInternals", si->T("Internals")); - CreateInternalsTab(internals); -#endif -} - -void SystemInfoScreen::CreateInternalsTab(UI::ViewGroup *internals) { - using namespace UI; - - auto di = GetI18NCategory(I18NCat::DIALOG); - auto si = GetI18NCategory(I18NCat::SYSINFO); - auto sy = GetI18NCategory(I18NCat::SYSTEM); - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - internals->Add(new ItemHeader(si->T("Icon cache"))); - IconCacheStats iconStats = g_iconCache.GetStats(); - internals->Add(new InfoItem(si->T("Image data count"), StringFromFormat("%d", iconStats.cachedCount))); - internals->Add(new InfoItem(si->T("Texture count"), StringFromFormat("%d", iconStats.textureCount))); - internals->Add(new InfoItem(si->T("Data size"), NiceSizeFormat(iconStats.dataSize))); - internals->Add(new Choice(di->T("Clear")))->OnClick.Add([&](UI::EventParams &) { - g_iconCache.ClearData(); - RecreateViews(); - return UI::EVENT_DONE; - }); - - internals->Add(new ItemHeader(si->T("Notification tests"))); - internals->Add(new Choice(si->T("Error")))->OnClick.Add([&](UI::EventParams &) { - std::string str = "Error " + CodepointToUTF8(0x1F41B) + CodepointToUTF8(0x1F41C) + CodepointToUTF8(0x1F914); - g_OSD.Show(OSDType::MESSAGE_ERROR, str); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Warning")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.Show(OSDType::MESSAGE_WARNING, "Warning", "Some\nAdditional\nDetail"); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Info")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.Show(OSDType::MESSAGE_INFO, "Info"); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Success")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.Show(OSDType::MESSAGE_SUCCESS, "Success"); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(sy->T("RetroAchievements")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.Show(OSDType::MESSAGE_WARNING, "RetroAchievements warning", "", "I_RETROACHIEVEMENTS_LOGO"); - return UI::EVENT_DONE; - }); - internals->Add(new ItemHeader(si->T("Progress tests"))); - internals->Add(new Choice(si->T("30%")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.SetProgressBar("testprogress", "Test Progress", 1, 100, 30, 0.0f); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("100%")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.SetProgressBar("testprogress", "Test Progress", 1, 100, 100, 1.0f); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("N/A%")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.SetProgressBar("testprogress", "Test Progress", 0, 0, 0, 0.0f); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Success")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.RemoveProgressBar("testprogress", true, 0.5f); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Failure")))->OnClick.Add([&](UI::EventParams &) { - g_OSD.RemoveProgressBar("testprogress", false, 0.5f); - return UI::EVENT_DONE; - }); - internals->Add(new ItemHeader(si->T("Achievement tests"))); - internals->Add(new Choice(si->T("Leaderboard tracker: Show")))->OnClick.Add([=](UI::EventParams &) { - g_OSD.ShowLeaderboardTracker(1, "My leaderboard tracker", true); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Leaderboard tracker: Update")))->OnClick.Add([=](UI::EventParams &) { - g_OSD.ShowLeaderboardTracker(1, "Updated tracker", true); - return UI::EVENT_DONE; - }); - internals->Add(new Choice(si->T("Leaderboard tracker: Hide")))->OnClick.Add([=](UI::EventParams &) { - g_OSD.ShowLeaderboardTracker(1, nullptr, false); - return UI::EVENT_DONE; - }); - - static const char *positions[] = { "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right", "None" }; - - internals->Add(new ItemHeader(ac->T("Notifications"))); - internals->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardTrackerPos, ac->T("Leaderboard tracker"), positions, 0, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); - -#if PPSSPP_PLATFORM(ANDROID) - internals->Add(new Choice(si->T("Exception")))->OnClick.Add([&](UI::EventParams &) { - System_Notify(SystemNotification::TEST_JAVA_EXCEPTION); - return UI::EVENT_DONE; - }); -#endif } void AddressPromptScreen::CreatePopupContents(UI::ViewGroup *parent) { @@ -1096,7 +970,7 @@ void JitCompareScreen::UpdateDisasm() { snprintf(temp, sizeof(temp), "%i/%i", currentBlock_, blockCacheDebug->GetNumBlocks()); blockName_->SetText(temp); - if (currentBlock_ < 0 || !blockCacheDebug || currentBlock_ >= blockCacheDebug->GetNumBlocks()) { + if (currentBlock_ < 0 || currentBlock_ >= blockCacheDebug->GetNumBlocks()) { leftDisasm_->Add(new TextView(dev->T("No block"))); rightDisasm_->Add(new TextView(dev->T("No block"))); blockStats_->SetText(""); @@ -1160,9 +1034,6 @@ UI::EventReturn JitCompareScreen::OnShowStats(UI::EventParams &e) { } JitBlockCacheDebugInterface *blockCache = MIPSComp::jit->GetBlockCacheDebugInterface(); - if (!blockCache) - return UI::EVENT_DONE; - BlockCacheStats bcStats; blockCache->ComputeStats(bcStats); NOTICE_LOG(JIT, "Num blocks: %i", bcStats.numBlocks); @@ -1268,11 +1139,11 @@ void JitCompareScreen::OnRandomBlock(int flag) { currentBlock_ = rand() % numBlocks; JitBlockDebugInfo b = blockCache->GetBlockDebugInfo(currentBlock_); u32 mipsBytes = (u32)b.origDisasm.size() * 4; - for (u32 addr = b.originalAddress; addr < b.originalAddress + mipsBytes; addr += 4) { + for (u32 addr = b.originalAddress; addr <= b.originalAddress + mipsBytes; addr += 4) { MIPSOpcode opcode = Memory::Read_Instruction(addr); if (MIPSGetInfo(opcode) & flag) { char temp[256]; - MIPSDisAsm(opcode, addr, temp, sizeof(temp)); + MIPSDisAsm(opcode, addr, temp); // INFO_LOG(HLE, "Stopping at random instruction: %08x %s", addr, temp); anyWanted = true; break; @@ -1436,7 +1307,7 @@ void FrameDumpTestScreen::update() { if (!listing_) { const char *acceptMime = "text/html, */*; q=0.8"; - listing_ = g_DownloadManager.StartDownload(framedumpsBaseUrl, Path(), http::ProgressBarMode::DELAYED, acceptMime); + listing_ = g_DownloadManager.StartDownload(framedumpsBaseUrl, Path(), acceptMime); } if (listing_ && listing_->Done() && files_.empty()) { diff --git a/UI/DevScreens.h b/UI/DevScreens.h index 3572061c9..4947ef0f1 100644 --- a/UI/DevScreens.h +++ b/UI/DevScreens.h @@ -24,7 +24,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Net/HTTPClient.h" #include "Common/UI/UIScreen.h" -#include "UI/TabbedDialogScreen.h" + #include "UI/MiscScreens.h" #include "GPU/Common/ShaderCommon.h" @@ -42,6 +42,8 @@ protected: UI::EventReturn OnLogConfig(UI::EventParams &e); UI::EventReturn OnJitCompare(UI::EventParams &e); UI::EventReturn OnShaderView(UI::EventParams &e); + UI::EventReturn OnFreezeFrame(UI::EventParams &e); + UI::EventReturn OnDumpFrame(UI::EventParams &e); UI::EventReturn OnDeveloperTools(UI::EventParams &e); UI::EventReturn OnResetLimitedLogging(UI::EventParams &e); @@ -103,18 +105,13 @@ private: void OnCompleted(DialogResult result) override; }; -class SystemInfoScreen : public TabbedUIDialogScreenWithGameBackground { +class SystemInfoScreen : public UIDialogScreenWithGameBackground { public: - SystemInfoScreen(const Path &filename) : TabbedUIDialogScreenWithGameBackground(filename) {} + SystemInfoScreen(const Path &filename) : UIDialogScreenWithGameBackground(filename) {} const char *tag() const override { return "SystemInfo"; } - void CreateTabs() override; - void update() override; - -protected: - bool ShowSearchControls() const override { return false; } - void CreateInternalsTab(UI::ViewGroup *internals); + void CreateViews() override; }; class AddressPromptScreen : public PopupScreen { @@ -218,11 +215,9 @@ private: UI::EventReturn OnLoadDump(UI::EventParams &e); std::vector files_; - std::shared_ptr listing_; - std::shared_ptr dumpDownload_; + std::shared_ptr listing_; + std::shared_ptr dumpDownload_; }; void DrawProfile(UIContext &ui); const char *GetCompilerABI(); - -void AddOverlayList(UI::ViewGroup *items, ScreenManager *screenManager); diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index 5d845ebb3..b0ec1750f 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -155,9 +155,9 @@ UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end()); FixPostShaderOrder(&g_Config.vPostShaderNames); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); // To deal with shaders that can change render resolution like upscaling. - System_PostUIMessage(UIMessage::POSTSHADER_UPDATED); + NativeMessageReceived("gpu_configChanged", ""); + NativeMessageReceived("gpu_renderResized", ""); // To deal with shaders that can change render resolution like upscaling. + NativeMessageReceived("postshader_updated", ""); if (gpu) { gpu->NotifyConfigChanged(); @@ -181,9 +181,9 @@ static std::string PostShaderTranslateName(const char *value) { } } -void DisplayLayoutScreen::sendMessage(UIMessage message, const char *value) { +void DisplayLayoutScreen::sendMessage(const char *message, const char *value) { UIDialogScreenWithGameBackground::sendMessage(message, value); - if (message == UIMessage::POSTSHADER_UPDATED) { + if (!strcmp(message, "postshader_updated")) { g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames)); RecreateViews(); } @@ -381,7 +381,7 @@ void DisplayLayoutScreen::CreateViews() { auto removeButton = shaderRow->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(0.0f))); removeButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn { g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); RecreateViews(); return UI::EVENT_DONE; }); @@ -409,7 +409,7 @@ void DisplayLayoutScreen::CreateViews() { return UI::EVENT_DONE; } FixPostShaderOrder(&g_Config.vPostShaderNames); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); RecreateViews(); return UI::EVENT_DONE; }); @@ -493,17 +493,18 @@ void PostProcScreen::OnCompleted(DialogResult result) { if (showStereoShaders_) { if (g_Config.sStereoToMonoShader != value) { g_Config.sStereoToMonoShader = value; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } } else { if (id_ < (int)g_Config.vPostShaderNames.size()) { if (g_Config.vPostShaderNames[id_] != value) { g_Config.vPostShaderNames[id_] = value; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } - } else { + } + else { g_Config.vPostShaderNames.push_back(value); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } } } diff --git a/UI/DisplayLayoutScreen.h b/UI/DisplayLayoutScreen.h index 0af2648bc..769e97592 100644 --- a/UI/DisplayLayoutScreen.h +++ b/UI/DisplayLayoutScreen.h @@ -43,7 +43,7 @@ public: protected: UI::EventReturn OnPostProcShaderChange(UI::EventParams &e); - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; private: UI::ChoiceStrip *mode_ = nullptr; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 72ae94778..0710ce0ff 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -42,7 +42,6 @@ using namespace std::placeholders; #include "Common/System/System.h" #include "Common/System/NativeApp.h" #include "Common/System/Request.h" -#include "Common/System/OSD.h" #include "Common/Profiler/Profiler.h" #include "Common/Math/curves.h" #include "Common/TimeUtil.h" @@ -69,7 +68,6 @@ using namespace std::placeholders; #include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceSas.h" #include "Core/Debugger/SymbolMap.h" -#include "Core/RetroAchievements.h" #include "Core/SaveState.h" #include "Core/MIPS/MIPS.h" #include "Core/HLE/__sceAudio.h" @@ -92,7 +90,6 @@ using namespace std::placeholders; #include "UI/ProfilerDraw.h" #include "UI/DiscordIntegration.h" #include "UI/ChatScreen.h" -#include "UI/DebugOverlay.h" #include "Core/Reporting.h" @@ -125,7 +122,7 @@ static void __EmuScreenVblank() if (g_Config.bDumpFrames && !startDumping) { avi.Start(PSP_CoreParameter().renderWidth, PSP_CoreParameter().renderHeight); - g_OSD.Show(OSDType::MESSAGE_INFO, sy->T("AVI Dump started."), 1.0f); + osm.Show(sy->T("AVI Dump started."), 0.5f); startDumping = true; } if (g_Config.bDumpFrames && startDumping) @@ -135,7 +132,7 @@ static void __EmuScreenVblank() else if (!g_Config.bDumpFrames && startDumping) { avi.Stop(); - g_OSD.Show(OSDType::MESSAGE_INFO, sy->T("AVI Dump stopped."), 1.0f); + osm.Show(sy->T("AVI Dump stopped."), 1.0f); startDumping = false; } #endif @@ -232,13 +229,6 @@ bool EmuScreen::bootAllowStorage(const Path &filename) { } void EmuScreen::bootGame(const Path &filename) { - auto sc = GetI18NCategory(I18NCat::SCREEN); - - if (Achievements::IsBlockingExecution()) { - // Keep waiting. - return; - } - if (PSP_IsRebooting()) return; if (PSP_IsInited()) { @@ -249,15 +239,13 @@ void EmuScreen::bootGame(const Path &filename) { } if (PSP_IsIniting()) { - std::string error_string = "(unknown error)"; - + std::string error_string; bootPending_ = !PSP_InitUpdate(&error_string); - if (!bootPending_) { invalid_ = !PSP_IsInited(); if (invalid_) { errorMessage_ = error_string; - ERROR_LOG(BOOT, "isIniting bootGame error: %s", errorMessage_.c_str()); + ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); return; } bootComplete(); @@ -271,6 +259,8 @@ void EmuScreen::bootGame(const Path &filename) { if (!bootAllowStorage(filename)) return; + auto sc = GetI18NCategory(I18NCat::SCREEN); + invalid_ = true; // We don't want to boot with the wrong game specific config, so wait until info is ready. @@ -338,22 +328,22 @@ void EmuScreen::bootGame(const Path &filename) { bootPending_ = false; invalid_ = true; errorMessage_ = error_string; - ERROR_LOG(BOOT, "InitStart bootGame error: %s", errorMessage_.c_str()); + ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); } if (PSP_CoreParameter().compat.flags().RequireBufferedRendering && g_Config.bSkipBufferEffects) { auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("BufferedRenderingRequired", "Warning: This game requires Rendering Mode to be set to Buffered."), 10.0f); + System_NotifyUserMessage(gr->T("BufferedRenderingRequired", "Warning: This game requires Rendering Mode to be set to Buffered."), 15.0f); } if (PSP_CoreParameter().compat.flags().RequireBlockTransfer && g_Config.bSkipGPUReadbacks) { auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("BlockTransferRequired", "Warning: This game requires Simulate Block Transfer Mode to be set to On."), 10.0f); + System_NotifyUserMessage(gr->T("BlockTransferRequired", "Warning: This game requires Simulate Block Transfer Mode to be set to On."), 15.0f); } if (PSP_CoreParameter().compat.flags().RequireDefaultCPUClock && g_Config.iLockedCPUSpeed != 0) { auto gr = GetI18NCategory(I18NCat::GRAPHICS); - g_OSD.Show(OSDType::MESSAGE_WARNING, gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 10.0f); + System_NotifyUserMessage(gr->T("DefaultCPUClockRequired", "Warning: This game requires the CPU clock to be set to default."), 15.0f); } loadingViewColor_->Divert(0xFFFFFFFF, 0.75f); @@ -367,17 +357,14 @@ void EmuScreen::bootComplete() { System_Notify(SystemNotification::BOOT_DONE); System_Notify(SystemNotification::DISASSEMBLY); - NOTICE_LOG(BOOT, "Booted %s...", PSP_CoreParameter().fileToStart.c_str()); - if (!Achievements::ChallengeModeActive()) { - // Don't auto-load savestates in hardcore mode. - autoLoad(); - } + NOTICE_LOG(BOOT, "Loading %s...", PSP_CoreParameter().fileToStart.c_str()); + autoLoad(); auto sc = GetI18NCategory(I18NCat::SCREEN); #ifndef MOBILE_DEVICE if (g_Config.bFirstRun) { - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("PressESC", "Press ESC to open the pause menu")); + osm.Show(sc->T("PressESC", "Press ESC to open the pause menu"), 3.0f); } #endif @@ -385,13 +372,13 @@ void EmuScreen::bootComplete() { if (GetGPUBackend() == GPUBackend::OPENGL) { const char *renderer = gl_extensions.model; if (strstr(renderer, "Chainfire3D") != 0) { - g_OSD.Show(OSDType::MESSAGE_WARNING, sc->T("Chainfire3DWarning", "WARNING: Chainfire3D detected, may cause problems"), 10.0f); + osm.Show(sc->T("Chainfire3DWarning", "WARNING: Chainfire3D detected, may cause problems"), 10.0f, 0xFF30a0FF, -1, true); } else if (strstr(renderer, "GLTools") != 0) { - g_OSD.Show(OSDType::MESSAGE_WARNING, sc->T("GLToolsWarning", "WARNING: GLTools detected, may cause problems"), 10.0f); + osm.Show(sc->T("GLToolsWarning", "WARNING: GLTools detected, may cause problems"), 10.0f, 0xFF30a0FF, -1, true); } if (g_Config.bGfxDebugOutput) { - g_OSD.Show(OSDType::MESSAGE_WARNING, "WARNING: GfxDebugOutput is enabled via ppsspp.ini. Things may be slow.", 10.0f); + osm.Show("WARNING: GfxDebugOutput is enabled via ppsspp.ini. Things may be slow.", 10.0f, 0xFF30a0FF, -1, true); } } #endif @@ -399,9 +386,9 @@ void EmuScreen::bootComplete() { if (Core_GetPowerSaving()) { auto sy = GetI18NCategory(I18NCat::SYSTEM); #ifdef __ANDROID__ - g_OSD.Show(OSDType::MESSAGE_WARNING, sy->T("WARNING: Android battery save mode is on"), 2.0f, "core_powerSaving"); + osm.Show(sy->T("WARNING: Android battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving"); #else - g_OSD.Show(OSDType::MESSAGE_WARNING, sy->T("WARNING: Battery save mode is on"), 2.0f, "core_powerSaving"); + osm.Show(sy->T("WARNING: Battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving"); #endif } @@ -409,29 +396,21 @@ void EmuScreen::bootComplete() { loadingViewColor_->Divert(0x00FFFFFF, 0.2f); loadingViewVisible_->Divert(UI::V_INVISIBLE, 0.2f); - - std::string gameID = g_paramSFO.GetValueString("DISC_ID"); - g_Config.TimeTracker().Start(gameID); } EmuScreen::~EmuScreen() { - std::string gameID = g_paramSFO.GetValueString("DISC_ID"); - g_Config.TimeTracker().Stop(gameID); - - // If we were invalid, it would already be shutdown. if (!invalid_ || bootPending_) { + // If we were invalid, it would already be shutdown. PSP_Shutdown(); } - g_OSD.ClearAchievementStuff(); - SetExtraAssertInfo(nullptr); #ifndef MOBILE_DEVICE if (g_Config.bDumpFrames && startDumping) { avi.Stop(); - g_OSD.Show(OSDType::MESSAGE_INFO, "AVI Dump stopped.", 2.0f); + osm.Show("AVI Dump stopped.", 1.0f); startDumping = false; } #endif @@ -445,7 +424,7 @@ EmuScreen::~EmuScreen() { void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { // TODO: improve the way with which we got commands from PauseMenu. // DR_CANCEL/DR_BACK means clicked on "continue", DR_OK means clicked on "back to menu", - // DR_YES means a message sent to PauseMenu by System_PostUIMessage. + // DR_YES means a message sent to PauseMenu by NativeMessageReceived. if (result == DR_OK || quit_) { screenManager()->switchScreen(new MainScreen()); quit_ = false; @@ -458,7 +437,7 @@ void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { static void AfterSaveStateAction(SaveState::Status status, const std::string &message, void *) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { - g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); + osm.Show(message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); } } @@ -468,36 +447,18 @@ static void AfterStateBoot(SaveState::Status status, const std::string &message, System_Notify(SystemNotification::DISASSEMBLY); } -void EmuScreen::focusChanged(ScreenFocusChange focusChange) { - Screen::focusChanged(focusChange); - - std::string gameID = g_paramSFO.GetValueString("DISC_ID"); - if (gameID.empty()) { - // startup or shutdown - return; - } - switch (focusChange) { - case ScreenFocusChange::FOCUS_LOST_TOP: - g_Config.TimeTracker().Stop(gameID); - break; - case ScreenFocusChange::FOCUS_BECAME_TOP: - g_Config.TimeTracker().Start(gameID); - break; - } -} - -void EmuScreen::sendMessage(UIMessage message, const char *value) { +void EmuScreen::sendMessage(const char *message, const char *value) { // External commands, like from the Windows UI. - if (message == UIMessage::REQUEST_GAME_PAUSE && screenManager()->topScreen() == this) { + if (!strcmp(message, "pause") && screenManager()->topScreen() == this) { screenManager()->push(new GamePauseScreen(gamePath_)); - } else if (message == UIMessage::REQUEST_GAME_STOP) { + } else if (!strcmp(message, "stop")) { // We will push MainScreen in update(). PSP_Shutdown(); bootPending_ = false; stopRender_ = true; invalid_ = true; System_Notify(SystemNotification::DISASSEMBLY); - } else if (message == UIMessage::REQUEST_GAME_RESET) { + } else if (!strcmp(message, "reset")) { PSP_Shutdown(); bootPending_ = true; invalid_ = true; @@ -510,7 +471,7 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) { screenManager()->switchScreen(new MainScreen()); return; } - } else if (message == UIMessage::REQUEST_GAME_BOOT) { + } else if (!strcmp(message, "boot")) { const char *ext = strrchr(value, '.'); if (ext != nullptr && !strcmp(ext, ".ppst")) { SaveState::Load(Path(value), -1, &AfterStateBoot); @@ -521,42 +482,41 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) { // Don't leave it on CORE_POWERDOWN, we'll sometimes aggressively bail. Core_UpdateState(CORE_POWERUP); } - } else if (message == UIMessage::CONFIG_LOADED) { + } else if (!strcmp(message, "config_loaded")) { // In case we need to position touch controls differently. RecreateViews(); - } else if (message == UIMessage::SHOW_CONTROL_MAPPING && screenManager()->topScreen() == this) { + } else if (!strcmp(message, "control mapping") && screenManager()->topScreen() == this) { UpdateUIState(UISTATE_PAUSEMENU); screenManager()->push(new ControlMappingScreen(gamePath_)); - } else if (message == UIMessage::SHOW_DISPLAY_LAYOUT_EDITOR && screenManager()->topScreen() == this) { + } else if (!strcmp(message, "display layout editor") && screenManager()->topScreen() == this) { UpdateUIState(UISTATE_PAUSEMENU); screenManager()->push(new DisplayLayoutScreen(gamePath_)); - } else if (message == UIMessage::SHOW_SETTINGS && screenManager()->topScreen() == this) { + } else if (!strcmp(message, "settings") && screenManager()->topScreen() == this) { UpdateUIState(UISTATE_PAUSEMENU); screenManager()->push(new GameSettingsScreen(gamePath_)); - } else if (message == UIMessage::REQUEST_GPU_DUMP_NEXT_FRAME) { + } else if (!strcmp(message, "gpu dump next frame")) { if (gpu) gpu->DumpNextFrame(); - } else if (message == UIMessage::REQUEST_CLEAR_JIT) { + } else if (!strcmp(message, "clear jit")) { currentMIPS->ClearJitCache(); if (PSP_IsInited()) { currentMIPS->UpdateCore((CPUCore)g_Config.iCpuCore); } - } else if (message == UIMessage::WINDOW_MINIMIZED) { + } else if (!strcmp(message, "window minimized")) { if (!strcmp(value, "true")) { gstate_c.skipDrawReason |= SKIPDRAW_WINDOW_MINIMIZED; } else { gstate_c.skipDrawReason &= ~SKIPDRAW_WINDOW_MINIMIZED; } - } else if (message == UIMessage::SHOW_CHAT_SCREEN) { + } else if (!strcmp(message, "chat screen")) { if (g_Config.bEnableNetworkChat) { if (!chatButton_) RecreateViews(); #if defined(USING_WIN_UI) - // temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable + //temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable if (g_Config.bBypassOSKWithKeyboard) { - // TODO: Make translatable. - g_OSD.Show(OSDType::MESSAGE_INFO, "Disable \"Use system native keyboard\" to use ctrl + c hotkey", 2.0f); + osm.Show("Disable windows native keyboard options to use ctrl + c hotkey", 2.0f); } else { UI::EventParams e{}; OnChatMenu.Trigger(e); @@ -566,7 +526,7 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) { OnChatMenu.Trigger(e); #endif } - } else if (message == UIMessage::APP_RESUMED && screenManager()->topScreen() == this) { + } else if (!strcmp(message, "app_resumed") && screenManager()->topScreen() == this) { if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_TV) { if (!KeyMap::IsKeyMapped(DEVICE_ID_PAD_0, VIRTKEY_PAUSE) || !KeyMap::IsKeyMapped(DEVICE_ID_PAD_1, VIRTKEY_PAUSE)) { // If it's a TV (so no built-in back button), and there's no back button mapped to a pad, @@ -575,27 +535,17 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) { screenManager()->push(new GamePauseScreen(gamePath_)); } } - } else if (message == UIMessage::REQUEST_PLAY_SOUND) { - if (g_Config.bAchievementsSoundEffects) { - // TODO: Handle this some nicer way. - if (!strcmp(value, "achievement_unlocked")) { - g_BackgroundAudio.SFX().Play(UI::UISound::ACHIEVEMENT_UNLOCKED, 0.6f); - } - if (!strcmp(value, "leaderboard_submitted")) { - g_BackgroundAudio.SFX().Play(UI::UISound::LEADERBOARD_SUBMITTED, 0.6f); - } - } } } -bool EmuScreen::UnsyncTouch(const TouchInput &touch) { - System_Notify(SystemNotification::ACTIVITY); +void EmuScreen::touch(const TouchInput &touch) { + Core_NotifyActivity(); if (chatMenu_ && chatMenu_->GetVisibility() == UI::V_VISIBLE) { // Avoid pressing touch button behind the chat if (chatMenu_->Contains(touch.x, touch.y)) { chatMenu_->Touch(touch); - return true; + return; } else if ((touch.flags & TOUCH_DOWN) != 0) { chatMenu_->Close(); if (chatButton_) @@ -605,9 +555,8 @@ bool EmuScreen::UnsyncTouch(const TouchInput &touch) { } if (root_) { - UIScreen::UnsyncTouch(touch); + root_->Touch(touch); } - return true; } void EmuScreen::onVKey(int virtualKeyCode, bool down) { @@ -631,13 +580,13 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { // Cycle through enabled speeds. if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL && g_Config.iFpsLimit1 >= 0) { PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM1; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("fixed", "Speed: alternate"), 1.0, "altspeed"); + osm.Show(sc->T("fixed", "Speed: alternate"), 1.0); } else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 && g_Config.iFpsLimit2 >= 0) { PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM2; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("SpeedCustom2", "Speed: alternate 2"), 1.0, "altspeed"); + osm.Show(sc->T("SpeedCustom2", "Speed: alternate 2"), 1.0); } else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 || PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) { PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0, "altspeed"); + osm.Show(sc->T("standard", "Speed: standard"), 1.0); } } break; @@ -646,12 +595,12 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { if (down) { if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) { PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM1; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("fixed", "Speed: alternate"), 1.0, "altspeed"); + osm.Show(sc->T("fixed", "Speed: alternate"), 1.0); } } else { if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1) { PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0, "altspeed"); + osm.Show(sc->T("standard", "Speed: standard"), 1.0); } } break; @@ -659,12 +608,12 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { if (down) { if (PSP_CoreParameter().fpsLimit == FPSLimit::NORMAL) { PSP_CoreParameter().fpsLimit = FPSLimit::CUSTOM2; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("SpeedCustom2", "Speed: alternate 2"), 1.0, "altspeed"); + osm.Show(sc->T("SpeedCustom2", "Speed: alternate 2"), 1.0); } } else { if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2) { PSP_CoreParameter().fpsLimit = FPSLimit::NORMAL; - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("standard", "Speed: standard"), 1.0, "altspeed"); + osm.Show(sc->T("standard", "Speed: standard"), 1.0); } } break; @@ -680,15 +629,13 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { break; case VIRTKEY_FRAME_ADVANCE: - if (!Achievements::WarnUserIfChallengeModeActive(false)) { - if (down) { - // If game is running, pause emulation immediately. Otherwise, advance a single frame. - if (Core_IsStepping()) { - frameStep_ = true; - Core_EnableStepping(false); - } else if (!frameStep_) { - Core_EnableStepping(true, "ui.frameAdvance", 0); - } + if (down) { + // If game is running, pause emulation immediately. Otherwise, advance a single frame. + if (Core_IsStepping()) { + frameStep_ = true; + Core_EnableStepping(false); + } else if (!frameStep_) { + Core_EnableStepping(true, "ui.frameAdvance", 0); } } break; @@ -704,7 +651,7 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { case VIRTKEY_AXIS_SWAP: if (down) { controlMapper_.ToggleSwapAxes(); - g_OSD.Show(OSDType::MESSAGE_INFO, mc->T("AxisSwap")); // best string we have. + osm.Show(mc->T("AxisSwap")); // best string we have. } break; @@ -738,34 +685,26 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { #endif case VIRTKEY_REWIND: - if (down && !Achievements::WarnUserIfChallengeModeActive(false)) { + if (down) { if (SaveState::CanRewind()) { SaveState::Rewind(&AfterSaveStateAction); } else { - g_OSD.Show(OSDType::MESSAGE_WARNING, sc->T("norewind", "No rewind save states available"), 2.0); + osm.Show(sc->T("norewind", "No rewind save states available"), 2.0); } } break; case VIRTKEY_SAVE_STATE: - if (down && !Achievements::WarnUserIfChallengeModeActive(true)) { + if (down) SaveState::SaveSlot(gamePath_, g_Config.iCurrentStateSlot, &AfterSaveStateAction); - } break; case VIRTKEY_LOAD_STATE: - if (down && !Achievements::WarnUserIfChallengeModeActive(false)) { + if (down) SaveState::LoadSlot(gamePath_, g_Config.iCurrentStateSlot, &AfterSaveStateAction); - } - break; - case VIRTKEY_PREVIOUS_SLOT: - if (down && !Achievements::WarnUserIfChallengeModeActive(true)) { - SaveState::PrevSlot(); - System_PostUIMessage(UIMessage::SAVESTATE_DISPLAY_SLOT); - } break; case VIRTKEY_NEXT_SLOT: - if (down && !Achievements::WarnUserIfChallengeModeActive(true)) { + if (down) { SaveState::NextSlot(); - System_PostUIMessage(UIMessage::SAVESTATE_DISPLAY_SLOT); + NativeMessageReceived("savestate_displayslot", ""); } break; case VIRTKEY_TOGGLE_FULLSCREEN: @@ -782,10 +721,10 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { if (down) { g_Config.bSaveNewTextures = !g_Config.bSaveNewTextures; if (g_Config.bSaveNewTextures) { - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("saveNewTextures_true", "Textures will now be saved to your storage"), 2.0); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + osm.Show(sc->T("saveNewTextures_true", "Textures will now be saved to your storage"), 2.0); + NativeMessageReceived("gpu_configChanged", ""); } else { - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("saveNewTextures_false", "Texture saving was disabled"), 2.0); + osm.Show(sc->T("saveNewTextures_false", "Texture saving was disabled"), 2.0); } } break; @@ -793,14 +732,14 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { if (down) { g_Config.bReplaceTextures = !g_Config.bReplaceTextures; if (g_Config.bReplaceTextures) - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("replaceTextures_true", "Texture replacement enabled"), 2.0); + osm.Show(sc->T("replaceTextures_true", "Texture replacement enabled"), 2.0); else - g_OSD.Show(OSDType::MESSAGE_INFO, sc->T("replaceTextures_false", "Textures no longer are being replaced"), 2.0); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + osm.Show(sc->T("replaceTextures_false", "Textures no longer are being replaced"), 2.0); + NativeMessageReceived("gpu_configChanged", ""); } break; case VIRTKEY_RAPID_FIRE: - __CtrlSetRapidFire(down, g_Config.iRapidFireInterval); + __CtrlSetRapidFire(down); break; case VIRTKEY_MUTE_TOGGLE: if (down) @@ -822,19 +761,6 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) { if (down) g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180; break; - case VIRTKEY_TOGGLE_WLAN: - if (down) { - auto n = GetI18NCategory(I18NCat::NETWORKING); - auto di = GetI18NCategory(I18NCat::DIALOG); - g_Config.bEnableWlan = !g_Config.bEnableWlan; - // Try to avoid adding more strings so we piece together a message from existing ones. - g_OSD.Show(OSDType::MESSAGE_INFO, StringFromFormat( - "%s: %s", n->T("Enable networking"), g_Config.bEnableWlan ? di->T("Enabled") : di->T("Disabled")), 2.0, "toggle_wlan"); - } - break; - case VIRTKEY_EXIT_APP: - System_ExitApp(); - break; } } @@ -870,39 +796,29 @@ void EmuScreen::onVKeyAnalog(int virtualKeyCode, float value) { limitMode = PSP_CoreParameter().analogFpsLimit == 60 ? FPSLimit::NORMAL : FPSLimit::ANALOG; } -bool EmuScreen::UnsyncKey(const KeyInput &key) { - System_Notify(SystemNotification::ACTIVITY); +bool EmuScreen::key(const KeyInput &key) { + Core_NotifyActivity(); if (UI::IsFocusMovementEnabled()) { - return UIScreen::UnsyncKey(key); + if (UIScreen::key(key)) { + return true; + } else if ((key.flags & KEY_DOWN) != 0 && UI::IsEscapeKey(key)) { + if (chatMenu_) + chatMenu_->Close(); + if (chatButton_) + chatButton_->SetVisibility(UI::V_VISIBLE); + UI::EnableFocusMovement(false); + return true; + } } return controlMapper_.Key(key, &pauseTrigger_); } -bool EmuScreen::key(const KeyInput &key) { - bool retval = UIScreen::key(key); +void EmuScreen::axis(const AxisInput &axis) { + Core_NotifyActivity(); - if (!retval && (key.flags & KEY_DOWN) != 0 && UI::IsEscapeKey(key)) { - if (chatMenu_) - chatMenu_->Close(); - if (chatButton_) - chatButton_->SetVisibility(UI::V_VISIBLE); - UI::EnableFocusMovement(false); - return true; - } - - return retval; -} - -void EmuScreen::UnsyncAxis(const AxisInput *axes, size_t count) { - System_Notify(SystemNotification::ACTIVITY); - - if (UI::IsFocusMovementEnabled()) { - return UIScreen::UnsyncAxis(axes, count); - } - - return controlMapper_.Axis(axes, count); + return controlMapper_.Axis(axis); } class GameInfoBGView : public UI::InertView { @@ -946,15 +862,15 @@ protected: // TODO: Shouldn't actually need bounds for this, Anchor can center too. static UI::AnchorLayoutParams *AnchorInCorner(const Bounds &bounds, int corner, float xOffset, float yOffset) { using namespace UI; - switch ((ScreenEdgePosition)g_Config.iChatButtonPosition) { - case ScreenEdgePosition::BOTTOM_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, NONE, NONE, yOffset, true); - case ScreenEdgePosition::BOTTOM_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), NONE, NONE, yOffset, true); - case ScreenEdgePosition::BOTTOM_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, NONE, xOffset, yOffset, true); - case ScreenEdgePosition::TOP_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, yOffset, NONE, NONE, true); - case ScreenEdgePosition::TOP_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), yOffset, NONE, NONE, true); - case ScreenEdgePosition::TOP_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, yOffset, xOffset, NONE, true); - case ScreenEdgePosition::CENTER_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, bounds.centerY(), NONE, NONE, true); - case ScreenEdgePosition::CENTER_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, bounds.centerY(), xOffset, NONE, true); + switch (g_Config.iChatButtonPosition) { + case 0: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, NONE, NONE, yOffset, true); + case 1: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), NONE, NONE, yOffset, true); + case 2: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, NONE, xOffset, yOffset, true); + case 3: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, yOffset, NONE, NONE, true); + case 4: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), yOffset, NONE, NONE, true); + case 5: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, yOffset, xOffset, NONE, true); + case 6: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, bounds.centerY(), NONE, NONE, true); + case 7: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, bounds.centerY(), xOffset, NONE, true); default: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, NONE, NONE, yOffset, true); } } @@ -1014,6 +930,7 @@ void EmuScreen::CreateViews() { saveStatePreview_->SetVisibility(V_GONE); saveStatePreview_->SetCanBeFocused(false); root_->Add(saveStatePreview_); + onScreenMessagesView_ = root_->Add(new OnScreenMessagesView(new AnchorLayoutParams((Size)bounds.w, (Size)bounds.h))); GameInfoBGView *loadingBG = root_->Add(new GameInfoBGView(gamePath_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT))); TextView *loadingTextView = root_->Add(new TextView(sc->T(PSP_GetLoading()), new AnchorLayoutParams(bounds.centerX(), NONE, NONE, 40, true))); @@ -1110,7 +1027,7 @@ UI::EventReturn EmuScreen::OnResume(UI::EventParams ¶ms) { UI::EventReturn EmuScreen::OnReset(UI::EventParams ¶ms) { if (coreState == CoreState::CORE_RUNTIME_ERROR) { - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); + NativeMessageReceived("reset", ""); } return UI::EVENT_DONE; } @@ -1119,6 +1036,7 @@ void EmuScreen::update() { using namespace UI; UIScreen::update(); + onScreenMessagesView_->SetVisibility(g_Config.bShowOnScreenMessages ? V_VISIBLE : V_GONE); resumeButton_->SetVisibility(coreState == CoreState::CORE_RUNTIME_ERROR && Memory::MemFault_MayBeResumable() ? V_VISIBLE : V_GONE); resetButton_->SetVisibility(coreState == CoreState::CORE_RUNTIME_ERROR ? V_VISIBLE : V_GONE); @@ -1134,8 +1052,6 @@ void EmuScreen::update() { } if (bootPending_) { - // Keep trying the boot until bootPending_ is lifted. - // It may be delayed due to RetroAchievements or any other cause. bootGame(gamePath_); } @@ -1169,9 +1085,7 @@ void EmuScreen::update() { if (invalid_) return; - double now = time_now_d(); - - controlMapper_.Update(now); + controlMapper_.Update(); if (pauseTrigger_) { pauseTrigger_ = false; @@ -1191,7 +1105,7 @@ void EmuScreen::update() { saveStatePreview_->SetFilename(fn); if (!fn.empty()) { saveStatePreview_->SetVisibility(UI::V_VISIBLE); - saveStatePreviewShownTime_ = now; + saveStatePreviewShownTime_ = time_now_d(); } else { saveStatePreview_->SetVisibility(UI::V_GONE); } @@ -1199,17 +1113,17 @@ void EmuScreen::update() { if (saveStatePreview_->GetVisibility() == UI::V_VISIBLE) { double endTime = saveStatePreviewShownTime_ + 2.0; - float alpha = clamp_value((endTime - now) * 4.0, 0.0, 1.0); + float alpha = clamp_value((endTime - time_now_d()) * 4.0, 0.0, 1.0); saveStatePreview_->SetColor(colorAlpha(0x00FFFFFF, alpha)); - if (now - saveStatePreviewShownTime_ > 2) { + if (time_now_d() - saveStatePreviewShownTime_ > 2) { saveStatePreview_->SetVisibility(UI::V_GONE); } } } } -bool EmuScreen::checkPowerDown() { +void EmuScreen::checkPowerDown() { if (PSP_IsRebooting()) { bootPending_ = true; invalid_ = true; @@ -1223,9 +1137,32 @@ bool EmuScreen::checkPowerDown() { screenManager()->switchScreen(new MainScreen()); bootPending_ = false; invalid_ = true; - return true; } - return false; +} + +static void DrawDebugStats(UIContext *ctx, const Bounds &bounds) { + FontID ubuntu24("UBUNTU24"); + + float left = std::max(bounds.w / 2 - 20.0f, 550.0f); + float right = bounds.w - left - 20.0f; + + char statbuf[4096]; + + ctx->Flush(); + ctx->BindFontTexture(); + ctx->Draw()->SetFontScale(.7f, .7f); + + __DisplayGetDebugStats(statbuf, sizeof(statbuf)); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, left, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, left, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); + + __SasGetDebugStats(statbuf, sizeof(statbuf)); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + left + 21, bounds.y + 31, right, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + left + 20, bounds.y + 30, right, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); + + ctx->Draw()->SetFontScale(1.0f, 1.0f); + ctx->Flush(); + ctx->RebindTexture(); } static const char *CPUCoreAsString(int core) { @@ -1233,7 +1170,6 @@ static const char *CPUCoreAsString(int core) { case 0: return "Interpreter"; case 1: return "JIT"; case 2: return "IR Interpreter"; - case 3: return "JIT Using IR"; default: return "N/A"; } } @@ -1375,6 +1311,38 @@ Invalid / Unknown (%d) ctx->RebindTexture(); } +static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) { + FontID ubuntu24("UBUNTU24"); + + char statbuf[4096] = { 0 }; + System_AudioGetDebugStats(statbuf, sizeof(statbuf)); + + ctx->Flush(); + ctx->BindFontTexture(); + ctx->Draw()->SetFontScale(0.7f, 0.7f); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); + ctx->Draw()->SetFontScale(1.0f, 1.0f); + ctx->Flush(); + ctx->RebindTexture(); +} + +static void DrawControlDebug(UIContext *ctx, const ControlMapper &mapper, const Bounds &bounds) { + FontID ubuntu24("UBUNTU24"); + + char statbuf[4096] = { 0 }; + mapper.GetDebugString(statbuf, sizeof(statbuf)); + + ctx->Flush(); + ctx->BindFontTexture(); + ctx->Draw()->SetFontScale(0.5f, 0.5f); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII); + ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); + ctx->Draw()->SetFontScale(1.0f, 1.0f); + ctx->Flush(); + ctx->RebindTexture(); +} + static void DrawFPS(UIContext *ctx, const Bounds &bounds) { FontID ubuntu24("UBUNTU24"); float vps, fps, actual_fps; @@ -1408,9 +1376,42 @@ static void DrawFPS(UIContext *ctx, const Bounds &bounds) { ctx->RebindTexture(); } +static void DrawFrameTimes(UIContext *ctx, const Bounds &bounds) { + FontID ubuntu24("UBUNTU24"); + int valid, pos; + double *sleepHistory; + double *history = __DisplayGetFrameTimes(&valid, &pos, &sleepHistory); + int scale = 7000; + int width = 600; + + ctx->Flush(); + ctx->BeginNoTex(); + int bottom = bounds.y2(); + for (int i = 0; i < valid; ++i) { + double activeTime = history[i] - sleepHistory[i]; + ctx->Draw()->vLine(bounds.x + i, bottom, bottom - activeTime * scale, 0xFF3FFF3F); + ctx->Draw()->vLine(bounds.x + i, bottom - activeTime * scale, bottom - history[i] * scale, 0x7F3FFF3F); + } + ctx->Draw()->vLine(bounds.x + pos, bottom, bottom - 512, 0xFFff3F3f); + + ctx->Draw()->hLine(bounds.x, bottom - 0.0333 * scale, bounds.x + width, 0xFF3f3Fff); + ctx->Draw()->hLine(bounds.x, bottom - 0.0167 * scale, bounds.x + width, 0xFF3f3Fff); + + ctx->Flush(); + ctx->Begin(); + ctx->BindFontTexture(); + ctx->Draw()->SetFontScale(0.5f, 0.5f); + ctx->Draw()->DrawText(ubuntu24, "33.3ms", bounds.x + width, bottom - 0.0333 * scale, 0xFF3f3Fff, ALIGN_BOTTOMLEFT | FLAG_DYNAMIC_ASCII); + ctx->Draw()->DrawText(ubuntu24, "16.7ms", bounds.x + width, bottom - 0.0167 * scale, 0xFF3f3Fff, ALIGN_BOTTOMLEFT | FLAG_DYNAMIC_ASCII); + ctx->Draw()->SetFontScale(1.0f, 1.0f); + ctx->Flush(); + ctx->RebindTexture(); +} + void EmuScreen::preRender() { using namespace Draw; DrawContext *draw = screenManager()->getDrawContext(); + draw->BeginFrame(); // Here we do NOT bind the backbuffer or clear the screen, unless non-buffered. // The emuscreen is different than the others - we really want to allow the game to render to framebuffers // before we ever bind the backbuffer for rendering. On mobile GPUs, switching back and forth between render @@ -1444,6 +1445,7 @@ void EmuScreen::postRender() { return; if (stopRender_) draw->WipeQueue(); + draw->EndFrame(); } void EmuScreen::render() { @@ -1453,12 +1455,6 @@ void EmuScreen::render() { if (!thin3d) return; // shouldn't really happen but I've seen a suspicious stack trace.. - g_OSD.NudgeSidebar(); - - if (screenManager()->topScreen() == this) { - System_Notify(SystemNotification::KEEP_SCREEN_AWAKE); - } - if (invalid_) { // Loading, or after shutdown? if (loadingTextView_->GetVisibility() == UI::V_VISIBLE) @@ -1485,58 +1481,55 @@ void EmuScreen::render() { } } - Core_UpdateDebugStats((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS || g_Config.bLogFrameDrops); + Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops); - bool blockedExecution = Achievements::IsBlockingExecution(); - bool rebind = false; - if (!blockedExecution) { - PSP_BeginHostFrame(); - PSP_RunLoopWhileState(); + PSP_BeginHostFrame(); - // Hopefully coreState is now CORE_NEXTFRAME - switch (coreState) { - case CORE_NEXTFRAME: - // Reached the end of the frame, all good. Set back to running for the next frame - coreState = CORE_RUNNING; - break; - case CORE_STEPPING: - case CORE_RUNTIME_ERROR: - { - // If there's an exception, display information. - const MIPSExceptionInfo &info = Core_GetExceptionInfo(); - if (info.type != MIPSExceptionType::NONE) { - // Clear to blue background screen - bool dangerousSettings = !Reporting::IsSupported(); - uint32_t color = dangerousSettings ? 0xFF900050 : 0xFF900000; - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, color }, "EmuScreen_RuntimeError"); - // The info is drawn later in renderUI - } else { - // If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output. - // This won't work in non-buffered, but that's fine. - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping"); - // Just to make sure. - if (PSP_IsInited()) { - gpu->CopyDisplayToOutput(true); - } + PSP_RunLoopWhileState(); + + // Hopefully coreState is now CORE_NEXTFRAME + switch (coreState) { + case CORE_NEXTFRAME: + // Reached the end of the frame, all good. Set back to running for the next frame + coreState = CORE_RUNNING; + break; + case CORE_STEPPING: + case CORE_RUNTIME_ERROR: + { + // If there's an exception, display information. + const MIPSExceptionInfo &info = Core_GetExceptionInfo(); + if (info.type != MIPSExceptionType::NONE) { + // Clear to blue background screen + bool dangerousSettings = !Reporting::IsSupported(); + uint32_t color = dangerousSettings ? 0xFF900050 : 0xFF900000; + thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, color }, "EmuScreen_RuntimeError"); + // The info is drawn later in renderUI + } else { + // If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output. + // This won't work in non-buffered, but that's fine. + thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping"); + // Just to make sure. + if (PSP_IsInited()) { + gpu->CopyDisplayToOutput(true); } - break; } - default: - // Didn't actually reach the end of the frame, ran out of the blockTicks cycles. - // In this case we need to bind and wipe the backbuffer, at least. - // It's possible we never ended up outputted anything - make sure we have the backbuffer cleared - rebind = true; - break; - } - - PSP_EndHostFrame(); + break; } + default: + // Didn't actually reach the end of the frame, ran out of the blockTicks cycles. + // In this case we need to bind and wipe the backbuffer, at least. + // It's possible we never ended up outputted anything - make sure we have the backbuffer cleared + thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame"); + break; + } + + PSP_EndHostFrame(); // This must happen after PSP_EndHostFrame so that things like push buffers are end-frame'd before we start destroying stuff. - if (checkPowerDown() || rebind) { - // Shutting down can end up ending the current render pass - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame"); - } + checkPowerDown(); + + if (invalid_) + return; if (hasVisibleUI()) { // In most cases, this should already be bound and a no-op. @@ -1557,12 +1550,12 @@ bool EmuScreen::hasVisibleUI() { // Regular but uncommon UI. if (saveStatePreview_->GetVisibility() != UI::V_GONE || loadingSpinner_->GetVisibility() == UI::V_VISIBLE) return true; - if (!g_OSD.IsEmpty() || g_Config.bShowTouchControls || g_Config.iShowStatusFlags != 0) + if (!osm.IsEmpty() || g_Config.bShowTouchControls || g_Config.iShowStatusFlags != 0) return true; if (g_Config.bEnableCardboardVR || g_Config.bEnableNetworkChat) return true; // Debug UI. - if ((DebugOverlay)g_Config.iDebugOverlay != DebugOverlay::OFF || g_Config.bShowDeveloperMenu) + if (g_Config.bShowDebugStats || g_Config.bShowDeveloperMenu || g_Config.bShowAudioDebug || g_Config.bShowFrameProfiler || g_Config.bShowControlDebug) return true; // Exception information. @@ -1597,16 +1590,40 @@ void EmuScreen::renderUI() { } if (!invalid_) { - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::CONTROL) { - DrawControlMapperOverlay(ctx, ctx->GetLayoutBounds(), controlMapper_); + if (g_Config.bShowDebugStats) { + DrawDebugStats(ctx, ctx->GetLayoutBounds()); } + + if (g_Config.bShowAudioDebug) { + DrawAudioDebugStats(ctx, ctx->GetLayoutBounds()); + } + if (g_Config.iShowStatusFlags) { DrawFPS(ctx, ctx->GetLayoutBounds()); } + + if (g_Config.bDrawFrameGraph) { + DrawFrameTimes(ctx, ctx->GetLayoutBounds()); + } + + if (g_Config.bShowControlDebug) { + DrawControlDebug(ctx, controlMapper_, ctx->GetLayoutBounds()); + } } +#if !PPSSPP_PLATFORM(UWP) && !PPSSPP_PLATFORM(SWITCH) + if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && g_Config.bShowAllocatorDebug) { + DrawAllocatorVis(ctx, gpu); + } + + if ((g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) && g_Config.bShowGpuProfile) { + DrawGPUProfilerVis(ctx, gpu); + } + +#endif + #ifdef USE_PROFILER - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::FRAME_PROFILE && !invalid_) { + if (g_Config.bShowFrameProfiler && !invalid_) { DrawProfile(*ctx); } #endif diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 9c9e922af..a7ee1c23a 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -32,6 +32,7 @@ struct AxisInput; class AsyncImageFileView; +class OnScreenMessagesView; class ChatMenu; class EmuScreen : public UIScreen { @@ -46,21 +47,12 @@ public: void preRender() override; void postRender() override; void dialogFinished(const Screen *dialog, DialogResult result) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *msg, const char *value) override; void resized() override; - // Note: Unlike your average boring UIScreen, here we override the Unsync* functions - // to get minimal latency and full control. We forward to UIScreen when needed. - bool UnsyncTouch(const TouchInput &touch) override; - bool UnsyncKey(const KeyInput &key) override; - void UnsyncAxis(const AxisInput *axes, size_t count) override; - - // We also need to do some special handling of queued UI events to handle closing the chat window. + void touch(const TouchInput &touch) override; bool key(const KeyInput &key) override; - -protected: - - void focusChanged(ScreenFocusChange focusChange) override; + void axis(const AxisInput &axis) override; private: void CreateViews() override; @@ -80,7 +72,7 @@ private: void onVKeyAnalog(int virtualKeyCode, float value); void autoLoad(); - bool checkPowerDown(); + void checkPowerDown(); UI::Event OnDevMenu; UI::Event OnChatMenu; @@ -119,6 +111,7 @@ private: ChatMenu *chatMenu_ = nullptr; UI::Button *cardboardDisableButton_ = nullptr; + OnScreenMessagesView *onScreenMessagesView_ = nullptr; ControlMapper controlMapper_; }; diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 2733dd8a2..bdecb6412 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -111,7 +111,7 @@ bool GameInfo::Delete() { } } -u64 GameInfo::GetGameSizeOnDiskInBytes() { +u64 GameInfo::GetGameSizeInBytes() { switch (fileType) { case IdentifiedFileType::PSP_PBP_DIRECTORY: case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: @@ -122,26 +122,6 @@ u64 GameInfo::GetGameSizeOnDiskInBytes() { } } -u64 GameInfo::GetGameSizeUncompressedInBytes() { - switch (fileType) { - case IdentifiedFileType::PSP_PBP_DIRECTORY: - case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: - return File::ComputeRecursiveDirectorySize(ResolvePBPDirectory(filePath_)); - - default: - { - BlockDevice *blockDevice = constructBlockDevice(GetFileLoader().get()); - if (blockDevice) { - u64 size = blockDevice->GetUncompressedSize(); - delete blockDevice; - return size; - } else { - return GetFileLoader()->FileSize(); - } - } - } -} - // Not too meaningful if the object itself is a savedata directory... std::vector GameInfo::GetSaveDataDirectories() { Path memc = GetSysDirectory(DIRECTORY_SAVEDATA); @@ -618,11 +598,14 @@ handleELF: info_->ParseParamSFO(); if (info_->wantFlags & GAMEINFO_WANTBG) { - info_->pic0.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, nullptr); - info_->pic1.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, nullptr); + ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, nullptr); + info_->pic0.dataLoaded = true; + ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, nullptr); + info_->pic1.dataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTSND) { - info_->sndDataLoaded = ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, nullptr); + ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, nullptr); + info_->pic1.dataLoaded = true; } } @@ -632,16 +615,15 @@ handleELF: Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png"); // Try using png/jpg screenshots first if (File::Exists(screenshot_png)) - info_->icon.dataLoaded = File::ReadFileToString(false, screenshot_png, info_->icon.data); + File::ReadFileToString(false, screenshot_png, info_->icon.data); else if (File::Exists(screenshot_jpg)) - info_->icon.dataLoaded = File::ReadFileToString(false, screenshot_jpg, info_->icon.data); + File::ReadFileToString(false, screenshot_jpg, info_->icon.data); else { DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found"); - info_->icon.dataLoaded = ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock); + ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock); } - } else { - info_->icon.dataLoaded = true; } + info_->icon.dataLoaded = true; break; } @@ -679,13 +661,10 @@ handleELF: if (info_->wantFlags & GAMEINFO_WANTSIZE) { std::lock_guard lock(info_->lock); - info_->gameSizeOnDisk = info_->GetGameSizeOnDiskInBytes(); + info_->gameSize = info_->GetGameSizeInBytes(); info_->saveDataSize = info_->GetSaveDataSizeInBytes(); info_->installDataSize = info_->GetInstallDataSizeInBytes(); } - if (info_->wantFlags & GAMEINFO_WANTUNCOMPRESSEDSIZE) { - info_->gameSizeUncompressed = info_->GetGameSizeUncompressedInBytes(); - } // INFO_LOG(SYSTEM, "Completed writing info for %s", info_->GetTitle().c_str()); } @@ -820,7 +799,7 @@ void GameInfoCache::SetupTexture(std::shared_ptr &info, Draw::DrawCont if (tex.texture) { tex.timeLoaded = time_now_d(); } else { - ERROR_LOG(G3D, "Failed creating texture (%s) from %d-byte file", info->GetTitle().c_str(), (int)tex.data.size()); + ERROR_LOG(G3D, "Failed creating texture (%s)", info->GetTitle().c_str()); } } if ((info->wantFlags & GAMEINFO_WANTBGDATA) == 0) { diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 6ec6b0ddf..6c8d6c40d 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -56,7 +56,6 @@ enum GameInfoWantFlags { GAMEINFO_WANTSIZE = 0x02, GAMEINFO_WANTSND = 0x04, GAMEINFO_WANTBGDATA = 0x08, // Use with WANTBG. - GAMEINFO_WANTUNCOMPRESSEDSIZE = 0x10, }; class FileLoader; @@ -95,8 +94,7 @@ public: std::shared_ptr GetFileLoader(); void DisposeFileLoader(); - u64 GetGameSizeUncompressedInBytes(); // NOTE: More expensive than GetGameSizeOnDiskInBytes(). - u64 GetGameSizeOnDiskInBytes(); + u64 GetGameSizeInBytes(); u64 GetSaveDataSizeInBytes(); u64 GetInstallDataSizeInBytes(); @@ -146,8 +144,7 @@ public: double lastAccessedTime = 0.0; - u64 gameSizeUncompressed = 0; - u64 gameSizeOnDisk = 0; // compressed size, in case of CSO + u64 gameSize = 0; u64 saveDataSize = 0; u64 installDataSize = 0; diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 238c8de13..5460dd5ae 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -25,7 +25,6 @@ #include "Common/UI/ViewGroup.h" #include "Common/Data/Text/I18n.h" -#include "Common/Data/Text/Parsers.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" @@ -36,8 +35,6 @@ #include "Core/Reporting.h" #include "Core/System.h" #include "Core/Loaders.h" -#include "Core/Util/GameDB.h" -#include "UI/OnScreenDisplay.h" #include "UI/CwCheatScreen.h" #include "UI/EmuScreen.h" #include "UI/GameScreen.h" @@ -108,51 +105,35 @@ void GameScreen::CreateViews() { leftColumn->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle(this, &GameScreen::OnSwitchBack); if (info) { - ViewGroup *badgeHolder = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(10, 10, 110, NONE)); - LinearLayout *mainGameInfo = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)); - mainGameInfo->SetSpacing(3.0f); - - // Need an explicit size here because homebrew uses screenshots as icons. - badgeHolder->Add(new GameIconView(gamePath_, 2.0f, new LinearLayoutParams(144 * 2, 80 * 2, UI::Margins(0)))); - badgeHolder->Add(mainGameInfo); - - leftColumn->Add(badgeHolder); + leftColumn->Add(new GameIconView(gamePath_, 2.0f, new AnchorLayoutParams(144 * 2, 80 * 2, 10, 10, NONE, NONE))); LinearLayout *infoLayout = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(10, 200, NONE, NONE)); leftColumn->Add(infoLayout); - // TODO: Add non-translated title here if available in gameDB. - tvTitle_ = mainGameInfo->Add(new TextView(info->GetTitle(), ALIGN_LEFT | FLAG_WRAP_TEXT, false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + tvTitle_ = infoLayout->Add(new TextView(info->GetTitle(), ALIGN_LEFT | FLAG_WRAP_TEXT, false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); tvTitle_->SetShadow(true); - tvID_ = mainGameInfo->Add(new TextView("", ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + tvID_ = infoLayout->Add(new TextView("", ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); tvID_->SetShadow(true); - tvRegion_ = mainGameInfo->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - tvRegion_->SetShadow(true); - tvGameSize_ = mainGameInfo->Add(new TextView("...", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - tvGameSize_->SetShadow(true); - // This one doesn't need to be updated. infoLayout->Add(new TextView(gamePath_.ToVisualString(), ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetShadow(true); + tvGameSize_ = infoLayout->Add(new TextView("...", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + tvGameSize_->SetShadow(true); tvSaveDataSize_ = infoLayout->Add(new TextView("...", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); tvSaveDataSize_->SetShadow(true); tvInstallDataSize_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); tvInstallDataSize_->SetShadow(true); tvInstallDataSize_->SetVisibility(V_GONE); - tvPlayTime_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - tvPlayTime_->SetShadow(true); - tvPlayTime_->SetVisibility(V_GONE); + tvRegion_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + tvRegion_->SetShadow(true); tvCRC_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); tvCRC_->SetShadow(true); tvCRC_->SetVisibility(Reporting::HasCRC(gamePath_) ? V_VISIBLE : V_GONE); - tvVerified_ = infoLayout->Add(new NoticeView(NoticeLevel::INFO, ga->T("Click \"Calculate CRC\" to verify ISO"), "", new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - tvVerified_->SetVisibility(UI::V_GONE); } else { tvTitle_ = nullptr; tvGameSize_ = nullptr; tvSaveDataSize_ = nullptr; tvInstallDataSize_ = nullptr; tvRegion_ = nullptr; - tvPlayTime_ = nullptr; tvCRC_ = nullptr; tvID_ = nullptr; } @@ -185,13 +166,7 @@ void GameScreen::CreateViews() { rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Delete Game"))))->OnClick.Handle(this, &GameScreen::OnDeleteGame); if (System_GetPropertyBool(SYSPROP_CAN_CREATE_SHORTCUT)) { - rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Create Shortcut"))))->OnClick.Add([=](UI::EventParams &e) { - std::shared_ptr info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); - if (info) { - System_CreateGameShortcut(gamePath_, info->GetTitle()); - } - return UI::EVENT_DONE; - }); + rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Create Shortcut"))))->OnClick.Handle(this, &GameScreen::OnCreateShortcut); } if (isRecentGame(gamePath_)) { rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Remove From Recent"))))->OnClick.Handle(this, &GameScreen::OnRemoveFromRecent); @@ -222,8 +197,8 @@ void GameScreen::CreateViews() { } } - isHomebrew_ = info && info->region > GAMEREGION_MAX; - if (fileTypeSupportCRC && !isHomebrew_ && !Reporting::HasCRC(gamePath_) ) { + bool isHomebrew = info && info->region > GAMEREGION_MAX; + if (fileTypeSupportCRC && !isHomebrew && !Reporting::HasCRC(gamePath_) ) { btnCalcCRC_ = rightColumnItems->Add(new ChoiceWithValueDisplay(&CRC32string, ga->T("Calculate CRC"), I18NCat::NONE)); btnCalcCRC_->OnClick.Handle(this, &GameScreen::OnDoCRC32); } else { @@ -281,24 +256,20 @@ void GameScreen::render() { Draw::DrawContext *thin3d = screenManager()->getDrawContext(); - std::shared_ptr info = g_gameInfoCache->GetInfo(thin3d, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE | GAMEINFO_WANTUNCOMPRESSEDSIZE); + std::shared_ptr info = g_gameInfoCache->GetInfo(thin3d, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (tvTitle_) { tvTitle_->SetText(info->GetTitle()); } - if (info->gameSizeOnDisk) { + if (info->gameSize) { char temp[256]; if (tvGameSize_) { - snprintf(temp, sizeof(temp), "%s: %s", ga->T("Game"), NiceSizeFormat(info->gameSizeOnDisk).c_str()); - if (info->gameSizeUncompressed != info->gameSizeOnDisk) { - size_t len = strlen(temp); - snprintf(temp + len, sizeof(temp) - len, " (%s: %s)", ga->T("Uncompressed"), NiceSizeFormat(info->gameSizeUncompressed).c_str()); - } + snprintf(temp, sizeof(temp), "%s: %1.1f %s", ga->T("Game"), (float)(info->gameSize) / 1024.f / 1024.f, ga->T("MB")); tvGameSize_->SetText(temp); } if (tvSaveDataSize_) { - snprintf(temp, sizeof(temp), "%s: %s", ga->T("SaveData"), NiceSizeFormat(info->saveDataSize).c_str()); + snprintf(temp, sizeof(temp), "%s: %1.2f %s", ga->T("SaveData"), (float)(info->saveDataSize) / 1024.f / 1024.f, ga->T("MB")); tvSaveDataSize_->SetText(temp); } if (info->installDataSize > 0 && tvInstallDataSize_) { @@ -324,71 +295,11 @@ void GameScreen::render() { } } - if (tvPlayTime_) { - std::string str; - if (g_Config.TimeTracker().GetPlayedTimeString(info->id, &str)) { - tvPlayTime_->SetText(str); - tvPlayTime_->SetVisibility(UI::V_VISIBLE); - } - } - if (tvCRC_ && Reporting::HasCRC(gamePath_)) { auto rp = GetI18NCategory(I18NCat::REPORTING); - uint32_t crcVal = Reporting::RetrieveCRC(gamePath_); - std::string crc = StringFromFormat("%08X", crcVal); + std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_)); tvCRC_->SetText(ReplaceAll(rp->T("FeedbackCRCValue", "Disc CRC: %1"), "%1", crc)); tvCRC_->SetVisibility(UI::V_VISIBLE); - - // Let's check the CRC in the game database, looking up the ID and also matching the crc. - std::vector dbInfos; - if (tvVerified_ && g_gameDB.GetGameInfos(info->id_version, &dbInfos)) { - bool found = false; - for (auto &dbInfo : dbInfos) { - if (dbInfo.crc == crcVal) { - found = true; - } - } - if (found) { - tvVerified_->SetText(ga->T("ISO OK according to the Redump project")); - tvVerified_->SetLevel(NoticeLevel::SUCCESS); - tvVerified_->SetVisibility(UI::V_VISIBLE); - } else { - // Like the other messages below, disabled until we have a database we have confidence in. - // tvVerified_->SetText(ga->T("CRC checksum does not match, bad or modified ISO")); - // tvVerified_->SetLevel(NoticeLevel::ERROR); - } - } else { - // tvVerified_->SetText(ga->T("Game ID unknown - not in the Redump database")); - // tvVerified_->SetVisibility(UI::V_VISIBLE); - // tvVerified_->SetLevel(NoticeLevel::WARN); - } - } else if (!isHomebrew_) { - GameDBInfo dbInfo; - if (tvVerified_) { - std::vector dbInfos; - if (!g_gameDB.GetGameInfos(info->id_version, &dbInfos)) { - // tvVerified_->SetText(ga->T("Game ID unknown - not in the ReDump database")); - // tvVerified_->SetVisibility(UI::V_VISIBLE); - // tvVerified_->SetLevel(NoticeLevel::WARN); - } else if (info->gameSizeUncompressed != 0) { // don't do this check if info still pending - bool found = false; - for (auto &dbInfo : dbInfos) { - // TODO: Doesn't take CSO/CHD into account. - if (info->gameSizeUncompressed == dbInfo.size) { - found = true; - } - } - if (!found) { - // tvVerified_->SetText(ga->T("File size incorrect, bad or modified ISO")); - // tvVerified_->SetVisibility(UI::V_VISIBLE); - // tvVerified_->SetLevel(NoticeLevel::ERROR); - } else { - tvVerified_->SetText(ga->T("Click \"Calculate CRC\" to verify ISO")); - tvVerified_->SetVisibility(UI::V_VISIBLE); - tvVerified_->SetLevel(NoticeLevel::INFO); - } - } - } } if (tvID_) { @@ -417,7 +328,7 @@ void GameScreen::render() { } UI::EventReturn GameScreen::OnShowInFolder(UI::EventParams &e) { - System_ShowFileInFolder(gamePath_); + System_ShowFileInFolder(gamePath_.c_str()); return UI::EVENT_DONE; } @@ -503,6 +414,14 @@ void GameScreen::CallbackDeleteGame(bool yes) { } } +UI::EventReturn GameScreen::OnCreateShortcut(UI::EventParams &e) { + std::shared_ptr info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); + if (info) { + System_CreateGameShortcut(gamePath_, info->GetTitle()); + } + return UI::EVENT_DONE; +} + bool GameScreen::isRecentGame(const Path &gamePath) { if (g_Config.iMaxRecent <= 0) return false; diff --git a/UI/GameScreen.h b/UI/GameScreen.h index 52c8907ea..cff0c4836 100644 --- a/UI/GameScreen.h +++ b/UI/GameScreen.h @@ -23,8 +23,6 @@ #include "Common/UI/UIScreen.h" #include "Common/File/Path.h" -class NoticeView; - // Game screen: Allows you to start a game, delete saves, delete the game, // set game specific settings, etc. @@ -58,6 +56,7 @@ private: UI::EventReturn OnDeleteSaveData(UI::EventParams &e); UI::EventReturn OnDeleteGame(UI::EventParams &e); UI::EventReturn OnSwitchBack(UI::EventParams &e); + UI::EventReturn OnCreateShortcut(UI::EventParams &e); UI::EventReturn OnRemoveFromRecent(UI::EventParams &e); UI::EventReturn OnShowInFolder(UI::EventParams &e); UI::EventReturn OnCreateConfig(UI::EventParams &e); @@ -72,10 +71,8 @@ private: UI::TextView *tvSaveDataSize_ = nullptr; UI::TextView *tvInstallDataSize_ = nullptr; UI::TextView *tvRegion_ = nullptr; - UI::TextView *tvPlayTime_ = nullptr; UI::TextView *tvCRC_ = nullptr; UI::TextView *tvID_ = nullptr; - NoticeView *tvVerified_ = nullptr; UI::Choice *btnGameSettings_ = nullptr; UI::Choice *btnCreateGameConfig_ = nullptr; @@ -88,6 +85,4 @@ private: std::vector otherChoices_; std::vector saveDirs; std::string CRC32string; - - bool isHomebrew_ = false; }; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index a56191a77..ab15e6137 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -31,7 +31,6 @@ #include "Common/System/Display.h" // Only to check screen aspect ratio with pixel_yres/pixel_xres #include "Common/System/Request.h" -#include "Common/System/OSD.h" #include "Common/Battery/Battery.h" #include "Common/System/NativeApp.h" #include "Common/Data/Color/RGBAUtil.h" @@ -54,7 +53,6 @@ #include "UI/GPUDriverTestScreen.h" #include "UI/MemStickScreen.h" #include "UI/Theme.h" -#include "UI/RetroAchievementScreens.h" #include "Common/File/FileUtil.h" #include "Common/File/AndroidContentURI.h" @@ -97,7 +95,7 @@ extern AndroidAudioState *g_audioState; #endif GameSettingsScreen::GameSettingsScreen(const Path &gamePath, std::string gameID, bool editThenRestore) - : TabbedUIDialogScreenWithGameBackground(gamePath), gameID_(gameID), editThenRestore_(editThenRestore) { + : UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), editThenRestore_(editThenRestore) { prevInflightFrames_ = g_Config.iInflightFrames; analogSpeedMapped_ = KeyMap::InputMappingsFromPspButton(VIRTKEY_SPEED_ANALOG, nullptr, true); } @@ -193,7 +191,7 @@ static std::string PostShaderTranslateName(const char *value) { } } -void GameSettingsScreen::PreCreateViews() { +void GameSettingsScreen::CreateViews() { ReloadAllPostShaderInfo(screenManager()->getDrawContext()); ReloadAllThemeInfo(); @@ -205,11 +203,49 @@ void GameSettingsScreen::PreCreateViews() { iAlternateSpeedPercent1_ = g_Config.iFpsLimit1 < 0 ? -1 : (g_Config.iFpsLimit1 * 100) / 60; iAlternateSpeedPercent2_ = g_Config.iFpsLimit2 < 0 ? -1 : (g_Config.iFpsLimit2 * 100) / 60; iAlternateSpeedPercentAnalog_ = (g_Config.iAnalogFpsLimit * 100) / 60; -} -void GameSettingsScreen::CreateTabs() { + bool vertical = UseVerticalLayout(); + + // Information in the top left. + // Back button to the bottom left. + // Scrolling action menu to the right. using namespace UI; + auto ms = GetI18NCategory(I18NCat::MAINSETTINGS); + auto di = GetI18NCategory(I18NCat::DIALOG); + + root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); + + if (vertical) { + LinearLayout *verticalLayout = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); + tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, new LinearLayoutParams(1.0f)); + verticalLayout->Add(tabHolder_); + verticalLayout->Add(new Choice(di->T("Back"), "", false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0))))->OnClick.Handle(this, &UIScreen::OnBack); + root_->Add(verticalLayout); + } else { + tabHolder_ = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false)); + root_->Add(tabHolder_); + AddStandardBack(root_); + } + tabHolder_->SetTag("GameSettings"); + root_->SetDefaultFocusView(tabHolder_); + settingTabContents_.clear(); + settingTabFilterNotices_.clear(); + + float leftSide = 40.0f; + if (!vertical) { + leftSide += 200.0f; + } + settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams( + g_display.dp_xres - leftSide - 40.0f, WRAP_CONTENT, + leftSide, g_display.dp_yres - 80.0f - 40.0f, NONE, NONE)); + settingInfo_->SetBottomCutoff(g_display.dp_yres - 200.0f); + root_->Add(settingInfo_); + + // Show it again if we recreated the view + if (!oldSettingInfo_.empty()) { + settingInfo_->Show(oldSettingInfo_, nullptr); + } LinearLayout *graphicsSettings = AddTab("GameSettingsGraphics", ms->T("Graphics")); CreateGraphicsSettings(graphicsSettings); @@ -235,6 +271,27 @@ void GameSettingsScreen::CreateTabs() { LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR")); CreateVRSettings(vrSettings); } + +#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID) + // Hide search if screen is too small. + if ((g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) && (deviceType != DEVICE_TYPE_VR)) { + auto se = GetI18NCategory(I18NCat::SEARCH); + // Search + LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true); + + searchSettings->Add(new ItemHeader(se->T("Find settings"))); + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) { + searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), I18NCat::NONE))->OnClick.Handle(this, &GameSettingsScreen::OnChangeSearchFilter); + } else { + searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &GameSettingsScreen::OnChangeSearchFilter); + } + clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter"))); + clearSearchChoice_->OnClick.Handle(this, &GameSettingsScreen::OnClearSearchFilter); + noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5)))); + + ApplySearchFilter(); + } +#endif } // Graphics @@ -298,7 +355,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) static const char *msaaModes[] = { "Off", "2x", "4x", "8x", "16x" }; auto msaaChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iMultiSampleLevel, gr->T("Antialiasing (MSAA)"), msaaModes, 0, ARRAY_SIZE(msaaModes), I18NCat::GRAPHICS, screenManager())); msaaChoice->OnChoice.Add([&](UI::EventParams &) -> UI::EventReturn { - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_renderResized", ""); return UI::EVENT_DONE; }); msaaChoice->SetDisabledPtr(&g_Config.bSoftwareRendering); @@ -319,10 +376,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) max_res_temp = 4; // At least allow 2x int max_res = std::min(max_res_temp, (int)ARRAY_SIZE(deviceResolutions)); UI::PopupMultiChoice *hwscale = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iAndroidHwScale, gr->T("Display Resolution (HW scaler)"), deviceResolutions, 0, max_res, I18NCat::GRAPHICS, screenManager())); - hwscale->OnChoice.Add([](UI::EventParams &) { - System_RecreateActivity(); - return UI::EVENT_DONE; - }); + hwscale->OnChoice.Handle(this, &GameSettingsScreen::OnHwScaleChange); // To refresh the display mode } #endif @@ -338,14 +392,13 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) } #endif - // All backends support FIFO. Check if any immediate modes are supported, if so we can allow the user to choose. - if (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::IMMEDIATE | Draw::PresentMode::MAILBOX)) { +#if !(PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS)) CheckBox *vSync = graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync"))); vSync->OnClick.Add([=](EventParams &e) { NativeResized(); return UI::EVENT_CONTINUE; }); - } +#endif #if PPSSPP_PLATFORM(ANDROID) // Hide Immersive Mode on pre-kitkat Android @@ -393,7 +446,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) settingInfo_->Show(gr->T("RenderingMode NonBuffered Tip", "Faster, but graphics may be missing in some games"), e.v); g_Config.bAutoFrameSkip = false; } - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_renderResized", ""); return UI::EVENT_DONE; }); skipBufferEffects->SetDisabledPtr(&g_Config.bSoftwareRendering); @@ -401,6 +454,15 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) CheckBox *skipGPUReadbacks = graphicsSettings->Add(new CheckBox(&g_Config.bSkipGPUReadbacks, gr->T("Skip GPU Readbacks"))); skipGPUReadbacks->SetDisabledPtr(&g_Config.bSoftwareRendering); + CheckBox *vtxCache = graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gr->T("Vertex Cache"))); + vtxCache->OnClick.Add([=](EventParams &e) { + settingInfo_->Show(gr->T("VertexCache Tip", "Faster, but may cause temporary flicker"), e.v); + return UI::EVENT_CONTINUE; + }); + vtxCache->SetEnabledFunc([] { + return !g_Config.bSoftwareRendering && g_Config.bHardwareTransform && g_Config.iGPUBackend != (int)GPUBackend::OPENGL; + }); + CheckBox *texBackoff = graphicsSettings->Add(new CheckBox(&g_Config.bTextureBackoffCache, gr->T("Lazy texture caching", "Lazy texture caching (speedup)"))); texBackoff->SetDisabledPtr(&g_Config.bSoftwareRendering); texBackoff->OnClick.Add([=](EventParams& e) { @@ -427,7 +489,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) return !g_Config.bSkipBufferEffects && g_Config.iFrameSkip == 0; }); - if (draw->GetDeviceCaps().setMaxFrameLatencySupported) { + if (GetGPUBackend() == GPUBackend::VULKAN || GetGPUBackend() == GPUBackend::OPENGL) { static const char *bufferOptions[] = { "No buffer", "Up to 1", "Up to 2" }; PopupMultiChoice *inflightChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iInflightFrames, gr->T("Buffer graphics commands (faster, input lag)"), bufferOptions, 1, ARRAY_SIZE(bufferOptions), I18NCat::GRAPHICS, screenManager())); inflightChoice->OnChoice.Handle(this, &GameSettingsScreen::OnInflightFramesChoice); @@ -557,7 +619,8 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) #ifdef CAN_DISPLAY_CURRENT_BATTERY_CAPACITY BitCheckBox *showBattery = graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::BATTERY_PERCENT, gr->T("Show Battery %"))); #endif - AddOverlayList(graphicsSettings, screenManager()); + + graphicsSettings->Add(new CheckBox(&g_Config.bShowDebugStats, gr->T("Show Debug Statistics")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting); } void GameSettingsScreen::CreateAudioSettings(UI::ViewGroup *audioSettings) { @@ -636,17 +699,15 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping); controlsSettings->Add(new Choice(co->T("Calibrate Analog Stick")))->OnClick.Handle(this, &GameSettingsScreen::OnCalibrateAnalogs); -#if defined(USING_WIN_UI) || (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)) - controlsSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys"))); -#endif #if defined(USING_WIN_UI) + controlsSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys"))); controlsSettings->Add(new CheckBox(&g_Config.bGamepadOnlyFocused, co->T("Ignore gamepads when not focused"))); #endif - if (System_GetPropertyBool(SYSPROP_HAS_ACCELEROMETER)) { + if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { Choice *customizeTilt = controlsSettings->Add(new Choice(co->T("Tilt control setup"))); customizeTilt->OnClick.Handle(this, &GameSettingsScreen::OnTiltCustomize); - } else if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_VR) { // TODO: This seems like a regression + } else if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_VR) { controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); } @@ -681,10 +742,6 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) CheckBox *hideStickBackground = controlsSettings->Add(new CheckBox(&g_Config.bHideStickBackground, co->T("Hide touch analog stick background circle"))); hideStickBackground->SetEnabledPtr(&g_Config.bShowTouchControls); - // Sticky D-pad. - CheckBox *stickyDpad = controlsSettings->Add(new CheckBox(&g_Config.bStickyTouchDPad, co->T("Sticky D-Pad (easier sweeping movements)"))); - stickyDpad->SetEnabledPtr(&g_Config.bShowTouchControls); - // Re-centers itself to the touch location on touch-down. CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls); @@ -721,7 +778,6 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) settingInfo_->Show(co->T("AnalogLimiter Tip", "When the analog limiter button is pressed"), e.v); return UI::EVENT_CONTINUE; }); - controlsSettings->Add(new PopupSliderChoice(&g_Config.iRapidFireInterval, 1, 10, 5, co->T("Rapid fire interval"), screenManager(), "frames")); #if defined(USING_WIN_UI) || defined(SDL) controlsSettings->Add(new ItemHeader(co->T("Mouse", "Mouse settings"))); CheckBox *mouseControl = controlsSettings->Add(new CheckBox(&g_Config.bMouseControl, co->T("Use Mouse Control"))); @@ -737,53 +793,6 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) } } -// Compound view just like the audio file choosers -class MacAddressChooser : public UI::LinearLayout { -public: - MacAddressChooser(Path gamePath, std::string *value, const std::string &title, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr); -}; - -static constexpr UI::Size ITEM_HEIGHT = 64.f; - -MacAddressChooser::MacAddressChooser(Path gamePath_, std::string *value, const std::string &title, ScreenManager *screenManager, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_HORIZONTAL, layoutParams) { - using namespace UI; - SetSpacing(5.0f); - if (!layoutParams) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = ITEM_HEIGHT; - } - auto n = GetI18NCategory(I18NCat::NETWORKING); - - std::string initialValue = *value; - Add(new PopupTextInputChoice(value, title, g_Config.sMACAddress, 17, screenManager, new LinearLayoutParams(1.0f)))->OnChange.Add([=](UI::EventParams &e) { - // Validate the chosen address, and restore to initialValue if bad. - if (g_Config.sMACAddress.size() != 17) { - // TODO: Alert the user - *value = initialValue; - } - return UI::EVENT_DONE; - }); - Add(new Choice(n->T("Randomize"), new LinearLayoutParams(WRAP_CONTENT, ITEM_HEIGHT)))->OnClick.Add([=](UI::EventParams &) { - auto n = GetI18NCategory(I18NCat::NETWORKING); - auto di = GetI18NCategory(I18NCat::DIALOG); - - const char *confirmMessage = n->T("ChangeMacSaveConfirm", "Generate a new MAC address?"); - const char *warningMessage = n->T("ChangeMacSaveWarning", "Some games verify the MAC address when loading savedata, so this may break old saves."); - std::string combined = g_Config.sMACAddress + "\n\n" + std::string(confirmMessage) + "\n\n" + warningMessage; - - auto confirmScreen = new PromptScreen( - gamePath_, - combined, di->T("Yes"), di->T("No"), - [&](bool success) { - if (success) { - g_Config.sMACAddress = CreateRandMAC(); - }} - ); - screenManager->push(confirmScreen); - return UI::EVENT_DONE; - }); -} - void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSettings) { using namespace UI; @@ -795,7 +804,7 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti networkingSettings->Add(new Choice(n->T("Open PPSSPP Multiplayer Wiki Page")))->OnClick.Handle(this, &GameSettingsScreen::OnAdhocGuides); networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)"))); - networkingSettings->Add(new MacAddressChooser(gamePath_, &g_Config.sMACAddress, n->T("Change Mac Address"), screenManager())); + networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sMACAddress, n->T("Change Mac Address"), I18NCat::NONE))->OnClick.Handle(this, &GameSettingsScreen::OnChangeMacAddress); static const char* wlanChannels[] = { "Auto", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11" }; auto wlanChannelChoice = networkingSettings->Add(new PopupMultiChoice(&g_Config.iWlanAdhocChannel, n->T("WLAN Channel"), wlanChannels, 0, ARRAY_SIZE(wlanChannels), I18NCat::NETWORKING, screenManager())); for (int i = 0; i < 4; i++) { @@ -821,9 +830,9 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti networkingSettings->Add(new ItemHeader(n->T("Chat"))); networkingSettings->Add(new CheckBox(&g_Config.bEnableNetworkChat, n->T("Enable network chat", "Enable network chat"))); static const char *chatButtonPositions[] = { "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right", "None" }; - networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatButtonPosition, n->T("Chat Button Position"), chatButtonPositions, 0, ARRAY_SIZE(chatButtonPositions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); + networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatButtonPosition, n->T("Chat Button Position"), chatButtonPositions, 0, ARRAY_SIZE(chatButtonPositions), I18NCat::NETWORKING, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); static const char *chatScreenPositions[] = { "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right" }; - networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatScreenPosition, n->T("Chat Screen Position"), chatScreenPositions, 0, ARRAY_SIZE(chatScreenPositions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); + networkingSettings->Add(new PopupMultiChoice(&g_Config.iChatScreenPosition, n->T("Chat Screen Position"), chatScreenPositions, 0, ARRAY_SIZE(chatScreenPositions), I18NCat::NETWORKING, screenManager()))->SetEnabledPtr(&g_Config.bEnableNetworkChat); #if (!defined(MOBILE_DEVICE) && !defined(USING_QT_UI)) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) // Missing only iOS? networkingSettings->Add(new ItemHeader(n->T("QuickChat", "Quick Chat"))); @@ -885,30 +894,11 @@ void GameSettingsScreen::CreateToolsSettings(UI::ViewGroup *tools) { auto ri = GetI18NCategory(I18NCat::REMOTEISO); tools->Add(new ItemHeader(ms->T("Tools"))); - - auto retro = tools->Add(new Choice(sy->T("RetroAchievements"))); - retro->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { - screenManager()->push(new RetroAchievementsSettingsScreen(gamePath_)); - return UI::EVENT_DONE; - }); - retro->SetIcon(ImageID("I_RETROACHIEVEMENTS_LOGO")); // These were moved here so use the wrong translation objects, to avoid having to change all inis... This isn't a sustainable situation :P - tools->Add(new Choice(sa->T("Savedata Manager")))->OnClick.Add([=](UI::EventParams &) { - screenManager()->push(new SavedataScreen(gamePath_)); - return UI::EVENT_DONE; - }); - tools->Add(new Choice(dev->T("System Information")))->OnClick.Add([=](UI::EventParams &) { - screenManager()->push(new SystemInfoScreen(gamePath_)); - return UI::EVENT_DONE; - }); - tools->Add(new Choice(sy->T("Developer Tools")))->OnClick.Add([=](UI::EventParams &) { - screenManager()->push(new DeveloperToolsScreen(gamePath_)); - return UI::EVENT_DONE; - }); - tools->Add(new Choice(ri->T("Remote disc streaming")))->OnClick.Add([=](UI::EventParams &) { - screenManager()->push(new RemoteISOScreen(gamePath_)); - return UI::EVENT_DONE; - }); + tools->Add(new Choice(sa->T("Savedata Manager")))->OnClick.Handle(this, &GameSettingsScreen::OnSavedataManager); + tools->Add(new Choice(dev->T("System Information")))->OnClick.Handle(this, &GameSettingsScreen::OnSysInfo); + tools->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &GameSettingsScreen::OnDeveloperTools); + tools->Add(new Choice(ri->T("Remote disc streaming")))->OnClick.Handle(this, &GameSettingsScreen::OnRemoteISO); } void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { @@ -918,7 +908,6 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { auto di = GetI18NCategory(I18NCat::DIALOG); auto vr = GetI18NCategory(I18NCat::VR); auto th = GetI18NCategory(I18NCat::THEMES); - auto psps = GetI18NCategory(I18NCat::PSPSETTINGS); // TODO: Should move more into this section. systemSettings->Add(new ItemHeader(sy->T("UI"))); @@ -987,7 +976,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { if (System_GetPropertyBool(SYSPROP_HAS_OPEN_DIRECTORY)) { systemSettings->Add(new Choice(sy->T("Show Memory Stick folder")))->OnClick.Add([](UI::EventParams &p) { - System_ShowFileInFolder(g_Config.memStickDirectory); + System_ShowFileInFolder(File::ResolvePath(g_Config.memStickDirectory.ToString()).c_str()); return UI::EVENT_DONE; }); } @@ -1013,13 +1002,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { systemSettings->Add(new InfoItem(sy->T("USB"), usbPath))->SetChoiceStyle(true); } } -#elif defined(_WIN32) -#if PPSSPP_PLATFORM(UWP) - memstickDisplay_ = g_Config.memStickDirectory.ToVisualString(); - auto memstickPath = systemSettings->Add(new ChoiceWithValueDisplay(&memstickDisplay_, sy->T("Memory Stick folder", "Memory Stick folder"), I18NCat::NONE)); - memstickPath->SetEnabled(!PSP_IsInited()); - memstickPath->OnClick.Handle(this, &GameSettingsScreen::OnChangeMemStickDir); -#else +#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP) SavePathInMyDocumentChoice = systemSettings->Add(new CheckBox(&installed_, sy->T("Save path in My Documents", "Save path in My Documents"))); SavePathInMyDocumentChoice->SetEnabled(!PSP_IsInited()); SavePathInMyDocumentChoice->OnClick.Handle(this, &GameSettingsScreen::OnSavePathMydoc); @@ -1062,7 +1045,6 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { SavePathInMyDocumentChoice->SetEnabled(false); } } -#endif #endif systemSettings->Add(new CheckBox(&g_Config.bMemStickInserted, sy->T("Memory Stick inserted"))); UI::PopupSliderChoice *sizeChoice = systemSettings->Add(new PopupSliderChoice(&g_Config.iMemStickSizeGB, 1, 32, 16, sy->T("Memory Stick size", "Memory Stick size"), screenManager(), "GB")); @@ -1081,7 +1063,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting); systemSettings->Add(new CheckBox(&g_Config.bIgnoreBadMemAccess, sy->T("Ignore bad memory accesses"))); - static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays", "Simulate UMD slow reading speed"}; + static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays" }; View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("IO timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), I18NCat::SYSTEM, screenManager())); systemSettings->Add(new CheckBox(&g_Config.bForceLagSync, sy->T("Force real clock sync (slower, less lag)")))->SetDisabledPtr(&g_Config.bAutoFrameSkip); PopupSliderChoice *lockedMhz = systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, 0, sy->T("Change CPU Clock", "Change CPU Clock (unstable)"), screenManager(), sy->T("MHz, 0:default"))); @@ -1128,13 +1110,19 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { }); systemSettings->Add(new ItemHeader(sy->T("PSP Settings"))); - - // The ordering here is simply mapping directly to PSP_SYSTEMPARAM_LANGUAGE_*. - static const char *defaultLanguages[] = { "Auto", "Japanese", "English", "French", "Spanish", "German", "Italian", "Dutch", "Portuguese", "Russian", "Korean", "Chinese (traditional)", "Chinese (simplified)" }; - systemSettings->Add(new PopupMultiChoice(&g_Config.iLanguage, psps->T("Game language"), defaultLanguages, -1, ARRAY_SIZE(defaultLanguages), I18NCat::PSPSETTINGS, screenManager())); static const char *models[] = { "PSP-1000", "PSP-2000/3000" }; systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), I18NCat::SYSTEM, screenManager()))->SetEnabled(!PSP_IsInited()); + // TODO: Come up with a way to display a keyboard for mobile users, + // so until then, this is Windows/Desktop only. +#if !defined(MOBILE_DEVICE) // TODO: Add all platforms where KEY_CHAR support is added systemSettings->Add(new PopupTextInputChoice(&g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager())); +#elif PPSSPP_PLATFORM(ANDROID) + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) + systemSettings->Add(new ChoiceWithValueDisplay(&g_Config.sNickName, sy->T("Change Nickname"), I18NCat::NONE))->OnClick.Handle(this, &GameSettingsScreen::OnChangeNickname); + else + systemSettings->Add(new PopupTextInputChoice(&g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager())); +#endif + systemSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, sy->T("Screenshots as PNG"))); #if defined(_WIN32) || (defined(USING_QT_UI) && !defined(MOBILE_DEVICE)) @@ -1160,16 +1148,14 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new ItemHeader(vr->T("Virtual reality"))); vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality"))); - vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement"))); + CheckBox *vr6DoF = vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement"))); + vr6DoF->SetEnabledPtr(&g_Config.bEnableVR); vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)"))); vrSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update"))); - if (IsPassthroughSupported()) { - vrSettings->Add(new CheckBox(&g_Config.bPassthrough, vr->T("Enable passthrough"))); - } vrSettings->Add(new ItemHeader(vr->T("VR camera"))); vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, 12.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), "")); - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvas3DDistance, 1.0f, 15.0f, 3.0f, vr->T("Distance to 3D scenes when VR disabled"), 1.0f, screenManager(), "")); + vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, 100.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV"))); vrSettings->Add(new CheckBox(&g_Config.bRescaleHUD, vr->T("Heads-up display detection"))); PopupSliderChoiceFloat* vrHudScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, 0.3f, vr->T("Heads-up display scale"), 0.1f, screenManager(), "")); vrHudScale->SetEnabledPtr(&g_Config.bRescaleHUD); @@ -1188,6 +1174,29 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new PopupMultiChoice(&g_Config.iCameraPitch, vr->T("Camera type"), cameraPitchModes, 0, 3, I18NCat::NONE, screenManager())); } +UI::LinearLayout *GameSettingsScreen::AddTab(const char *tag, const std::string &title, bool isSearch) { + auto se = GetI18NCategory(I18NCat::SEARCH); + + using namespace UI; + ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + scroll->SetTag(tag); + + LinearLayout *contents = new LinearLayoutList(ORIENT_VERTICAL); + contents->SetSpacing(0); + scroll->Add(contents); + tabHolder_->AddTab(title, scroll); + + if (!isSearch) { + settingTabContents_.push_back(contents); + + auto notice = contents->Add(new TextView(se->T("Filtering settings by '%1'"), new LinearLayoutParams(Margins(20, 5)))); + notice->SetVisibility(V_GONE); + settingTabFilterNotices_.push_back(notice); + } + + return contents; +} + UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) { g_Config.UpdateAfterSettingAutoFrameSkip(); return UI::EVENT_DONE; @@ -1221,7 +1230,7 @@ UI::EventReturn GameSettingsScreen::OnSustainedPerformanceModeChange(UI::EventPa } UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) { - System_PostUIMessage(UIMessage::REQUEST_CLEAR_JIT); + NativeMessageReceived("clear jit", ""); return UI::EVENT_DONE; } @@ -1304,21 +1313,20 @@ UI::EventReturn GameSettingsScreen::OnChangeBackground(UI::EventParams &e) { File::Delete(bgPng); File::Delete(bgJpg); UIBackgroundShutdown(); - RecreateViews(); } else { auto sy = GetI18NCategory(I18NCat::SYSTEM); - System_BrowseForImage(sy->T("Set UI background..."), [=](const std::string &value, int) { + System_BrowseForImage(sy->T("Set UI background..."), [](const std::string &value, int) { if (!value.empty()) { Path dest = GetSysDirectory(DIRECTORY_SYSTEM) / (endsWithNoCase(value, ".jpg") ? "background.jpg" : "background.png"); File::Copy(Path(value), dest); } // It will init again automatically. We can't init outside a frame on Vulkan. UIBackgroundShutdown(); - RecreateViews(); }); } // Change to a browse or clear button. + RecreateViews(); return UI::EVENT_DONE; } @@ -1338,7 +1346,12 @@ UI::EventReturn GameSettingsScreen::OnResolutionChange(UI::EventParams &e) { System_RecreateActivity(); } Reporting::UpdateConfig(); - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_renderResized", ""); + return UI::EVENT_DONE; +} + +UI::EventReturn GameSettingsScreen::OnHwScaleChange(UI::EventParams &e) { + System_RecreateActivity(); return UI::EVENT_DONE; } @@ -1362,7 +1375,55 @@ void GameSettingsScreen::onFinish(DialogResult result) { // Wipe some caches after potentially changing settings. // Let's not send resize messages here, handled elsewhere. - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); +} + +void GameSettingsScreen::sendMessage(const char *message, const char *value) { + UIDialogScreenWithGameBackground::sendMessage(message, value); + if (!strcmp(message, "gameSettings_search")) { + std::string filter = value ? value : ""; + searchFilter_.resize(filter.size()); + std::transform(filter.begin(), filter.end(), searchFilter_.begin(), tolower); + + ApplySearchFilter(); + } +} + +void GameSettingsScreen::ApplySearchFilter() { + auto se = GetI18NCategory(I18NCat::SEARCH); + + bool matches = searchFilter_.empty(); + for (int t = 0; t < (int)settingTabContents_.size(); ++t) { + auto tabContents = settingTabContents_[t]; + bool tabMatches = searchFilter_.empty(); + + // Show an indicator that a filter is applied. + settingTabFilterNotices_[t]->SetVisibility(tabMatches ? UI::V_GONE : UI::V_VISIBLE); + settingTabFilterNotices_[t]->SetText(ReplaceAll(se->T("Filtering settings by '%1'"), "%1", searchFilter_)); + + UI::View *lastHeading = nullptr; + for (int i = 1; i < tabContents->GetNumSubviews(); ++i) { + UI::View *v = tabContents->GetViewByIndex(i); + if (!v->CanBeFocused()) { + lastHeading = v; + } + + std::string label = v->DescribeText(); + std::transform(label.begin(), label.end(), label.begin(), tolower); + bool match = v->CanBeFocused() && label.find(searchFilter_) != label.npos; + tabMatches = tabMatches || match; + + if (match && lastHeading) + lastHeading->SetVisibility(UI::V_VISIBLE); + v->SetVisibility(searchFilter_.empty() || match ? UI::V_VISIBLE : UI::V_GONE); + } + tabHolder_->EnableTab(t, tabMatches); + matches = matches || tabMatches; + } + + noSearchResults_->SetText(ReplaceAll(se->T("No settings matched '%1'"), "%1", searchFilter_)); + noSearchResults_->SetVisibility(matches ? UI::V_GONE : UI::V_VISIBLE); + clearSearchChoice_->SetVisibility(searchFilter_.empty() ? UI::V_GONE : UI::V_VISIBLE); } void GameSettingsScreen::dialogFinished(const Screen *dialog, DialogResult result) { @@ -1381,6 +1442,11 @@ void GameSettingsScreen::dialogFinished(const Screen *dialog, DialogResult resul } } +void GameSettingsScreen::RecreateViews() { + oldSettingInfo_ = settingInfo_ ? settingInfo_->GetText() : "N/A"; + UIScreen::RecreateViews(); +} + void GameSettingsScreen::CallbackMemstickFolder(bool yes) { auto sy = GetI18NCategory(I18NCat::SYSTEM); @@ -1425,18 +1491,45 @@ void GameSettingsScreen::TriggerRestart(const char *why) { System_RestartApp(param); } +void GameSettingsScreen::CallbackRenderingBackend(bool yes) { + // If the user ends up deciding not to restart, set the config back to the current backend + // so it doesn't get switched by accident. + if (yes) { + TriggerRestart("GameSettingsScreen::RenderingBackendYes"); + } else { + g_Config.iGPUBackend = (int)GetGPUBackend(); + } +} + +void GameSettingsScreen::CallbackRenderingDevice(bool yes) { + // If the user ends up deciding not to restart, set the config back to the current backend + // so it doesn't get switched by accident. + if (yes) { + TriggerRestart("GameSettingsScreen::RenderingDeviceYes"); + } else { + std::string *deviceNameSetting = GPUDeviceNameSetting(); + if (deviceNameSetting) + *deviceNameSetting = GetGPUBackendDevice(); + // Needed to redraw the setting. + RecreateViews(); + } +} + +void GameSettingsScreen::CallbackInflightFrames(bool yes) { + if (yes) { + TriggerRestart("GameSettingsScreen::InflightFramesYes"); + } else { + g_Config.iInflightFrames = prevInflightFrames_; + } +} + UI::EventReturn GameSettingsScreen::OnRenderingBackend(UI::EventParams &e) { auto di = GetI18NCategory(I18NCat::DIALOG); // It only makes sense to show the restart prompt if the backend was actually changed. if (g_Config.iGPUBackend != (int)GetGPUBackend()) { - screenManager()->push(new PromptScreen(gamePath_, di->T("Changing this setting requires PPSSPP to restart."), di->T("Restart"), di->T("Cancel"), [=](bool yes) { - if (yes) { - TriggerRestart("GameSettingsScreen::RenderingBackendYes"); - } else { - g_Config.iGPUBackend = (int)GetGPUBackend(); - } - })); + screenManager()->push(new PromptScreen(gamePath_, di->T("ChangingGPUBackends", "Changing GPU backends requires PPSSPP to restart. Restart now?"), di->T("Yes"), di->T("No"), + std::bind(&GameSettingsScreen::CallbackRenderingBackend, this, std::placeholders::_1))); } return UI::EVENT_DONE; } @@ -1447,19 +1540,8 @@ UI::EventReturn GameSettingsScreen::OnRenderingDevice(UI::EventParams &e) { // It only makes sense to show the restart prompt if the device was actually changed. std::string *deviceNameSetting = GPUDeviceNameSetting(); if (deviceNameSetting && *deviceNameSetting != GetGPUBackendDevice()) { - screenManager()->push(new PromptScreen(gamePath_, di->T("Changing this setting requires PPSSPP to restart."), di->T("Restart"), di->T("Cancel"), [=](bool yes) { - // If the user ends up deciding not to restart, set the config back to the current backend - // so it doesn't get switched by accident. - if (yes) { - TriggerRestart("GameSettingsScreen::RenderingDeviceYes"); - } else { - std::string *deviceNameSetting = GPUDeviceNameSetting(); - if (deviceNameSetting) - *deviceNameSetting = GetGPUBackendDevice(); - // Needed to redraw the setting. - RecreateViews(); - } - })); + screenManager()->push(new PromptScreen(gamePath_, di->T("ChangingGPUBackends", "Changing GPU backends requires PPSSPP to restart. Restart now?"), di->T("Yes"), di->T("No"), + std::bind(&GameSettingsScreen::CallbackRenderingDevice, this, std::placeholders::_1))); } return UI::EVENT_DONE; } @@ -1467,13 +1549,8 @@ UI::EventReturn GameSettingsScreen::OnRenderingDevice(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnInflightFramesChoice(UI::EventParams &e) { auto di = GetI18NCategory(I18NCat::DIALOG); if (g_Config.iInflightFrames != prevInflightFrames_) { - screenManager()->push(new PromptScreen(gamePath_, di->T("Changing this setting requires PPSSPP to restart."), di->T("Restart"), di->T("Cancel"), [=](bool yes) { - if (yes) { - TriggerRestart("GameSettingsScreen::InflightFramesYes"); - } else { - g_Config.iInflightFrames = prevInflightFrames_; - } - })); + screenManager()->push(new PromptScreen(gamePath_, di->T("ChangingInflightFrames", "Changing graphics command buffering requires PPSSPP to restart. Restart now?"), di->T("Yes"), di->T("No"), + std::bind(&GameSettingsScreen::CallbackInflightFrames, this, std::placeholders::_1))); } return UI::EVENT_DONE; } @@ -1498,7 +1575,7 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](const std::string &value, int) { g_Config.sQuickChat0 = value; @@ -1508,7 +1585,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](const std::string &value, int) { g_Config.sQuickChat1 = value; @@ -1518,7 +1595,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](const std::string &value, int) { g_Config.sQuickChat2 = value; @@ -1528,7 +1605,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](const std::string &value, int) { g_Config.sQuickChat3 = value; @@ -1538,7 +1615,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](const std::string &value, int) { g_Config.sQuickChat4 = value; @@ -1548,7 +1625,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) { -#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(n->T("Enter a new PSP nickname"), g_Config.sNickName, [](const std::string &value, int) { g_Config.sNickName = StripSpaces(value); @@ -1565,6 +1642,27 @@ UI::EventReturn GameSettingsScreen::OnChangeproAdhocServerAddress(UI::EventParam return UI::EVENT_DONE; } +UI::EventReturn GameSettingsScreen::OnChangeMacAddress(UI::EventParams &e) { + auto n = GetI18NCategory(I18NCat::NETWORKING); + auto di = GetI18NCategory(I18NCat::DIALOG); + + const char *confirmMessage = n->T("ChangeMacSaveConfirm", "Generate a new MAC address?"); + const char *warningMessage = n->T("ChangeMacSaveWarning", "Some games verify the MAC address when loading savedata, so this may break old saves."); + std::string combined = std::string(confirmMessage) + "\n\n" + warningMessage; + + auto confirmScreen = new PromptScreen( + gamePath_, + combined, di->T("Yes"), di->T("No"), + [&](bool success) { + if (success) { + g_Config.sMACAddress = CreateRandMAC(); + }} + ); + screenManager()->push(confirmScreen); + + return UI::EVENT_DONE; +} + UI::EventReturn GameSettingsScreen::OnTextureShader(UI::EventParams &e) { auto gr = GetI18NCategory(I18NCat::GRAPHICS); auto shaderScreen = new TextureShaderScreen(gr->T("Texture Shader")); @@ -1576,12 +1674,22 @@ UI::EventReturn GameSettingsScreen::OnTextureShader(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnTextureShaderChange(UI::EventParams &e) { - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); RecreateViews(); // Update setting name g_Config.bTexHardwareScaling = g_Config.sTextureShaderName != "Off"; return UI::EVENT_DONE; } +UI::EventReturn GameSettingsScreen::OnDeveloperTools(UI::EventParams &e) { + screenManager()->push(new DeveloperToolsScreen(gamePath_)); + return UI::EVENT_DONE; +} + +UI::EventReturn GameSettingsScreen::OnRemoteISO(UI::EventParams &e) { + screenManager()->push(new RemoteISOScreen(gamePath_)); + return UI::EVENT_DONE; +} + UI::EventReturn GameSettingsScreen::OnControlMapping(UI::EventParams &e) { screenManager()->push(new ControlMappingScreen(gamePath_)); return UI::EVENT_DONE; @@ -1602,6 +1710,35 @@ UI::EventReturn GameSettingsScreen::OnTiltCustomize(UI::EventParams &e) { return UI::EVENT_DONE; }; +UI::EventReturn GameSettingsScreen::OnSavedataManager(UI::EventParams &e) { + auto saveData = new SavedataScreen(gamePath_); + screenManager()->push(saveData); + return UI::EVENT_DONE; +} + +UI::EventReturn GameSettingsScreen::OnSysInfo(UI::EventParams &e) { + screenManager()->push(new SystemInfoScreen(gamePath_)); + return UI::EVENT_DONE; +} + +UI::EventReturn GameSettingsScreen::OnChangeSearchFilter(UI::EventParams &e) { +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) + auto se = GetI18NCategory(I18NCat::SEARCH); + System_InputBoxGetString(se->T("Search term"), searchFilter_, [](const std::string &value, int) { + NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str()); + }); +#else + if (!System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) + NativeMessageReceived("gameSettings_search", StripSpaces(searchFilter_).c_str()); +#endif + return UI::EVENT_DONE; +} + +UI::EventReturn GameSettingsScreen::OnClearSearchFilter(UI::EventParams &e) { + NativeMessageReceived("gameSettings_search", ""); + return UI::EVENT_DONE; +} + void DeveloperToolsScreen::CreateViews() { using namespace UI; root_ = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); @@ -1620,33 +1757,13 @@ void DeveloperToolsScreen::CreateViews() { LinearLayout *list = settingsScroll->Add(new LinearLayoutList(ORIENT_VERTICAL, new LinearLayoutParams(1.0f))); list->SetSpacing(0); - - list->Add(new ItemHeader(dev->T("Texture Replacement"))); - list->Add(new CheckBox(&g_Config.bSaveNewTextures, dev->T("Save new textures"))); - list->Add(new CheckBox(&g_Config.bReplaceTextures, dev->T("Replace textures"))); - - Choice *createTextureIni = list->Add(new Choice(dev->T("Create/Open textures.ini file for current game"))); - createTextureIni->OnClick.Handle(this, &DeveloperToolsScreen::OnOpenTexturesIniFile); - createTextureIni->SetEnabledFunc([&] { - if (!PSP_IsInited()) - return false; - - // Disable the choice to Open/Create if the textures.ini file already exists, and we can't open it due to platform support limitations. - if (!System_GetPropertyBool(SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR)) { - if (hasTexturesIni_ == HasIni::MAYBE) - hasTexturesIni_ = TextureReplacer::IniExists(g_paramSFO.GetDiscID()) ? HasIni::YES : HasIni::NO; - return hasTexturesIni_ != HasIni::YES; - } - return true; - }); - list->Add(new ItemHeader(sy->T("General"))); bool canUseJit = true; // iOS can now use JIT on all modes, apparently. // The bool may come in handy for future non-jit platforms though (UWP XB1?) - static const char *cpuCores[] = {"Interpreter", "Dynarec (JIT)", "IR Interpreter", "JIT Using IR"}; + static const char *cpuCores[] = {"Interpreter", "Dynarec (JIT)", "IR Interpreter"}; PopupMultiChoice *core = list->Add(new PopupMultiChoice(&g_Config.iCpuCore, gr->T("CPU Core"), cpuCores, 0, ARRAY_SIZE(cpuCores), I18NCat::SYSTEM, screenManager())); core->OnChoice.Handle(this, &DeveloperToolsScreen::OnJitAffectingSetting); core->OnChoice.Add([](UI::EventParams &) { @@ -1655,12 +1772,7 @@ void DeveloperToolsScreen::CreateViews() { }); if (!canUseJit) { core->HideChoice(1); - core->HideChoice(3); } - // TODO: Enable on more architectures. -#if !PPSSPP_ARCH(X86) && !PPSSPP_ARCH(AMD64) && !PPSSPP_ARCH(ARM64) - core->HideChoice(3); -#endif list->Add(new Choice(dev->T("JIT debug tools")))->OnClick.Handle(this, &DeveloperToolsScreen::OnJitDebugTools); list->Add(new CheckBox(&g_Config.bShowDeveloperMenu, dev->T("Show Developer Menu"))); @@ -1672,17 +1784,6 @@ void DeveloperToolsScreen::CreateViews() { cpuTests->SetEnabled(TestsAvailable()); #endif - - AddOverlayList(list, screenManager()); - - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - list->Add(new CheckBox(&g_Config.bRenderMultiThreading, dev->T("Multi-threaded rendering"), ""))->OnClick.Add([](UI::EventParams &e) { - // TODO: Not translating yet. Will combine with other translations of settings that need restart. - g_OSD.Show(OSDType::MESSAGE_WARNING, "Restart required"); - return UI::EVENT_DONE; - }); - } - // For now, we only implement GPU driver tests for Vulkan and OpenGL. This is simply // because the D3D drivers are generally solid enough to not need this type of investigation. if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { @@ -1705,27 +1806,27 @@ void DeveloperToolsScreen::CreateViews() { if (GetGPUBackend() == GPUBackend::VULKAN) { list->Add(new CheckBox(&g_Config.bGpuLogProfiler, dev->T("GPU log profiler"))); } + list->Add(new ItemHeader(dev->T("Texture Replacement"))); + list->Add(new CheckBox(&g_Config.bSaveNewTextures, dev->T("Save new textures"))); + list->Add(new CheckBox(&g_Config.bReplaceTextures, dev->T("Replace textures"))); - static const char *ffModes[] = { "Render all frames", "", "Frame Skipping" }; - PopupMultiChoice *ffMode = list->Add(new PopupMultiChoice(&g_Config.iFastForwardMode, dev->T("Fast-forward mode"), ffModes, 0, ARRAY_SIZE(ffModes), I18NCat::GRAPHICS, screenManager())); - ffMode->SetEnabledFunc([]() { return !g_Config.bVSync; }); - ffMode->HideChoice(1); // not used + Choice *createTextureIni = list->Add(new Choice(dev->T("Create/Open textures.ini file for current game"))); + createTextureIni->OnClick.Handle(this, &DeveloperToolsScreen::OnOpenTexturesIniFile); + createTextureIni->SetEnabledFunc([&] { + if (!PSP_IsInited()) + return false; + + // Disable the choice to Open/Create if the textures.ini file already exists, and we can't open it due to platform support limitations. + if (!System_GetPropertyBool(SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR)) { + if (hasTexturesIni_ == HasIni::MAYBE) + hasTexturesIni_ = TextureReplacer::IniExists(g_paramSFO.GetDiscID()) ? HasIni::YES : HasIni::NO; + return hasTexturesIni_ != HasIni::YES; + } + return true; + }); Draw::DrawContext *draw = screenManager()->getDrawContext(); - list->Add(new ItemHeader(dev->T("Ubershaders"))); - if (draw->GetShaderLanguageDesc().bitwiseOps && !draw->GetBugs().Has(Draw::Bugs::UNIFORM_INDEXING_BROKEN)) { - // If the above if fails, the checkbox is redundant since it'll be force disabled anyway. - list->Add(new CheckBox(&g_Config.bUberShaderVertex, dev->T("Vertex"))); - } -#if !PPSSPP_PLATFORM(UWP) - if (g_Config.iGPUBackend != (int)GPUBackend::OPENGL || gl_extensions.GLES3) { -#else - { -#endif - list->Add(new CheckBox(&g_Config.bUberShaderFragment, dev->T("Fragment"))); - } - // Experimental, will move to main graphics settings later. bool multiViewSupported = draw->GetDeviceCaps().multiViewSupported; @@ -1733,7 +1834,7 @@ void DeveloperToolsScreen::CreateViews() { return g_Config.bStereoRendering && multiViewSupported; }; - if (multiViewSupported) { + if (draw->GetDeviceCaps().multiViewSupported) { list->Add(new ItemHeader(gr->T("Stereo rendering"))); list->Add(new CheckBox(&g_Config.bStereoRendering, gr->T("Stereo rendering"))); std::vector stereoShaderNames; @@ -1780,7 +1881,7 @@ void DeveloperToolsScreen::CreateViews() { void DeveloperToolsScreen::onFinish(DialogResult result) { g_Config.Save("DeveloperToolsScreen::onFinish"); - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } void GameSettingsScreen::CallbackRestoreDefaults(bool yes) { @@ -1861,7 +1962,7 @@ UI::EventReturn DeveloperToolsScreen::OnTouchscreenTest(UI::EventParams &e) { } UI::EventReturn DeveloperToolsScreen::OnJitAffectingSetting(UI::EventParams &e) { - System_PostUIMessage(UIMessage::REQUEST_CLEAR_JIT); + NativeMessageReceived("clear jit", ""); return UI::EVENT_DONE; } @@ -1890,7 +1991,7 @@ UI::EventReturn DeveloperToolsScreen::OnRemoteDebugger(UI::EventParams &e) { } // Persist the setting. Maybe should separate? g_Config.bRemoteDebuggerOnStartup = allowDebugger_; - return UI::EVENT_DONE; + return UI::EVENT_CONTINUE; } void DeveloperToolsScreen::update() { @@ -1928,9 +2029,10 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) { buttonsRow1->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT))); buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_LEFT))); - if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { +#if PPSSPP_PLATFORM(ANDROID) + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) buttonsRow2->Add(new Button(di->T("Edit")))->OnClick.Handle(this, &HostnameSelectScreen::OnEditClick); - } +#endif buttonsRow2->Add(new Button(di->T("Delete")))->OnClick.Handle(this, &HostnameSelectScreen::OnDeleteClick); buttonsRow2->Add(new Button(di->T("Delete all")))->OnClick.Handle(this, &HostnameSelectScreen::OnDeleteAllClick); buttonsRow2->Add(new Button(di->T("Toggle List")))->OnClick.Handle(this, &HostnameSelectScreen::OnShowIPListClick); @@ -1961,7 +2063,7 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) { progressView_->SetVisibility(UI::V_GONE); } -void HostnameSelectScreen::SendEditKey(InputKeyCode keyCode, int flags) { +void HostnameSelectScreen::SendEditKey(int keyCode, int flags) { auto oldView = UI::GetFocusedView(); UI::SetFocusedView(addrView_); KeyInput fakeKey{ DEVICE_ID_KEYBOARD, keyCode, KEY_DOWN | flags }; @@ -1972,13 +2074,13 @@ void HostnameSelectScreen::SendEditKey(InputKeyCode keyCode, int flags) { UI::EventReturn HostnameSelectScreen::OnNumberClick(UI::EventParams &e) { std::string text = e.v ? e.v->Tag() : ""; if (text.length() == 1 && text[0] >= '0' && text[0] <= '9') { - SendEditKey((InputKeyCode)text[0], KEY_CHAR); // ASCII for digits match keycodes. + SendEditKey(text[0], KEY_CHAR); } return UI::EVENT_DONE; } UI::EventReturn HostnameSelectScreen::OnPointClick(UI::EventParams &e) { - SendEditKey((InputKeyCode)'.', KEY_CHAR); + SendEditKey('.', KEY_CHAR); return UI::EVENT_DONE; } @@ -1994,9 +2096,11 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) { UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) { auto n = GetI18NCategory(I18NCat::NETWORKING); +#if PPSSPP_PLATFORM(ANDROID) System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) { addrView_->SetText(value); }); +#endif return UI::EVENT_DONE; } @@ -2137,10 +2241,6 @@ void GestureMappingScreen::CreateViews() { vert->Add(new ItemHeader(co->T("Double tap"))); vert->Add(new PopupMultiChoice(&g_Config.iDoubleTapGesture, mc->T("Double tap button"), gestureButton, 0, ARRAY_SIZE(gestureButton), I18NCat::MAPPABLECONTROLS, screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled); - - vert->Add(new ItemHeader(co->T("Analog Stick"))); - vert->Add(new CheckBox(&g_Config.bAnalogGesture, co->T("Enable analog stick gesture"))); - vert->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogGestureSensibility, 0.01f, 5.0f, 1.0f, co->T("Sensitivity"), 0.01f, screenManager(), "x"))->SetEnabledPtr(&g_Config.bAnalogGesture); } RestoreSettingsScreen::RestoreSettingsScreen(const char *title) diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index 4c83715cf..882b60263 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -25,11 +25,10 @@ #include "Common/UI/UIScreen.h" #include "Core/ConfigValues.h" #include "UI/MiscScreens.h" -#include "UI/TabbedDialogScreen.h" // Per-game settings screen - enables you to configure graphic options, control options, etc // per game. -class GameSettingsScreen : public TabbedUIDialogScreenWithGameBackground { +class GameSettingsScreen : public UIDialogScreenWithGameBackground { public: GameSettingsScreen(const Path &gamePath, std::string gameID = "", bool editThenRestore = false); @@ -37,15 +36,17 @@ public: const char *tag() const override { return "GameSettings"; } protected: + void sendMessage(const char *message, const char *value) override; + void CreateViews() override; void CallbackRestoreDefaults(bool yes); + void CallbackRenderingBackend(bool yes); + void CallbackRenderingDevice(bool yes); + void CallbackInflightFrames(bool yes); void CallbackMemstickFolder(bool yes); void dialogFinished(const Screen *dialog, DialogResult result) override; - - void CreateTabs() override; + void RecreateViews() override; private: - void PreCreateViews() override; - void CreateGraphicsSettings(UI::ViewGroup *graphicsSettings); void CreateControlsSettings(UI::ViewGroup *tools); void CreateAudioSettings(UI::ViewGroup *audioSettings); @@ -54,6 +55,8 @@ private: void CreateSystemSettings(UI::ViewGroup *systemSettings); void CreateVRSettings(UI::ViewGroup *vrSettings); + UI::LinearLayout *AddTab(const char *tag, const std::string &title, bool isSearch = false); + void ApplySearchFilter(); void TriggerRestart(const char *why); std::string gameID_; @@ -63,6 +66,9 @@ private: UI::Choice *backgroundChoice_ = nullptr; UI::PopupMultiChoice *resolutionChoice_ = nullptr; UI::CheckBox *frameSkipAuto_ = nullptr; + SettingInfoMessage *settingInfo_ = nullptr; + UI::Choice *clearSearchChoice_ = nullptr; + UI::TextView *noSearchResults_ = nullptr; #ifdef _WIN32 UI::CheckBox *SavePathInMyDocumentChoice = nullptr; UI::CheckBox *SavePathInOtherChoice = nullptr; @@ -73,16 +79,23 @@ private: std::string memstickDisplay_; + UI::TabHolder *tabHolder_ = nullptr; + std::vector settingTabContents_; + std::vector settingTabFilterNotices_; + // Event handlers UI::EventReturn OnControlMapping(UI::EventParams &e); UI::EventReturn OnCalibrateAnalogs(UI::EventParams &e); UI::EventReturn OnTouchControlLayout(UI::EventParams &e); + UI::EventReturn OnTiltTypeChange(UI::EventParams &e); UI::EventReturn OnTiltCustomize(UI::EventParams &e); // Global settings handlers UI::EventReturn OnAutoFrameskip(UI::EventParams &e); UI::EventReturn OnTextureShader(UI::EventParams &e); UI::EventReturn OnTextureShaderChange(UI::EventParams &e); + UI::EventReturn OnDeveloperTools(UI::EventParams &e); + UI::EventReturn OnRemoteISO(UI::EventParams &e); UI::EventReturn OnChangeQuickChat0(UI::EventParams &e); UI::EventReturn OnChangeQuickChat1(UI::EventParams &e); UI::EventReturn OnChangeQuickChat2(UI::EventParams &e); @@ -90,11 +103,14 @@ private: UI::EventReturn OnChangeQuickChat4(UI::EventParams &e); UI::EventReturn OnChangeNickname(UI::EventParams &e); UI::EventReturn OnChangeproAdhocServerAddress(UI::EventParams &e); + UI::EventReturn OnChangeMacAddress(UI::EventParams &e); UI::EventReturn OnChangeBackground(UI::EventParams &e); UI::EventReturn OnFullscreenChange(UI::EventParams &e); UI::EventReturn OnFullscreenMultiChange(UI::EventParams &e); UI::EventReturn OnResolutionChange(UI::EventParams &e); + UI::EventReturn OnHwScaleChange(UI::EventParams &e); UI::EventReturn OnRestoreDefaultSettings(UI::EventParams &e); + UI::EventReturn OnRenderingMode(UI::EventParams &e); UI::EventReturn OnRenderingBackend(UI::EventParams &e); UI::EventReturn OnRenderingDevice(UI::EventParams &e); UI::EventReturn OnInflightFramesChoice(UI::EventParams &e); @@ -113,6 +129,11 @@ private: UI::EventReturn OnAdhocGuides(UI::EventParams &e); + UI::EventReturn OnSavedataManager(UI::EventParams &e); + UI::EventReturn OnSysInfo(UI::EventParams &e); + UI::EventReturn OnChangeSearchFilter(UI::EventParams &e); + UI::EventReturn OnClearSearchFilter(UI::EventParams &e); + // Temporaries to convert setting types, cache enabled, etc. int iAlternateSpeedPercent1_ = 0; int iAlternateSpeedPercent2_ = 0; @@ -122,11 +143,16 @@ private: bool enableReportsSet_ = false; bool analogSpeedMapped_ = false; + std::string searchFilter_; + // edit the game-specific settings and restore the global settings after exiting bool editThenRestore_ = false; // Android-only std::string pendingMemstickFolder_; + + // If we recreate the views while this is active we show it again + std::string oldSettingInfo_; }; class DeveloperToolsScreen : public UIDialogScreenWithGameBackground { @@ -188,7 +214,7 @@ protected: private: void ResolverThread(); - void SendEditKey(InputKeyCode keyCode, int flags = 0); + void SendEditKey(int keyCode, int flags = 0); UI::EventReturn OnNumberClick(UI::EventParams &e); UI::EventReturn OnPointClick(UI::EventParams &e); diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index 30dda6760..53b6412ce 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -264,7 +264,7 @@ void CustomButton::Update() { } bool PSPButton::IsDown() { - return (__CtrlPeekButtonsVisual() & pspButtonBit_) != 0; + return (__CtrlPeekButtons() & pspButtonBit_) != 0; } PSPDpad::PSPDpad(ImageID arrowIndex, const char *key, ImageID arrowDownIndex, ImageID overlayIndex, float scale, float spacing, UI::LayoutParams *layoutParams) @@ -318,56 +318,55 @@ void PSPDpad::ProcessTouch(float x, float y, bool down) { float dx = (x - bounds_.centerX()) * inv_stick_size; float dy = (y - bounds_.centerY()) * inv_stick_size; - float rad = sqrtf(dx * dx + dy * dy); - if (!g_Config.bStickyTouchDPad && (rad < deadzone || fabs(dx) > 0.5f || fabs(dy) > 0.5)) + float rad = sqrtf(dx*dx + dy*dy); + if (rad < deadzone || fabs(dx) > 0.5f || fabs(dy) > 0.5) down = false; int ctrlMask = 0; + int lastDown = down_; + bool fourWay = g_Config.bDisableDpadDiagonals || rad < 0.2f; if (down) { if (fourWay) { int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 4) + 0.5f)) & 3; switch (direction) { - case 0: ctrlMask = CTRL_RIGHT; break; - case 1: ctrlMask = CTRL_DOWN; break; - case 2: ctrlMask = CTRL_LEFT; break; - case 3: ctrlMask = CTRL_UP; break; + case 0: ctrlMask |= CTRL_RIGHT; break; + case 1: ctrlMask |= CTRL_DOWN; break; + case 2: ctrlMask |= CTRL_LEFT; break; + case 3: ctrlMask |= CTRL_UP; break; } // 4 way pad } else { // 8 way pad int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 8) + 0.5f)) & 7; switch (direction) { - case 0: ctrlMask = CTRL_RIGHT; break; - case 1: ctrlMask = CTRL_RIGHT | CTRL_DOWN; break; - case 2: ctrlMask = CTRL_DOWN; break; - case 3: ctrlMask = CTRL_DOWN | CTRL_LEFT; break; - case 4: ctrlMask = CTRL_LEFT; break; - case 5: ctrlMask = CTRL_UP | CTRL_LEFT; break; - case 6: ctrlMask = CTRL_UP; break; - case 7: ctrlMask = CTRL_UP | CTRL_RIGHT; break; + case 0: ctrlMask |= CTRL_RIGHT; break; + case 1: ctrlMask |= CTRL_RIGHT | CTRL_DOWN; break; + case 2: ctrlMask |= CTRL_DOWN; break; + case 3: ctrlMask |= CTRL_DOWN | CTRL_LEFT; break; + case 4: ctrlMask |= CTRL_LEFT; break; + case 5: ctrlMask |= CTRL_UP | CTRL_LEFT; break; + case 6: ctrlMask |= CTRL_UP; break; + case 7: ctrlMask |= CTRL_UP | CTRL_RIGHT; break; } } } - int lastDown = down_; - int pressed = ctrlMask & ~lastDown; - int released = (~ctrlMask) & lastDown; down_ = ctrlMask; - bool vibrate = false; - static const int dir[4] = { CTRL_RIGHT, CTRL_DOWN, CTRL_LEFT, CTRL_UP }; + int pressed = down_ & ~lastDown; + int released = (~down_) & lastDown; + static const int dir[4] = {CTRL_RIGHT, CTRL_DOWN, CTRL_LEFT, CTRL_UP}; for (int i = 0; i < 4; i++) { if (pressed & dir[i]) { - vibrate = true; + if (g_Config.bHapticFeedback) { + System_Vibrate(HAPTIC_VIRTUAL_KEY); + } __CtrlUpdateButtons(dir[i], 0); } if (released & dir[i]) { __CtrlUpdateButtons(0, dir[i]); } } - if (vibrate && g_Config.bHapticFeedback) { - System_Vibrate(HAPTIC_VIRTUAL_KEY); - } } void PSPDpad::Draw(UIContext &dc) { @@ -739,27 +738,46 @@ void InitPadLayout(float xres, float yres, float globalScale) { int r_key_Y = l_key_Y; initTouchPos(g_Config.touchRKey, r_key_X, r_key_Y); - struct { float x; float y; } customButtonPositions[10] = { - { 1.2f, 0.5f }, - { 2.2f, 0.5f }, - { 3.2f, 0.5f }, - { 1.2f, 0.333f }, - { 2.2f, 0.333f }, - { -1.2f, 0.5f }, - { -2.2f, 0.5f }, - { -3.2f, 0.5f }, - { -1.2f, 0.333f }, - { -2.2f, 0.333f }, - }; + //Combo key + int combo_key_X = halfW + bottom_key_spacing * scale * 1.2f; + int combo_key_Y = yres / 2; + initTouchPos(g_Config.touchCustom0, combo_key_X, combo_key_Y); - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { - float y_offset = (float)(i / 10) * 0.08333f; + int combo1_key_X = halfW + bottom_key_spacing * scale * 2.2f; + int combo1_key_Y = yres / 2; + initTouchPos(g_Config.touchCustom1, combo1_key_X, combo1_key_Y); - int combo_key_X = halfW + bottom_key_spacing * scale * customButtonPositions[i % 10].x; - int combo_key_Y = yres * (y_offset + customButtonPositions[i % 10].y); + int combo2_key_X = halfW + bottom_key_spacing * scale * 3.2f; + int combo2_key_Y = yres / 2; + initTouchPos(g_Config.touchCustom2, combo2_key_X, combo2_key_Y); - initTouchPos(g_Config.touchCustom[i], combo_key_X, combo_key_Y); - } + int combo3_key_X = halfW + bottom_key_spacing * scale * 1.2f; + int combo3_key_Y = yres / 3; + initTouchPos(g_Config.touchCustom3, combo3_key_X, combo3_key_Y); + + int combo4_key_X = halfW + bottom_key_spacing * scale * 2.2f; + int combo4_key_Y = yres / 3; + initTouchPos(g_Config.touchCustom4, combo4_key_X, combo4_key_Y); + + int combo5_key_X = halfW - bottom_key_spacing * scale * 1.2f; + int combo5_key_Y = yres / 2; + initTouchPos(g_Config.touchCustom5, combo5_key_X, combo5_key_Y); + + int combo6_key_X = halfW - bottom_key_spacing * scale * 2.2f; + int combo6_key_Y = yres / 2; + initTouchPos(g_Config.touchCustom6, combo6_key_X, combo6_key_Y); + + int combo7_key_X = halfW - bottom_key_spacing * scale * 3.2f; + int combo7_key_Y = yres / 2; + initTouchPos(g_Config.touchCustom7, combo7_key_X, combo7_key_Y); + + int combo8_key_X = halfW - bottom_key_spacing * scale * 1.2f; + int combo8_key_Y = yres / 3; + initTouchPos(g_Config.touchCustom8, combo8_key_X, combo8_key_Y); + + int combo9_key_X = halfW - bottom_key_spacing * scale * 2.2f; + int combo9_key_Y = yres / 3; + initTouchPos(g_Config.touchCustom9, combo9_key_X, combo9_key_Y); } UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPauseButton, ControlMapper* controllMapper) { @@ -866,11 +884,16 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau root->Add(new PSPStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); } - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { - char temp[64]; - snprintf(temp, sizeof(temp), "Custom %d button", i + 1); - addCustomButton(g_Config.CustomButton[i], temp, g_Config.touchCustom[i]); - } + addCustomButton(g_Config.CustomButton0, "Custom 1 button", g_Config.touchCustom0); + addCustomButton(g_Config.CustomButton1, "Custom 2 button", g_Config.touchCustom1); + addCustomButton(g_Config.CustomButton2, "Custom 3 button", g_Config.touchCustom2); + addCustomButton(g_Config.CustomButton3, "Custom 4 button", g_Config.touchCustom3); + addCustomButton(g_Config.CustomButton4, "Custom 5 button", g_Config.touchCustom4); + addCustomButton(g_Config.CustomButton5, "Custom 6 button", g_Config.touchCustom5); + addCustomButton(g_Config.CustomButton6, "Custom 7 button", g_Config.touchCustom6); + addCustomButton(g_Config.CustomButton7, "Custom 8 button", g_Config.touchCustom7); + addCustomButton(g_Config.CustomButton8, "Custom 9 button", g_Config.touchCustom8); + addCustomButton(g_Config.CustomButton9, "Custom 10 button", g_Config.touchCustom9); if (g_Config.bGestureControlEnabled) root->Add(new GestureGamepad(controllMapper)); @@ -895,8 +918,7 @@ bool GestureGamepad::Touch(const TouchInput &input) { dragPointerId_ = input.id; lastX_ = input.x; lastY_ = input.y; - downX_ = input.x; - downY_ = input.y; + const float now = time_now_d(); if (now - lastTapRelease_ < 0.3f && !haveDoubleTapped_) { if (g_Config.iDoubleTapGesture != 0 ) @@ -913,15 +935,6 @@ bool GestureGamepad::Touch(const TouchInput &input) { deltaY_ += input.y - lastY_; lastX_ = input.x; lastY_ = input.y; - - if (g_Config.bAnalogGesture) { - const float k = g_Config.fAnalogGestureSensibility * 0.02; - float dx = (input.x - downX_)*g_display.dpi_scale_x * k; - float dy = (input.y - downY_)*g_display.dpi_scale_y * k; - dx = std::min(1.0f, std::max(-1.0f, dx)); - dy = std::min(1.0f, std::max(-1.0f, dy)); - __CtrlSetAnalogXY(0, dx, -dy); - } } } if (input.flags & TOUCH_UP) { @@ -935,27 +948,11 @@ bool GestureGamepad::Touch(const TouchInput &input) { controlMapper_->PSPKey(DEVICE_ID_TOUCH, GestureKey::keyList[g_Config.iDoubleTapGesture-1], KEY_UP); haveDoubleTapped_ = false; } - - if (g_Config.bAnalogGesture) - __CtrlSetAnalogXY(0, 0, 0); } } return true; } -void GestureGamepad::Draw(UIContext &dc) { - float opacity = g_Config.iTouchButtonOpacity / 100.0; - if (opacity <= 0.0f) - return; - - uint32_t colorBg = colorAlpha(GetButtonColor(), opacity); - - if (g_Config.bAnalogGesture && dragPointerId_ != -1) { - dc.Draw()->DrawImage(ImageID("I_CIRCLE"), downX_, downY_, 0.7f, colorBg, ALIGN_CENTER); - } -} - - void GestureGamepad::Update() { const float th = 1.0f; float dx = deltaX_ * g_display.dpi_scale_x * g_Config.fSwipeSensitivity; diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index 43737f55b..3779088b7 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -44,7 +44,7 @@ public: protected: virtual float GetButtonOpacity(); - std::string key_; + const char *key_; double lastFrameTime_; float secondsWithoutTouch_ = 0.0; bool forceVisible_ = false; @@ -199,7 +199,6 @@ public: bool Touch(const TouchInput &input) override; void Update() override; - void Draw(UIContext &dc) override; protected: @@ -207,8 +206,6 @@ protected: float lastY_ = 0.0f; float deltaX_ = 0.0f; float deltaY_ = 0.0f; - float downX_; - float downY_; float lastTapRelease_ = 0.0f; float lastTouchDown_ = 0.0f; int dragPointerId_ = -1; @@ -284,7 +281,6 @@ namespace CustomKeyData { { ImageID("I_DIR"), ImageID("I_DIR_LINE"), 180.0f, false, false }, { ImageID("I_DIR"), ImageID("I_DIR_LINE"), 0.0f, false, false }, { ImageID("I_SQUARE_SHAPE"), ImageID("I_SQUARE_SHAPE_LINE"), 0.0f, false, false }, - { ImageID("I_EMPTY"), ImageID("I_EMPTY"), 0.0f, false, false }, }; // Button list @@ -333,7 +329,6 @@ namespace CustomKeyData { { ImageID::invalid(), VIRTKEY_AXIS_Y_MIN }, { ImageID::invalid(), VIRTKEY_AXIS_X_MAX }, { ImageID::invalid(), VIRTKEY_AXIS_Y_MAX }, - { ImageID::invalid(), VIRTKEY_PREVIOUS_SLOT }, }; static_assert(ARRAY_SIZE(customKeyList) <= 64, "Too many key for a uint64_t bit mask"); }; @@ -361,7 +356,6 @@ namespace GestureKey { VIRTKEY_REWIND, VIRTKEY_SAVE_STATE, VIRTKEY_LOAD_STATE, - VIRTKEY_PREVIOUS_SLOT, VIRTKEY_NEXT_SLOT, VIRTKEY_TEXTURE_DUMP, VIRTKEY_TEXTURE_REPLACE, diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index f52d00698..9d0b5dbd9 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -158,10 +158,12 @@ public: std::vector pspKeys; bool showInfo = false; - if (HasFocus() && UI::IsInfoKey(key)) { - // If the button mapped to triangle, then show the info. - if (key.flags & KEY_UP) { - showInfo = true; + if (KeyMap::InputMappingToPspButton(InputMapping(key.deviceId, key.keyCode), &pspKeys)) { + for (auto it = pspKeys.begin(), end = pspKeys.end(); it != end; ++it) { + // If the button mapped to triangle, then show the info. + if (HasFocus() && (key.flags & KEY_UP) && *it == CTRL_TRIANGLE) { + showInfo = true; + } } } else if (hovering_ && key.deviceId == DEVICE_ID_MOUSE && key.keyCode == NKCODE_EXT_MOUSEBUTTON_2) { // If it's the right mouse button, and it's not otherwise mapped, show the info also. @@ -427,11 +429,8 @@ void GameButton::Draw(UIContext &dc) { std::string GameButton::DescribeText() const { std::shared_ptr ginfo = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0); - if (ginfo->pending) - return "..."; - auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 button"), ginfo->GetTitle()); + return ReplaceAll(u->T("%1 button"), "%1", ginfo->GetTitle()); } class DirButton : public UI::Button { @@ -529,67 +528,6 @@ void GameBrowser::SetPath(const Path &path) { Refresh(); } -void GameBrowser::ApplySearchFilter(const std::string &filter) { - searchFilter_ = filter; - std::transform(searchFilter_.begin(), searchFilter_.end(), searchFilter_.begin(), tolower); - - // We don't refresh because game info loads asynchronously anyway. - ApplySearchFilter(); -} - -void GameBrowser::ApplySearchFilter() { - if (searchFilter_.empty() && searchStates_.empty()) { - // We haven't hidden anything, and we're not searching, so do nothing. - searchPending_ = false; - return; - } - - searchPending_ = false; - // By default, everything is matching. - searchStates_.resize(gameList_->GetNumSubviews(), SearchState::MATCH); - - if (searchFilter_.empty()) { - // Just quickly mark anything we hid as visible again. - for (int i = 0; i < gameList_->GetNumSubviews(); ++i) { - UI::View *v = gameList_->GetViewByIndex(i); - if (searchStates_[i] != SearchState::MATCH) - v->SetVisibility(UI::V_VISIBLE); - } - - searchStates_.clear(); - return; - } - - for (int i = 0; i < gameList_->GetNumSubviews(); ++i) { - UI::View *v = gameList_->GetViewByIndex(i); - std::string label = v->DescribeText(); - // TODO: Maybe we should just save the gameButtons list, though nice to search dirs too? - // This is a bit of a hack to recognize a pending game title. - if (label == "...") { - searchPending_ = true; - // Hide anything pending while, we'll pop-in search results as they match. - // Note: we leave it at MATCH if gone before, so we don't show it again. - if (v->GetVisibility() == UI::V_VISIBLE) { - if (searchStates_[i] == SearchState::MATCH) - v->SetVisibility(UI::V_GONE); - searchStates_[i] = SearchState::PENDING; - } - continue; - } - - std::transform(label.begin(), label.end(), label.begin(), tolower); - bool match = v->CanBeFocused() && label.find(searchFilter_) != label.npos; - if (match && searchStates_[i] != SearchState::MATCH) { - // It was previously visible and force hidden, so show it again. - v->SetVisibility(UI::V_VISIBLE); - searchStates_[i] = SearchState::MATCH; - } else if (!match && searchStates_[i] == SearchState::MATCH && v->GetVisibility() == UI::V_VISIBLE) { - v->SetVisibility(UI::V_GONE); - searchStates_[i] = SearchState::MISMATCH; - } - } -} - UI::EventReturn GameBrowser::LayoutChange(UI::EventParams &e) { *gridStyle_ = e.a == 0 ? true : false; Refresh(); @@ -684,9 +622,6 @@ void GameBrowser::Update() { if (listingPending_ && path_.IsListingReady()) { Refresh(); } - if (searchPending_) { - ApplySearchFilter(); - } } void GameBrowser::Draw(UIContext &dc) { @@ -751,7 +686,6 @@ void GameBrowser::Refresh() { // Kill all the contents Clear(); - searchStates_.clear(); Add(new Spacer(1.0f)); auto mm = GetI18NCategory(I18NCat::MAINMENU); @@ -761,7 +695,7 @@ void GameBrowser::Refresh() { LinearLayout *topBar = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); if (browseFlags_ & BrowseFlags::NAVIGATE) { topBar->Add(new Spacer(2.0f)); - topBar->Add(new TextView(path_.GetFriendlyPath(), ALIGN_VCENTER | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); + topBar->Add(new TextView(path_.GetFriendlyPath().c_str(), ALIGN_VCENTER | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); topBar->Add(new Choice(ImageID("I_HOME"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::OnHomeClick); if (System_GetPropertyBool(SYSPROP_HAS_ADDITIONAL_STORAGE)) { topBar->Add(new Choice(ImageID("I_SDCARD"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::StorageClick); @@ -774,15 +708,6 @@ void GameBrowser::Refresh() { if (System_GetPropertyBool(SYSPROP_HAS_FOLDER_BROWSER)) { topBar->Add(new Choice(mm->T("Browse"), ImageID("I_FOLDER_OPEN"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::BrowseClick); } - if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_TV) { - topBar->Add(new Choice(mm->T("Enter Path"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Add([=](UI::EventParams &) { - auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_InputBoxGetString(mm->T("Enter Path"), path_.GetPath().ToString(), [=](const char *responseString, int responseValue) { - this->SetPath(Path(responseString)); - }); - return UI::EVENT_DONE; - }); - } #endif } else { topBar->Add(new Spacer(new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); @@ -844,7 +769,7 @@ void GameBrowser::Refresh() { } } else if (!listingPending_) { std::vector fileInfo; - path_.GetListing(fileInfo, "iso:cso:chd:pbp:elf:prx:ppdmp:"); + path_.GetListing(fileInfo, "iso:cso:pbp:elf:prx:ppdmp:"); for (size_t i = 0; i < fileInfo.size(); i++) { bool isGame = !fileInfo[i].isDirectory; bool isSaveData = false; @@ -1242,8 +1167,11 @@ void MainScreen::CreateViews() { } } +#if !PPSSPP_PLATFORM(UWP) + // Having an exit button is against UWP guidelines. rightColumnChoices->Add(new Spacer(25.0)); rightColumnChoices->Add(new Choice(mm->T("Exit")))->OnClick.Handle(this, &MainScreen::OnExit); +#endif if (vertical) { root_ = new LinearLayout(ORIENT_VERTICAL); @@ -1264,8 +1192,6 @@ void MainScreen::CreateViews() { root_->SetDefaultFocusView(tabHolder_); } - root_->SetTag("mainroot"); - auto u = GetI18NCategory(I18NCat::UPGRADE); upgradeBar_ = 0; @@ -1293,25 +1219,6 @@ void MainScreen::CreateViews() { } } -bool MainScreen::key(const KeyInput &touch) { - if (touch.flags & KEY_DOWN) { - if (touch.keyCode == NKCODE_CTRL_LEFT || touch.keyCode == NKCODE_CTRL_RIGHT) - searchKeyModifier_ = true; - if (touch.keyCode == NKCODE_F && searchKeyModifier_ && System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { - auto se = GetI18NCategory(I18NCat::SEARCH); - System_InputBoxGetString(se->T("Search term"), searchFilter_, [&](const std::string &value, int) { - searchFilter_ = StripSpaces(value); - searchChanged_ = true; - }); - } - } else if (touch.flags & KEY_UP) { - if (touch.keyCode == NKCODE_CTRL_LEFT || touch.keyCode == NKCODE_CTRL_RIGHT) - searchKeyModifier_ = false; - } - - return UIScreenWithBackground::key(touch); -} - UI::EventReturn MainScreen::OnAllowStorage(UI::EventParams &e) { System_AskForPermission(SYSTEM_PERMISSION_STORAGE); return UI::EVENT_DONE; @@ -1341,15 +1248,27 @@ UI::EventReturn MainScreen::OnDismissUpgrade(UI::EventParams &e) { return UI::EVENT_DONE; } -void MainScreen::sendMessage(UIMessage message, const char *value) { +void MainScreen::sendMessage(const char *message, const char *value) { // Always call the base class method first to handle the most common messages. UIScreenWithBackground::sendMessage(message, value); - if (message == UIMessage::REQUEST_GAME_BOOT) { - if (screenManager()->topScreen() == this) { + if (screenManager()->topScreen() == this) { + if (!strcmp(message, "boot")) { LaunchFile(screenManager(), Path(std::string(value))); } - } else if (message == UIMessage::PERMISSION_GRANTED && !strcmp(value, "storage")) { + if (!strcmp(message, "browse_fileSelect")) { + INFO_LOG(SYSTEM, "Attempting to launch: '%s'", value); + LaunchFile(screenManager(), Path(std::string(value))); + } + if (!strcmp(message, "browse_folderSelect")) { + std::string filename = value; + INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str());; + // switch to the 'Games' tab which has the file browser + tabHolder_->SetCurrentTab(1); + gameBrowsers_[1]->SetPath(Path(filename)); + } + } + if (!strcmp(message, "permission_granted") && !strcmp(value, "storage")) { RecreateViews(); } } @@ -1357,19 +1276,13 @@ void MainScreen::sendMessage(UIMessage message, const char *value) { void MainScreen::update() { UIScreen::update(); UpdateUIState(UISTATE_MENU); - - if (searchChanged_) { - for (auto browser : gameBrowsers_) - browser->ApplySearchFilter(searchFilter_); - searchChanged_ = false; - } } UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) { if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { auto mm = GetI18NCategory(I18NCat::MAINMENU); System_BrowseForFile(mm->T("Load"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, value); + NativeMessageReceived("boot", value.c_str()); }); } return UI::EVENT_DONE; @@ -1584,7 +1497,7 @@ void UmdReplaceScreen::CreateViews() { new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); scrollRecentGames->Add(tabRecentGames); leftColumn->AddTab(mm->T("Recent"), scrollRecentGames); - tabRecentGames->OnChoice.Handle(this, &UmdReplaceScreen::OnGameSelected); + tabRecentGames->OnChoice.Handle(this, &UmdReplaceScreen::OnGameSelectedInstant); tabRecentGames->OnHoldChoice.Handle(this, &UmdReplaceScreen::OnGameSelected); } ScrollView *scrollAllGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); @@ -1598,23 +1511,11 @@ void UmdReplaceScreen::CreateViews() { leftColumn->AddTab(mm->T("Games"), scrollAllGames); - tabAllGames->OnChoice.Handle(this, &UmdReplaceScreen::OnGameSelected); + tabAllGames->OnChoice.Handle(this, &UmdReplaceScreen::OnGameSelectedInstant); tabAllGames->OnHoldChoice.Handle(this, &UmdReplaceScreen::OnGameSelected); - if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { - rightColumnItems->Add(new Choice(mm->T("Load", "Load...")))->OnClick.Add([&](UI::EventParams &e) { - auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFile(mm->T("Load"), BrowseFileType::BOOTABLE, [&](const std::string &value, int) { - __UmdReplace(Path(value)); - TriggerFinish(DR_OK); - }); - return EVENT_DONE; - }); - } - rightColumnItems->Add(new Choice(di->T("Cancel")))->OnClick.Handle(this, &UIScreen::OnCancel); - rightColumnItems->Add(new Spacer()); rightColumnItems->Add(new Choice(mm->T("Game Settings")))->OnClick.Handle(this, &UmdReplaceScreen::OnGameSettings); if (g_Config.HasRecentIsos()) { @@ -1644,6 +1545,12 @@ UI::EventReturn UmdReplaceScreen::OnGameSettings(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn UmdReplaceScreen::OnGameSelectedInstant(UI::EventParams &e) { + __UmdReplace(Path(e.s)); + TriggerFinish(DR_OK); + return UI::EVENT_DONE; +} + void GridSettingsScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; diff --git a/UI/MainScreen.h b/UI/MainScreen.h index aaea6bff1..ee79725fd 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -51,7 +51,6 @@ public: void FocusGame(const Path &gamePath); void SetPath(const Path &path); - void ApplySearchFilter(const std::string &filter); void Draw(UIContext &dc) override; void Update() override; @@ -59,7 +58,6 @@ protected: virtual bool DisplayTopBar(); virtual bool HasSpecialFiles(std::vector &filenames); virtual Path HomePath(); - void ApplySearchFilter(); void Refresh(); @@ -82,23 +80,14 @@ private: UI::EventReturn OnRecentClear(UI::EventParams &e); UI::EventReturn OnHomebrewStore(UI::EventParams &e); - enum class SearchState { - MATCH, - MISMATCH, - PENDING, - }; - UI::ViewGroup *gameList_ = nullptr; PathBrowser path_; bool *gridStyle_ = nullptr; BrowseFlags browseFlags_; std::string lastText_; std::string lastLink_; - std::string searchFilter_; - std::vector searchStates_; Path focusGamePath_; bool listingPending_ = false; - bool searchPending_ = false; float lastScale_ = 1.0f; bool lastLayoutWasGrid_ = true; ScreenManager *screenManager_; @@ -118,13 +107,11 @@ public: // Horrible hack to show the demos & homebrew tab after having installed a game from a zip file. static bool showHomebrewTab; - bool key(const KeyInput &touch) override; - protected: void CreateViews() override; void DrawBackground(UIContext &dc) override; void update() override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; void dialogFinished(const Screen *dialog, DialogResult result) override; bool DrawBackgroundFor(UIContext &dc, const Path &gamePath, float progress); @@ -161,9 +148,6 @@ protected: bool lastVertical_; bool confirmedTemporary_ = false; UI::ScrollView *scrollAllGames_ = nullptr; - bool searchKeyModifier_ = false; - bool searchChanged_ = false; - std::string searchFilter_; friend class RemoteISOBrowseScreen; }; @@ -175,9 +159,12 @@ public: protected: void CreateViews() override; void update() override; + //virtual void sendMessage(const char *message, const char *value); private: UI::EventReturn OnGameSelected(UI::EventParams &e); + UI::EventReturn OnGameSelectedInstant(UI::EventParams &e); + UI::EventReturn OnGameSettings(UI::EventParams &e); }; diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 3e39811df..8aad6a820 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -29,7 +29,6 @@ #include "Common/System/Request.h" #include "Common/System/NativeApp.h" #include "Common/System/Display.h" -#include "Common/System/OSD.h" #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" @@ -48,7 +47,6 @@ #include "UI/MemStickScreen.h" #include "UI/MainScreen.h" #include "UI/MiscScreens.h" -#include "UI/OnScreenDisplay.h" static bool FolderSeemsToBeUsed(Path newMemstickFolder) { // Inspect the potential new folder, quickly. @@ -80,21 +78,12 @@ static bool SwitchMemstickFolderTo(Path newMemstickFolder) { } Path memStickDirFile = g_Config.internalDataDirectory / "memstick_dir.txt"; -#if PPSSPP_PLATFORM(UWP) - File::Delete(memStickDirFile); - if (newMemstickFolder != g_Config.internalDataDirectory) { -#endif - std::string str = newMemstickFolder.ToString(); if (!File::WriteDataToFile(true, str.c_str(), (unsigned int)str.size(), memStickDirFile)) { ERROR_LOG(SYSTEM, "Failed to write memstick path '%s' to '%s'", newMemstickFolder.c_str(), memStickDirFile.c_str()); // Not sure what to do if this file can't be written. Disk full? } -#if PPSSPP_PLATFORM(UWP) - } -#endif - // Save so the settings, at least, are transferred. g_Config.memStickDirectory = newMemstickFolder; g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); @@ -135,11 +124,7 @@ MemStickScreen::MemStickScreen(bool initialSetup) } } else { // Detect the current choice, so it's preselected in the UI. -#if PPSSPP_PLATFORM(UWP) - if (g_Config.memStickDirectory == g_Config.internalDataDirectory) { -#else if (g_Config.memStickDirectory == Path(g_extFilesDir)) { -#endif choice_ = CHOICE_PRIVATE_DIRECTORY; } else if (g_Config.memStickDirectory == Path(g_externalDir)) { choice_ = CHOICE_STORAGE_ROOT; @@ -179,20 +164,16 @@ static void AddExplanation(UI::ViewGroup *viewGroup, MemStickScreen::Choice choi case MemStickScreen::CHOICE_BROWSE_FOLDER: holder->Add(new TextView(iz->T("DataWillStay", "Data will stay even if you uninstall PPSSPP"), flags, false))->SetBullet(true); holder->Add(new TextView(iz->T("DataCanBeShared", "Data can be shared between PPSSPP regular/Gold"), flags, false))->SetBullet(true); -#if !PPSSPP_PLATFORM(UWP) holder->Add(new TextView(iz->T("EasyUSBAccess", "Easy USB access"), flags, false))->SetBullet(true); -#endif break; case MemStickScreen::CHOICE_PRIVATE_DIRECTORY: // Consider https://www.compart.com/en/unicode/U+26A0 (unicode warning sign?)? or a graphic? holder->Add(new TextView(iz->T("DataWillBeLostOnUninstall", "Warning! Data will be lost when you uninstall PPSSPP!"), flags, false))->SetBullet(true); holder->Add(new TextView(iz->T("DataCannotBeShared", "Data CANNOT be shared between PPSSPP regular/Gold!"), flags, false))->SetBullet(true); -#if !PPSSPP_PLATFORM(UWP) #if GOLD holder->Add(new TextView(iz->T("USBAccessThroughGold", "USB access through Android/data/org.ppsspp.ppssppgold/files"), flags, false))->SetBullet(true); #else holder->Add(new TextView(iz->T("USBAccessThrough", "USB access through Android/data/org.ppsspp.ppsspp/files"), flags, false))->SetBullet(true); -#endif #endif break; case MemStickScreen::CHOICE_SET_MANUAL: @@ -245,7 +226,8 @@ void MemStickScreen::CreateViews() { // For legacy Android systems, so you can switch back to the old ways if you move to SD or something. // Trying to avoid needing a scroll view, so only showing the explanation for one option at a time. -#if !PPSSPP_PLATFORM(UWP) + +#if PPSSPP_PLATFORM(ANDROID) if (!System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE)) { leftColumn->Add(new RadioButton(&choice_, CHOICE_STORAGE_ROOT, iz->T("Use PSP folder at root of storage")))->OnClick.Handle(this, &MemStickScreen::OnChoiceClick); if (choice_ == CHOICE_STORAGE_ROOT) { @@ -255,6 +237,7 @@ void MemStickScreen::CreateViews() { #endif if (storageBrowserWorking_) { + //ImageID("I_FOLDER_OPEN") leftColumn->Add(new RadioButton(&choice_, CHOICE_BROWSE_FOLDER, iz->T("Create or Choose a PSP folder")))->OnClick.Handle(this, &MemStickScreen::OnChoiceClick); // TODO: Show current folder here if we have one set. @@ -264,9 +247,6 @@ void MemStickScreen::CreateViews() { leftColumn->Add(new TextView(iz->T("DataCanBeShared", "Data can be shared between PPSSPP regular/Gold.")))->SetBullet(true); // TODO: Show current folder here if we have one set. } - errorNoticeView_ = leftColumn->Add(new NoticeView(NoticeLevel::WARN, iz->T("Cancelled - try again"), "")); - errorNoticeView_->SetVisibility(UI::V_GONE); - if (choice_ == CHOICE_BROWSE_FOLDER || choice_ == CHOICE_SET_MANUAL) { UI::View *extraView = nullptr; if (!g_Config.memStickDirectory.empty()) { @@ -276,7 +256,6 @@ void MemStickScreen::CreateViews() { } std::string privateString = iz->T("Use App Private Data"); - if (initialSetup_) { privateString = StringFromFormat("%s (%s)", iz->T("Skip for now"), privateString.c_str()); } @@ -335,6 +314,7 @@ UI::EventReturn MemStickScreen::OnChoiceClick(UI::EventParams ¶ms) { // Change the confirm button to match the choice, // and change the text that we show. RecreateViews(); + return UI::EVENT_DONE; } @@ -355,7 +335,7 @@ UI::EventReturn MemStickScreen::OnConfirmClick(UI::EventParams ¶ms) { UI::EventReturn MemStickScreen::SetFolderManually(UI::EventParams ¶ms) { // The old way, from before scoped storage. -#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(ANDROID) auto sy = GetI18NCategory(I18NCat::SYSTEM); System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](const std::string &value, int) { auto sy = GetI18NCategory(I18NCat::SYSTEM); @@ -419,11 +399,7 @@ UI::EventReturn MemStickScreen::SetFolderManually(UI::EventParams ¶ms) { } UI::EventReturn MemStickScreen::UseInternalStorage(UI::EventParams ¶ms) { -#if PPSSPP_PLATFORM(UWP) - Path pendingMemStickFolder = g_Config.internalDataDirectory; -#else Path pendingMemStickFolder = Path(g_extFilesDir); -#endif if (initialSetup_) { // There's not gonna be any files here in this case since it's a fresh install. @@ -471,20 +447,20 @@ UI::EventReturn MemStickScreen::UseStorageRoot(UI::EventParams ¶ms) { UI::EventReturn MemStickScreen::Browse(UI::EventParams ¶ms) { auto mm = GetI18NCategory(I18NCat::MAINMENU); System_BrowseForFolder(mm->T("Choose folder"), [=](const std::string &value, int) { - Path pendingMemStickFolder = Path(value); - INFO_LOG(SYSTEM, "Got folder: '%s'", pendingMemStickFolder.c_str()); + std::string filename; + filename = value; + INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str()); + // Browse finished. Let's pop up the confirmation dialog. - if (!pendingMemStickFolder.empty() && pendingMemStickFolder == g_Config.memStickDirectory && File::IsDirectory(pendingMemStickFolder)) { + Path pendingMemStickFolder = Path(filename); + + if (pendingMemStickFolder == g_Config.memStickDirectory) { auto iz = GetI18NCategory(I18NCat::MEMSTICK); - // Not sure how this could happen, but let's go with it. - g_OSD.Show(OSDType::MESSAGE_SUCCESS, iz->T("Done!")); - done_ = true; return; } - errorNoticeView_->SetVisibility(UI::V_GONE); + + bool existingFiles = FolderSeemsToBeUsed(pendingMemStickFolder); screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, initialSetup_)); - }, [=]() { - errorNoticeView_->SetVisibility(UI::V_VISIBLE); }); return UI::EVENT_DONE; } @@ -584,15 +560,15 @@ void ConfirmMemstickMoveScreen::CreateViews() { leftColumn->Add(new TextView(iz->T("Selected PSP Data Folder"), ALIGN_LEFT, false)); if (!initialSetup_) { - leftColumn->Add(new NoticeView(NoticeLevel::WARN, iz->T("PPSSPP will restart after the change"), "")); + leftColumn->Add(new TextView(iz->T("PPSSPP will restart after the change"), ALIGN_LEFT, false)); } leftColumn->Add(new TextView(newMemstickFolder_.ToVisualString(), ALIGN_LEFT, false)); std::string newFreeSpaceText = std::string(iz->T("Free space")) + ": " + FormatSpaceString(freeSpaceNew); leftColumn->Add(new TextView(newFreeSpaceText, ALIGN_LEFT, false)); if (existingFilesInNewFolder_) { - leftColumn->Add(new NoticeView(NoticeLevel::SUCCESS, iz->T("Already contains PSP data"), "")); + leftColumn->Add(new TextView(iz->T("Already contains PSP data"), ALIGN_LEFT, false)); if (!moveData_) { - leftColumn->Add(new NoticeView(NoticeLevel::INFO, iz->T("No data will be changed"), "")); + leftColumn->Add(new TextView(iz->T("No data will be changed"), ALIGN_LEFT, false)); } } if (!error_.empty()) { @@ -601,7 +577,6 @@ void ConfirmMemstickMoveScreen::CreateViews() { if (!oldMemstickFolder.empty()) { std::string oldFreeSpaceText = std::string(iz->T("Free space")) + ": " + FormatSpaceString(freeSpaceOld); - rightColumn->Add(new TextView(std::string(iz->T("Current")) + ":", ALIGN_LEFT, false)); rightColumn->Add(new TextView(oldMemstickFolder.ToVisualString(), ALIGN_LEFT, false)); rightColumn->Add(new TextView(oldFreeSpaceText, ALIGN_LEFT, false)); @@ -791,7 +766,6 @@ void ConfirmMemstickMoveScreen::FinishFolderMove() { // If the chosen folder already had a config, reload it! g_Config.Load(); - PostLoadConfig(); if (!initialSetup_) { // We restart the app here, to get the new settings. diff --git a/UI/MemStickScreen.h b/UI/MemStickScreen.h index 62ad37c08..3912e095b 100644 --- a/UI/MemStickScreen.h +++ b/UI/MemStickScreen.h @@ -29,8 +29,6 @@ #include "UI/MiscScreens.h" -class NoticeView; - // MemStickScreen - let's you configure your memory stick directory. // Currently only useful for Android. class MemStickScreen : public UIDialogScreenWithBackground { @@ -77,17 +75,12 @@ private: UI::EventReturn OnChoiceClick(UI::EventParams ¶ms); SettingInfoMessage *settingInfo_ = nullptr; - NoticeView *errorNoticeView_ = nullptr; bool initialSetup_; bool storageBrowserWorking_; bool done_ = false; -#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__) - int choice_ = CHOICE_PRIVATE_DIRECTORY; -#else int choice_ = 0; -#endif }; class ProgressReporter { @@ -133,11 +126,7 @@ private: Path newMemstickFolder_; bool existingFilesInNewFolder_; -#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__) - bool moveData_ = false; -#else bool moveData_ = true; -#endif bool initialSetup_; ProgressReporter progressReporter_; diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 438bc5f9c..6754c0a14 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -34,7 +34,6 @@ #include "Common/File/VFS/VFS.h" #include "Common/Data/Color/RGBAUtil.h" -#include "Common/Data/Encoding/Utf8.h" #include "Common/Data/Text/I18n.h" #include "Common/Data/Random/Rng.h" #include "Common/TimeUtil.h" @@ -141,17 +140,16 @@ public: for (int n = 0; n < steps; n++) { float x = (float)n * step; - float nextX = (float)(n + 1) * step; float i = x * 1280 / bounds.w; float wave0 = sin(i*0.005+t*0.8)*0.05 + sin(i*0.002+t*0.25)*0.02 + sin(i*0.001+t*0.3)*0.03 + 0.625; float wave1 = sin(i*0.0044+t*0.4)*0.07 + sin(i*0.003+t*0.1)*0.02 + sin(i*0.001+t*0.3)*0.01 + 0.625; - dc.Draw()->RectVGradient(x, wave0*bounds.h, nextX, bounds.h, color, 0x00000000); - dc.Draw()->RectVGradient(x, wave1*bounds.h, nextX, bounds.h, color, 0x00000000); + dc.Draw()->RectVGradient(x, wave0*bounds.h, step, (1.0-wave0)*bounds.h, color, 0x00000000); + dc.Draw()->RectVGradient(x, wave1*bounds.h, step, (1.0-wave1)*bounds.h, color, 0x00000000); // Add some "antialiasing" - dc.Draw()->RectVGradient(x, wave0*bounds.h-3.0f * g_display.pixel_in_dps_y, nextX, wave0 * bounds.h, 0x00000000, color); - dc.Draw()->RectVGradient(x, wave1*bounds.h-3.0f * g_display.pixel_in_dps_y, nextX, wave1 * bounds.h, 0x00000000, color); + dc.Draw()->RectVGradient(x, wave0*bounds.h-3.0f * g_display.pixel_in_dps_y, step, 3.0f * g_display.pixel_in_dps_y, 0x00000000, color); + dc.Draw()->RectVGradient(x, wave1*bounds.h-3.0f * g_display.pixel_in_dps_y, step, 3.0f * g_display.pixel_in_dps_y, 0x00000000, color); } dc.Flush(); @@ -335,7 +333,6 @@ void DrawBackground(UIContext &dc, float alpha, float x, float y, float z) { if (bgTexture != nullptr) { dc.Flush(); - dc.Begin(); dc.GetDrawContext()->BindTexture(0, bgTexture->GetTexture()); dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, bgColor); @@ -344,9 +341,7 @@ void DrawBackground(UIContext &dc, float alpha, float x, float y, float z) { } else { // I_BG original color: 0xFF754D24 ImageID img = ImageID("I_BG"); - dc.Begin(); - dc.Draw()->DrawImageStretch(img, dc.GetBounds(), bgColor & dc.theme->backgroundColor); - dc.Flush(); + ui_draw2d.DrawImageStretch(img, dc.GetBounds(), bgColor & dc.theme->backgroundColor); } #if PPSSPP_PLATFORM(IOS) @@ -417,36 +412,35 @@ void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, f } } -void HandleCommonMessages(UIMessage message, const char *value, ScreenManager *manager, const Screen *activeScreen) { +void HandleCommonMessages(const char *message, const char *value, ScreenManager *manager, const Screen *activeScreen) { bool isActiveScreen = manager->topScreen() == activeScreen; - if (message == UIMessage::REQUEST_CLEAR_JIT && PSP_IsInited()) { - // TODO: This seems to clearly be the wrong place to handle this. + if (!strcmp(message, "clear jit") && PSP_IsInited()) { if (MIPSComp::jit) { std::lock_guard guard(MIPSComp::jitLock); if (MIPSComp::jit) MIPSComp::jit->ClearCache(); } currentMIPS->UpdateCore((CPUCore)g_Config.iCpuCore); - } else if (message == UIMessage::SHOW_CONTROL_MAPPING && isActiveScreen && std::string(activeScreen->tag()) != "ControlMapping") { + } else if (!strcmp(message, "control mapping") && isActiveScreen && std::string(activeScreen->tag()) != "ControlMapping") { UpdateUIState(UISTATE_MENU); manager->push(new ControlMappingScreen(Path())); - } else if (message == UIMessage::SHOW_DISPLAY_LAYOUT_EDITOR && isActiveScreen && std::string(activeScreen->tag()) != "DisplayLayout") { + } else if (!strcmp(message, "display layout editor") && isActiveScreen && std::string(activeScreen->tag()) != "DisplayLayout") { UpdateUIState(UISTATE_MENU); manager->push(new DisplayLayoutScreen(Path())); - } else if (message == UIMessage::SHOW_SETTINGS && isActiveScreen && std::string(activeScreen->tag()) != "GameSettings") { + } else if (!strcmp(message, "settings") && isActiveScreen && std::string(activeScreen->tag()) != "GameSettings") { UpdateUIState(UISTATE_MENU); manager->push(new GameSettingsScreen(Path())); - } else if (message == UIMessage::SHOW_LANGUAGE_SCREEN && isActiveScreen) { + } else if (!strcmp(message, "language screen") && isActiveScreen) { auto sy = GetI18NCategory(I18NCat::SYSTEM); auto langScreen = new NewLanguageScreen(sy->T("Language")); langScreen->OnChoice.Add([](UI::EventParams &) { - System_PostUIMessage(UIMessage::RECREATE_VIEWS); + NativeMessageReceived("recreateviews", ""); System_Notify(SystemNotification::UI); return UI::EVENT_DONE; }); manager->push(langScreen); - } else if (message == UIMessage::WINDOW_MINIMIZED) { + } else if (!strcmp(message, "window minimized")) { if (!strcmp(value, "true")) { gstate_c.skipDrawReason |= SKIPDRAW_WINDOW_MINIMIZED; } else { @@ -473,8 +467,8 @@ void UIScreenWithGameBackground::DrawBackground(UIContext &dc) { } } -void UIScreenWithGameBackground::sendMessage(UIMessage message, const char *value) { - if (message == UIMessage::SHOW_SETTINGS && screenManager()->topScreen() == this) { +void UIScreenWithGameBackground::sendMessage(const char *message, const char *value) { + if (!strcmp(message, "settings") && screenManager()->topScreen() == this) { screenManager()->push(new GameSettingsScreen(gamePath_)); } else { UIScreenWithBackground::sendMessage(message, value); @@ -494,15 +488,15 @@ void UIDialogScreenWithGameBackground::DrawBackground(UIContext &dc) { } } -void UIDialogScreenWithGameBackground::sendMessage(UIMessage message, const char *value) { - if (message == UIMessage::SHOW_SETTINGS && screenManager()->topScreen() == this) { +void UIDialogScreenWithGameBackground::sendMessage(const char *message, const char *value) { + if (!strcmp(message, "settings") && screenManager()->topScreen() == this) { screenManager()->push(new GameSettingsScreen(gamePath_)); } else { UIDialogScreenWithBackground::sendMessage(message, value); } } -void UIScreenWithBackground::sendMessage(UIMessage message, const char *value) { +void UIScreenWithBackground::sendMessage(const char *message, const char *value) { HandleCommonMessages(message, value, screenManager(), this); } @@ -519,7 +513,7 @@ void UIDialogScreenWithBackground::AddStandardBack(UI::ViewGroup *parent) { parent->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, 64, 10, NONE, NONE, 10)))->OnClick.Handle(this, &UIScreen::OnBack); } -void UIDialogScreenWithBackground::sendMessage(UIMessage message, const char *value) { +void UIDialogScreenWithBackground::sendMessage(const char *message, const char *value) { HandleCommonMessages(message, value, screenManager(), this); } @@ -548,14 +542,8 @@ void PromptScreen::CreateViews() { Choice *yesButton = rightColumnItems->Add(new Choice(yesButtonText_)); yesButton->OnClick.Handle(this, &PromptScreen::OnYes); root_->SetDefaultFocusView(yesButton); - if (!noButtonText_.empty()) { + if (!noButtonText_.empty()) rightColumnItems->Add(new Choice(noButtonText_))->OnClick.Handle(this, &PromptScreen::OnNo); - } else { - // This is an information screen, not a question. - // Sneak in the version of PPSSPP in the corner, for debug-reporting user screenshots. - std::string version = System_GetProperty(SYSPROP_BUILD_VERSION); - root_->Add(new TextView(version, 0, true, new AnchorLayoutParams(10.0f, NONE, NONE, 10.0f))); - } } UI::EventReturn PromptScreen::OnYes(UI::EventParams &e) { @@ -683,9 +671,18 @@ void NewLanguageScreen::OnCompleted(DialogResult result) { iniLoadedSuccessfully = g_i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath); if (iniLoadedSuccessfully) { + // Dunno what else to do here. + auto &langValuesMapping = g_Config.GetLangValuesMapping(); + + auto iter = langValuesMapping.find(code); + if (iter == langValuesMapping.end()) { + // Fallback to English + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; + } else { + g_Config.iLanguage = iter->second.second; + } RecreateViews(); } else { - // Failed to load the language ini. Shouldn't really happen, but let's just switch back to the old language. g_Config.sLanguageIni = oldLang; } } @@ -736,8 +733,8 @@ void LogoScreen::update() { sinceStart_ = (double)frames_ / rate; } -void LogoScreen::sendMessage(UIMessage message, const char *value) { - if (message == UIMessage::REQUEST_GAME_BOOT && screenManager()->topScreen() == this) { +void LogoScreen::sendMessage(const char *message, const char *value) { + if (!strcmp(message, "boot") && screenManager()->topScreen() == this) { screenManager()->switchScreen(new EmuScreen(Path(value))); } } @@ -800,13 +797,11 @@ void LogoScreen::render() { int ppsspp_org_y = bounds.h / 2 + 130; dc.DrawText("www.ppsspp.org", bounds.centerX(), ppsspp_org_y, textColor, ALIGN_CENTER); -#if !PPSSPP_PLATFORM(UWP) || defined(_DEBUG) +#if !PPSSPP_PLATFORM(UWP) // Draw the graphics API, except on UWP where it's always D3D11 std::string apiName = screenManager()->getDrawContext()->GetInfoString(InfoField::APINAME); #ifdef _DEBUG - apiName += ", debug build "; - // Add some emoji for testing. - apiName += CodepointToUTF8(0x1F41B) + CodepointToUTF8(0x1F41C) + CodepointToUTF8(0x1F914); + apiName += ", debug build"; #endif dc.DrawText(gr->T(apiName), bounds.centerX(), ppsspp_org_y + 50, textColor, ALIGN_CENTER); #endif @@ -977,8 +972,6 @@ void CreditsScreen::render() { "adenovan", "iota97", "Lubos", - "stenzek", // For retroachievements integration - "fp64", "", cr->T("specialthanks", "Special thanks to:"), specialthanksMaxim.c_str(), @@ -1070,8 +1063,8 @@ void CreditsScreen::render() { dc.Flush(); } -SettingInfoMessage::SettingInfoMessage(int align, float cutOffY, UI::AnchorLayoutParams *lp) - : UI::LinearLayout(UI::ORIENT_HORIZONTAL, lp), cutOffY_(cutOffY) { +SettingInfoMessage::SettingInfoMessage(int align, UI::AnchorLayoutParams *lp) + : UI::LinearLayout(UI::ORIENT_HORIZONTAL, lp) { using namespace UI; SetSpacing(0.0f); Add(new UI::Spacer(10.0f)); @@ -1083,7 +1076,7 @@ void SettingInfoMessage::Show(const std::string &text, const UI::View *refView) if (refView) { Bounds b = refView->GetBounds(); const UI::AnchorLayoutParams *lp = GetLayoutParams()->As(); - if (cutOffY_ != -1.0f && b.y >= cutOffY_) { + if (b.y >= cutOffY_) { ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, 80.0f, lp->right, lp->bottom, lp->center)); } else { ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, g_display.dp_yres - 80.0f - 40.0f, lp->right, lp->bottom, lp->center)); diff --git a/UI/MiscScreens.h b/UI/MiscScreens.h index df9d991ab..55b748494 100644 --- a/UI/MiscScreens.h +++ b/UI/MiscScreens.h @@ -41,7 +41,7 @@ public: UIScreenWithBackground() : UIScreen() {} protected: void DrawBackground(UIContext &dc) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; }; class UIScreenWithGameBackground : public UIScreenWithBackground { @@ -49,7 +49,7 @@ public: UIScreenWithGameBackground(const std::string &gamePath) : UIScreenWithBackground(), gamePath_(gamePath) {} void DrawBackground(UIContext &dc) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; protected: Path gamePath_; @@ -62,7 +62,7 @@ public: UIDialogScreenWithBackground() : UIDialogScreen() {} protected: void DrawBackground(UIContext &dc) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; void AddStandardBack(UI::ViewGroup *parent); }; @@ -72,7 +72,7 @@ public: UIDialogScreenWithGameBackground(const Path &gamePath) : UIDialogScreenWithBackground(), gamePath_(gamePath) {} void DrawBackground(UIContext &dc) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; protected: Path gamePath_; @@ -141,7 +141,7 @@ public: void touch(const TouchInput &touch) override; void update() override; void render() override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; void CreateViews() override {} const char *tag() const override { return "Logo"; } @@ -178,8 +178,11 @@ private: class SettingInfoMessage : public UI::LinearLayout { public: - SettingInfoMessage(int align, float cutOffY, UI::AnchorLayoutParams *lp); + SettingInfoMessage(int align, UI::AnchorLayoutParams *lp); + void SetBottomCutoff(float y) { + cutOffY_ = y; + } void Show(const std::string &text, const UI::View *refView = nullptr); void Draw(UIContext &dc) override; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 01e9dc027..22c8543d6 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -55,14 +55,11 @@ #include "Common/UI/Screen.h" #include "Common/UI/Context.h" #include "Common/UI/View.h" -#include "Common/UI/IconCache.h" - #include "android/jni/app-android.h" #include "Common/System/Display.h" #include "Common/System/Request.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/System/NativeApp.h" #include "Common/Data/Text/I18n.h" @@ -90,10 +87,8 @@ #include "Core/ConfigValues.h" #include "Core/Core.h" #include "Core/FileLoaders/DiskCachingFileLoader.h" -#include "Core/FrameTiming.h" #include "Core/KeyMap.h" #include "Core/Reporting.h" -#include "Core/RetroAchievements.h" #include "Core/SaveState.h" #include "Core/Screenshot.h" #include "Core/System.h" @@ -104,7 +99,6 @@ #include "Core/HLE/proAdhoc.h" #include "Core/HW/MemoryStick.h" #include "Core/Util/GameManager.h" -#include "Core/Util/PortManager.h" #include "Core/Util/AudioFormat.h" #include "Core/WebServer.h" #include "Core/TiltEventProcessor.h" @@ -129,7 +123,6 @@ #endif #if PPSSPP_PLATFORM(UWP) #include -#include "UWP/UWPHelpers/InputHelpers.h" #endif #if PPSSPP_PLATFORM(ANDROID) #include "android/jni/app-android.h" @@ -151,14 +144,8 @@ #include "UI/DarwinFileSystemServices.h" #endif -#if !defined(__LIBRETRO__) -#include "Core/Util/GameDB.h" -#endif - #include -bool HandleGlobalMessage(UIMessage message, const std::string &value); - ScreenManager *g_screenManager; std::string config_filename; @@ -171,7 +158,7 @@ static bool restarting = false; static int renderCounter = 0; struct PendingMessage { - UIMessage message; + std::string msg; std::string value; }; @@ -193,18 +180,18 @@ public: void Log(const LogMessage &message) override { // Log with simplified headers as Android already provides timestamp etc. switch (message.level) { - case LogLevel::LVERBOSE: - case LogLevel::LDEBUG: - case LogLevel::LINFO: + case LogTypes::LVERBOSE: + case LogTypes::LDEBUG: + case LogTypes::LINFO: printf("INFO [%s] %s", message.log, message.msg.c_str()); break; - case LogLevel::LERROR: + case LogTypes::LERROR: printf("ERR [%s] %s", message.log, message.msg.c_str()); break; - case LogLevel::LWARNING: + case LogTypes::LWARNING: printf("WARN [%s] %s", message.log, message.msg.c_str()); break; - case LogLevel::LNOTICE: + case LogTypes::LNOTICE: default: printf("NOTE [%s] !!! %s", message.log, message.msg.c_str()); break; @@ -295,10 +282,15 @@ static bool CheckFontIsUsable(const wchar_t *fontFace) { } #endif +bool CreateDirectoriesAndroid(); + void PostLoadConfig() { + // On Windows, we deal with currentDirectory in InitSysDirectories(). +#if !PPSSPP_PLATFORM(WINDOWS) if (g_Config.currentDirectory.empty()) { g_Config.currentDirectory = g_Config.defaultCurrentDirectory; } +#endif // Allow the lang directory to be overridden for testing purposes (e.g. Android, where it's hard to // test new languages without recompiling the entire app, which is a hassle). @@ -310,11 +302,44 @@ void PostLoadConfig() { else g_i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath); -#if !PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(UWP) - CreateSysDirectories(); +#if PPSSPP_PLATFORM(ANDROID) + CreateDirectoriesAndroid(); #endif } +bool CreateDirectoriesAndroid() { + // TODO: We should probably simply use this as the shared function to create memstick directories. + + Path pspDir = g_Config.memStickDirectory; + if (pspDir.GetFilename() != "PSP") { + pspDir /= "PSP"; + } + + INFO_LOG(IO, "Creating '%s' and subdirs:", pspDir.c_str()); + File::CreateFullPath(pspDir); + if (!File::Exists(pspDir)) { + INFO_LOG(IO, "Not a workable memstick directory. Giving up"); + return false; + } + + File::CreateFullPath(GetSysDirectory(DIRECTORY_CHEATS)); + File::CreateFullPath(GetSysDirectory(DIRECTORY_SAVEDATA)); + File::CreateFullPath(GetSysDirectory(DIRECTORY_SAVESTATE)); + File::CreateFullPath(GetSysDirectory(DIRECTORY_GAME)); + File::CreateFullPath(GetSysDirectory(DIRECTORY_SYSTEM)); + File::CreateFullPath(GetSysDirectory(DIRECTORY_TEXTURES)); + File::CreateFullPath(GetSysDirectory(DIRECTORY_PLUGINS)); + + // Avoid media scanners in PPSSPP_STATE and SAVEDATA directories, + // and in the root PSP directory as well. + File::CreateEmptyFile(GetSysDirectory(DIRECTORY_SAVESTATE) / ".nomedia"); + File::CreateEmptyFile(GetSysDirectory(DIRECTORY_SAVEDATA) / ".nomedia"); + File::CreateEmptyFile(GetSysDirectory(DIRECTORY_SYSTEM) / ".nomedia"); + File::CreateEmptyFile(GetSysDirectory(DIRECTORY_TEXTURES) / ".nomedia"); + File::CreateEmptyFile(GetSysDirectory(DIRECTORY_PLUGINS) / ".nomedia"); + return true; +} + static void CheckFailedGPUBackends() { #ifdef _DEBUG // If you're in debug mode, you probably don't want a fallback. If you're in release mode, use IGNORE below. @@ -436,15 +461,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch #endif g_VFS.Register("", new DirectoryReader(Path(savegame_dir))); -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC) - g_Config.defaultCurrentDirectory = Path(System_GetProperty(SYSPROP_USER_DOCUMENTS_DIR)); -#else g_Config.defaultCurrentDirectory = Path("/"); -#endif - -#if !PPSSPP_PLATFORM(UWP) g_Config.internalDataDirectory = Path(savegame_dir); -#endif #if PPSSPP_PLATFORM(ANDROID) // In Android 12 with scoped storage, due to the above, the external directory @@ -487,34 +505,15 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // Attempt to create directories after reading the path. if (!System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE)) { - CreateSysDirectories(); - } -#elif PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__) - Path memstickDirFile = g_Config.internalDataDirectory / "memstick_dir.txt"; - if (File::Exists(memstickDirFile)) { - INFO_LOG(SYSTEM, "Reading '%s' to find memstick dir.", memstickDirFile.c_str()); - std::string memstickDir; - if (File::ReadFileToString(true, memstickDirFile, memstickDir)) { - Path memstickPath(memstickDir); - if (!memstickPath.empty() && File::Exists(memstickPath)) { - g_Config.memStickDirectory = memstickPath; - g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); - g_Config.Reload(); - INFO_LOG(SYSTEM, "Memstick Directory from memstick_dir.txt: '%s'", g_Config.memStickDirectory.c_str()); - } else { - ERROR_LOG(SYSTEM, "Couldn't read directory '%s' specified by memstick_dir.txt.", memstickDir.c_str()); - g_Config.memStickDirectory.clear(); - } - } - } - else { - INFO_LOG(SYSTEM, "No memstick directory file found (tried to open '%s')", memstickDirFile.c_str()); + CreateDirectoriesAndroid(); } + #elif PPSSPP_PLATFORM(IOS) g_Config.defaultCurrentDirectory = g_Config.internalDataDirectory; g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse(); g_Config.flash0Directory = Path(std::string(external_dir)) / "flash0"; #elif PPSSPP_PLATFORM(MAC) + g_Config.defaultCurrentDirectory = Path(getenv("HOME")); g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse(); g_Config.flash0Directory = Path(std::string(external_dir)) / "flash0"; #elif PPSSPP_PLATFORM(SWITCH) @@ -540,9 +539,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } #endif +#if (PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)) || PPSSPP_PLATFORM(MAC) if (g_Config.currentDirectory.empty()) { - g_Config.currentDirectory = g_Config.defaultCurrentDirectory; + g_Config.currentDirectory = Path("/"); } +#endif if (cache_dir && strlen(cache_dir)) { g_Config.appCacheDirectory = Path(cache_dir); @@ -572,9 +573,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch boot_filename.clear(); // Parse command line - LogLevel logLevel = LogLevel::LINFO; + LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO; bool forceLogLevel = false; - const auto setLogLevel = [&logLevel, &forceLogLevel](LogLevel level) { + const auto setLogLevel = [&logLevel, &forceLogLevel](LogTypes::LOG_LEVELS level) { logLevel = level; forceLogLevel = true; }; @@ -592,12 +593,12 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch case 'd': // Enable debug logging // Note that you must also change the max log level in Log.h. - setLogLevel(LogLevel::LDEBUG); + setLogLevel(LogTypes::LDEBUG); break; case 'v': // Enable verbose logging // Note that you must also change the max log level in Log.h. - setLogLevel(LogLevel::LVERBOSE); + setLogLevel(LogTypes::LVERBOSE); break; case 'j': g_Config.iCpuCore = (int)CPUCore::JIT; @@ -608,16 +609,12 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_Config.bSaveSettings = false; break; case 'r': - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; - g_Config.bSaveSettings = false; - break; - case 'J': - g_Config.iCpuCore = (int)CPUCore::JIT_IR; + g_Config.iCpuCore = (int)CPUCore::IR_JIT; g_Config.bSaveSettings = false; break; case '-': if (!strncmp(argv[i], "--loglevel=", strlen("--loglevel=")) && strlen(argv[i]) > strlen("--loglevel=")) - setLogLevel(static_cast(std::atoi(argv[i] + strlen("--loglevel=")))); + setLogLevel(static_cast(std::atoi(argv[i] + strlen("--loglevel=")))); if (!strncmp(argv[i], "--log=", strlen("--log=")) && strlen(argv[i]) > strlen("--log=")) fileToLog = argv[i] + strlen("--log="); if (!strncmp(argv[i], "--state=", strlen("--state=")) && strlen(argv[i]) > strlen("--state=")) @@ -763,25 +760,16 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch #endif // TODO: Load these in the background instead of synchronously. - g_BackgroundAudio.SFX().LoadSamples(); + g_BackgroundAudio.LoadSamples(); if (!boot_filename.empty() && stateToLoad.Valid()) { SaveState::Load(stateToLoad, -1, [](SaveState::Status status, const std::string &message, void *) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { - g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, - message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); + osm.Show(message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); } }); } - if (g_Config.bAchievementsEnable) { - FILE *iconCacheFile = File::OpenCFile(GetSysDirectory(DIRECTORY_CACHE) / "icon.cache", "rb"); - if (iconCacheFile) { - g_iconCache.LoadFromFile(iconCacheFile); - fclose(iconCacheFile); - } - } - DEBUG_LOG(SYSTEM, "ScreenManager!"); g_screenManager = new ScreenManager(); if (g_Config.memStickDirectory.empty()) { @@ -798,8 +786,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::DEFAULT)); } - g_screenManager->SetOverlayScreen(new OSDOverlayScreen()); - // Easy testing // screenManager->push(new GPUDriverTestScreen()); @@ -816,27 +802,20 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // We do this here, instead of in NativeInitGraphics, because the display may be reset. // When it's reset we don't want to forget all our managed things. CheckFailedGPUBackends(); - SetGPUBackend((GPUBackend)g_Config.iGPUBackend); + SetGPUBackend((GPUBackend) g_Config.iGPUBackend); renderCounter = 0; - // Initialize retro achievements runtime. - Achievements::Initialize(); - -#if !defined(__LIBRETRO__) - g_gameDB.LoadFromVFS(g_VFS, "redump.csv"); -#endif - // Must be done restarting by now. restarting = false; } -void CallbackPostRender(UIContext *dc, void *userdata); +void RenderOverlays(UIContext *dc, void *userdata); bool CreateGlobalPipelines(); bool NativeInitGraphics(GraphicsContext *graphicsContext) { INFO_LOG(SYSTEM, "NativeInitGraphics"); - _assert_msg_(g_screenManager, "No screenmanager, bad init order. Backend = %d", g_Config.iGPUBackend); + _assert_(g_screenManager); // We set this now so any resize during init is processed later. resized = false; @@ -869,7 +848,7 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { g_screenManager->setUIContext(uiContext); g_screenManager->setDrawContext(g_draw); - g_screenManager->setPostRenderCallback(&CallbackPostRender, nullptr); + g_screenManager->setPostRenderCallback(&RenderOverlays, nullptr); g_screenManager->deviceRestored(); #ifdef _WIN32 @@ -893,8 +872,6 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { g_gameInfoCache = new GameInfoCache(); if (gpu) { - PSP_CoreParameter().pixelWidth = g_display.pixel_xres; - PSP_CoreParameter().pixelHeight = g_display.pixel_yres; gpu->DeviceRestore(g_draw); } @@ -1004,7 +981,9 @@ void NativeShutdownGraphics() { INFO_LOG(SYSTEM, "NativeShutdownGraphics done"); } -static void TakeScreenshot() { +void TakeScreenshot() { + g_TakeScreenshot = false; + Path path = GetSysDirectory(DIRECTORY_SCREENSHOT); if (!File::Exists(path)) { File::CreateDir(path); @@ -1029,22 +1008,57 @@ static void TakeScreenshot() { bool success = TakeGameScreenshot(filename, g_Config.bScreenshotsAsPNG ? ScreenshotFormat::PNG : ScreenshotFormat::JPG, SCREENSHOT_OUTPUT); if (success) { - g_OSD.Show(OSDType::MESSAGE_FILE_LINK, filename.ToString()); + osm.Show(filename.ToVisualString()); } else { auto err = GetI18NCategory(I18NCat::ERRORS); - g_OSD.Show(OSDType::MESSAGE_ERROR, err->T("Could not save screenshot file")); + osm.Show(err->T("Could not save screenshot file")); } } -void CallbackPostRender(UIContext *dc, void *userdata) { +void RenderOverlays(UIContext *dc, void *userdata) { + // Thin bar at the top of the screen. + std::vector progress = g_DownloadManager.GetCurrentProgress(); + if (!progress.empty()) { + static const uint32_t colors[4] = { + 0xFFFFFFFF, + 0xFFCCCCCC, + 0xFFAAAAAA, + 0xFF777777, + }; + + dc->Begin(); + int h = 5; + for (size_t i = 0; i < progress.size(); i++) { + float barWidth = 10 + (dc->GetBounds().w - 10) * progress[i]; + Bounds bounds(0, h * i, barWidth, h); + UI::Drawable solid(colors[i & 3]); + dc->FillRect(solid, bounds); + } + dc->Flush(); + } + if (g_TakeScreenshot) { TakeScreenshot(); - g_TakeScreenshot = false; } } -static Matrix4x4 ComputeOrthoMatrix(float xres, float yres) { - // TODO: Should be able to share the y-flip logic here with the one in postprocessing/presentation, for example. +void NativeRender(GraphicsContext *graphicsContext) { + _dbg_assert_(graphicsContext != nullptr); + _dbg_assert_(g_screenManager != nullptr); + + g_GameManager.Update(); + + if (GetUIState() != UISTATE_INGAME) { + // Note: We do this from NativeRender so that the graphics context is + // guaranteed valid, to be safe - g_gameInfoCache messes around with textures. + g_BackgroundAudio.Update(); + } + + float xres = g_display.dp_xres; + float yres = g_display.dp_yres; + + // Apply the UIContext bounds as a 2D transformation matrix. + // TODO: This should be moved into the draw context... Matrix4x4 ortho; switch (GetGPUBackend()) { case GPUBackend::VULKAN: @@ -1072,102 +1086,25 @@ static Matrix4x4 ComputeOrthoMatrix(float xres, float yres) { if (g_display.rotation != DisplayRotation::ROTATE_0) { ortho = ortho * g_display.rot_matrix; } - return ortho; -} - -void NativeFrame(GraphicsContext *graphicsContext) { - PROFILE_END_FRAME(); - - bool menuThrottle = (GetUIState() != UISTATE_INGAME || !PSP_IsInited()) && GetUIState() != UISTATE_EXIT; - - double startTime; - if (menuThrottle) { - startTime = time_now_d(); - } - - std::vector toProcess; - { - std::lock_guard lock(pendingMutex); - toProcess = std::move(pendingMessages); - pendingMessages.clear(); - } - - for (const auto &item : toProcess) { - if (HandleGlobalMessage(item.message, item.value)) { - // TODO: Add a to-string thingy. - INFO_LOG(SYSTEM, "Handled global message: %d / %s", (int)item.message, item.value.c_str()); - } - g_screenManager->sendMessage(item.message, item.value.c_str()); - } - - g_requestManager.ProcessRequests(); - - // it's ok to call this redundantly with DoFrame from EmuScreen - Achievements::Idle(); - - g_DownloadManager.Update(); - g_screenManager->update(); - - g_Discord.Update(); - g_BackgroundAudio.Play(); - - g_OSD.Update(); - - UI::SetSoundEnabled(g_Config.bUISound); - - _dbg_assert_(graphicsContext != nullptr); - _dbg_assert_(g_screenManager != nullptr); - - g_GameManager.Update(); - - if (GetUIState() != UISTATE_INGAME) { - // Note: We do this from NativeFrame so that the graphics context is - // guaranteed valid, to be safe - g_gameInfoCache messes around with textures. - g_BackgroundAudio.Update(); - } - - // Apply the UIContext bounds as a 2D transformation matrix. - // TODO: This should be moved into the draw context... - Matrix4x4 ortho = ComputeOrthoMatrix(g_display.dp_xres, g_display.dp_yres); - - Draw::DebugFlags debugFlags = Draw::DebugFlags::NONE; - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::GPU_PROFILE) - debugFlags |= Draw::DebugFlags::PROFILE_TIMESTAMPS; - if (g_Config.bGpuLogProfiler) - debugFlags |= Draw::DebugFlags::PROFILE_SCOPES; - - g_frameTiming.Reset(g_draw); - - g_draw->BeginFrame(debugFlags); ui_draw2d.PushDrawMatrix(ortho); ui_draw2d_front.PushDrawMatrix(ortho); g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation); + Draw::DebugFlags debugFlags = Draw::DebugFlags::NONE; + if (g_Config.bShowGpuProfile) + debugFlags |= Draw::DebugFlags::PROFILE_TIMESTAMPS; + if (g_Config.bGpuLogProfiler) + debugFlags |= Draw::DebugFlags::PROFILE_SCOPES; + g_screenManager->getDrawContext()->SetDebugFlags(debugFlags); + // All actual rendering happen in here. g_screenManager->render(); if (g_screenManager->getUIContext()->Text()) { g_screenManager->getUIContext()->Text()->OncePerFrame(); } - ui_draw2d.PopDrawMatrix(); - ui_draw2d_front.PopDrawMatrix(); - - g_draw->EndFrame(); - - // This, between EndFrame and Present, is where we should actually wait to do present time management. - // There might not be a meaningful distinction here for all backends.. - - if (renderCounter < 10 && ++renderCounter == 10) { - // We're rendering fine, clear out failure info. - ClearFailedGPUBackends(); - } - - int interval; - Draw::PresentMode presentMode = ComputePresentMode(g_draw, &interval); - g_draw->Present(presentMode, interval); - if (resized) { INFO_LOG(G3D, "Resized flag set - recalculating bounds"); resized = false; @@ -1193,85 +1130,110 @@ void NativeFrame(GraphicsContext *graphicsContext) { #if !PPSSPP_PLATFORM(WINDOWS) && !defined(ANDROID) PSP_CoreParameter().pixelWidth = g_display.pixel_xres; PSP_CoreParameter().pixelHeight = g_display.pixel_yres; - System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED); + NativeMessageReceived("gpu_displayResized", ""); #endif } else { // INFO_LOG(G3D, "Polling graphics context"); graphicsContext->Poll(); } - if (menuThrottle) { - float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); - // Simple throttling to not burn the GPU in the menu. - // TODO: This should move into NativeFrame. Also, it's only necessary in MAILBOX or IMMEDIATE presentation modes. - double diffTime = time_now_d() - startTime; - int sleepTime = (int)(1000.0 / refreshRate) - (int)(diffTime * 1000.0); - if (sleepTime > 0) - sleep_ms(sleepTime); + ui_draw2d.PopDrawMatrix(); + ui_draw2d_front.PopDrawMatrix(); + + if (renderCounter < 10 && ++renderCounter == 10) { + // We're rendering fine, clear out failure info. + ClearFailedGPUBackends(); } } -bool HandleGlobalMessage(UIMessage message, const std::string &value) { - if (message == UIMessage::SAVESTATE_DISPLAY_SLOT) { +void HandleGlobalMessage(const std::string &msg, const std::string &value) { + int nextInputDeviceID = -1; + if (msg == "inputDeviceConnectedID") { + nextInputDeviceID = parseLong(value); + } + else if (msg == "inputDeviceConnected") { + KeyMap::NotifyPadConnected(nextInputDeviceID, value); + } + else if (msg == "savestate_displayslot") { auto sy = GetI18NCategory(I18NCat::SYSTEM); std::string msg = StringFromFormat("%s: %d", sy->T("Savestate Slot"), SaveState::GetCurrentSlot() + 1); // Show for the same duration as the preview. - g_OSD.Show(OSDType::MESSAGE_INFO, msg, 2.0f, "savestate_slot"); - return true; + osm.Show(msg, 2.0f, 0xFFFFFF, -1, true, "savestate_slot"); } - else if (message == UIMessage::GPU_DISPLAY_RESIZED) { + else if (msg == "gpu_displayResized") { if (gpu) { gpu->NotifyDisplayResized(); } - return true; } - else if (message == UIMessage::GPU_RENDER_RESIZED) { + else if (msg == "gpu_renderResized") { if (gpu) { gpu->NotifyRenderResized(); } - return true; } - else if (message == UIMessage::GPU_CONFIG_CHANGED) { + else if (msg == "gpu_configChanged") { if (gpu) { gpu->NotifyConfigChanged(); } Reporting::UpdateConfig(); - return true; } - else if (message == UIMessage::POWER_SAVING) { + else if (msg == "core_powerSaving") { if (value != "false") { auto sy = GetI18NCategory(I18NCat::SYSTEM); #if PPSSPP_PLATFORM(ANDROID) - g_OSD.Show(OSDType::MESSAGE_WARNING, sy->T("WARNING: Android battery save mode is on"), 2.0f, "core_powerSaving"); + osm.Show(sy->T("WARNING: Android battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving"); #else - g_OSD.Show(OSDType::MESSAGE_WARNING, sy->T("WARNING: Battery save mode is on"), 2.0f, "core_powerSaving"); + osm.Show(sy->T("WARNING: Battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving"); #endif } Core_SetPowerSaving(value != "false"); - return true; } - else if (message == UIMessage::PERMISSION_GRANTED && value == "storage") { - CreateSysDirectories(); + else if (msg == "permission_granted" && value == "storage") { +#if PPSSPP_PLATFORM(ANDROID) + CreateDirectoriesAndroid(); +#endif // We must have failed to load the config before, so load it now to avoid overwriting the old config // with a freshly generated one. // NOTE: If graphics backend isn't what's in the config (due to error fallback, or not matching the default // and then getting permission), it will get out of sync. So we save and restore g_Config.iGPUBackend. - // Ideally we should simply reinitialize graphics to the mode from the config, but there are potential issues. + // Ideally we should simply reinitialize graphics to the mode from the config, but there are potential issues + // and I can't risk it before 1.9.0. int gpuBackend = g_Config.iGPUBackend; INFO_LOG(IO, "Reloading config after storage permission grant."); g_Config.Reload(); PostLoadConfig(); g_Config.iGPUBackend = gpuBackend; - return true; - } else if (message == UIMessage::APP_RESUMED || message == UIMessage::GOT_FOCUS) { + } else if (msg == "app_resumed" || msg == "got_focus") { // Assume that the user may have modified things. MemoryStick_NotifyWrite(); - return true; - } else { - return false; } } +void NativeUpdate() { + PROFILE_END_FRAME(); + + std::vector toProcess; + { + std::lock_guard lock(pendingMutex); + toProcess = std::move(pendingMessages); + pendingMessages.clear(); + } + + for (const auto &item : toProcess) { + HandleGlobalMessage(item.msg, item.value); + g_screenManager->sendMessage(item.msg.c_str(), item.value.c_str()); + } + + g_requestManager.ProcessRequests(); + + g_DownloadManager.Update(); + g_screenManager->update(); + + g_Discord.Update(); + g_BackgroundAudio.Play(); + + UI::SetSoundEnabled(g_Config.bUISound); +} + bool NativeIsAtTopLevel() { // This might need some synchronization? if (!g_screenManager) { @@ -1308,14 +1270,6 @@ bool NativeKey(const KeyInput &key) { return false; } -#if PPSSPP_PLATFORM(UWP) - // Ignore if key sent from OnKeyDown/OnKeyUp/XInput while text edit active - // it's already handled by `OnCharacterReceived` - if (IgnoreInput(key.keyCode) && !(key.flags & KEY_CHAR)) { - return false; - } -#endif - // INFO_LOG(SYSTEM, "Key code: %i flags: %i", key.keyCode, key.flags); #if !defined(MOBILE_DEVICE) if (g_Config.bPauseExitsEmulator) { @@ -1345,9 +1299,9 @@ bool NativeKey(const KeyInput &key) { return retval; } -void NativeAxis(const AxisInput *axes, size_t count) { +void NativeAxis(const AxisInput &axis) { // VR actions - if (IsVREnabled() && !UpdateVRAxis(axes, count)) { + if (IsVREnabled() && !UpdateVRAxis(axis)) { return; } @@ -1356,20 +1310,30 @@ void NativeAxis(const AxisInput *axes, size_t count) { return; } - g_screenManager->axis(axes, count); + using namespace TiltEventProcessor; - for (size_t i = 0; i < count; i++) { - const AxisInput &axis = axes[i]; - HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; - } -} + // only do special handling of tilt events if tilt is enabled. + HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; + g_screenManager->axis(axis); -void NativeAccelerometer(float tiltX, float tiltY, float tiltZ) { if (g_Config.iTiltInputType == TILT_NULL) { // if tilt events are disabled, don't do anything special. return; } + // figure out what the current tilt orientation is by checking the axis event + // This is static, since we need to remember where we last were (in terms of orientation) + static float tiltX; + static float tiltY; + static float tiltZ; + + switch (axis.axisId) { + case JOYSTICK_AXIS_ACCELEROMETER_X: tiltX = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Y: tiltY = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Z: tiltZ = axis.value; break; + default: break; + } + // create the base coordinate tilt system from the calibration data. float tiltBaseAngleY = g_Config.fTiltBaseAngleY; @@ -1387,23 +1351,27 @@ void NativeAccelerometer(float tiltX, float tiltY, float tiltZ) { // see [http://developer.android.com/guide/topics/sensors/sensors_overview.html] for details bool landscape = g_display.dp_yres < g_display.dp_xres; // now transform out current tilt to the calibrated coordinate system - TiltEventProcessor::ProcessTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, + ProcessTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, g_Config.bInvertTiltX, g_Config.bInvertTiltY, xSensitivity, ySensitivity); - - HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_ACCELEROMETER_X] = tiltX; - HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_ACCELEROMETER_Y] = tiltY; - HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_ACCELEROMETER_Z] = tiltZ; } -void System_PostUIMessage(UIMessage message, const std::string &value) { +void NativeMessageReceived(const char *message, const char *value) { std::lock_guard lock(pendingMutex); PendingMessage pendingMessage; - pendingMessage.message = message; + pendingMessage.msg = message; pendingMessage.value = value; pendingMessages.push_back(pendingMessage); } +void System_PostUIMessage(const std::string &message, const std::string &value) { + NativeMessageReceived(message.c_str(), value.c_str()); +} + +void System_NotifyUserMessage(const std::string &message, float duration_s, u32 color, const char *id) { + osm.Show(message, duration_s, color, -1, true, id); +} + void NativeResized() { // NativeResized can come from any thread so we just set a flag, then process it later. VERBOSE_LOG(G3D, "NativeResized - setting flag"); @@ -1419,16 +1387,6 @@ bool NativeIsRestarting() { } void NativeShutdown() { - Achievements::Shutdown(); - - if (g_Config.bAchievementsEnable) { - FILE *iconCacheFile = File::OpenCFile(GetSysDirectory(DIRECTORY_CACHE) / "icon.cache", "wb"); - if (iconCacheFile) { - g_iconCache.SaveToFile(iconCacheFile); - fclose(iconCacheFile); - } - } - if (g_screenManager) { g_screenManager->shutdown(); delete g_screenManager; @@ -1447,8 +1405,6 @@ void NativeShutdown() { System_ExitApp(); #endif - g_PortManager.Shutdown(); - net::Shutdown(); g_Discord.Shutdown(); @@ -1473,30 +1429,3 @@ void NativeShutdown() { // Previously we did exit() here on Android but that makes it hard to do things like restart on backend change. // I think we handle most globals correctly or correct-enough now. } - -// In the future, we might make this more sophisticated, such as storing in the app private directory on Android. -// Right now we just store secrets in separate files next to ppsspp.ini. The important thing is keeping them out of it -// since we often ask people to post or send the ini for debugging. -static Path GetSecretPath(const char *nameOfSecret) { - return GetSysDirectory(DIRECTORY_SYSTEM) / ("ppsspp_" + std::string(nameOfSecret) + ".dat"); -} - -// name should be simple alphanumerics to avoid problems on Windows. -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { - Path path = GetSecretPath(nameOfSecret); - if (!File::WriteDataToFile(false, data.data(), (unsigned int)data.size(), path)) { - WARN_LOG(SYSTEM, "Failed to write secret '%s' to path '%s'", nameOfSecret, path.c_str()); - return false; - } - return true; -} - -// On failure, returns an empty string. Good enough since any real secret is non-empty. -std::string NativeLoadSecret(const char *nameOfSecret) { - Path path = GetSecretPath(nameOfSecret); - std::string data; - if (!File::ReadFileToString(false, path, data)) { - data.clear(); // just to be sure. - } - return data; -} diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 520967388..06d3d2f9f 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -1,485 +1,73 @@ #include #include - #include "UI/OnScreenDisplay.h" #include "Common/Data/Color/RGBAUtil.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/Render/TextureAtlas.h" #include "Common/Render/DrawBuffer.h" -#include "Common/Math/math_util.h" -#include "Common/UI/IconCache.h" -#include "UI/RetroAchievementScreens.h" -#include "UI/DebugOverlay.h" -#include "UI/Root.h" #include "Common/UI/Context.h" -#include "Common/System/OSD.h" #include "Common/TimeUtil.h" -#include "Common/Net/HTTPClient.h" -#include "Core/Config.h" -static inline const char *DeNull(const char *ptr) { - return ptr ? ptr : ""; -} - -static const float g_atlasIconSize = 36.0f; -static const float extraTextScale = 0.7f; - -static uint32_t GetNoticeBackgroundColor(NoticeLevel type) { - // Colors from Infima - switch (type) { - case NoticeLevel::ERROR: return 0x3530d5; // danger-darker - case NoticeLevel::WARN: return 0x009ed9; // warning-darker - case NoticeLevel::INFO: return 0x706760; // gray-700 - case NoticeLevel::SUCCESS: return 0x008b00; // nice green - default: return 0x606770; - } -} - -static ImageID GetOSDIcon(NoticeLevel level) { - switch (level) { - case NoticeLevel::INFO: return ImageID("I_INFO"); - case NoticeLevel::ERROR: return ImageID("I_CROSS"); - case NoticeLevel::WARN: return ImageID("I_WARNING"); - case NoticeLevel::SUCCESS: return ImageID("I_CHECKMARK"); - default: return ImageID::invalid(); - } -} - -static NoticeLevel GetNoticeLevel(OSDType type) { - switch (type) { - case OSDType::MESSAGE_INFO: return NoticeLevel::INFO; - case OSDType::MESSAGE_ERROR: - case OSDType::MESSAGE_ERROR_DUMP: return NoticeLevel::ERROR; - case OSDType::MESSAGE_WARNING: return NoticeLevel::WARN; - case OSDType::MESSAGE_SUCCESS: return NoticeLevel::SUCCESS; - default: return NoticeLevel::SUCCESS; - } -} - -// Align only matters here for the ASCII-only flag. -static void MeasureNotice(const UIContext &dc, NoticeLevel level, const std::string &text, const std::string &details, const std::string &iconName, int align, float *width, float *height, float *height1) { - dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text.c_str(), width, height, align); - - *height1 = *height; - - float width2 = 0.0f, height2 = 0.0f; - if (!details.empty()) { - dc.MeasureText(dc.theme->uiFont, extraTextScale, extraTextScale, details.c_str(), &width2, &height2, align); - *width = std::max(*width, width2); - *height += 5.0f + height2; - } - - float iconW = 0.0f; - float iconH = 0.0f; - if (!iconName.empty() && !startsWith(iconName, "I_")) { // Check for atlas image. Bit hacky, but we choose prefixes for icon IDs anyway in a way that this is safe. - // Normal entry but with a cached icon. - int iconWidth, iconHeight; - if (g_iconCache.GetDimensions(iconName, &iconWidth, &iconHeight)) { - *width += 5.0f + iconWidth; - iconW = iconWidth; - iconH = iconHeight; - } - } else { - ImageID iconID = iconName.empty() ? GetOSDIcon(level) : ImageID(iconName.c_str()); - if (iconID.isValid()) { - dc.Draw()->GetAtlas()->measureImage(iconID, &iconW, &iconH); - } - } - - iconW += 5.0f; - - *width += iconW + 12.0f; - *height = std::max(*height, iconH + 5.0f); -} - -// Align only matters here for the ASCII-only flag. -static void MeasureOSDEntry(const UIContext &dc, const OnScreenDisplay::Entry &entry, int align, float *width, float *height, float *height1) { - if (entry.type == OSDType::ACHIEVEMENT_UNLOCKED) { - const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - MeasureAchievement(dc, achievement, AchievementRenderStyle::UNLOCKED, width, height); - *width = 550.0f; - *height1 = *height; - } else { - MeasureNotice(dc, GetNoticeLevel(entry.type), entry.text, entry.text2, entry.iconName, align, width, height, height1); - } -} - -static void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, const std::string &text, const std::string &details, const std::string &iconName, int align, float alpha) { - UI::Drawable background = UI::Drawable(colorAlpha(GetNoticeBackgroundColor(level), alpha)); - - uint32_t foreGround = whiteAlpha(alpha); - - dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); - dc.FillRect(background, bounds); - - float iconW = 0.0f; - float iconH = 0.0f; - if (!iconName.empty() && !startsWith(iconName, "I_")) { - dc.Flush(); - // Normal entry but with a cached icon. - Draw::Texture *texture = g_iconCache.BindIconTexture(&dc, iconName); - if (texture) { - iconW = texture->Width(); - iconH = texture->Height(); - dc.Draw()->DrawTexRect(Bounds(bounds.x + 2.5f, bounds.y + 2.5f, iconW, iconH), 0.0f, 0.0f, 1.0f, 1.0f, foreGround); - dc.Flush(); - dc.RebindTexture(); - } - dc.Begin(); - } else { - ImageID iconID = iconName.empty() ? GetOSDIcon(level) : ImageID(iconName.c_str()); - if (iconID.isValid()) { - // Atlas icon. - dc.Draw()->GetAtlas()->measureImage(iconID, &iconW, &iconH); - Bounds iconBounds = Bounds(bounds.x + 2.5f, bounds.y + 2.5f, iconW, iconH); - if (!iconName.empty()) { - // If it's not a preset OSD icon, give it some background to blend in. The RA icon for example - // easily melts into the orange of warnings otherwise. - dc.FillRect(UI::Drawable(0x50000000), iconBounds.Expand(2.0f)); - } - dc.DrawImageVGradient(iconID, foreGround, foreGround, Bounds(bounds.x + 2.5f, bounds.y + 2.5f, iconW, iconH)); - } - } - - // Make room - bounds.x += iconW + 5.0f; - bounds.w -= iconW + 5.0f; - - dc.DrawTextShadowRect(text.c_str(), bounds.Inset(0.0f, 1.0f, 0.0f, 0.0f), foreGround, (align & FLAG_DYNAMIC_ASCII)); - - if (!details.empty()) { - Bounds bottomTextBounds = bounds.Inset(3.0f, height1 + 5.0f, 3.0f, 3.0f); - UI::Drawable backgroundDark = UI::Drawable(colorAlpha(darkenColor(GetNoticeBackgroundColor(level)), alpha)); - dc.FillRect(backgroundDark, bottomTextBounds); - dc.SetFontScale(extraTextScale, extraTextScale); - dc.DrawTextRect(details.c_str(), bottomTextBounds, foreGround, (align & FLAG_DYNAMIC_ASCII) | ALIGN_LEFT); - } - dc.SetFontScale(1.0f, 1.0f); -} - -static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, Bounds bounds, float height1, int align, float alpha) { - if (entry.type == OSDType::ACHIEVEMENT_UNLOCKED) { - const rc_client_achievement_t * achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - if (achievement) { - RenderAchievement(dc, achievement, AchievementRenderStyle::UNLOCKED, bounds, alpha, entry.startTime, time_now_d(), false); - } - return; - } else { - RenderNotice(dc, bounds, height1, GetNoticeLevel(entry.type), entry.text, entry.text2, entry.iconName, align, alpha); - } -} - -static void MeasureOSDProgressBar(const UIContext &dc, const OnScreenDisplay::Entry &bar, float *width, float *height) { - *height = 36; - *width = 450.0f; -} - -static void RenderOSDProgressBar(UIContext &dc, const OnScreenDisplay::Entry &entry, Bounds bounds, int align, float alpha) { - uint32_t foreGround = whiteAlpha(alpha); - - dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); - - uint32_t backgroundColor = colorAlpha(0x806050, alpha); - uint32_t progressBackgroundColor = colorAlpha(0xa08070, alpha); - - if (entry.maxValue > entry.minValue) { - // Normal progress bar - - UI::Drawable background = UI::Drawable(backgroundColor); - UI::Drawable progressBackground = UI::Drawable(progressBackgroundColor); - - float ratio = (float)(entry.progress - entry.minValue) / (float)entry.maxValue; - - Bounds boundLeft = bounds; - Bounds boundRight = bounds; - - boundLeft.w *= ratio; - boundRight.x += ratio * boundRight.w; - boundRight.w *= (1.0f - ratio); - - dc.FillRect(progressBackground, boundLeft); - dc.FillRect(background, boundRight); - } else { - // Indeterminate spinner - float alpha = cos(time_now_d() * 5.0) * 0.5f + 0.5f; - uint32_t pulse = colorBlend(backgroundColor, progressBackgroundColor, alpha); - UI::Drawable background = UI::Drawable(pulse); - dc.FillRect(background, bounds); - } - - dc.SetFontStyle(dc.theme->uiFont); - dc.SetFontScale(1.0f, 1.0f); - - dc.DrawTextShadowRect(entry.text.c_str(), bounds, colorAlpha(0xFFFFFFFF, alpha), (align & FLAG_DYNAMIC_ASCII) | ALIGN_CENTER); -} - -static void MeasureLeaderboardTracker(UIContext &dc, const std::string &text, float *width, float *height) { - dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, text.c_str(), width, height); - *width += 16.0f; - *height += 10.0f; -} - -static void RenderLeaderboardTracker(UIContext &dc, const Bounds &bounds, const std::string &text, float alpha) { - // TODO: Awful color. - uint32_t backgroundColor = colorAlpha(0x806050, alpha); - UI::Drawable background = UI::Drawable(backgroundColor); - dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); - dc.FillRect(background, bounds); - dc.SetFontStyle(dc.theme->uiFont); - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextShadowRect(text.c_str(), bounds.Inset(5.0f, 5.0f), colorAlpha(0xFFFFFFFF, alpha), ALIGN_VCENTER | ALIGN_HCENTER); -} +OnScreenMessages osm; void OnScreenMessagesView::Draw(UIContext &dc) { - if (!g_Config.bShowOnScreenMessages) { - return; - } + // First, clean out old messages. + osm.Lock(); + osm.Clean(); - dc.Flush(); + // Get height + float w, h; + dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, "Wg", &w, &h); + float y = 10.0f; + // Then draw them all. + const std::list &messages = osm.Messages(); double now = time_now_d(); + for (auto iter = messages.begin(); iter != messages.end(); ++iter) { + float alpha = (iter->endTime - now) * 4.0f; + if (alpha > 1.0) alpha = 1.0f; + if (alpha < 0.0) alpha = 0.0f; + dc.SetFontScale(1.0f, 1.0f); + // Messages that are wider than the screen are left-aligned instead of centered. - const float padding = 5.0f; - - const float fadeinCoef = 1.0f / OnScreenDisplay::FadeinTime(); - const float fadeoutCoef = 1.0f / OnScreenDisplay::FadeoutTime(); - - float sidebarAlpha = g_OSD.SidebarAlpha(); - - struct LayoutEdge { - float height; - float maxWidth; - float alpha; - }; - - struct MeasuredEntry { - float w; - float h; - float h1; - float alpha; - int align; - int align2; - AchievementRenderStyle style; - }; - - // Grab all the entries. Makes a copy so we can release the lock ASAP. - const std::vector entries = g_OSD.Entries(); - - std::vector measuredEntries; - measuredEntries.resize(entries.size()); - - // Indexed by the enum ScreenEdgePosition. - LayoutEdge edges[(size_t)ScreenEdgePosition::VALUE_COUNT]{}; - for (size_t i = 0; i < (size_t)ScreenEdgePosition::VALUE_COUNT; i++) { - edges[i].alpha = sidebarAlpha; - } - edges[(size_t)ScreenEdgePosition::TOP_CENTER].alpha = 1.0f; - - ScreenEdgePosition typeEdges[(size_t)OSDType::VALUE_COUNT]{}; - // Default to top. - for (int i = 0; i < (size_t)OSDType::VALUE_COUNT; i++) { - typeEdges[i] = ScreenEdgePosition::TOP_CENTER; - } - - typeEdges[(size_t)OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR] = (ScreenEdgePosition)g_Config.iAchievementsChallengePos; - typeEdges[(size_t)OSDType::ACHIEVEMENT_PROGRESS] = (ScreenEdgePosition)g_Config.iAchievementsProgressPos; - typeEdges[(size_t)OSDType::LEADERBOARD_TRACKER] = (ScreenEdgePosition)g_Config.iAchievementsLeaderboardTrackerPos; - typeEdges[(size_t)OSDType::LEADERBOARD_STARTED_FAILED] = (ScreenEdgePosition)g_Config.iAchievementsLeaderboardStartedOrFailedPos; - typeEdges[(size_t)OSDType::LEADERBOARD_SUBMITTED] = (ScreenEdgePosition)g_Config.iAchievementsLeaderboardSubmittedPos; - typeEdges[(size_t)OSDType::ACHIEVEMENT_UNLOCKED] = (ScreenEdgePosition)g_Config.iAchievementsUnlockedPos; - - dc.SetFontScale(1.0f, 1.0f); - - // First pass: Measure all the sides. - for (size_t i = 0; i < entries.size(); i++) { - const auto &entry = entries[i]; - auto &measuredEntry = measuredEntries[i]; - - ScreenEdgePosition pos = typeEdges[(size_t)entry.type]; - if (pos == ScreenEdgePosition::VALUE_COUNT || pos == (ScreenEdgePosition)-1) { - // NONE. - continue; - } - - measuredEntry.align = 0; - measuredEntry.align2 = 0; + int align = 0; // If we have newlines, we may be looking at ASCII debug output. But let's verify. - if (entry.text.find('\n') != std::string::npos) { - if (!UTF8StringHasNonASCII(entry.text.c_str())) - measuredEntry.align |= FLAG_DYNAMIC_ASCII; - } - if (entry.text2.find('\n') != std::string::npos) { - if (!UTF8StringHasNonASCII(entry.text2.c_str())) - measuredEntry.align2 |= FLAG_DYNAMIC_ASCII; + if (iter->text.find('\n') != 0) { + if (!UTF8StringHasNonASCII(iter->text.c_str())) + align |= FLAG_DYNAMIC_ASCII; } - switch (entry.type) { - case OSDType::ACHIEVEMENT_PROGRESS: - { - const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - if (!achievement) - continue; - measuredEntry.style = AchievementRenderStyle::PROGRESS_INDICATOR; - MeasureAchievement(dc, achievement, measuredEntry.style, &measuredEntry.w, &measuredEntry.h); - break; + float tw, th; + dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, iter->text.c_str(), &tw, &th, align); + float x = bounds_.centerX(); + if (tw > bounds_.w) { + align |= ALIGN_TOP | ALIGN_LEFT; + x = 2; + } else { + align |= ALIGN_TOP | ALIGN_HCENTER; } - case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: - { - const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - if (!achievement) - continue; - measuredEntry.style = AchievementRenderStyle::CHALLENGE_INDICATOR; - MeasureAchievement(dc, achievement, measuredEntry.style, &measuredEntry.w, &measuredEntry.h); - break; + float scale = 1.0f; + if (th > bounds_.h - y) { + // Scale down! + scale = std::max(0.15f, (bounds_.h - y) / th); + dc.SetFontScale(scale, scale); } - case OSDType::LEADERBOARD_TRACKER: - { - MeasureLeaderboardTracker(dc, entry.text, &measuredEntry.w, &measuredEntry.h); - break; - } - case OSDType::ACHIEVEMENT_UNLOCKED: - { - const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - if (!achievement) - continue; - measuredEntry.style = AchievementRenderStyle::UNLOCKED; - MeasureAchievement(dc, achievement, AchievementRenderStyle::UNLOCKED, &measuredEntry.w, &measuredEntry.h); - measuredEntry.h1 = measuredEntry.h; - measuredEntry.w = 550.0f; - break; - } - case OSDType::PROGRESS_BAR: - MeasureOSDProgressBar(dc, entry, &measuredEntry.w, &measuredEntry.h); - break; - default: - MeasureOSDEntry(dc, entry, measuredEntry.align, &measuredEntry.w, &measuredEntry.h, &measuredEntry.h1); - break; - } - - float enterAlpha = saturatef((float)(now - entry.startTime) * fadeoutCoef); - float leaveAlpha = saturatef((float)(entry.endTime - now) * fadeoutCoef); - float alpha = std::min(enterAlpha, leaveAlpha); - measuredEntry.alpha = alpha; - - edges[(size_t)pos].height += (measuredEntry.h + 4.0f) * alpha; - edges[(size_t)pos].maxWidth = std::max(edges[(size_t)pos].maxWidth, measuredEntry.w); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawTextShadow(iter->text.c_str(), x, y, colorAlpha(iter->color, alpha), align); + y += th * scale; } - std::vector dismissZones; - - // Now, perform layout for all 8 edges. - for (size_t i = 0; i < (size_t)ScreenEdgePosition::VALUE_COUNT; i++) { - if (edges[i].height == 0.0f) { - // Nothing on this side, ignore it entirely. - continue; - } - - // First, compute the start position. - float y = padding; - int horizAdj = 0; - int vertAdj = 0; - switch ((ScreenEdgePosition)i) { - case ScreenEdgePosition::TOP_LEFT: horizAdj = -1; vertAdj = -1; break; - case ScreenEdgePosition::CENTER_LEFT: horizAdj = -1; break; - case ScreenEdgePosition::BOTTOM_LEFT: horizAdj = -1; vertAdj = 1; break; - case ScreenEdgePosition::TOP_RIGHT: horizAdj = 1; vertAdj = -1; break; - case ScreenEdgePosition::CENTER_RIGHT: horizAdj = 1; break; - case ScreenEdgePosition::BOTTOM_RIGHT: horizAdj = 1; vertAdj = 1; break; - case ScreenEdgePosition::TOP_CENTER: vertAdj = -1; break; - case ScreenEdgePosition::BOTTOM_CENTER: vertAdj = 1; break; - default: break; - } - - if (vertAdj == 0) { - // Center vertically - y = (bounds_.h - edges[i].height) * 0.5f; - } else if (vertAdj == 1) { - y = (bounds_.h - edges[i].height); - } - - // Then, loop through the entries and those belonging here, get rendered here. - for (size_t j = 0; j < (size_t)entries.size(); j++) { - auto &entry = entries[j]; - if (typeEdges[(size_t)entry.type] != (ScreenEdgePosition)i) { // yes, i - continue; - } - auto &measuredEntry = measuredEntries[j]; - float alpha = measuredEntry.alpha * edges[i].alpha; - - Bounds b(padding, y, measuredEntry.w, measuredEntry.h); - - if (horizAdj == 0) { - // Centered - b.x = (bounds_.w - b.w) * 0.5f; - } else if (horizAdj == 1) { - // Right-aligned - b.x = bounds_.w - (b.w + padding); - } - - switch (entry.type) { - case OSDType::ACHIEVEMENT_PROGRESS: - case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: - { - const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - RenderAchievement(dc, achievement, measuredEntry.style, b, alpha, entry.startTime, now, false); - break; - } - case OSDType::LEADERBOARD_TRACKER: - RenderLeaderboardTracker(dc, b, entry.text, alpha); - break; - case OSDType::PROGRESS_BAR: - RenderOSDProgressBar(dc, entry, b, 0, alpha); - break; - default: - { - // Scale down if height doesn't fit. - float scale = 1.0f; - if (measuredEntry.h > bounds_.h - y) { - // Scale down! - scale = std::max(0.15f, (bounds_.h - y) / measuredEntry.h); - dc.SetFontScale(scale, scale); - b.w *= scale; - b.h *= scale; - } - - float alpha = Clamp((float)(entry.endTime - now) * 4.0f, 0.0f, 1.0f); - RenderOSDEntry(dc, entry, b, measuredEntry.h1, measuredEntry.align, alpha); - - switch (entry.type) { - case OSDType::MESSAGE_INFO: - case OSDType::MESSAGE_SUCCESS: - case OSDType::MESSAGE_WARNING: - case OSDType::MESSAGE_ERROR: - case OSDType::MESSAGE_ERROR_DUMP: - case OSDType::MESSAGE_FILE_LINK: - case OSDType::ACHIEVEMENT_UNLOCKED: - // Save the location of the popup, for easy dismissal. - dismissZones.push_back(ClickZone{ (int)j, b }); - break; - default: - break; - } - break; - } - } - - - y += (measuredEntry.h + 4.0f) * measuredEntry.alpha; - } - } - - std::lock_guard lock(clickMutex_); - clickZones_ = dismissZones; + osm.Unlock(); } std::string OnScreenMessagesView::DescribeText() const { std::stringstream ss; - const auto &entries = g_OSD.Entries(); - for (auto iter = entries.begin(); iter != entries.end(); ++iter) { - if (iter != entries.begin()) { + const auto &messages = osm.Messages(); + for (auto iter = messages.begin(); iter != messages.end(); ++iter) { + if (iter != messages.begin()) { ss << "\n"; } ss << iter->text; @@ -487,73 +75,42 @@ std::string OnScreenMessagesView::DescribeText() const { return ss.str(); } -// Asynchronous! -bool OnScreenMessagesView::Dismiss(float x, float y) { - bool dismissed = false; - std::lock_guard lock(clickMutex_); +void OnScreenMessages::Clean() { +restart: double now = time_now_d(); - for (auto &zone : clickZones_) { - if (zone.bounds.Contains(x, y)) { - g_OSD.DismissEntry(zone.index, now); - dismissed = true; + for (auto iter = messages_.begin(); iter != messages_.end(); iter++) { + if (iter->endTime < now) { + messages_.erase(iter); + goto restart; } } - return dismissed; } -bool OSDOverlayScreen::UnsyncTouch(const TouchInput &touch) { - // Don't really need to forward. - // UIScreen::UnsyncTouch(touch); - if ((touch.flags & TOUCH_DOWN) && osmView_) { - return osmView_->Dismiss(touch.x, touch.y); - } else { - return false; +void OnScreenMessages::Show(const std::string &text, float duration_s, uint32_t color, int icon, bool checkUnique, const char *id) { + double now = time_now_d(); + std::lock_guard guard(mutex_); + if (checkUnique) { + for (auto iter = messages_.begin(); iter != messages_.end(); ++iter) { + if (iter->text == text || (id && iter->id && !strcmp(iter->id, id))) { + Message msg = *iter; + msg.endTime = now + duration_s; + msg.text = text; + msg.color = color; + messages_.erase(iter); + messages_.insert(messages_.begin(), msg); + return; + } + } } + Message msg; + msg.text = text; + msg.color = color; + msg.endTime = now + duration_s; + msg.icon = icon; + msg.id = id; + messages_.insert(messages_.begin(), msg); } -void OSDOverlayScreen::CreateViews() { - root_ = new UI::AnchorLayout(); - root_->SetTag("OSDOverlayScreen"); - osmView_ = root_->Add(new OnScreenMessagesView(new UI::AnchorLayoutParams(0.0f, 0.0f, 0.0f, 0.0f))); -} - -void OSDOverlayScreen::render() { - UIScreen::render(); - - DebugOverlay debugOverlay = (DebugOverlay)g_Config.iDebugOverlay; - - // Special case control for now, since it uses the control mapper that's owned by EmuScreen. - if (debugOverlay != DebugOverlay::OFF && debugOverlay != DebugOverlay::CONTROL) { - UIContext *uiContext = screenManager()->getUIContext(); - DrawDebugOverlay(uiContext, uiContext->GetLayoutBounds(), debugOverlay); - } -} - -void OSDOverlayScreen::update() { - // Partial version of UIScreen::update() but doesn't do event processing to avoid duplicate event processing. - bool vertical = UseVerticalLayout(); - if (vertical != lastVertical_) { - RecreateViews(); - lastVertical_ = vertical; - } - - DoRecreateViews(); -} - -void NoticeView::GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec horiz, UI::MeasureSpec vert, float &w, float &h) const { - Bounds bounds(0, 0, layoutParams_->width, layoutParams_->height); - if (bounds.w < 0) { - // If there's no size, let's grow as big as we want. - bounds.w = horiz.size; - } - if (bounds.h < 0) { - bounds.h = vert.size; - } - - ApplyBoundsBySpec(bounds, horiz, vert); - MeasureNotice(dc, level_, text_, detailsText_, iconName_, 0, &w, &h, &height1_); -} - -void NoticeView::Draw(UIContext &dc) { - RenderNotice(dc, bounds_, height1_, level_, text_, detailsText_, iconName_, 0, 1.0f); +void OnScreenMessages::ShowOnOff(const std::string &message, bool b, float duration_s, uint32_t color, int icon) { + Show(message + (b ? ": on" : ": off"), duration_s, color, icon); } diff --git a/UI/OnScreenDisplay.h b/UI/OnScreenDisplay.h index c22d5478e..7a56c0b08 100644 --- a/UI/OnScreenDisplay.h +++ b/UI/OnScreenDisplay.h @@ -6,77 +6,44 @@ #include "Common/Math/geom2d.h" #include "Common/UI/View.h" -#include "Common/UI/UIScreen.h" -#include "Common/System/System.h" - -#ifdef ERROR -#undef ERROR -#endif class DrawBuffer; -// Infrastructure for rendering overlays. +class OnScreenMessages { +public: + void Show(const std::string &message, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1, bool checkUnique = true, const char *id = nullptr); + void ShowOnOff(const std::string &message, bool b, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1); + bool IsEmpty() const { return messages_.empty(); } + + void Lock() { + mutex_.lock(); + } + void Unlock() { + mutex_.unlock(); + } + + void Clean(); + + struct Message { + int icon; + uint32_t color; + std::string text; + const char *id; + double endTime; + double duration; + }; + const std::list &Messages() { return messages_; } + +private: + std::list messages_; + std::mutex mutex_; +}; class OnScreenMessagesView : public UI::InertView { public: OnScreenMessagesView(UI::LayoutParams *layoutParams = nullptr) : UI::InertView(layoutParams) {} void Draw(UIContext &dc) override; - bool Dismiss(float x, float y); // Not reusing Touch since it's asynchronous. std::string DescribeText() const override; -private: - struct ClickZone { - int index; - Bounds bounds; - }; - - // Argh, would really like to avoid this. - std::mutex clickMutex_; - std::vector clickZones_; }; -class OSDOverlayScreen : public UIScreen { -public: - const char *tag() const override { return "OSDOverlayScreen"; } - - bool UnsyncTouch(const TouchInput &touch) override; - - void CreateViews() override; - void render() override; - void update() override; - -private: - OnScreenMessagesView *osmView_ = nullptr; -}; - -enum class NoticeLevel { - SUCCESS, - INFO, - WARN, - ERROR, -}; - -class NoticeView : public UI::InertView { -public: - NoticeView(NoticeLevel level, std::string_view text, std::string_view detailsText, UI::LayoutParams *layoutParams = 0) - : InertView(layoutParams), level_(level), text_(text), detailsText_(detailsText), iconName_("") {} - - void SetIconName(std::string_view name) { - iconName_ = name; - } - void SetText(std::string_view text) { - text_ = text; - } - void SetLevel(NoticeLevel level) { - level_ = level; - } - - void GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec horiz, UI::MeasureSpec vert, float &w, float &h) const override; - void Draw(UIContext &dc) override; - -private: - std::string text_; - std::string detailsText_; - std::string iconName_; - NoticeLevel level_; - mutable float height1_ = 0.0f; -}; +extern OnScreenMessages osm; diff --git a/UI/PSPNSApplicationDelegate.mm b/UI/PSPNSApplicationDelegate.mm index 36eaf3b59..36aeed84d 100644 --- a/UI/PSPNSApplicationDelegate.mm +++ b/UI/PSPNSApplicationDelegate.mm @@ -6,11 +6,9 @@ // #import - #import "PSPNSApplicationDelegate.h" - -#include "Common/System/System.h" #include "Core/SaveState.h" +#include "Common/System/NativeApp.h" #include "Core/Config.h" @implementation PSPNSApplicationDelegate @@ -28,7 +26,7 @@ NSURL *firstURL = urls.firstObject; if (!firstURL) return; // No URLs, don't do anything - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, firstURL.fileSystemRepresentation); + NativeMessageReceived("boot", firstURL.fileSystemRepresentation); } - (NSMenu *)applicationDockMenu:(NSApplication *)sender { diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index b88a38ec1..ac12066af 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -27,7 +27,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/StringUtils.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "Common/System/Request.h" #include "Common/VR/PPSSPPVR.h" #include "Common/UI/AsyncImageFileView.h" @@ -36,7 +36,6 @@ #include "Core/SaveState.h" #include "Core/System.h" #include "Core/Config.h" -#include "Core/RetroAchievements.h" #include "Core/ELF/ParamSFO.h" #include "Core/HLE/sceDisplay.h" #include "Core/HLE/sceUmd.h" @@ -52,12 +51,10 @@ #include "UI/OnScreenDisplay.h" #include "UI/GameInfoCache.h" #include "UI/DisplayLayoutScreen.h" -#include "UI/RetroAchievementScreens.h" static void AfterSaveStateAction(SaveState::Status status, const std::string &message, void *) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { - g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, - message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); + osm.Show(message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); } } @@ -200,10 +197,8 @@ SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, bool vertical, UI fv->OnClick.Handle(this, &SaveSlotView::OnScreenshotClick); if (SaveState::HasSaveInSlot(gamePath_, slot)) { - if (!Achievements::ChallengeModeActive()) { - loadStateButton_ = buttons->Add(new Button(pa->T("Load State"), new LinearLayoutParams(0.0, G_VCENTER))); - loadStateButton_->OnClick.Handle(this, &SaveSlotView::OnLoadState); - } + loadStateButton_ = buttons->Add(new Button(pa->T("Load State"), new LinearLayoutParams(0.0, G_VCENTER))); + loadStateButton_->OnClick.Handle(this, &SaveSlotView::OnLoadState); std::string dateStr = SaveState::GetSlotDateAsString(gamePath_, slot_); if (!dateStr.empty()) { @@ -263,58 +258,21 @@ void GamePauseScreen::update() { SetVRAppMode(VRAppMode::VR_MENU_MODE); } -GamePauseScreen::GamePauseScreen(const Path &filename) - : UIDialogScreenWithGameBackground(filename) { -} - GamePauseScreen::~GamePauseScreen() { __DisplaySetWasPaused(); } -void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems, bool vertical) { - auto pa = GetI18NCategory(I18NCat::PAUSE); - +void GamePauseScreen::CreateViews() { static const int NUM_SAVESLOTS = 5; using namespace UI; - leftColumnItems->SetSpacing(10.0); - for (int i = 0; i < NUM_SAVESLOTS; i++) { - SaveSlotView *slot = leftColumnItems->Add(new SaveSlotView(gamePath_, i, vertical, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); - slot->OnStateLoaded.Handle(this, &GamePauseScreen::OnState); - slot->OnStateSaved.Handle(this, &GamePauseScreen::OnState); - slot->OnScreenshotClicked.Handle(this, &GamePauseScreen::OnScreenshotClicked); - } - leftColumnItems->Add(new Spacer(0.0)); - - LinearLayout *buttonRow = leftColumnItems->Add(new LinearLayout(ORIENT_HORIZONTAL)); - if (g_Config.bEnableStateUndo && !Achievements::ChallengeModeActive()) { - UI::Choice *loadUndoButton = buttonRow->Add(new Choice(pa->T("Undo last load"))); - loadUndoButton->SetEnabled(SaveState::HasUndoLoad(gamePath_)); - loadUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLoadUndo); - - UI::Choice *saveUndoButton = buttonRow->Add(new Choice(pa->T("Undo last save"))); - saveUndoButton->SetEnabled(SaveState::HasUndoLastSave(gamePath_)); - saveUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLastSaveUndo); - } - - if (g_Config.iRewindSnapshotInterval > 0 && !Achievements::ChallengeModeActive()) { - UI::Choice *rewindButton = buttonRow->Add(new Choice(pa->T("Rewind"))); - rewindButton->SetEnabled(SaveState::CanRewind()); - rewindButton->OnClick.Handle(this, &GamePauseScreen::OnRewind); - } -} - -void GamePauseScreen::CreateViews() { - using namespace UI; - bool vertical = UseVerticalLayout(); - Margins scrollMargins(0, 10, 0, 0); - Margins actionMenuMargins(0, 10, 15, 0); + Margins scrollMargins(0, 20, 0, 0); + Margins actionMenuMargins(0, 20, 15, 0); auto gr = GetI18NCategory(I18NCat::GRAPHICS); auto pa = GetI18NCategory(I18NCat::PAUSE); - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); root_ = new LinearLayout(ORIENT_HORIZONTAL); @@ -325,29 +283,30 @@ void GamePauseScreen::CreateViews() { leftColumn->Add(leftColumnItems); leftColumnItems->Add(new Spacer(0.0)); - if (Achievements::IsActive()) { - leftColumnItems->Add(new GameAchievementSummaryView()); - leftColumnItems->Add(new Spacer(5.0)); + leftColumnItems->SetSpacing(10.0); + for (int i = 0; i < NUM_SAVESLOTS; i++) { + SaveSlotView *slot = leftColumnItems->Add(new SaveSlotView(gamePath_, i, vertical, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + slot->OnStateLoaded.Handle(this, &GamePauseScreen::OnState); + slot->OnStateSaved.Handle(this, &GamePauseScreen::OnState); + slot->OnScreenshotClicked.Handle(this, &GamePauseScreen::OnScreenshotClicked); + } + leftColumnItems->Add(new Spacer(0.0)); + + LinearLayout *buttonRow = leftColumnItems->Add(new LinearLayout(ORIENT_HORIZONTAL)); + if (g_Config.bEnableStateUndo) { + UI::Choice *loadUndoButton = buttonRow->Add(new Choice(pa->T("Undo last load"))); + loadUndoButton->SetEnabled(SaveState::HasUndoLoad(gamePath_)); + loadUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLoadUndo); + + UI::Choice *saveUndoButton = buttonRow->Add(new Choice(pa->T("Undo last save"))); + saveUndoButton->SetEnabled(SaveState::HasUndoLastSave(gamePath_)); + saveUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLastSaveUndo); } - if (!Achievements::ChallengeModeActive() || g_Config.bAchievementsSaveStateInChallengeMode) { - CreateSavestateControls(leftColumnItems, vertical); - } else { - // Let's show the active challenges. - std::set ids = Achievements::GetActiveChallengeIDs(); - if (!ids.empty()) { - leftColumnItems->Add(new ItemHeader(ac->T("Active Challenges"))); - for (auto id : ids) { - const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), id); - if (!achievement) - continue; - leftColumnItems->Add(new AchievementView(achievement)); - } - } - - // And tack on an explanation for why savestate options are not available. - const char *notAvailable = ac->T("Save states not available in Hardcore Mode"); - leftColumnItems->Add(new NoticeView(NoticeLevel::INFO, notAvailable, "")); + if (g_Config.iRewindSnapshotInterval > 0) { + UI::Choice *rewindButton = buttonRow->Add(new Choice(pa->T("Rewind"))); + rewindButton->SetEnabled(SaveState::CanRewind()); + rewindButton->OnClick.Handle(this, &GamePauseScreen::OnRewind); } ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(vertical ? 200 : 300, FILL_PARENT, actionMenuMargins)); @@ -358,10 +317,7 @@ void GamePauseScreen::CreateViews() { rightColumnItems->SetSpacing(0.0f); if (getUMDReplacePermit()) { - rightColumnItems->Add(new Choice(pa->T("Switch UMD")))->OnClick.Add([=](UI::EventParams &) { - screenManager()->push(new UmdReplaceScreen()); - return UI::EVENT_DONE; - }); + rightColumnItems->Add(new Choice(pa->T("Switch UMD")))->OnClick.Handle(this, &GamePauseScreen::OnSwitchUMD); } Choice *continueChoice = rightColumnItems->Add(new Choice(pa->T("Continue"))); root_->SetDefaultFocusView(continueChoice); @@ -383,16 +339,7 @@ void GamePauseScreen::CreateViews() { return UI::EVENT_DONE; }); if (g_Config.bEnableCheats) { - rightColumnItems->Add(new Choice(pa->T("Cheats")))->OnClick.Add([&](UI::EventParams &e) { - screenManager()->push(new CwCheatScreen(gamePath_)); - return UI::EVENT_DONE; - }); - } - if (g_Config.bAchievementsEnable && Achievements::HasAchievementsOrLeaderboards()) { - rightColumnItems->Add(new Choice(ac->T("Achievements")))->OnClick.Add([&](UI::EventParams &e) { - screenManager()->push(new RetroAchievementsListScreen(gamePath_)); - return UI::EVENT_DONE; - }); + rightColumnItems->Add(new Choice(pa->T("Cheats")))->OnClick.Handle(this, &GamePauseScreen::OnCwCheat); } // TODO, also might be nice to show overall compat rating here? @@ -478,6 +425,16 @@ UI::EventReturn GamePauseScreen::OnLastSaveUndo(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn GamePauseScreen::OnCwCheat(UI::EventParams &e) { + screenManager()->push(new CwCheatScreen(gamePath_)); + return UI::EVENT_DONE; +} + +UI::EventReturn GamePauseScreen::OnSwitchUMD(UI::EventParams &e) { + screenManager()->push(new UmdReplaceScreen()); + return UI::EVENT_DONE; +} + void GamePauseScreen::CallbackDeleteConfig(bool yes) { if (yes) { diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index c7e32dc18..f9f0a949a 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -32,7 +32,7 @@ enum class PauseScreenMode { class GamePauseScreen : public UIDialogScreenWithGameBackground { public: - GamePauseScreen(const Path &filename); + GamePauseScreen(const Path &filename) : UIDialogScreenWithGameBackground(filename), gamePath_(filename) {} ~GamePauseScreen(); void dialogFinished(const Screen *dialog, DialogResult dr) override; @@ -45,8 +45,6 @@ protected: void CallbackDeleteConfig(bool yes); private: - void CreateSavestateControls(UI::LinearLayout *viewGroup, bool vertical); - UI::EventReturn OnGameSettings(UI::EventParams &e); UI::EventReturn OnExitToMenu(UI::EventParams &e); UI::EventReturn OnReportFeedback(UI::EventParams &e); @@ -56,13 +54,16 @@ private: UI::EventReturn OnLastSaveUndo(UI::EventParams &e); UI::EventReturn OnScreenshotClicked(UI::EventParams &e); + UI::EventReturn OnCwCheat(UI::EventParams &e); UI::EventReturn OnCreateConfig(UI::EventParams &e); UI::EventReturn OnDeleteConfig(UI::EventParams &e); + UI::EventReturn OnSwitchUMD(UI::EventParams &e); UI::EventReturn OnState(UI::EventParams &e); // hack bool finishNextFrame_ = false; + Path gamePath_; PauseScreenMode mode_ = PauseScreenMode::MAIN; }; diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 9ade1fd80..5cb901e5b 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -139,7 +139,7 @@ bool RemoteISOConnectScreen::FindServer(std::string &resultHost, int &resultPort } SetStatus("Loading game list from [URL]...", host, port); - net::RequestProgress progress(&scanCancelled); + http::RequestProgress progress(&scanCancelled); code = http.GET(http::RequestParams(subdir.c_str()), &result, &progress); http.Disconnect(); @@ -193,7 +193,7 @@ bool RemoteISOConnectScreen::FindServer(std::string &resultHost, int &resultPort SetStatus("Looking for peers...", "", 0); if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) { if (http.Connect(2, 20.0, &scanCancelled)) { - net::RequestProgress progress(&scanCancelled); + http::RequestProgress progress(&scanCancelled); code = http.GET(http::RequestParams("/match/list"), &result, &progress); http.Disconnect(); } @@ -503,8 +503,8 @@ void RemoteISOConnectScreen::ExecuteLoad() { class RemoteGameBrowser : public GameBrowser { public: - RemoteGameBrowser(const Path &url, BrowseFlags browseFlags, bool *gridStyle, ScreenManager *screenManager, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams = nullptr) - : GameBrowser(url, browseFlags, gridStyle, screenManager, lastText, lastLink, layoutParams) { + RemoteGameBrowser(const Path &url, BrowseFlags browseFlags, bool *gridStyle_, ScreenManager *screenManager, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams = nullptr) + : GameBrowser(url, browseFlags, gridStyle_, screenManager, lastText, lastLink, layoutParams) { initialPath_ = url; } @@ -602,6 +602,12 @@ void RemoteISOSettingsScreen::CreateViews() { remoteisoSettings->Add(new CheckBox(&g_Config.bRemoteISOManual, ri->T("Manual Mode Client", "Manually configure client"))); UI::Choice *remoteServer; +#if defined(MOBILE_DEVICE) + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) { + remoteServer = new ChoiceWithValueDisplay(&g_Config.sLastRemoteISOServer, ri->T("Remote Server"), I18NCat::NONE); + remoteServer->OnClick.Handle(this, &RemoteISOSettingsScreen::OnClickRemoteServer); + } else +#endif remoteServer = new PopupTextInputChoice(&g_Config.sLastRemoteISOServer, ri->T("Remote Server"), "", 255, screenManager()); remoteisoSettings->Add(remoteServer); remoteServer->SetEnabledPtr(&g_Config.bRemoteISOManual); @@ -610,6 +616,12 @@ void RemoteISOSettingsScreen::CreateViews() { remotePort->SetEnabledPtr(&g_Config.bRemoteISOManual); UI::Choice *remoteSubdir; +#if defined(MOBILE_DEVICE) + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) { + remoteSubdir = new ChoiceWithValueDisplay(&g_Config.sRemoteISOSubdir, ri->T("Remote Subdirectory"), I18NCat::NONE); + remoteSubdir->OnClick.Handle(this, &RemoteISOSettingsScreen::OnClickRemoteISOSubdir); + } else +#endif { PopupTextInputChoice *remoteSubdirInput = new PopupTextInputChoice(&g_Config.sRemoteISOSubdir, ri->T("Remote Subdirectory"), "", 255, screenManager()); remoteSubdirInput->OnChange.Handle(this, &RemoteISOSettingsScreen::OnChangeRemoteISOSubdir); @@ -628,6 +640,16 @@ void RemoteISOSettingsScreen::CreateViews() { AddStandardBack(root_); } +UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteServer(UI::EventParams &e) { +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) + auto ri = GetI18NCategory(I18NCat::REMOTEISO); + System_InputBoxGetString(ri->T("Remote Server"), g_Config.sLastRemoteISOServer, [](const std::string &value, int) { + g_Config.sLastRemoteISOServer = value; + }); +#endif + return UI::EVENT_DONE; +} + static void CleanupRemoteISOSubdir() { // Replace spaces and force forward slashes. // TODO: Maybe we should uri escape this after? @@ -638,6 +660,18 @@ static void CleanupRemoteISOSubdir() { g_Config.sRemoteISOSubdir = "/" + g_Config.sRemoteISOSubdir; } +UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteISOSubdir(UI::EventParams &e) { +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) + auto ri = GetI18NCategory(I18NCat::REMOTEISO); + System_InputBoxGetString(ri->T("Remote Subdirectory"), g_Config.sRemoteISOSubdir, [](const std::string &value, int) { + g_Config.sRemoteISOSubdir = value; + // Apply the cleanup logic, too. + CleanupRemoteISOSubdir(); + }); +#endif + return UI::EVENT_DONE; +} + UI::EventReturn RemoteISOSettingsScreen::OnChangeRemoteISOSubdir(UI::EventParams &e) { CleanupRemoteISOSubdir(); return UI::EVENT_DONE; diff --git a/UI/RemoteISOScreen.h b/UI/RemoteISOScreen.h index 884dba8fe..49f89eb39 100644 --- a/UI/RemoteISOScreen.h +++ b/UI/RemoteISOScreen.h @@ -102,7 +102,10 @@ public: const char *tag() const override { return "RemoteISOSettings"; } + UI::EventReturn OnClickRemoteISOSubdir(UI::EventParams &e); + UI::EventReturn OnClickRemoteServer(UI::EventParams &e); protected: + void update() override; void CreateViews() override; diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index 92136d456..0ce978aa4 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -338,7 +338,7 @@ void ReportScreen::UpdateCRCInfo() { if (Reporting::HasCRC(gamePath_)) { std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_)); - updated = ApplySafeSubstitutions(rp->T("FeedbackCRCValue", "Disc CRC: %1"), crc); + updated = ReplaceAll(rp->T("FeedbackCRCValue", "Disc CRC: %1"), "%1", crc); } else if (showCRC_) { updated = rp->T("FeedbackCRCCalculating", "Disc CRC: Calculating..."); } diff --git a/UI/RetroAchievementScreens.cpp b/UI/RetroAchievementScreens.cpp deleted file mode 100644 index 071aae17b..000000000 --- a/UI/RetroAchievementScreens.cpp +++ /dev/null @@ -1,721 +0,0 @@ -#include "Common/System/OSD.h" -#include "Common/System/Request.h" -#include "Common/UI/View.h" -#include "Common/UI/ViewGroup.h" -#include "Common/UI/Context.h" -#include "Common/Data/Text/I18n.h" -#include "Common/UI/IconCache.h" - -#include "Core/Config.h" -#include "Core/RetroAchievements.h" - -#include "UI/RetroAchievementScreens.h" -#include "UI/BackgroundAudio.h" -#include "UI/OnScreenDisplay.h" - -static inline const char *DeNull(const char *ptr) { - return ptr ? ptr : ""; -} - -// Compound view, creating a FileChooserChoice inside. -class AudioFileChooser : public UI::LinearLayout { -public: - AudioFileChooser(std::string *value, const std::string &title, UI::UISound sound, UI::LayoutParams *layoutParams = nullptr); - - UI::UISound sound_; -}; - -static constexpr UI::Size ITEM_HEIGHT = 64.f; - -AudioFileChooser::AudioFileChooser(std::string *value, const std::string &title, UI::UISound sound, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_HORIZONTAL, layoutParams), sound_(sound) { - using namespace UI; - SetSpacing(2.0f); - if (!layoutParams) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = ITEM_HEIGHT; - } - Add(new Choice(ImageID("I_PLAY"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT)))->OnClick.Add([=](UI::EventParams &) { - g_BackgroundAudio.SFX().Play(sound_, 0.6f); - return UI::EVENT_DONE; - }); - Add(new FileChooserChoice(value, title, BrowseFileType::SOUND_EFFECT, new LinearLayoutParams(1.0f)))->OnChange.Add([=](UI::EventParams &e) { - std::string path = e.s; - Sample *sample = Sample::Load(path); - if (sample) { - g_BackgroundAudio.SFX().UpdateSample(sound, sample); - } else { - auto au = GetI18NCategory(I18NCat::AUDIO); - g_OSD.Show(OSDType::MESSAGE_ERROR, au->T("Audio file format not supported. Must be WAV.")); - value->clear(); - } - return UI::EVENT_DONE; - }); - Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT)))->OnClick.Add([=](UI::EventParams &) { - g_BackgroundAudio.SFX().UpdateSample(sound, nullptr); - value->clear(); - return UI::EVENT_DONE; - }); -} - -void RetroAchievementsListScreen::CreateTabs() { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - UI::LinearLayout *achievements = AddTab("Achievements", ac->T("Achievements")); - achievements->SetSpacing(5.0f); - CreateAchievementsTab(achievements); - - UI::LinearLayout *leaderboards = AddTab("Leaderboards", ac->T("Leaderboards")); - leaderboards->SetSpacing(5.0f); - CreateLeaderboardsTab(leaderboards); - -#ifdef _DEBUG - CreateStatisticsTab(AddTab("AchievementsStatistics", ac->T("Statistics"))); -#endif -} - -inline const char *AchievementBucketTitle(int bucketType) { - switch (bucketType) { - case RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED: return "Locked achievements"; - case RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED: return "Unlocked achievements"; - case RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED: return "Unsupported achievements"; - case RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL: return "Unofficial achievements"; - case RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED: return "Recently unlocked achievements"; - case RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE: return "Achievements with active challenges"; - case RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE: return "Almost completed achievements"; - default: return "?"; - } -} - -void RetroAchievementsListScreen::CreateAchievementsTab(UI::ViewGroup *achievements) { - auto di = GetI18NCategory(I18NCat::DIALOG); - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - using namespace UI; - - int filter = RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE; - if (Achievements::UnofficialEnabled()) { - filter = RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL; - } - - achievements->Add(new ItemHeader(ac->T("Achievements"))); - achievements->Add(new GameAchievementSummaryView()); - - if (Achievements::EncoreModeActive()) { - achievements->Add(new NoticeView(NoticeLevel::WARN, ac->T("In Encore mode - unlock state may not be accurate"), "")); - } - - rc_client_achievement_list_t *list = rc_client_create_achievement_list(Achievements::GetClient(), - filter, RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS); - - for (uint32_t i = 0; i < list->num_buckets; i++) { - const rc_client_achievement_bucket_t &bucket = list->buckets[i]; - if (!bucket.num_achievements) { - continue; - } - std::string title = StringFromFormat("%s (%d)", ac->T(AchievementBucketTitle(bucket.bucket_type)), bucket.num_achievements); - CollapsibleSection *section = achievements->Add(new CollapsibleSection(title)); - section->SetSpacing(2.0f); - for (uint32_t j = 0; j < bucket.num_achievements; j++) { - section->Add(new AchievementView(bucket.achievements[j])); - } - } -} - -void RetroAchievementsListScreen::CreateLeaderboardsTab(UI::ViewGroup *viewGroup) { - auto di = GetI18NCategory(I18NCat::DIALOG); - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - using namespace UI; - - viewGroup->Add(new GameAchievementSummaryView()); - - viewGroup->Add(new ItemHeader(ac->T("Leaderboards"))); - - std::vector leaderboards; - rc_client_leaderboard_list_t *list = rc_client_create_leaderboard_list(Achievements::GetClient(), RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE); - for (uint32_t i = 0; i < list->num_buckets; i++) { - const rc_client_leaderboard_bucket_t &bucket = list->buckets[i]; - for (uint32_t j = 0; j < bucket.num_leaderboards; j++) { - leaderboards.push_back(bucket.leaderboards[j]); - } - } - - for (auto &leaderboard : leaderboards) { - int leaderboardID = leaderboard->id; - viewGroup->Add(new LeaderboardSummaryView(leaderboard))->OnClick.Add([=](UI::EventParams &e) -> UI::EventReturn { - screenManager()->push(new RetroAchievementsLeaderboardScreen(gamePath_, leaderboardID)); - return UI::EVENT_DONE; - }); - } -} - -void RetroAchievementsListScreen::CreateStatisticsTab(UI::ViewGroup *viewGroup) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - using namespace UI; - - Achievements::Statistics stats = Achievements::GetStatistics(); - viewGroup->Add(new ItemHeader(ac->T("Statistics"))); - viewGroup->Add(new InfoItem(ac->T("Bad memory accesses"), StringFromFormat("%d", stats.badMemoryAccessCount))); -} - -RetroAchievementsLeaderboardScreen::~RetroAchievementsLeaderboardScreen() { - if (pendingAsyncCall_) { - rc_client_abort_async(Achievements::GetClient(), pendingAsyncCall_); - } - Poll(); // Gets rid of pendingEntryList_. - if (entryList_) { - rc_client_destroy_leaderboard_entry_list(entryList_); - } -} - -RetroAchievementsLeaderboardScreen::RetroAchievementsLeaderboardScreen(const Path &gamePath, int leaderboardID) - : TabbedUIDialogScreenWithGameBackground(gamePath), leaderboardID_(leaderboardID) { - FetchEntries(); -} - -void RetroAchievementsLeaderboardScreen::FetchEntries() { - auto callback = [](int result, const char *error_message, rc_client_leaderboard_entry_list_t *list, rc_client_t *client, void *userdata) { - if (result != RC_OK) { - g_OSD.Show(OSDType::MESSAGE_ERROR, error_message, 10.0f); - return; - } - - RetroAchievementsLeaderboardScreen *thiz = (RetroAchievementsLeaderboardScreen *)userdata; - thiz->pendingEntryList_ = list; - thiz->pendingAsyncCall_ = nullptr; - }; - - if (nearMe_) { - rc_client_begin_fetch_leaderboard_entries_around_user(Achievements::GetClient(), leaderboardID_, 10, callback, this); - } else { - rc_client_begin_fetch_leaderboard_entries(Achievements::GetClient(), leaderboardID_, 0, 25, callback, this); - } -} - -void RetroAchievementsLeaderboardScreen::CreateTabs() { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - const rc_client_leaderboard_t *leaderboard = rc_client_get_leaderboard_info(Achievements::GetClient(), leaderboardID_); - - using namespace UI; - UI::LinearLayout *layout = AddTab("AchievementsLeaderboard", leaderboard->title); - layout->Add(new TextView(leaderboard->description)); - layout->Add(new ItemHeader(ac->T("Leaderboard"))); - - auto strip = layout->Add(new ChoiceStrip(ORIENT_HORIZONTAL)); - strip->AddChoice(ac->T("Top players")); - strip->AddChoice(ac->T("Around me")); - strip->OnChoice.Add([=](UI::EventParams &e) { - strip->SetSelection(e.a, false); - nearMe_ = e.a != 0; - FetchEntries(); - return UI::EVENT_DONE; - }); - strip->SetSelection(nearMe_ ? 1 : 0, false); - - if (entryList_) { - for (uint32_t i = 0; i < entryList_->num_entries; i++) { - bool is_self = (i == entryList_->user_index); - // Should highlight somehow. - const rc_client_leaderboard_entry_t &entry = entryList_->entries[i]; - - char buffer[512]; - rc_client_leaderboard_entry_get_user_image_url(&entryList_->entries[i], buffer, sizeof(buffer)); - // Can also show entry.submitted, which is a time_t. And maybe highlight recent ones? - layout->Add(new LeaderboardEntryView(&entryList_->entries[i], is_self)); - } - } -} - -void RetroAchievementsLeaderboardScreen::Poll() { - if (pendingEntryList_) { - if (entryList_) { - rc_client_destroy_leaderboard_entry_list(entryList_); - } - entryList_ = pendingEntryList_; - pendingEntryList_ = nullptr; - RecreateViews(); - } -} - -void RetroAchievementsLeaderboardScreen::update() { - TabbedUIDialogScreenWithGameBackground::update(); - Poll(); -} - -RetroAchievementsSettingsScreen::~RetroAchievementsSettingsScreen() {} - -void RetroAchievementsSettingsScreen::CreateTabs() { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - auto di = GetI18NCategory(I18NCat::DIALOG); - auto sy = GetI18NCategory(I18NCat::SYSTEM); - - using namespace UI; - - CreateAccountTab(AddTab("AchievementsAccount", ac->T("Account"))); - if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { - // Don't bother creating this tab if we don't have a file browser. - CreateCustomizeTab(AddTab("AchievementsCustomize", ac->T("Customize"))); - } - CreateDeveloperToolsTab(AddTab("AchievementsDeveloperTools", sy->T("Developer Tools"))); -} - -void RetroAchievementsSettingsScreen::sendMessage(UIMessage message, const char *value) { - TabbedUIDialogScreenWithGameBackground::sendMessage(message, value); - - if (message == UIMessage::ACHIEVEMENT_LOGIN_STATE_CHANGE) { - RecreateViews(); - } -} - -void RetroAchievementsSettingsScreen::CreateAccountTab(UI::ViewGroup *viewGroup) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - auto di = GetI18NCategory(I18NCat::DIALOG); - - using namespace UI; - - if (!g_Config.bAchievementsEnable) { - viewGroup->Add(new NoticeView(NoticeLevel::INFO, ac->T("Achievements are disabled"), "", new LinearLayoutParams(Margins(5)))); - } else if (Achievements::IsLoggedIn()) { - const rc_client_user_t *info = rc_client_get_user_info(Achievements::GetClient()); - - // In the future, RetroAchievements will support display names. Prepare for that. - if (strcmp(info->display_name, info->username) != 0) { - viewGroup->Add(new InfoItem(ac->T("Name"), info->display_name)); - } - viewGroup->Add(new InfoItem(di->T("Username"), info->username)); - // viewGroup->Add(new InfoItem(ac->T("Unread messages"), info.numUnreadMessages)); - viewGroup->Add(new Choice(di->T("Log out")))->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { - Achievements::Logout(); - return UI::EVENT_DONE; - }); - } else { - std::string errorMessage; - if (Achievements::LoginProblems(&errorMessage)) { - viewGroup->Add(new NoticeView(NoticeLevel::WARN, ac->T("Failed logging in to RetroAchievements"), errorMessage)); - viewGroup->Add(new Choice(di->T("Log out")))->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { - Achievements::Logout(); - return UI::EVENT_DONE; - }); - } else if (System_GetPropertyBool(SYSPROP_HAS_LOGIN_DIALOG)) { - viewGroup->Add(new Choice(di->T("Log in")))->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { - System_AskUsernamePassword(di->T("Log in"), [](const std::string &value, int) { - std::vector parts; - SplitString(value, '\n', parts); - if (parts.size() == 2 && !parts[0].empty() && !parts[1].empty()) { - Achievements::LoginAsync(parts[0].c_str(), parts[1].c_str()); - } - }); - return UI::EVENT_DONE; - }); - } else { - // Hack up a temporary quick login-form-ish-thing - viewGroup->Add(new PopupTextInputChoice(&username_, di->T("Username"), "", 128, screenManager())); - viewGroup->Add(new PopupTextInputChoice(&password_, di->T("Password"), "", 128, screenManager()))->SetPasswordDisplay(); - Choice *loginButton = viewGroup->Add(new Choice(di->T("Log in"))); - loginButton->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { - if (!username_.empty() && !password_.empty()) { - Achievements::LoginAsync(username_.c_str(), password_.c_str()); - memset(&password_[0], 0, password_.size()); - password_.clear(); - } - return UI::EVENT_DONE; - }); - loginButton->SetEnabledFunc([&]() { - return !username_.empty() && !password_.empty(); - }); - } - viewGroup->Add(new Choice(ac->T("Register on www.retroachievements.org")))->OnClick.Add([&](UI::EventParams &) -> UI::EventReturn { - System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://retroachievements.org/createaccount.php"); - return UI::EVENT_DONE; - }); - } - - using namespace UI; - viewGroup->Add(new ItemHeader(di->T("Settings"))); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsEnable, ac->T("Achievements enabled")))->OnClick.Add([&](UI::EventParams &e) -> UI::EventReturn { - Achievements::UpdateSettings(); - RecreateViews(); - return UI::EVENT_DONE; - }); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsChallengeMode, ac->T("Hardcore Mode (no savestates)")))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsSoundEffects, ac->T("Sound Effects")))->SetEnabledPtr(&g_Config.bAchievementsEnable); // not yet implemented - - viewGroup->Add(new ItemHeader(di->T("Links"))); - viewGroup->Add(new Choice(ac->T("RetroAchievements website")))->OnClick.Add([&](UI::EventParams &) -> UI::EventReturn { - System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.retroachievements.org/"); - return UI::EVENT_DONE; - }); - viewGroup->Add(new Choice(ac->T("How to use RetroAchievements")))->OnClick.Add([&](UI::EventParams &) -> UI::EventReturn { - System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/reference/retro-achievements"); - return UI::EVENT_DONE; - }); -} - -void RetroAchievementsSettingsScreen::CreateCustomizeTab(UI::ViewGroup *viewGroup) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - - using namespace UI; - viewGroup->Add(new ItemHeader(ac->T("Sound Effects"))); - viewGroup->Add(new AudioFileChooser(&g_Config.sAchievementsUnlockAudioFile, ac->T("Achievement unlocked"), UISound::ACHIEVEMENT_UNLOCKED)); - viewGroup->Add(new AudioFileChooser(&g_Config.sAchievementsLeaderboardSubmitAudioFile, ac->T("Leaderboard score submission"), UISound::LEADERBOARD_SUBMITTED)); - - static const char *positions[] = { "None", "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right" }; - - viewGroup->Add(new ItemHeader(ac->T("Notifications"))); - viewGroup->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardStartedOrFailedPos, ac->T("Leaderboard attempt started or failed"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardSubmittedPos, ac->T("Leaderboard result submitted"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardTrackerPos, ac->T("Leaderboard tracker"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new PopupMultiChoice(&g_Config.iAchievementsUnlockedPos, ac->T("Achievement unlocked"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new PopupMultiChoice(&g_Config.iAchievementsChallengePos, ac->T("Challenge indicator"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new PopupMultiChoice(&g_Config.iAchievementsProgressPos, ac->T("Achievement progress"), positions, -1, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable); -} - -void RetroAchievementsSettingsScreen::CreateDeveloperToolsTab(UI::ViewGroup *viewGroup) { - auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); - auto di = GetI18NCategory(I18NCat::DIALOG); - - using namespace UI; - viewGroup->Add(new ItemHeader(di->T("Settings"))); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsEncoreMode, ac->T("Encore Mode")))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsUnofficial, ac->T("Unofficial achievements")))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsLogBadMemReads, ac->T("Log bad memory accesses")))->SetEnabledPtr(&g_Config.bAchievementsEnable); - viewGroup->Add(new CheckBox(&g_Config.bAchievementsSaveStateInChallengeMode, ac->T("Allow Save State in Hardcore Mode (but not Load State)")))->SetEnabledPtr(&g_Config.bAchievementsEnable); -} - -void MeasureAchievement(const UIContext &dc, const rc_client_achievement_t *achievement, AchievementRenderStyle style, float *w, float *h) { - *w = 0.0f; - switch (style) { - case AchievementRenderStyle::PROGRESS_INDICATOR: - dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, achievement->measured_progress, w, h); - *w += 44.0f + 4.0f * 3.0f; - *h = 44.0f; - break; - case AchievementRenderStyle::CHALLENGE_INDICATOR: - // ONLY the icon. - *w = 60.0f; - *h = 60.0f; - break; - default: - *h = 72.0f; - break; - } -} - -void MeasureGameAchievementSummary(const UIContext &dc, float *w, float *h) { - std::string description = Achievements::GetGameAchievementSummary(); - - float tw, th; - dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, "Wg", &tw, &th); - - dc.MeasureText(dc.theme->uiFont, 0.66f, 0.66f, description.c_str(), w, h); - *h += 8.0f + th; - *w += 8.0f; -} - -void MeasureLeaderboardSummary(const UIContext &dc, const rc_client_leaderboard_t *leaderboard, float *w, float *h) { - *w = 0.0f; - *h = 72.0f; -} - -void MeasureLeaderboardEntry(const UIContext &dc, const rc_client_leaderboard_entry_t *entry, float *w, float *h) { - *w = 0.0f; - *h = 72.0f; -} - -// Graphical -void RenderAchievement(UIContext &dc, const rc_client_achievement_t *achievement, AchievementRenderStyle style, const Bounds &bounds, float alpha, float startTime, float time_s, bool hasFocus) { - using namespace UI; - UI::Drawable background = UI::Drawable(dc.theme->backgroundColor); - - if (hasFocus) { - background = dc.theme->itemFocusedStyle.background; - } - - // Set some alpha, if displayed in list. - if (style == AchievementRenderStyle::LISTED) { - background.color = colorAlpha(background.color, 0.6f); - } - - if (!achievement->unlocked && !hasFocus) { - // Make the background color gray. - // TODO: Different colors in hardcore mode, or even in the "re-take achievements" mode when we add that? - background.color = (background.color & 0xFF000000) | 0x706060; - } - - int iconState = achievement->state; - - background.color = alphaMul(background.color, alpha); - uint32_t fgColor = alphaMul(dc.theme->itemStyle.fgColor, alpha); - - if (style == AchievementRenderStyle::UNLOCKED) { - float mixWhite = pow(Clamp((float)(1.0f - (time_s - startTime)), 0.0f, 1.0f), 3.0f); - background.color = colorBlend(0xFFE0FFFF, background.color, mixWhite); - } - - float padding = 4.0f; - - float iconSpace = bounds.h - padding * 2.0f; - dc.Flush(); - dc.RebindTexture(); - dc.PushScissor(bounds); - - dc.Begin(); - - if (style != AchievementRenderStyle::LISTED) { - dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); - } - - dc.FillRect(background, bounds); - - dc.Flush(); - dc.Begin(); - - dc.SetFontStyle(dc.theme->uiFont); - - char temp[512]; - - switch (style) { - case AchievementRenderStyle::LISTED: - case AchievementRenderStyle::UNLOCKED: - { - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextRect(achievement->title, bounds.Inset(iconSpace + 12.0f, 2.0f, padding, padding), fgColor, ALIGN_TOPLEFT); - - dc.SetFontScale(0.66f, 0.66f); - dc.DrawTextRectSqueeze(DeNull(achievement->description), bounds.Inset(iconSpace + 12.0f, 39.0f, padding, padding), fgColor, ALIGN_TOPLEFT); - - if (style == AchievementRenderStyle::LISTED && strlen(achievement->measured_progress) > 0) { - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextRect(achievement->measured_progress, bounds.Inset(iconSpace + 12.0f, padding, padding + 100.0f, padding), fgColor, ALIGN_VCENTER | ALIGN_RIGHT); - } - - // TODO: Draw measured_progress / measured_percent in a cute way - snprintf(temp, sizeof(temp), "%d", achievement->points); - - dc.SetFontScale(1.5f, 1.5f); - dc.DrawTextRect(temp, bounds.Expand(-5.0f, -5.0f), fgColor, ALIGN_RIGHT | ALIGN_VCENTER); - - dc.SetFontScale(1.0f, 1.0f); - dc.Flush(); - break; - } - case AchievementRenderStyle::PROGRESS_INDICATOR: - // TODO: Also render a progress bar. - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextRect(achievement->measured_progress, bounds.Inset(iconSpace + padding * 2.0f, padding, padding, padding), fgColor, ALIGN_LEFT | ALIGN_VCENTER); - // Show the unlocked icon. - iconState = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED; - break; - case AchievementRenderStyle::CHALLENGE_INDICATOR: - // Nothing but the icon, unlocked. - iconState = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED; - break; - } - - // Download and display the image. - char cacheKey[256]; - snprintf(cacheKey, sizeof(cacheKey), "ai:%s:%s", achievement->badge_name, iconState == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED ? "unlocked" : "locked"); - if (RC_OK == rc_client_achievement_get_image_url(achievement, iconState, temp, sizeof(temp))) { - Achievements::DownloadImageIfMissing(cacheKey, std::string(temp)); - if (g_iconCache.BindIconTexture(&dc, cacheKey)) { - dc.Draw()->DrawTexRect(Bounds(bounds.x + padding, bounds.y + padding, iconSpace, iconSpace), 0.0f, 0.0f, 1.0f, 1.0f, whiteAlpha(alpha)); - } - dc.Flush(); - dc.RebindTexture(); - } - - dc.Flush(); - dc.PopScissor(); -} - -void RenderGameAchievementSummary(UIContext &dc, const Bounds &bounds, float alpha) { - using namespace UI; - UI::Drawable background = dc.theme->itemStyle.background; - - background.color = alphaMul(background.color, alpha); - uint32_t fgColor = colorAlpha(dc.theme->itemStyle.fgColor, alpha); - - float iconSpace = 64.0f; - dc.Flush(); - - dc.Begin(); - dc.FillRect(background, bounds); - - dc.SetFontStyle(dc.theme->uiFont); - - const rc_client_game_t *gameInfo = rc_client_get_game_info(Achievements::GetClient()); - - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextRect(gameInfo->title, bounds.Inset(iconSpace + 5.0f, 2.0f, 5.0f, 5.0f), fgColor, ALIGN_TOPLEFT); - - std::string description = Achievements::GetGameAchievementSummary(); - - dc.SetFontScale(0.66f, 0.66f); - dc.DrawTextRect(description.c_str(), bounds.Inset(iconSpace + 5.0f, 38.0f, 5.0f, 5.0f), fgColor, ALIGN_TOPLEFT); - - dc.SetFontScale(1.0f, 1.0f); - dc.Flush(); - - char url[512]; - char cacheKey[256]; - snprintf(cacheKey, sizeof(cacheKey), "gi:%s", gameInfo->badge_name); - if (RC_OK == rc_client_game_get_image_url(gameInfo, url, sizeof(url))) { - Achievements::DownloadImageIfMissing(cacheKey, std::string(url)); - if (g_iconCache.BindIconTexture(&dc, cacheKey)) { - dc.Draw()->DrawTexRect(Bounds(bounds.x, bounds.y, iconSpace, iconSpace), 0.0f, 0.0f, 1.0f, 1.0f, whiteAlpha(alpha)); - } - } - - dc.Flush(); - dc.RebindTexture(); -} - -void RenderLeaderboardSummary(UIContext &dc, const rc_client_leaderboard_t *leaderboard, AchievementRenderStyle style, const Bounds &bounds, float alpha, float startTime, float time_s, bool hasFocus) { - using namespace UI; - UI::Drawable background = dc.theme->itemStyle.background; - if (hasFocus) { - background = dc.theme->itemFocusedStyle.background; - } - - background.color = alphaMul(background.color, alpha); - uint32_t fgColor = alphaMul(dc.theme->itemStyle.fgColor, alpha); - - if (style == AchievementRenderStyle::UNLOCKED) { - float mixWhite = pow(Clamp((float)(1.0f - (time_s - startTime)), 0.0f, 1.0f), 3.0f); - background.color = colorBlend(0xFFE0FFFF, background.color, mixWhite); - } - - dc.Flush(); - - dc.Begin(); - dc.FillRect(background, bounds); - - dc.SetFontStyle(dc.theme->uiFont); - - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextRect(DeNull(leaderboard->title), bounds.Inset(12.0f, 2.0f, 5.0f, 5.0f), fgColor, ALIGN_TOPLEFT); - - dc.SetFontScale(0.66f, 0.66f); - dc.DrawTextRectSqueeze(DeNull(leaderboard->description), bounds.Inset(12.0f, 39.0f, 5.0f, 5.0f), fgColor, ALIGN_TOPLEFT); - - /* - char temp[64]; - snprintf(temp, sizeof(temp), "%d", leaderboard.points); - - dc.SetFontScale(1.5f, 1.5f); - dc.DrawTextRect(temp, bounds.Expand(-5.0f, -5.0f), fgColor, ALIGN_RIGHT | ALIGN_VCENTER); - - dc.Flush(); - */ - dc.SetFontScale(1.0f, 1.0f); - - dc.Flush(); - dc.RebindTexture(); -} - -void RenderLeaderboardEntry(UIContext &dc, const rc_client_leaderboard_entry_t *entry, const Bounds &bounds, float alpha, bool hasFocus, bool isCurrentUser) { - using namespace UI; - UI::Drawable background = dc.theme->itemStyle.background; - if (hasFocus) { - background = dc.theme->itemFocusedStyle.background; - } - if (isCurrentUser) { - background = dc.theme->itemDownStyle.background; - } - - background.color = alphaMul(background.color, alpha); - uint32_t fgColor = alphaMul(dc.theme->itemStyle.fgColor, alpha); - - float iconSize = 64.0f; - float numberSpace = 128.0f; - float iconLeft = numberSpace + 5.0f; - float iconSpace = numberSpace + 5.0f + iconSize; - - // Sanity check - if (!entry->user) { - return; - } - - dc.Flush(); - - dc.Begin(); - dc.FillRect(background, bounds); - - dc.SetFontStyle(dc.theme->uiFont); - - dc.SetFontScale(1.5f, 1.5f); - dc.DrawTextRect(StringFromFormat("%d", entry->rank).c_str(), Bounds(bounds.x + 4.0f, bounds.y + 4.0f, numberSpace - 10.0f, bounds.h - 4.0f * 2.0f), fgColor, ALIGN_TOPRIGHT); - - dc.SetFontScale(1.0f, 1.0f); - dc.DrawTextRect(entry->user, bounds.Inset(iconSpace + 5.0f, 2.0f, 5.0f, 5.0f), fgColor, ALIGN_TOPLEFT); - - dc.SetFontScale(0.66f, 0.66f); - dc.DrawTextRect(DeNull(entry->display), bounds.Inset(iconSpace + 5.0f, 38.0f, 5.0f, 5.0f), fgColor, ALIGN_TOPLEFT); - - dc.SetFontScale(1.0f, 1.0f); - dc.Flush(); - - // Come up with a unique name for the icon entry. - char cacheKey[256]; - snprintf(cacheKey, sizeof(cacheKey), "lbe:%s", entry->user); - char temp[512]; - if (RC_OK == rc_client_leaderboard_entry_get_user_image_url(entry, temp, sizeof(temp))) { - Achievements::DownloadImageIfMissing(cacheKey, std::string(temp)); - if (g_iconCache.BindIconTexture(&dc, cacheKey)) { - dc.Draw()->DrawTexRect(Bounds(bounds.x + iconLeft, bounds.y + 4.0f, 64.0f, 64.0f), 0.0f, 0.0f, 1.0f, 1.0f, whiteAlpha(alpha)); - } - } - - dc.Flush(); - dc.RebindTexture(); -} - -void AchievementView::Draw(UIContext &dc) { - RenderAchievement(dc, achievement_, AchievementRenderStyle::LISTED, bounds_, 1.0f, 0.0f, 0.0f, HasFocus()); -} - -void AchievementView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - MeasureAchievement(dc, achievement_, AchievementRenderStyle::LISTED, &w, &h); -} - -void AchievementView::Click() { - // In debug builds, clicking achievements will show them being unlocked (which may be a lie). -#ifdef _DEBUG - static int type = 0; - type++; - type = type % 5; - switch (type) { - case 0: g_OSD.ShowAchievementUnlocked(achievement_->id); break; - case 1: g_OSD.ShowAchievementProgress(achievement_->id, true); break; - case 2: g_OSD.ShowAchievementProgress(achievement_->id, false); break; - case 3: g_OSD.ShowChallengeIndicator(achievement_->id, true); break; - case 4: g_OSD.ShowChallengeIndicator(achievement_->id, false); break; - } -#endif -} - -void GameAchievementSummaryView::Draw(UIContext &dc) { - RenderGameAchievementSummary(dc, bounds_, 1.0f); -} - -void GameAchievementSummaryView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - // Somehow wrong! - MeasureGameAchievementSummary(dc, &w, &h); -} - -void LeaderboardSummaryView::Draw(UIContext &dc) { - RenderLeaderboardSummary(dc, leaderboard_, AchievementRenderStyle::LISTED, bounds_, 1.0f, 0.0f, 0.0f, HasFocus()); -} - -void LeaderboardSummaryView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - MeasureLeaderboardSummary(dc, leaderboard_, &w, &h); -} - -void LeaderboardEntryView::Draw(UIContext &dc) { - RenderLeaderboardEntry(dc, entry_, bounds_, 1.0f, HasFocus(), isCurrentUser_); -} - -void LeaderboardEntryView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - MeasureLeaderboardEntry(dc, entry_, &w, &h); -} diff --git a/UI/RetroAchievementScreens.h b/UI/RetroAchievementScreens.h deleted file mode 100644 index 48d13b167..000000000 --- a/UI/RetroAchievementScreens.h +++ /dev/null @@ -1,148 +0,0 @@ -#pragma once - -#include - -#include "Common/File/Path.h" -#include "Common/UI/View.h" -#include "Common/UI/UIScreen.h" -#include "Common/UI/ViewGroup.h" -#include "Core/RetroAchievements.h" -#include "UI/MiscScreens.h" -#include "UI/TabbedDialogScreen.h" - -// Lists the achievements and leaderboards for one game. -class RetroAchievementsListScreen : public TabbedUIDialogScreenWithGameBackground { -public: - RetroAchievementsListScreen(const Path &gamePath) : TabbedUIDialogScreenWithGameBackground(gamePath) {} - const char *tag() const override { return "RetroAchievementsListScreen"; } - - void CreateTabs() override; - -protected: - bool ShowSearchControls() const override { return false; } - -private: - void CreateAchievementsTab(UI::ViewGroup *viewGroup); - void CreateLeaderboardsTab(UI::ViewGroup *viewGroup); - void CreateStatisticsTab(UI::ViewGroup *viewGroup); -}; - -// Lets you manage your account, and shows some achievement stats and stuff. -class RetroAchievementsSettingsScreen : public TabbedUIDialogScreenWithGameBackground { -public: - RetroAchievementsSettingsScreen(const Path &gamePath) : TabbedUIDialogScreenWithGameBackground(gamePath) {} - ~RetroAchievementsSettingsScreen(); - const char *tag() const override { return "RetroAchievementsSettingsScreen"; } - - void CreateTabs() override; - void sendMessage(UIMessage message, const char *value) override; - -protected: - bool ShowSearchControls() const override { return false; } - -private: - void CreateAccountTab(UI::ViewGroup *viewGroup); - void CreateCustomizeTab(UI::ViewGroup *viewGroup); - void CreateDeveloperToolsTab(UI::ViewGroup *viewGroup); - - std::string username_; - std::string password_; -}; - -class RetroAchievementsLeaderboardScreen : public TabbedUIDialogScreenWithGameBackground { -public: - RetroAchievementsLeaderboardScreen(const Path &gamePath, int leaderboardID); - ~RetroAchievementsLeaderboardScreen(); - - const char *tag() const override { return "RetroAchievementsLeaderboardScreen"; } - - void CreateTabs() override; - - void update() override; - -protected: - bool ShowSearchControls() const override { return false; } - -private: - void FetchEntries(); - void Poll(); - - int leaderboardID_; - bool nearMe_ = false; - - // Keep the fetched list alive and destroy in destructor. - rc_client_leaderboard_entry_list_t *entryList_ = nullptr; - - rc_client_leaderboard_entry_list_t *pendingEntryList_ = nullptr; - - rc_client_async_handle_t *pendingAsyncCall_ = nullptr; -}; - -class UIContext; - -enum class AchievementRenderStyle { - LISTED, - UNLOCKED, - PROGRESS_INDICATOR, - CHALLENGE_INDICATOR, -}; - -void MeasureAchievement(const UIContext &dc, const rc_client_achievement_t *achievement, AchievementRenderStyle style, float *w, float *h); -void RenderAchievement(UIContext &dc, const rc_client_achievement_t *achievement, AchievementRenderStyle style, const Bounds &bounds, float alpha, float startTime, float time_s, bool hasFocus); - -void MeasureGameAchievementSummary(const UIContext &dc, float *w, float *h); -void RenderGameAchievementSummary(UIContext &dc, const Bounds &bounds, float alpha); - -void MeasureLeaderboardEntry(const UIContext &dc, const rc_client_leaderboard_entry_t *entry, float *w, float *h); -void RenderLeaderboardEntry(UIContext &dc, const rc_client_leaderboard_entry_t *entry, const Bounds &bounds, float alpha); - -class AchievementView : public UI::ClickableItem { -public: - AchievementView(const rc_client_achievement_t *achievement, UI::LayoutParams *layoutParams = nullptr) : UI::ClickableItem(layoutParams), achievement_(achievement) { - layoutParams_->height = UI::WRAP_CONTENT; // Override the standard Item fixed height. - } - - void Click() override; - void Draw(UIContext &dc) override; - void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; -private: - const rc_client_achievement_t *achievement_; -}; - -class GameAchievementSummaryView : public UI::Item { -public: - GameAchievementSummaryView(UI::LayoutParams *layoutParams = nullptr) : UI::Item(layoutParams) { - layoutParams_->height = UI::WRAP_CONTENT; // Override the standard Item fixed height. - } - - void Draw(UIContext &dc) override; - void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; -}; - -class LeaderboardSummaryView : public UI::ClickableItem { -public: - LeaderboardSummaryView(const rc_client_leaderboard_t *leaderboard, UI::LayoutParams *layoutParams = nullptr) : UI::ClickableItem(layoutParams), leaderboard_(leaderboard) { - layoutParams_->height = UI::WRAP_CONTENT; // Override the standard Item fixed height. - } - - void Draw(UIContext &dc) override; - void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; - -private: - const rc_client_leaderboard_t *leaderboard_; -}; - -class LeaderboardEntryView : public UI::Item { -public: - LeaderboardEntryView(const rc_client_leaderboard_entry_t *entry, bool isCurrentUser, UI::LayoutParams *layoutParams = nullptr) - : UI::Item(layoutParams), entry_(entry), isCurrentUser_(isCurrentUser) { - layoutParams_->height = UI::WRAP_CONTENT; // Override the standard Item fixed height. - } - - void Draw(UIContext &dc) override; - void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; - -private: - const rc_client_leaderboard_entry_t *entry_; - bool isCurrentUser_; -}; diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index de24b953b..77396a5f4 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -109,7 +109,7 @@ public: LinearLayout *topright = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f)); topright->SetSpacing(1.0f); topright->Add(new TextView(savedata_title, ALIGN_LEFT | FLAG_WRAP_TEXT, false))->SetTextColor(textStyle.fgColor); - topright->Add(new TextView(StringFromFormat("%lld kB", ginfo->gameSizeOnDisk / 1024), 0, true))->SetTextColor(textStyle.fgColor); + topright->Add(new TextView(StringFromFormat("%lld kB", ginfo->gameSize / 1024), 0, true))->SetTextColor(textStyle.fgColor); topright->Add(new TextView(GetFileDateAsString(savePath_ / "PARAM.SFO"), 0, true))->SetTextColor(textStyle.fgColor); toprow->Add(topright); content->Add(new Spacer(3.0)); @@ -287,9 +287,9 @@ void SavedataButton::UpdateText(const std::shared_ptr &ginfo) { if (!currentTitle.empty()) { title_ = CleanSaveString(currentTitle); } - if (subtitle_.empty() && ginfo->gameSizeOnDisk > 0) { + if (subtitle_.empty() && ginfo->gameSize > 0) { std::string savedata_title = ginfo->paramSFO.GetValueString("SAVEDATA_TITLE"); - subtitle_ = CleanSaveString(savedata_title) + StringFromFormat(" (%lld kB)", ginfo->gameSizeOnDisk / 1024); + subtitle_ = CleanSaveString(savedata_title) + StringFromFormat(" (%lld kB)", ginfo->gameSize / 1024); } } @@ -409,7 +409,7 @@ void SavedataButton::Draw(UIContext &dc) { std::string SavedataButton::DescribeText() const { auto u = GetI18NCategory(I18NCat::UI_ELEMENTS); - return ApplySafeSubstitutions(u->T("%1 button"), title_) + "\n" + subtitle_; + return ReplaceAll(u->T("%1 button"), "%1", title_) + "\n" + subtitle_; } SavedataBrowser::SavedataBrowser(const Path &path, UI::LayoutParams *layoutParams) @@ -465,9 +465,9 @@ void SavedataBrowser::SetSearchFilter(const std::string &filter) { if (gameList_) searchPending_ = true; if (noMatchView_) - noMatchView_->SetText(ApplySafeSubstitutions(sa->T("Nothing matching '%1' was found."), filter)); + noMatchView_->SetText(ReplaceAll(sa->T("Nothing matching '%1' was found."), "%1", filter)); if (searchingView_) - searchingView_->SetText(ApplySafeSubstitutions(sa->T("Showing matches for '%1'."), filter)); + searchingView_->SetText(ReplaceAll(sa->T("Showing matches for '%1'."), "%1", filter)); } void SavedataBrowser::SetSortOption(SavedataSortOption opt) { @@ -654,9 +654,8 @@ void SavedataScreen::CreateViews() { sortStrip->OnChoice.Handle(this, &SavedataScreen::OnSortClick); AddStandardBack(root_); - if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) root_->Add(new Choice(di->T("Search"), "", false, new AnchorLayoutParams(WRAP_CONTENT, 64, NONE, NONE, 10, 10)))->OnClick.Handle(this, &SavedataScreen::OnSearch); - } root_->Add(main); root_->Add(sortStrip); @@ -673,11 +672,13 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) { UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) { auto di = GetI18NCategory(I18NCat::DIALOG); - if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { - System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) { - System_PostUIMessage(UIMessage::SAVEDATA_SEARCH, value); - }); - } +#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) + System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) { + if (ivalue) { + NativeMessageReceived("savedatascreen_search", value.c_str()); + } + }); +#endif return UI::EVENT_DONE; } @@ -698,9 +699,9 @@ void SavedataScreen::dialogFinished(const Screen *dialog, DialogResult result) { } } -void SavedataScreen::sendMessage(UIMessage message, const char *value) { +void SavedataScreen::sendMessage(const char *message, const char *value) { UIDialogScreenWithGameBackground::sendMessage(message, value); - if (message == UIMessage::SAVEDATA_SEARCH) { + if (!strcmp(message, "savedatascreen_search")) { searchFilter_ = value; dataBrowser_->SetSearchFilter(searchFilter_); stateBrowser_->SetSearchFilter(searchFilter_); diff --git a/UI/SavedataScreen.h b/UI/SavedataScreen.h index b1dc6565e..10cd63125 100644 --- a/UI/SavedataScreen.h +++ b/UI/SavedataScreen.h @@ -73,7 +73,7 @@ public: ~SavedataScreen(); void dialogFinished(const Screen *dialog, DialogResult result) override; - void sendMessage(UIMessage message, const char *value) override; + void sendMessage(const char *message, const char *value) override; const char *tag() const override { return "Savedata"; } diff --git a/UI/Store.cpp b/UI/Store.cpp index 52d60878f..e744b99ac 100644 --- a/UI/Store.cpp +++ b/UI/Store.cpp @@ -20,7 +20,6 @@ #include "Common/UI/Screen.h" #include "Common/UI/Context.h" #include "Common/UI/ViewGroup.h" -#include "Common/UI/IconCache.h" #include "Common/Render/DrawBuffer.h" #include "Common/Log.h" @@ -28,19 +27,13 @@ #include "Common/Data/Format/JSONReader.h" #include "Common/StringUtils.h" #include "Common/Render/ManagedTexture.h" -#include "Common/Net/NetBuffer.h" #include "Core/Config.h" #include "Core/System.h" #include "Core/Util/GameManager.h" #include "UI/EmuScreen.h" #include "UI/Store.h" -const char *storeBaseUrlHttp = "http://store.ppsspp.org/"; -const char *storeBaseUrlHttps = "https://store.ppsspp.org/"; - -static std::string StoreBaseUrl() { - return System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS) ? storeBaseUrlHttps : storeBaseUrlHttp; -} +const std::string storeBaseUrl = "http://store.ppsspp.org/"; // baseUrl is assumed to have a trailing slash, and not contain any subdirectories. std::string ResolveUrl(std::string baseUrl, std::string url) { @@ -58,33 +51,12 @@ std::string ResolveUrl(std::string baseUrl, std::string url) { class HttpImageFileView : public UI::View { public: - HttpImageFileView(http::RequestManager *requestManager, const std::string &path, UI::ImageSizeMode sizeMode = UI::IS_DEFAULT, bool useIconCache = true, UI::LayoutParams *layoutParams = nullptr) - : UI::View(layoutParams), path_(path), sizeMode_(sizeMode), requestManager_(requestManager), useIconCache_(useIconCache) { - - if (useIconCache && g_iconCache.MarkPending(path_)) { - const char *acceptMime = "image/png, image/jpeg, image/*; q=0.9, */*; q=0.8"; - requestManager_->StartDownloadWithCallback(path_, Path(), http::ProgressBarMode::DELAYED, [](http::Request &download) { - // Can't touch 'this' in this function! Don't use captures! - std::string path = download.url(); - if (download.ResultCode() == 200) { - std::string data; - download.buffer().TakeAll(&data); - if (!data.empty()) { - g_iconCache.InsertIcon(path, IconFormat::PNG, std::move(data)); - } else { - g_iconCache.CancelPending(path); - } - } else { - g_iconCache.CancelPending(path); - } - }, acceptMime); - } - } + HttpImageFileView(http::Downloader *downloader, const std::string &path, UI::ImageSizeMode sizeMode = UI::IS_DEFAULT, UI::LayoutParams *layoutParams = 0) + : UI::View(layoutParams), path_(path), sizeMode_(sizeMode), downloader_(downloader) {} ~HttpImageFileView() { - if (download_) { + if (download_) download_->Cancel(); - } } void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; @@ -101,15 +73,14 @@ public: const std::string &GetFilename() const { return path_; } private: - void DownloadCompletedCallback(http::Request &download); + void DownloadCompletedCallback(http::Download &download); bool canFocus_ = false; - bool useIconCache_ = false; - std::string path_; // or cache key + std::string path_; uint32_t color_ = 0xFFFFFFFF; UI::ImageSizeMode sizeMode_; - http::RequestManager *requestManager_; - std::shared_ptr download_; + http::Downloader *downloader_; + std::shared_ptr download_; std::string textureData_; std::unique_ptr texture_; @@ -126,39 +97,28 @@ void HttpImageFileView::GetContentDimensions(const UIContext &dc, float &w, floa break; case UI::IS_DEFAULT: default: - if (useIconCache_) { - int width, height; - if (g_iconCache.GetDimensions(path_, &width, &height)) { - w = width; - h = height; - } else { - w = 16; - h = 16; - } + if (texture_) { + float texw = (float)texture_->Width(); + float texh = (float)texture_->Height(); + w = texw; + h = texh; } else { - if (texture_) { - float texw = (float)texture_->Width(); - float texh = (float)texture_->Height(); - w = texw; - h = texh; - } else { - w = 16; - h = 16; - } + w = 16; + h = 16; } break; } } void HttpImageFileView::SetFilename(std::string filename) { - if (!useIconCache_ && path_ != filename) { + if (path_ != filename) { textureFailed_ = false; path_ = filename; texture_.reset(nullptr); } } -void HttpImageFileView::DownloadCompletedCallback(http::Request &download) { +void HttpImageFileView::DownloadCompletedCallback(http::Download &download) { if (download.IsCancelled()) { // We were probably destroyed. Can't touch "this" (heh). return; @@ -172,21 +132,19 @@ void HttpImageFileView::DownloadCompletedCallback(http::Request &download) { void HttpImageFileView::Draw(UIContext &dc) { using namespace Draw; + if (!texture_ && !textureFailed_ && !path_.empty() && !download_) { + auto cb = std::bind(&HttpImageFileView::DownloadCompletedCallback, this, std::placeholders::_1); + const char *acceptMime = "image/png, image/jpeg, image/*; q=0.9, */*; q=0.8"; + download_ = downloader_->StartDownloadWithCallback(path_, Path(), cb, acceptMime); + download_->SetHidden(true); + } - if (!useIconCache_) { - if (!texture_ && !textureFailed_ && !path_.empty() && !download_) { - auto cb = std::bind(&HttpImageFileView::DownloadCompletedCallback, this, std::placeholders::_1); - const char *acceptMime = "image/png, image/jpeg, image/*; q=0.9, */*; q=0.8"; - requestManager_->StartDownloadWithCallback(path_, Path(), http::ProgressBarMode::NONE, cb, acceptMime); - } - - if (!textureData_.empty()) { - texture_ = CreateTextureFromFileData(dc.GetDrawContext(), (const uint8_t *)(textureData_.data()), (int)textureData_.size(), DETECT, false, "store_icon"); - if (!texture_) - textureFailed_ = true; - textureData_.clear(); - download_.reset(); - } + if (!textureData_.empty()) { + texture_ = CreateTextureFromFileData(dc.GetDrawContext(), (const uint8_t *)(textureData_.data()), (int)textureData_.size(), DETECT, false, "store_icon"); + if (!texture_) + textureFailed_ = true; + textureData_.clear(); + download_.reset(); } if (HasFocus()) { @@ -194,16 +152,9 @@ void HttpImageFileView::Draw(UIContext &dc) { } // TODO: involve sizemode - Draw::Texture *texture = nullptr; - if (useIconCache_) { - texture = g_iconCache.BindIconTexture(&dc, path_); - } else { - texture = texture_->GetTexture(); - } - - if (texture) { - float tw = texture->Width(); - float th = texture->Height(); + if (texture_) { + float tw = texture_->Width(); + float th = texture_->Height(); float x = bounds_.x; float y = bounds_.y; @@ -221,7 +172,7 @@ void HttpImageFileView::Draw(UIContext &dc) { } dc.Flush(); - dc.GetDrawContext()->BindTexture(0, texture); + dc.GetDrawContext()->BindTexture(0, texture_->GetTexture()); dc.Draw()->Rect(x, y, w, h, color_); dc.Flush(); dc.RebindTexture(); @@ -287,7 +238,7 @@ void ProductView::CreateViews() { Clear(); if (!entry_.iconURL.empty()) { - Add(new HttpImageFileView(&g_DownloadManager, ResolveUrl(StoreBaseUrl(), entry_.iconURL), IS_FIXED))->SetFixedSize(144, 88); + Add(new HttpImageFileView(&g_DownloadManager, ResolveUrl(storeBaseUrl, entry_.iconURL), IS_FIXED))->SetFixedSize(144, 88); } Add(new TextView(entry_.name)); Add(new TextView(entry_.author)); @@ -358,7 +309,7 @@ void ProductView::Update() { std::string ProductView::DownloadURL() { if (entry_.downloadURL.empty()) { // Construct the URL. - return StoreBaseUrl() + "files/" + entry_.file + ".zip"; + return storeBaseUrl + "files/" + entry_.file + ".zip"; } else { // Use the provided URL, for external hosting. return entry_.downloadURL; @@ -413,9 +364,9 @@ StoreScreen::StoreScreen() { lang_ = g_Config.sLanguageIni; loading_ = true; - std::string indexPath = StoreBaseUrl() + "index.json"; + std::string indexPath = storeBaseUrl + "index.json"; const char *acceptMime = "application/json, */*; q=0.8"; - listing_ = g_DownloadManager.StartDownload(indexPath, Path(), http::ProgressBarMode::DELAYED, acceptMime); + listing_ = g_DownloadManager.StartDownload(indexPath, Path(), acceptMime); } StoreScreen::~StoreScreen() { diff --git a/UI/Store.h b/UI/Store.h index 3c0be4668..0c4677d51 100644 --- a/UI/Store.h +++ b/UI/Store.h @@ -78,8 +78,8 @@ private: std::string GetTranslatedString(const json::JsonGet json, std::string key, const char *fallback = nullptr) const; - std::shared_ptr listing_; - std::shared_ptr image_; + std::shared_ptr listing_; + std::shared_ptr image_; // TODO: Replace with a PathBrowser or similar. Though that one only supports // local filesystems at the moment. diff --git a/UI/TabbedDialogScreen.cpp b/UI/TabbedDialogScreen.cpp deleted file mode 100644 index 7f80be305..000000000 --- a/UI/TabbedDialogScreen.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include - -#include "Common/StringUtils.h" -#include "Common/System/NativeApp.h" -#include "Common/System/Request.h" -#include "Common/System/Display.h" -#include "UI/TabbedDialogScreen.h" - -UI::LinearLayout *TabbedUIDialogScreenWithGameBackground::AddTab(const char *tag, const std::string &title, bool isSearch) { - auto se = GetI18NCategory(I18NCat::SEARCH); - - using namespace UI; - ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); - scroll->SetTag(tag); - - LinearLayout *contents = new LinearLayoutList(ORIENT_VERTICAL); - contents->SetSpacing(0); - scroll->Add(contents); - tabHolder_->AddTab(title, scroll); - - if (!isSearch) { - settingTabContents_.push_back(contents); - - auto notice = contents->Add(new TextView(se->T("Filtering settings by '%1'"), new LinearLayoutParams(Margins(20, 5)))); - notice->SetVisibility(V_GONE); - settingTabFilterNotices_.push_back(notice); - } - - return contents; -} - -void TabbedUIDialogScreenWithGameBackground::CreateViews() { - PreCreateViews(); - - bool vertical = UseVerticalLayout(); - - // Information in the top left. - // Back button to the bottom left. - // Scrolling action menu to the right. - using namespace UI; - - auto ms = GetI18NCategory(I18NCat::MAINSETTINGS); - auto di = GetI18NCategory(I18NCat::DIALOG); - - root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - - if (vertical) { - LinearLayout *verticalLayout = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); - tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, new LinearLayoutParams(1.0f)); - verticalLayout->Add(tabHolder_); - verticalLayout->Add(new Choice(di->T("Back"), "", false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0))))->OnClick.Handle(this, &UIScreen::OnBack); - root_->Add(verticalLayout); - } else { - tabHolder_ = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false)); - root_->Add(tabHolder_); - AddStandardBack(root_); - } - tabHolder_->SetTag(tag()); // take the tag from the screen. - root_->SetDefaultFocusView(tabHolder_); - settingTabContents_.clear(); - settingTabFilterNotices_.clear(); - - float leftSide = 40.0f; - if (!vertical) { - leftSide += 200.0f; - } - settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, g_display.dp_yres - 200.0f, new AnchorLayoutParams( - g_display.dp_xres - leftSide - 40.0f, WRAP_CONTENT, - leftSide, g_display.dp_yres - 80.0f - 40.0f, NONE, NONE)); - root_->Add(settingInfo_); - - // Show it again if we recreated the view - if (!oldSettingInfo_.empty()) { - settingInfo_->Show(oldSettingInfo_, nullptr); - } - - // Let the subclass create its tabs. - CreateTabs(); - - if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD) || System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { - // Hide search if screen is too small. - int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); - if ((g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) && (deviceType != DEVICE_TYPE_VR) && ShowSearchControls()) { - auto se = GetI18NCategory(I18NCat::SEARCH); - // Search - LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true); - - searchSettings->Add(new ItemHeader(se->T("Find settings"))); - searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Add([=](UI::EventParams &e) { - System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, StripSpaces(searchFilter_)); - return UI::EVENT_DONE; - }); - - clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter"))); - clearSearchChoice_->OnClick.Add([=](UI::EventParams &e) { - System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, ""); - return UI::EVENT_DONE; - }); - - noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5)))); - - ApplySearchFilter(); - } - } -} - -void TabbedUIDialogScreenWithGameBackground::sendMessage(UIMessage message, const char *value) { - UIDialogScreenWithGameBackground::sendMessage(message, value); - if (message == UIMessage::GAMESETTINGS_SEARCH) { - std::string filter = value ? value : ""; - searchFilter_.resize(filter.size()); - std::transform(filter.begin(), filter.end(), searchFilter_.begin(), tolower); - - ApplySearchFilter(); - } -} - -void TabbedUIDialogScreenWithGameBackground::RecreateViews() { - oldSettingInfo_ = settingInfo_ ? settingInfo_->GetText() : "N/A"; - UIScreen::RecreateViews(); -} - -void TabbedUIDialogScreenWithGameBackground::ApplySearchFilter() { - auto se = GetI18NCategory(I18NCat::SEARCH); - - bool matches = searchFilter_.empty(); - for (int t = 0; t < (int)settingTabContents_.size(); ++t) { - auto tabContents = settingTabContents_[t]; - bool tabMatches = searchFilter_.empty(); - - // Show an indicator that a filter is applied. - settingTabFilterNotices_[t]->SetVisibility(tabMatches ? UI::V_GONE : UI::V_VISIBLE); - settingTabFilterNotices_[t]->SetText(ApplySafeSubstitutions(se->T("Filtering settings by '%1'"), searchFilter_)); - - UI::View *lastHeading = nullptr; - for (int i = 1; i < tabContents->GetNumSubviews(); ++i) { - UI::View *v = tabContents->GetViewByIndex(i); - if (!v->CanBeFocused()) { - lastHeading = v; - } - - std::string label = v->DescribeText(); - std::transform(label.begin(), label.end(), label.begin(), tolower); - bool match = v->CanBeFocused() && label.find(searchFilter_) != label.npos; - tabMatches = tabMatches || match; - - if (match && lastHeading) - lastHeading->SetVisibility(UI::V_VISIBLE); - v->SetVisibility(searchFilter_.empty() || match ? UI::V_VISIBLE : UI::V_GONE); - } - tabHolder_->EnableTab(t, tabMatches); - matches = matches || tabMatches; - } - - noSearchResults_->SetText(ApplySafeSubstitutions(se->T("No settings matched '%1'"), searchFilter_)); - noSearchResults_->SetVisibility(matches ? UI::V_GONE : UI::V_VISIBLE); - clearSearchChoice_->SetVisibility(searchFilter_.empty() ? UI::V_GONE : UI::V_VISIBLE); -} diff --git a/UI/TabbedDialogScreen.h b/UI/TabbedDialogScreen.h deleted file mode 100644 index 70e131017..000000000 --- a/UI/TabbedDialogScreen.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "ppsspp_config.h" - -#include "Common/UI/UIScreen.h" -#include "Common/System/System.h" -#include "Core/ConfigValues.h" -#include "UI/MiscScreens.h" - -class TabbedUIDialogScreenWithGameBackground : public UIDialogScreenWithGameBackground { -public: - TabbedUIDialogScreenWithGameBackground(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) {} - - UI::LinearLayout *AddTab(const char *tag, const std::string &title, bool isSearch = false); - void CreateViews() override; - - -protected: - // Load data and define your tabs here. - virtual void PreCreateViews() {} - virtual void CreateTabs() = 0; - virtual bool ShowSearchControls() const { return true; } - - void RecreateViews() override; - void sendMessage(UIMessage message, const char *value) override; - - SettingInfoMessage *settingInfo_ = nullptr; - -private: - void ApplySearchFilter(); - - UI::TabHolder *tabHolder_ = nullptr; - std::vector settingTabContents_; - std::vector settingTabFilterNotices_; - UI::Choice *clearSearchChoice_ = nullptr; - UI::TextView *noSearchResults_ = nullptr; - // If we recreate the views while this is active we show it again - std::string oldSettingInfo_; - std::string searchFilter_; -}; diff --git a/UI/Theme.cpp b/UI/Theme.cpp index c59a59127..9119259e7 100644 --- a/UI/Theme.cpp +++ b/UI/Theme.cpp @@ -113,7 +113,7 @@ static void LoadThemeInfo(const std::vector &directories) { // Alright, let's loop through the sections and see if any is a theme. for (size_t i = 0; i < ini.Sections().size(); i++) { - Section §ion = *(ini.Sections()[i].get()); + Section §ion = ini.Sections()[i]; ThemeInfo info; section.Get("Name", &info.name, section.name().c_str()); @@ -191,12 +191,12 @@ void UpdateTheme(UIContext *ctx) { #if defined(USING_WIN_UI) || PPSSPP_PLATFORM(UWP) || defined(USING_QT_UI) ui_theme.uiFont = UI::FontStyle(FontID("UBUNTU24"), g_Config.sFont.c_str(), 22); - ui_theme.uiFontSmall = UI::FontStyle(FontID("UBUNTU24"), g_Config.sFont.c_str(), 17); - ui_theme.uiFontSmaller = UI::FontStyle(FontID("UBUNTU24"), g_Config.sFont.c_str(), 13); + ui_theme.uiFontSmall = UI::FontStyle(FontID("UBUNTU24"), g_Config.sFont.c_str(), 15); + ui_theme.uiFontSmaller = UI::FontStyle(FontID("UBUNTU24"), g_Config.sFont.c_str(), 12); #else ui_theme.uiFont = UI::FontStyle(FontID("UBUNTU24"), "", 20); - ui_theme.uiFontSmall = UI::FontStyle(FontID("UBUNTU24"), "", 15); - ui_theme.uiFontSmaller = UI::FontStyle(FontID("UBUNTU24"), "", 12); + ui_theme.uiFontSmall = UI::FontStyle(FontID("UBUNTU24"), "", 14); + ui_theme.uiFontSmaller = UI::FontStyle(FontID("UBUNTU24"), "", 11); #endif ui_theme.checkOn = ImageID("I_CHECKEDBOX"); diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index 4f3d3d215..97430af42 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -54,7 +54,6 @@ void TiltAnalogSettingsScreen::CreateViews() { tilt_ = new JoystickHistoryView(StickHistoryViewType::OTHER, "", new LinearLayoutParams(1.0f)); root_->Add(tilt_); } else { - tilt_ = nullptr; AnchorLayout *rightSide = new AnchorLayout(new LinearLayoutParams(1.0)); root_->Add(rightSide); switch (g_Config.iTiltInputType) { @@ -100,6 +99,7 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->SetSpacing(0); + static const char *tiltTypes[] = { "None (Disabled)", "Analog Stick", "D-PAD", "PSP Action Buttons", "L/R Trigger Buttons" }; settings->Add(new ItemHeader(co->T("Tilt control setup"))); settings->Add(new PopupMultiChoice(&g_Config.iTiltInputType, co->T("Tilt Input Type"), tiltTypes, 0, ARRAY_SIZE(tiltTypes), I18NCat::CONTROLS, screenManager()))->OnChoice.Add( @@ -122,9 +122,7 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new ItemHeader(co->T("Sensitivity"))); if (g_Config.iTiltInputType == 1) { - settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltAnalogDeadzoneRadius, 0.0f, 0.8f, 0.0f, co->T("Deadzone radius"), 0.02f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltInverseDeadzone, 0.0f, 0.8f, 0.0f, co->T("Low end radius"), 0.02f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); - settings->Add(new CheckBox(&g_Config.bTiltCircularInverseDeadzone, co->T("Circular low end radius")))->SetEnabledFunc(enabledFunc); + settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltAnalogDeadzoneRadius, 0.0f, 0.8f, 0.0f, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); } settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, 60, co->T("Tilt Sensitivity along X axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, 60, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); @@ -137,8 +135,21 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); } +void TiltAnalogSettingsScreen::axis(const AxisInput &axis) { + UIDialogScreenWithGameBackground::axis(axis); + + if (axis.deviceId == DEVICE_ID_ACCELEROMETER) { + switch (axis.axisId) { + case JOYSTICK_AXIS_ACCELEROMETER_X: down_.x = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Y: down_.y = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Z: down_.z = axis.value; break; + } + } +} + UI::EventReturn TiltAnalogSettingsScreen::OnCalibrate(UI::EventParams &e) { - g_Config.fTiltBaseAngleY = TiltEventProcessor::GetCurrentYAngle(); + Lin::Vec3 down = down_.normalized(); + g_Config.fTiltBaseAngleY = atan2(down.z, down.x); return UI::EVENT_DONE; } diff --git a/UI/TiltAnalogSettingsScreen.h b/UI/TiltAnalogSettingsScreen.h index b1416cfb6..1c338e5e9 100644 --- a/UI/TiltAnalogSettingsScreen.h +++ b/UI/TiltAnalogSettingsScreen.h @@ -29,6 +29,7 @@ public: TiltAnalogSettingsScreen(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) {} void CreateViews() override; + void axis(const AxisInput &axis) override; void update() override; const char *tag() const override { return "TiltAnalogSettings"; } diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index ad95e1d7d..646056ff2 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -520,12 +520,16 @@ void ControlLayoutView::CreateViews() { } return b; }; - - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { - char temp[64]; - snprintf(temp, sizeof(temp), "Custom %d button", i); - addDragCustomKey(g_Config.touchCustom[i], temp, g_Config.CustomButton[i]); - } + addDragCustomKey(g_Config.touchCustom0, "Custom 1 button", g_Config.CustomButton0); + addDragCustomKey(g_Config.touchCustom1, "Custom 2 button", g_Config.CustomButton1); + addDragCustomKey(g_Config.touchCustom2, "Custom 3 button", g_Config.CustomButton2); + addDragCustomKey(g_Config.touchCustom3, "Custom 4 button", g_Config.CustomButton3); + addDragCustomKey(g_Config.touchCustom4, "Custom 5 button", g_Config.CustomButton4); + addDragCustomKey(g_Config.touchCustom5, "Custom 6 button", g_Config.CustomButton5); + addDragCustomKey(g_Config.touchCustom6, "Custom 7 button", g_Config.CustomButton6); + addDragCustomKey(g_Config.touchCustom7, "Custom 8 button", g_Config.CustomButton7); + addDragCustomKey(g_Config.touchCustom8, "Custom 9 button", g_Config.CustomButton8); + addDragCustomKey(g_Config.touchCustom9, "Custom 10 button", g_Config.CustomButton9); for (size_t i = 0; i < controls_.size(); i++) { Add(controls_[i]); diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index 8fee0169c..0828e97eb 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -17,7 +17,6 @@ #include "Common/Render/TextureAtlas.h" #include "Common/Data/Text/I18n.h" -#include "Common/StringUtils.h" #include "Core/Config.h" @@ -90,15 +89,46 @@ void TouchControlVisibilityScreen::CreateViews() { return UI::EVENT_DONE; }}); toggles_.push_back({ "Fast-forward", &g_Config.touchFastForwardKey.show, ImageID::invalid(), nullptr }); - - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { - char temp[256]; - snprintf(temp, sizeof(temp), "Custom %d", i + 1); - toggles_.push_back({ temp, &g_Config.touchCustom[i].show, ImageID::invalid(), [=](EventParams &e) { - screenManager()->push(new CustomButtonMappingScreen(gamePath_, i)); - return UI::EVENT_DONE; - } }); - } + toggles_.push_back({ "Custom 1", &g_Config.touchCustom0.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 0)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 2", &g_Config.touchCustom1.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 1)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 3", &g_Config.touchCustom2.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 2)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 4", &g_Config.touchCustom3.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 3)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 5", &g_Config.touchCustom4.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 4)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 6", &g_Config.touchCustom5.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 5)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 7", &g_Config.touchCustom6.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 6)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 8", &g_Config.touchCustom7.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 7)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 9", &g_Config.touchCustom8.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 8)); + return UI::EVENT_DONE; + }}); + toggles_.push_back({ "Custom 10", &g_Config.touchCustom9.show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(gamePath_, 9)); + return UI::EVENT_DONE; + }}); auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS); for (auto toggle : toggles_) { @@ -109,15 +139,7 @@ void TouchControlVisibilityScreen::CreateViews() { row->Add(checkbox); Choice *choice; if (toggle.handle) { - // Handle custom button strings differently, and hackily. But will extend to arbitrary button counts. - char translated[256]; - int i = 0; - if (sscanf(toggle.key.c_str(), "Custom %d", &i) == 1) { - snprintf(translated, sizeof(translated), mc->T("Custom %d"), i); - } else { - truncate_cpy(translated, mc->T(toggle.key)); - } - choice = new Choice(std::string(translated) + " (" + mc->T("tap to customize") + ")", "", false, new LinearLayoutParams(1.0f)); + choice = new Choice(std::string(mc->T(toggle.key))+" ("+mc->T("tap to customize")+")", "", false, new LinearLayoutParams(1.0f)); choice->OnClick.Add(toggle.handle); } else if (toggle.img.isValid()) { choice = new CheckBoxChoice(toggle.img, checkbox, new LinearLayoutParams(1.0f)); diff --git a/UI/TouchControlVisibilityScreen.h b/UI/TouchControlVisibilityScreen.h index f52862735..c21efbde8 100644 --- a/UI/TouchControlVisibilityScreen.h +++ b/UI/TouchControlVisibilityScreen.h @@ -25,7 +25,7 @@ namespace UI { } struct TouchButtonToggle { - std::string key; + const char *key; bool *show; ImageID img; std::function handle; diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index bc54fd4ce..d7286261b 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -40,7 +40,6 @@ - @@ -60,11 +59,9 @@ - - @@ -77,7 +74,6 @@ - @@ -97,10 +93,8 @@ - - @@ -108,15 +102,9 @@ - - {533f1d30-d04d-47cc-ad71-20f658907e36} - {beb0a821-3c7f-410f-a525-63afbc69bf8f} - - {31694510-a8c0-40f6-b09b-e8df825adefa} - {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 5c1d68dab..120b04c9d 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -83,15 +83,6 @@ Screens - - Screens - - - Screens - - - Screens - @@ -175,15 +166,6 @@ Screens - - Screens - - - Screens - - - Screens - diff --git a/UWP/.gitignore b/UWP/.gitignore index dae79e7ce..bc18c645d 100644 --- a/UWP/.gitignore +++ b/UWP/.gitignore @@ -1,5 +1,6 @@ # We copy other files on top of these at build time, depending on configuration (Normal/Gold) +Package.appxmanifest Assets AppPackages x64 diff --git a/UWP/App.cpp b/UWP/App.cpp index 6383d5951..13611a04f 100644 --- a/UWP/App.cpp +++ b/UWP/App.cpp @@ -3,27 +3,19 @@ #include "pch.h" #include "App.h" -#include #include -#include "Common/Net/HTTPClient.h" -#include "Common/Net/Resolve.h" - -#include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/DirectoryReader.h" -#include "Common/Data/Encoding/Utf8.h" #include "Common/Input/InputState.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" -#include "Common/LogManager.h" #include "Core/System.h" #include "Core/Config.h" #include "Core/Core.h" -#include "UWPHelpers/LaunchItem.h" -#include + +#include using namespace UWP; - + using namespace concurrency; using namespace Windows::ApplicationModel; using namespace Windows::ApplicationModel::Core; @@ -52,59 +44,6 @@ App::App() : { } -void App::InitialPPSSPP() { - // Initial net - net::Init(); - - // Get install location - auto packageDirectory = Package::Current->InstalledPath; - const Path& exePath = Path(FromPlatformString(packageDirectory)); - g_VFS.Register("", new DirectoryReader(exePath / "Content")); - g_VFS.Register("", new DirectoryReader(exePath)); - - // Mount a filesystem - g_Config.flash0Directory = exePath / "assets/flash0"; - - // Prepare for initialization - std::wstring internalDataFolderW = ApplicationData::Current->LocalFolder->Path->Data(); - g_Config.internalDataDirectory = Path(internalDataFolderW); - g_Config.memStickDirectory = g_Config.internalDataDirectory; - - // On Win32 it makes more sense to initialize the system directories here - // because the next place it was called was in the EmuThread, and it's too late by then. - CreateSysDirectories(); - - LogManager::Init(&g_Config.bEnableLogging); - - // Set the config path to local state by default - // it will be overrided by `NativeInit` if there is custom memStick - g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); - g_Config.Load(); - - if (g_Config.bFirstRun) { - // Clear `memStickDirectory` to show memory stick screen on first start - g_Config.memStickDirectory.clear(); - } - - // Since we don't have any async operation in `NativeInit` - // it's better to call it here - const char* argv[2] = { "fake", nullptr }; - std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data()); - // We will not be able to use `argv` - // since launch parameters usually handled by `OnActivated` - // and `OnActivated` will be invoked later, even after `PPSSPP_UWPMain(..)` - // so we are handling launch cases using `LaunchItem` - NativeInit(1, argv, "", "", cacheFolder.c_str()); - - // Override backend, `DIRECT3D11` is the only way for UWP apps - g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11; - - // Calling `NativeInit` before will help us to deal with custom configs - // such as custom adapter, so it's better to initial render device here - m_deviceResources = std::make_shared(); - m_deviceResources->CreateWindowSizeDependentResources(); -} - // The first method called when the IFrameworkView is being created. void App::Initialize(CoreApplicationView^ applicationView) { // Register event handlers for app lifecycle. This example includes Activated, so that we @@ -117,6 +56,10 @@ void App::Initialize(CoreApplicationView^ applicationView) { CoreApplication::Resuming += ref new EventHandler(this, &App::OnResuming); + + // At this point we have access to the device. + // We can create the device-dependent resources. + m_deviceResources = std::make_shared(); } // Called when the CoreWindow object is created (or re-created). @@ -143,7 +86,6 @@ void App::SetWindow(CoreWindow^ window) { window->KeyDown += ref new TypedEventHandler(this, &App::OnKeyDown); window->KeyUp += ref new TypedEventHandler(this, &App::OnKeyUp); - window->CharacterReceived += ref new TypedEventHandler(this, &App::OnCharacterReceived); window->PointerMoved += ref new TypedEventHandler(this, &App::OnPointerMoved); window->PointerEntered += ref new TypedEventHandler(this, &App::OnPointerEntered); @@ -166,7 +108,7 @@ void App::SetWindow(CoreWindow^ window) { Windows::UI::Core::BackRequestedEventArgs^>( this, &App::App_BackRequested); - InitialPPSSPP(); + m_deviceResources->SetWindow(window); } bool App::HasBackButton() { @@ -192,10 +134,6 @@ void App::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyE m_main->OnKeyUp(args->KeyStatus.ScanCode, args->VirtualKey); } -void App::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args) { - m_main->OnCharacterReceived(args->KeyStatus.ScanCode, args->KeyCode); -} - void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) { int pointerId = touchMap_.TouchId(args->CurrentPoint->PointerId); if (pointerId < 0) @@ -260,8 +198,9 @@ void App::Run() { while (!m_windowClosed) { if (m_windowVisible) { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); - m_main->Render(); - // TODO: Adopt some practices from m_deviceResources->Present(); + if (m_main->Render()) { + m_deviceResources->Present(); + } } else { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); } @@ -275,6 +214,7 @@ void App::Uninitialize() { } // Application lifecycle event handlers. + void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) { // Run() won't start until the CoreWindow is activated. CoreWindow::GetForCurrentThread()->Activate(); @@ -284,9 +224,6 @@ void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ if (g_Config.UseFullScreen()) Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->TryEnterFullScreenMode(); - - //Detect if app started or activated by launch item (file, uri) - DetectLaunchItem(args); } void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { @@ -298,7 +235,6 @@ void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { auto app = this; create_task([app, deferral]() { - g_Config.Save("App::OnSuspending"); app->m_deviceResources->Trim(); deferral->Complete(); }); @@ -331,11 +267,18 @@ void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ ar PSP_CoreParameter().pixelWidth = (int)(width * scale); PSP_CoreParameter().pixelHeight = (int)(height * scale); if (UpdateScreenScale((int)width, (int)height)) { - System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED); + NativeMessageReceived("gpu_displayResized", ""); } } void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) { + + if (args->Visible == false) { + // MainScreen::OnExit and even App::OnWindowClosed + // doesn't seem to be called when closing the window + // Try to save the config here + g_Config.Save("App::OnVisibilityChanged"); + } m_windowVisible = args->Visible; } diff --git a/UWP/App.h b/UWP/App.h index 595b618fc..bd1fd0b33 100644 --- a/UWP/App.h +++ b/UWP/App.h @@ -84,7 +84,6 @@ namespace UWP { // Input void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); - void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args); void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); @@ -95,7 +94,6 @@ namespace UWP { void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); void App_BackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ e); - void InitialPPSSPP(); private: std::shared_ptr m_deviceResources; diff --git a/UWP/Armips_UWP/Armips_UWP.vcxproj b/UWP/Armips_UWP/Armips_UWP.vcxproj index e0dc7a917..330b730cd 100644 --- a/UWP/Armips_UWP/Armips_UWP.vcxproj +++ b/UWP/Armips_UWP/Armips_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,6 +25,10 @@ Release ARM64 + + Release + Win32 + Release x64 @@ -46,7 +54,7 @@ StaticLibrary false - false + true @@ -61,7 +69,105 @@ false $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + false + stdcpp17 + _UNICODE;UNICODE;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + + + Console + false + false + + + NotUsing false diff --git a/UWP/Assets/.empty b/UWP/Assets/.empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/UWP/AssetsGold/StoreLogo.scale-100.png b/UWP/AssetsGold/StoreLogo.scale-100.png new file mode 100644 index 000000000..730cc243f Binary files /dev/null and b/UWP/AssetsGold/StoreLogo.scale-100.png differ diff --git a/UWP/Common/DeviceResources.cpp b/UWP/Common/DeviceResources.cpp index 6a2edb7d3..ab1bbcbf4 100644 --- a/UWP/Common/DeviceResources.cpp +++ b/UWP/Common/DeviceResources.cpp @@ -3,10 +3,6 @@ #include "DeviceResources.h" #include "DirectXHelper.h" -#include "Core/Config.h" -#include "Common/StringUtils.h" -#include "Common/Data/Encoding/Utf8.h" - using namespace D2D1; using namespace DirectX; using namespace Microsoft::WRL; @@ -129,7 +125,7 @@ void DX::DeviceResources::CreateDeviceIndependentResources() } // Configures the Direct3D device, and stores handles to it and the device context. -void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter) +void DX::DeviceResources::CreateDeviceResources() { // This flag adds support for surfaces with a different color channel ordering // than the API default. It is required for compatibility with Direct2D. @@ -163,10 +159,10 @@ void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter) // Create the Direct3D 11 API device object and a corresponding context. ComPtr device; ComPtr context; - auto hardwareType = (vAdapter != nullptr ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE); + HRESULT hr = D3D11CreateDevice( - vAdapter, // Specify nullptr to use the default adapter. - hardwareType, // Create a device using the hardware graphics driver. + nullptr, // Specify nullptr to use the default adapter. + D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver. 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. creationFlags, // Set debug and Direct2D compatibility flags. featureLevels, // List of feature levels this app can support. @@ -198,14 +194,6 @@ void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter) ); } - if (!vAdapter && CreateAdaptersList(device)) { - // While fetching the adapters list - // we will check if the configs has custom adapter - // then will recall this function to create device with custom adapter - // so we have to stop here, if the `CreateAdaptersList` return true - return; - } - // Store pointers to the Direct3D 11.3 API device and immediate context. DX::ThrowIfFailed( device.As(&m_d3dDevice) @@ -215,25 +203,14 @@ void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter) context.As(&m_d3dContext) ); - DX::ThrowIfFailed( - m_d3dDevice.As(&m_dxgiDevice) - ); - - DX::ThrowIfFailed( - m_dxgiDevice->GetAdapter(&m_dxgiAdapter) - ); - - DX::ThrowIfFailed( - m_dxgiAdapter->GetParent(IID_PPV_ARGS(&m_dxgiFactory)) - ); - // Create the Direct2D device object and a corresponding context. + ComPtr dxgiDevice; DX::ThrowIfFailed( - m_d3dDevice.As(&m_dxgiDevice) + m_d3dDevice.As(&dxgiDevice) ); DX::ThrowIfFailed( - m_d2dFactory->CreateDevice(m_dxgiDevice.Get(), &m_d2dDevice) + m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice) ); DX::ThrowIfFailed( @@ -244,72 +221,9 @@ void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter) ); } -bool DX::DeviceResources::CreateAdaptersList(ComPtr device) { - ComPtr dxgi_device; - DX::ThrowIfFailed( - device.As(&dxgi_device) - ); - - Microsoft::WRL::ComPtr deviceAdapter; - dxgi_device->GetAdapter(&deviceAdapter); - - Microsoft::WRL::ComPtr deviceFactory; - deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory)); - - // Current adapter (Get current adapter name) - DXGI_ADAPTER_DESC currentDefaultAdapterDesc; - deviceAdapter->GetDesc(¤tDefaultAdapterDesc); - std::string currentDefaultAdapterName = ConvertWStringToUTF8(currentDefaultAdapterDesc.Description); - - UINT i = 0; - IDXGIAdapter* pAdapter; - IDXGIAdapter* customAdapter = nullptr; - auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo; - bool isXbox = deviceInfo->DeviceFamily == "Windows.Xbox"; - while (deviceFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND) - { - ++i; - DXGI_ADAPTER_DESC vAdapterDesc; - pAdapter->GetDesc(&vAdapterDesc); - auto adapterDescription = ConvertWStringToUTF8(vAdapterDesc.Description); - if (isXbox && adapterDescription == "Microsoft Basic Render Driver") { - // Skip, very slow and not usefull for Xbox - continue; - } - m_vAdapters.push_back(adapterDescription); - if (!g_Config.sD3D11Device.empty() && g_Config.sD3D11Device == adapterDescription) { - // Double check if it's the same default adapter - if (adapterDescription != currentDefaultAdapterName) { - customAdapter = pAdapter; - } - } - } - deviceFactory->Release(); - - if (m_vAdapters.size() == 1) { - // Only one (default) adapter, clear the list to hide device option from settings - m_vAdapters.clear(); - } - - bool reCreateDevice = false; - if (customAdapter) { - reCreateDevice = true; - // Recreate device with custom adapter - CreateDeviceResources(customAdapter); - } - - return reCreateDevice; -} - // These resources need to be recreated every time the window size is changed. void DX::DeviceResources::CreateWindowSizeDependentResources() { - // Window pointer was previously submited by `SetWindow` called from (App.cpp) - // we don't have to do that since we can easily get the current window - auto coreWindow = CoreWindow::GetForCurrentThread(); - - SetWindow(coreWindow); - // Clear the previous window size specific context. ID3D11RenderTargetView* nullViews[] = {nullptr}; m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); @@ -373,11 +287,27 @@ void DX::DeviceResources::CreateWindowSizeDependentResources() swapChainDesc.Scaling = scaling; swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + ComPtr dxgiAdapter; + DX::ThrowIfFailed( + dxgiDevice->GetAdapter(&dxgiAdapter) + ); + + ComPtr dxgiFactory; + DX::ThrowIfFailed( + dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)) + ); + ComPtr swapChain; DX::ThrowIfFailed( - m_dxgiFactory->CreateSwapChainForCoreWindow( + dxgiFactory->CreateSwapChainForCoreWindow( m_d3dDevice.Get(), - reinterpret_cast(coreWindow), + reinterpret_cast(m_window.Get()), &swapChainDesc, nullptr, &swapChain @@ -390,7 +320,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources() // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and // ensures that the application will only render after each VSync, minimizing power consumption. DX::ThrowIfFailed( - m_dxgiDevice->SetMaximumFrameLatency(1) + dxgiDevice->SetMaximumFrameLatency(1) ); } @@ -531,6 +461,7 @@ void DX::DeviceResources::SetWindow(CoreWindow^ window) { DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); + m_window = window; if (Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily == L"Windows.Xbox") { const auto hdi = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView(); @@ -563,6 +494,8 @@ void DX::DeviceResources::SetWindow(CoreWindow^ window) m_currentOrientation = currentDisplayInformation->CurrentOrientation; m_d2dContext->SetDpi(m_dpi, m_dpi); + + CreateWindowSizeDependentResources(); } // This method is called in the event handler for the SizeChanged event. @@ -582,8 +515,10 @@ void DX::DeviceResources::SetDpi(float dpi) { m_dpi = dpi; - // When the display DPI changes, the logical size of the window (measured in Dips) - // also changes and needs to be updated. + // When the display DPI changes, the logical size of the window (measured in Dips) also changes and needs to be updated. + m_logicalSize = Windows::Foundation::Size(m_window->Bounds.Width, m_window->Bounds.Height); + + m_d2dContext->SetDpi(m_dpi, m_dpi); CreateWindowSizeDependentResources(); } } @@ -605,8 +540,18 @@ void DX::DeviceResources::ValidateDevice() // was created or if the device has been removed. // First, get the information for the default adapter from when the device was created. + + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + + ComPtr deviceAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(&deviceAdapter)); + + ComPtr deviceFactory; + DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory))); + ComPtr previousDefaultAdapter; - DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter)); + DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, &previousDefaultAdapter)); DXGI_ADAPTER_DESC1 previousDesc; DX::ThrowIfFailed(previousDefaultAdapter->GetDesc1(&previousDesc)); @@ -630,6 +575,9 @@ void DX::DeviceResources::ValidateDevice() FAILED(m_d3dDevice->GetDeviceRemovedReason())) { // Release references to resources related to the old device. + dxgiDevice = nullptr; + deviceAdapter = nullptr; + deviceFactory = nullptr; previousDefaultAdapter = nullptr; // Create a new device and swap chain. diff --git a/UWP/Common/DeviceResources.h b/UWP/Common/DeviceResources.h index 8d2723cf1..8942c4901 100644 --- a/UWP/Common/DeviceResources.h +++ b/UWP/Common/DeviceResources.h @@ -1,7 +1,4 @@ -#pragma once - -#include -#include +#pragma once namespace DX { @@ -17,7 +14,6 @@ namespace DX { public: DeviceResources(); - void CreateWindowSizeDependentResources(); void SetWindow(Windows::UI::Core::CoreWindow^ window); void SetLogicalSize(Windows::Foundation::Size logicalSize); void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation); @@ -56,24 +52,16 @@ namespace DX DXGI_MODE_ROTATION ComputeDisplayRotation(); - std::vector GetAdapters() const { return m_vAdapters; }; - private: void CreateDeviceIndependentResources(); - void CreateDeviceResources(IDXGIAdapter* vAdapter = nullptr); + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); void UpdateRenderTargetSize(); - bool CreateAdaptersList(Microsoft::WRL::ComPtr device); // Direct3D objects. Microsoft::WRL::ComPtr m_d3dDevice; Microsoft::WRL::ComPtr m_d3dContext; Microsoft::WRL::ComPtr m_swapChain; - Microsoft::WRL::ComPtr m_dxgiDevice; - Microsoft::WRL::ComPtr m_dxgiFactory; - Microsoft::WRL::ComPtr m_dxgiAdapter; - - // Direct3D adapters - std::vector m_vAdapters; // Direct3D rendering objects. Required for 3D. Microsoft::WRL::ComPtr m_d3dRenderTargetView; @@ -89,6 +77,9 @@ namespace DX Microsoft::WRL::ComPtr m_dwriteFactory; Microsoft::WRL::ComPtr m_wicFactory; + // Cached reference to the Window. + Platform::Agile m_window; + // Cached device properties. D3D_FEATURE_LEVEL m_d3dFeatureLevel; Windows::Foundation::Size m_d3dRenderTargetSize; @@ -108,4 +99,4 @@ namespace DX // The IDeviceNotify can be held directly as it owns the DeviceResources. IDeviceNotify* m_deviceNotify; }; -} +} \ No newline at end of file diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index b4d9a8937..353aa305b 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {acb316ca-3ecb-48e5-be0a-91e72d5b0f12} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,7 +84,23 @@ false - + + + false + false + pch.h + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + NotUsing + stdcpp17 + + + Console + false + false + + + false false @@ -76,7 +116,23 @@ false - + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + + false false @@ -92,6 +148,134 @@ false + + + false + false + pch.h + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + pch.h + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + + + + false + false + ../..;../../ext/openxr;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + pch.h + NotUsing + stdcpp17 + + + Console + false + false + + @@ -103,11 +287,8 @@ - - - @@ -208,7 +389,6 @@ - @@ -220,7 +400,6 @@ - @@ -253,7 +432,6 @@ - @@ -265,11 +443,8 @@ - - - @@ -350,7 +525,6 @@ - @@ -359,7 +533,6 @@ - @@ -395,7 +568,6 @@ - diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index 2eedf9e8c..18faba3ae 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -94,9 +94,6 @@ {8b92cc15-8e3e-45b1-ba80-ad39b1a9cdc8} - - {403c3154-5e8a-4da1-ba82-8f69bef25e14} - @@ -438,24 +435,6 @@ File - - GPU - - - UI - - - System - - - Net - - - Net - - - ext\naett - @@ -844,24 +823,6 @@ File - - GPU - - - UI - - - System - - - Net - - - Net - - - ext\naett - diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 7e157036d..1eaeaef5b 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {40b76674-02de-40ef-889b-fad1489685e7} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,13 +84,61 @@ false - + Use false false pch.h - ../../ext/libchdr/include;../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -76,13 +148,13 @@ false - + Use false false pch.h - ../../ext/libchdr/include;../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -92,13 +164,110 @@ false - + Use false false pch.h - ../../ext/libchdr/include;../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -126,7 +295,6 @@ - @@ -172,7 +340,6 @@ - @@ -271,8 +438,6 @@ - - @@ -281,8 +446,6 @@ - - @@ -301,25 +464,22 @@ + - - - - @@ -374,7 +534,6 @@ - @@ -420,7 +579,6 @@ - @@ -523,15 +681,6 @@ - - - - - - - - - @@ -554,8 +703,6 @@ - - @@ -581,30 +728,20 @@ + - - - - - - - - - - - @@ -621,459 +758,573 @@ NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing @@ -1112,9 +1363,6 @@ {acb316ca-3ecb-48e5-be0a-91e72d5b0f12} - - {191b6f52-ad66-4172-bd20-733eeeceef8c} - {d31fd4f0-53eb-477c-9dc7-149796f628e2} diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 0f70f5854..85f5201e0 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -174,6 +174,9 @@ MIPS\x86 + + MIPS\x86 + MIPS\x86 @@ -186,33 +189,6 @@ MIPS\x86 - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - - - MIPS\x86 - FileSystems @@ -669,12 +645,6 @@ MIPS\IR - - MIPS\IR - - - MIPS\IR - MIPS\IR @@ -701,9 +671,6 @@ Debugger\WebSocket - - Debugger\WebSocket - Debugger\WebSocket @@ -782,33 +749,6 @@ MIPS\ARM64 - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - - - MIPS\ARM64 - HW @@ -1187,11 +1127,6 @@ MIPS - - - - Util - @@ -1239,6 +1174,9 @@ MIPS\JitCommon + + MIPS\x86 + MIPS\x86 @@ -1251,12 +1189,6 @@ MIPS\x86 - - MIPS\x86 - - - MIPS\x86 - FileSystems @@ -1731,12 +1663,6 @@ MIPS\IR - - MIPS\IR - - - MIPS\IR - MIPS\IR @@ -1820,12 +1746,6 @@ MIPS\ARM64 - - MIPS\ARM64 - - - MIPS\ARM64 - HW @@ -1862,12 +1782,6 @@ MIPS - - - - - Util - diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index ffc2d6f0c..26e69ea6e 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {5d271429-c288-4534-98af-94475d940058} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,7 +84,7 @@ false - + Use false @@ -76,7 +100,39 @@ false - + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + Use false @@ -92,7 +148,7 @@ false - + Use false @@ -108,6 +164,118 @@ false + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + + + + Use + false + false + pch.h + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) + stdcpp17 + + + Console + false + false + + diff --git a/UWP/NKCodeFromWindowsSystem.cpp b/UWP/NKCodeFromWindowsSystem.cpp index fe109d62d..01c6aeda2 100644 --- a/UWP/NKCodeFromWindowsSystem.cpp +++ b/UWP/NKCodeFromWindowsSystem.cpp @@ -3,7 +3,7 @@ using namespace Windows::System; -std::map virtualKeyCodeToNKCode{ +std::map virtualKeyCodeToNKCode{ { VirtualKey::A, NKCODE_A }, { VirtualKey::B, NKCODE_B }, { VirtualKey::C, NKCODE_C }, @@ -73,7 +73,6 @@ std::map virtualKeyCodeToNKCode{ { VirtualKey::PageUp, NKCODE_PAGE_UP }, { VirtualKey::PageDown, NKCODE_PAGE_DOWN }, { VirtualKey::Delete, NKCODE_FORWARD_DEL }, - { VirtualKey::Back, NKCODE_DEL }, { VirtualKey::End, NKCODE_MOVE_END }, { VirtualKey::Tab, NKCODE_TAB }, { VirtualKey::Down, NKCODE_DPAD_DOWN }, @@ -108,4 +107,4 @@ std::map virtualKeyCodeToNKCode{ //{ VK_OEM_102, NKCODE_EXT_PIPE }, //{ VK_LBUTTON, NKCODE_EXT_MOUSEBUTTON_1 }, //{ VK_RBUTTON, NKCODE_EXT_MOUSEBUTTON_2 },; -}; +}; \ No newline at end of file diff --git a/UWP/NKCodeFromWindowsSystem.h b/UWP/NKCodeFromWindowsSystem.h index 230b5a986..94905fb69 100644 --- a/UWP/NKCodeFromWindowsSystem.h +++ b/UWP/NKCodeFromWindowsSystem.h @@ -4,4 +4,4 @@ #include "Common/Input/KeyCodes.h" -extern std::map virtualKeyCodeToNKCode; +extern std::map virtualKeyCodeToNKCode; \ No newline at end of file diff --git a/UWP/PPSSPP_UWP.sln b/UWP/PPSSPP_UWP.sln index 8f1c7d1ae..e54559c70 100644 --- a/UWP/PPSSPP_UWP.sln +++ b/UWP/PPSSPP_UWP.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.6.33801.468 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.202 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPP_UWP", "UWP.vcxproj", "{01D7D581-09A3-4A26-94BD-A7C529B29329}" ProjectSection(ProjectDependencies) = postProject @@ -34,29 +34,199 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc_UWP", "miniupnpc_ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu_features_UWP", "cpu_features_UWP\cpu_features_UWP.vcxproj", "{C249F016-7F82-45CF-BB6E-0642A988C4D3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcheevos_UWP", "rcheevos_UWP\rcheevos_UWP.vcxproj", "{4C9D52D0-310A-4347-8991-E3788CB22169}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchdr_UWP", "libchdr_UWP\libchdr_UWP.vcxproj", "{191B6F52-AD66-4172-BD20-733EEECEEF8C}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 + Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 + Release|Win32 = Release|Win32 Release|x64 = Release|x64 UWP Gold|ARM = UWP Gold|ARM UWP Gold|ARM64 = UWP Gold|ARM64 + UWP Gold|Win32 = UWP Gold|Win32 UWP Gold|x64 = UWP Gold|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM.ActiveCfg = Debug|ARM + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM.Build.0 = Debug|ARM + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM64.Build.0 = Debug|ARM64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|Win32.ActiveCfg = Debug|Win32 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|Win32.Build.0 = Debug|Win32 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|x64.ActiveCfg = Debug|x64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|x64.Build.0 = Debug|x64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM.ActiveCfg = Release|ARM + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM.Build.0 = Release|ARM + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM64.ActiveCfg = Release|ARM64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM64.Build.0 = Release|ARM64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|Win32.ActiveCfg = Release|Win32 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|Win32.Build.0 = Release|Win32 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|x64.ActiveCfg = Release|x64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|x64.Build.0 = Release|x64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|x64.Build.0 = UWP Gold|x64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM.ActiveCfg = Debug|ARM + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM.Build.0 = Debug|ARM + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM64.Build.0 = Debug|ARM64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|Win32.ActiveCfg = Debug|Win32 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|Win32.Build.0 = Debug|Win32 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|x64.ActiveCfg = Debug|x64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|x64.Build.0 = Debug|x64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM.ActiveCfg = Release|ARM + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM.Build.0 = Release|ARM + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM64.ActiveCfg = Release|ARM64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM64.Build.0 = Release|ARM64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|Win32.ActiveCfg = Release|Win32 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|Win32.Build.0 = Release|Win32 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|x64.ActiveCfg = Release|x64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|x64.Build.0 = Release|x64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|x64.Build.0 = UWP Gold|x64 + {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM.ActiveCfg = Debug|ARM + {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM.Build.0 = Debug|ARM + {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM64.Build.0 = Debug|ARM64 + {5D271429-C288-4534-98AF-94475D940058}.Debug|Win32.ActiveCfg = Debug|Win32 + {5D271429-C288-4534-98AF-94475D940058}.Debug|Win32.Build.0 = Debug|Win32 + {5D271429-C288-4534-98AF-94475D940058}.Debug|x64.ActiveCfg = Debug|x64 + {5D271429-C288-4534-98AF-94475D940058}.Debug|x64.Build.0 = Debug|x64 + {5D271429-C288-4534-98AF-94475D940058}.Release|ARM.ActiveCfg = Release|ARM + {5D271429-C288-4534-98AF-94475D940058}.Release|ARM.Build.0 = Release|ARM + {5D271429-C288-4534-98AF-94475D940058}.Release|ARM64.ActiveCfg = Release|ARM64 + {5D271429-C288-4534-98AF-94475D940058}.Release|ARM64.Build.0 = Release|ARM64 + {5D271429-C288-4534-98AF-94475D940058}.Release|Win32.ActiveCfg = Release|Win32 + {5D271429-C288-4534-98AF-94475D940058}.Release|Win32.Build.0 = Release|Win32 + {5D271429-C288-4534-98AF-94475D940058}.Release|x64.ActiveCfg = Release|x64 + {5D271429-C288-4534-98AF-94475D940058}.Release|x64.Build.0 = Release|x64 + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|x64.Build.0 = UWP Gold|x64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|ARM.ActiveCfg = Debug|ARM + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|ARM.Build.0 = Debug|ARM + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|ARM64.Build.0 = Debug|ARM64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|Win32.ActiveCfg = Debug|Win32 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|Win32.Build.0 = Debug|Win32 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|x64.ActiveCfg = Debug|x64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Debug|x64.Build.0 = Debug|x64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|ARM.ActiveCfg = Release|ARM + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|ARM.Build.0 = Release|ARM + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|ARM64.ActiveCfg = Release|ARM64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|ARM64.Build.0 = Release|ARM64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|Win32.ActiveCfg = Release|Win32 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|Win32.Build.0 = Release|Win32 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|x64.ActiveCfg = Release|x64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.Release|x64.Build.0 = Release|x64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {935028AF-B850-4AD7-A00E-7BA84FB97D05}.UWP Gold|x64.Build.0 = UWP Gold|x64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM.ActiveCfg = Debug|ARM + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM.Build.0 = Debug|ARM + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM64.Build.0 = Debug|ARM64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|Win32.ActiveCfg = Debug|Win32 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|Win32.Build.0 = Debug|Win32 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|x64.ActiveCfg = Debug|x64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|x64.Build.0 = Debug|x64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM.ActiveCfg = Release|ARM + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM.Build.0 = Release|ARM + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM64.ActiveCfg = Release|ARM64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM64.Build.0 = Release|ARM64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|Win32.ActiveCfg = Release|Win32 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|Win32.Build.0 = Release|Win32 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|x64.ActiveCfg = Release|x64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|x64.Build.0 = Release|x64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|x64.Build.0 = UWP Gold|x64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM.ActiveCfg = Debug|ARM + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM.Build.0 = Debug|ARM + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM64.Build.0 = Debug|ARM64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|Win32.ActiveCfg = Debug|Win32 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|Win32.Build.0 = Debug|Win32 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|x64.ActiveCfg = Debug|x64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|x64.Build.0 = Debug|x64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM.ActiveCfg = Release|ARM + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM.Build.0 = Release|ARM + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM64.ActiveCfg = Release|ARM64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM64.Build.0 = Release|ARM64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|Win32.ActiveCfg = Release|Win32 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|Win32.Build.0 = Release|Win32 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|x64.ActiveCfg = Release|x64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|x64.Build.0 = Release|x64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|x64.Build.0 = UWP Gold|x64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM.ActiveCfg = Debug|ARM + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM.Build.0 = Debug|ARM + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM64.Build.0 = Debug|ARM64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|Win32.ActiveCfg = Debug|Win32 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|Win32.Build.0 = Debug|Win32 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|x64.ActiveCfg = Debug|x64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|x64.Build.0 = Debug|x64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM.ActiveCfg = Release|ARM + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM.Build.0 = Release|ARM + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM64.ActiveCfg = Release|ARM64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM64.Build.0 = Release|ARM64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|Win32.ActiveCfg = Release|Win32 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|Win32.Build.0 = Release|Win32 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|x64.ActiveCfg = Release|x64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|x64.Build.0 = Release|x64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|x64.Build.0 = UWP Gold|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|ARM.ActiveCfg = Debug|ARM {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|ARM.Build.0 = Debug|ARM {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|ARM.Deploy.0 = Debug|ARM {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|ARM64.ActiveCfg = Debug|ARM64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|ARM64.Build.0 = Debug|ARM64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|Win32.ActiveCfg = Debug|Win32 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|Win32.Build.0 = Debug|Win32 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|Win32.Deploy.0 = Debug|Win32 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|x64.ActiveCfg = Debug|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|x64.Build.0 = Debug|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Debug|x64.Deploy.0 = Debug|x64 @@ -66,6 +236,9 @@ Global {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|ARM64.ActiveCfg = Release|ARM64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|ARM64.Build.0 = Release|ARM64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|ARM64.Deploy.0 = Release|ARM64 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|Win32.ActiveCfg = Release|Win32 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|Win32.Build.0 = Release|Win32 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|Win32.Deploy.0 = Release|Win32 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|x64.ActiveCfg = Release|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|x64.Build.0 = Release|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.Release|x64.Deploy.0 = Release|x64 @@ -75,261 +248,156 @@ Global {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|ARM64.Deploy.0 = UWP Gold|ARM64 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|Win32.Deploy.0 = UWP Gold|Win32 {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|x64.Build.0 = UWP Gold|x64 {01D7D581-09A3-4A26-94BD-A7C529B29329}.UWP Gold|x64.Deploy.0 = UWP Gold|x64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM.ActiveCfg = Debug|ARM - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM.Build.0 = Debug|ARM - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|ARM64.Build.0 = Debug|ARM64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|x64.ActiveCfg = Debug|x64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Debug|x64.Build.0 = Debug|x64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM.ActiveCfg = Release|ARM - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM.Build.0 = Release|ARM - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM64.ActiveCfg = Release|ARM64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|ARM64.Build.0 = Release|ARM64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|x64.ActiveCfg = Release|x64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.Release|x64.Build.0 = Release|x64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM.ActiveCfg = Release|ARM - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM.Build.0 = Release|ARM - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|x64.ActiveCfg = Release|x64 - {ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}.UWP Gold|x64.Build.0 = Release|x64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM.ActiveCfg = Debug|ARM - {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM.Build.0 = Debug|ARM - {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|ARM64.Build.0 = Debug|ARM64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|x64.ActiveCfg = Debug|x64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Debug|x64.Build.0 = Debug|x64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM.ActiveCfg = Release|ARM - {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM.Build.0 = Release|ARM - {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM64.ActiveCfg = Release|ARM64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|ARM64.Build.0 = Release|ARM64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|x64.ActiveCfg = Release|x64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.Release|x64.Build.0 = Release|x64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM.ActiveCfg = Release|ARM - {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM.Build.0 = Release|ARM - {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|x64.ActiveCfg = Release|x64 - {40B76674-02DE-40EF-889B-FAD1489685E7}.UWP Gold|x64.Build.0 = Release|x64 - {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM.ActiveCfg = Debug|ARM - {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM.Build.0 = Debug|ARM - {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5D271429-C288-4534-98AF-94475D940058}.Debug|ARM64.Build.0 = Debug|ARM64 - {5D271429-C288-4534-98AF-94475D940058}.Debug|x64.ActiveCfg = Debug|x64 - {5D271429-C288-4534-98AF-94475D940058}.Debug|x64.Build.0 = Debug|x64 - {5D271429-C288-4534-98AF-94475D940058}.Release|ARM.ActiveCfg = Release|ARM - {5D271429-C288-4534-98AF-94475D940058}.Release|ARM.Build.0 = Release|ARM - {5D271429-C288-4534-98AF-94475D940058}.Release|ARM64.ActiveCfg = Release|ARM64 - {5D271429-C288-4534-98AF-94475D940058}.Release|ARM64.Build.0 = Release|ARM64 - {5D271429-C288-4534-98AF-94475D940058}.Release|x64.ActiveCfg = Release|x64 - {5D271429-C288-4534-98AF-94475D940058}.Release|x64.Build.0 = Release|x64 - {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM.ActiveCfg = Release|ARM - {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM.Build.0 = Release|ARM - {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|x64.ActiveCfg = Release|x64 - {5D271429-C288-4534-98AF-94475D940058}.UWP Gold|x64.Build.0 = Release|x64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM.ActiveCfg = Debug|ARM - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM.Build.0 = Debug|ARM - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|ARM64.Build.0 = Debug|ARM64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|x64.ActiveCfg = Debug|x64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Debug|x64.Build.0 = Debug|x64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM.ActiveCfg = Release|ARM - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM.Build.0 = Release|ARM - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM64.ActiveCfg = Release|ARM64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|ARM64.Build.0 = Release|ARM64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|x64.ActiveCfg = Release|x64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.Release|x64.Build.0 = Release|x64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM.ActiveCfg = Release|ARM - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM.Build.0 = Release|ARM - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|x64.ActiveCfg = Release|x64 - {5FAC15BD-7397-4512-99D5-66CDC03AF5B7}.UWP Gold|x64.Build.0 = Release|x64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM.ActiveCfg = Debug|ARM - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM.Build.0 = Debug|ARM - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|ARM64.Build.0 = Debug|ARM64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|x64.ActiveCfg = Debug|x64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Debug|x64.Build.0 = Debug|x64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM.ActiveCfg = Release|ARM - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM.Build.0 = Release|ARM - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM64.ActiveCfg = Release|ARM64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|ARM64.Build.0 = Release|ARM64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|x64.ActiveCfg = Release|x64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.Release|x64.Build.0 = Release|x64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM.ActiveCfg = Release|ARM - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM.Build.0 = Release|ARM - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|x64.ActiveCfg = Release|x64 - {2F911C05-B341-4291-8BF5-09EDECBDD5F5}.UWP Gold|x64.Build.0 = Release|x64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM.ActiveCfg = Debug|ARM - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM.Build.0 = Debug|ARM - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|ARM64.Build.0 = Debug|ARM64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|x64.ActiveCfg = Debug|x64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Debug|x64.Build.0 = Debug|x64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM.ActiveCfg = Release|ARM - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM.Build.0 = Release|ARM - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM64.ActiveCfg = Release|ARM64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|ARM64.Build.0 = Release|ARM64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|x64.ActiveCfg = Release|x64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.Release|x64.Build.0 = Release|x64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM.ActiveCfg = Release|ARM - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM.Build.0 = Release|ARM - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|x64.ActiveCfg = Release|x64 - {DDF90203-0AAE-4F38-B589-2E9637658CE6}.UWP Gold|x64.Build.0 = Release|x64 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|ARM.ActiveCfg = Debug|ARM {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|ARM.Build.0 = Debug|ARM {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|ARM64.Build.0 = Debug|ARM64 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|Win32.ActiveCfg = Debug|Win32 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|Win32.Build.0 = Debug|Win32 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|x64.ActiveCfg = Debug|x64 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Debug|x64.Build.0 = Debug|x64 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|ARM.ActiveCfg = Release|ARM {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|ARM.Build.0 = Release|ARM {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|ARM64.ActiveCfg = Release|ARM64 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|ARM64.Build.0 = Release|ARM64 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|Win32.ActiveCfg = Release|Win32 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|Win32.Build.0 = Release|Win32 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|x64.ActiveCfg = Release|x64 {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.Release|x64.Build.0 = Release|x64 - {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM.ActiveCfg = Release|ARM - {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM.Build.0 = Release|ARM - {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|x64.ActiveCfg = Release|x64 - {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|x64.Build.0 = Release|x64 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}.UWP Gold|x64.Build.0 = UWP Gold|x64 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|ARM.ActiveCfg = Debug|ARM {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|ARM.Build.0 = Debug|ARM {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|ARM64.ActiveCfg = Debug|ARM64 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|ARM64.Build.0 = Debug|ARM64 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|Win32.Build.0 = Debug|Win32 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|x64.ActiveCfg = Debug|x64 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Debug|x64.Build.0 = Debug|x64 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|ARM.ActiveCfg = Release|ARM {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|ARM.Build.0 = Release|ARM {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|ARM64.ActiveCfg = Release|ARM64 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|ARM64.Build.0 = Release|ARM64 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|Win32.ActiveCfg = Release|Win32 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|Win32.Build.0 = Release|Win32 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|x64.ActiveCfg = Release|x64 {2B2D16BD-1D37-46AF-A3F8-552900951B26}.Release|x64.Build.0 = Release|x64 - {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM.ActiveCfg = Release|ARM - {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM.Build.0 = Release|ARM - {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|x64.ActiveCfg = Release|x64 - {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|x64.Build.0 = Release|x64 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {2B2D16BD-1D37-46AF-A3F8-552900951B26}.UWP Gold|x64.Build.0 = UWP Gold|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|ARM.ActiveCfg = Debug|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|ARM.Build.0 = Debug|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|ARM64.Build.0 = Debug|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|Win32.ActiveCfg = Debug|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|Win32.Build.0 = Debug|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|x64.ActiveCfg = Debug|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Debug|x64.Build.0 = Debug|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|ARM.ActiveCfg = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|ARM.Build.0 = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|ARM64.ActiveCfg = Release|ARM64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|ARM64.Build.0 = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|Win32.ActiveCfg = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|Win32.Build.0 = Release|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|x64.ActiveCfg = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.Release|x64.Build.0 = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|ARM.ActiveCfg = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|ARM.Build.0 = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|ARM64.Build.0 = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|Win32.ActiveCfg = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|Win32.Build.0 = Release|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|x64.ActiveCfg = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|x64.Build.0 = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM.ActiveCfg = Debug|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM.Build.0 = Debug|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM64.ActiveCfg = Debug|ARM64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM64.Build.0 = Debug|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|Win32.ActiveCfg = Debug|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|Win32.Build.0 = Debug|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|x64.ActiveCfg = Debug|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|x64.Build.0 = Debug|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM.ActiveCfg = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM.Build.0 = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM64.ActiveCfg = Release|ARM64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM64.Build.0 = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|Win32.ActiveCfg = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|Win32.Build.0 = Release|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|x64.ActiveCfg = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|x64.Build.0 = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM.ActiveCfg = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM.Build.0 = Release|ARM {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM64.Build.0 = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|Win32.ActiveCfg = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|Win32.Build.0 = Release|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|x64.ActiveCfg = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|x64.Build.0 = Release|x64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM.ActiveCfg = Debug|ARM {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM.Build.0 = Debug|ARM {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM64.Build.0 = Debug|ARM64 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|Win32.ActiveCfg = Debug|Win32 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|Win32.Build.0 = Debug|Win32 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|x64.ActiveCfg = Debug|x64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|x64.Build.0 = Debug|x64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|ARM.ActiveCfg = Release|ARM {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|ARM.Build.0 = Release|ARM {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|ARM64.ActiveCfg = Release|ARM64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|ARM64.Build.0 = Release|ARM64 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|Win32.ActiveCfg = Release|Win32 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|Win32.Build.0 = Release|Win32 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|x64.ActiveCfg = Release|x64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Release|x64.Build.0 = Release|x64 - {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM.ActiveCfg = Release|ARM - {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM.Build.0 = Release|ARM - {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|x64.ActiveCfg = Release|x64 - {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|x64.Build.0 = Release|x64 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|x64.Build.0 = UWP Gold|x64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM.ActiveCfg = Debug|ARM {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM.Build.0 = Debug|ARM {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM64.Build.0 = Debug|ARM64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|Win32.Build.0 = Debug|Win32 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|x64.ActiveCfg = Debug|x64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|x64.Build.0 = Debug|x64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM.ActiveCfg = Release|ARM {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM.Build.0 = Release|ARM {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM64.ActiveCfg = Release|ARM64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM64.Build.0 = Release|ARM64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.ActiveCfg = Release|Win32 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.Build.0 = Release|Win32 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.ActiveCfg = Release|x64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.Build.0 = Release|x64 - {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM.ActiveCfg = Release|ARM - {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM.Build.0 = Release|ARM - {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|x64.ActiveCfg = Release|x64 - {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|x64.Build.0 = Release|x64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Debug|ARM.ActiveCfg = Debug|ARM - {4C9D52D0-310A-4347-8991-E3788CB22169}.Debug|ARM.Build.0 = Debug|ARM - {4C9D52D0-310A-4347-8991-E3788CB22169}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Debug|ARM64.Build.0 = Debug|ARM64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Debug|x64.ActiveCfg = Debug|x64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Debug|x64.Build.0 = Debug|x64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Release|ARM.ActiveCfg = Release|ARM - {4C9D52D0-310A-4347-8991-E3788CB22169}.Release|ARM.Build.0 = Release|ARM - {4C9D52D0-310A-4347-8991-E3788CB22169}.Release|ARM64.ActiveCfg = Release|ARM64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Release|ARM64.Build.0 = Release|ARM64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Release|x64.ActiveCfg = Release|x64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.Release|x64.Build.0 = Release|x64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|ARM.ActiveCfg = Release|ARM - {4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|ARM.Build.0 = Release|ARM - {4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|x64.ActiveCfg = Release|x64 - {4C9D52D0-310A-4347-8991-E3788CB22169}.UWP Gold|x64.Build.0 = Release|x64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM.ActiveCfg = Debug|ARM - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM.Build.0 = Debug|ARM - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|ARM64.Build.0 = Debug|ARM64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|x64.ActiveCfg = Debug|x64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Debug|x64.Build.0 = Debug|x64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM.ActiveCfg = Release|ARM - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM.Build.0 = Release|ARM - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM64.ActiveCfg = Release|ARM64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|ARM64.Build.0 = Release|ARM64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|x64.ActiveCfg = Release|x64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.Release|x64.Build.0 = Release|x64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM.ActiveCfg = Release|ARM - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM.Build.0 = Release|ARM - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|ARM64.Build.0 = Release|ARM64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|x64.ActiveCfg = Release|x64 - {191B6F52-AD66-4172-BD20-733EEECEEF8C}.UWP Gold|x64.Build.0 = Release|x64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM.Build.0 = UWP Gold|ARM + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|Win32.Build.0 = UWP Gold|Win32 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|x64.ActiveCfg = UWP Gold|x64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|x64.Build.0 = UWP Gold|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 52e1b37ac..904906fbb 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -13,6 +13,7 @@ #include "Common/Common.h" #include "Common/Input/InputState.h" #include "Common/File/VFS/VFS.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/DirectXHelper.h" @@ -24,7 +25,6 @@ #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/Request.h" -#include "Common/OSVersion.h" #include "Core/System.h" #include "Core/Loaders.h" @@ -37,12 +37,6 @@ #include "UWPUtil.h" #include "App.h" -// UWP Helpers includes -#include "UWPHelpers/StorageManager.h" -#include "UWPHelpers/StorageAsync.h" -#include "UWPHelpers/LaunchItem.h" -#include "UWPHelpers/InputHelpers.h" - using namespace UWP; using namespace Windows::Foundation; using namespace Windows::Storage; @@ -53,9 +47,12 @@ using namespace Windows::Devices::Enumeration; using namespace Concurrency; // UGLY! +PPSSPP_UWPMain *g_main; extern WindowsAudioBackend *winAudioBackend; +std::string langRegion; std::list> g_input; + // TODO: Use Microsoft::WRL::ComPtr<> for D3D11 objects? // TODO: See https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/WindowsAudioSession for WASAPI with UWP // TODO: Low latency input: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/LowLatencyInput/cpp @@ -65,20 +62,68 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptrRegisterDeviceNotify(this); + // create_task(KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::RemovableDevices)).then([this](StorageFolder ^)); + + // TODO: Change the timer settings if you want something other than the default variable timestep mode. + // e.g. for 60 FPS fixed timestep update logic, call: + /* + m_timer.SetFixedTimeStep(true); + m_timer.SetTargetElapsedSeconds(1.0 / 60); + */ + ctx_.reset(new UWPGraphicsContext(deviceResources)); -#if _DEBUG - LogManager::GetInstance()->SetAllLogLevels(LogLevel::LDEBUG); + const Path &exePath = File::GetExeDirectory(); + g_VFS.Register("", new DirectoryReader(exePath / "Content")); + g_VFS.Register("", new DirectoryReader(exePath)); - if (g_Config.bEnableLogging) { - LogManager::GetInstance()->ChangeFileLog(GetLogFile().c_str()); + wchar_t lcCountry[256]; + + if (0 != GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, lcCountry, 256)) { + langRegion = ConvertWStringToUTF8(lcCountry); + for (size_t i = 0; i < langRegion.size(); i++) { + if (langRegion[i] == '-') + langRegion[i] = '_'; } -#endif + } else { + langRegion = "en_US"; + } + + std::wstring memstickFolderW = ApplicationData::Current->LocalFolder->Path->Data(); + g_Config.memStickDirectory = Path(memstickFolderW); + + // On Win32 it makes more sense to initialize the system directories here + // because the next place it was called was in the EmuThread, and it's too late by then. + InitSysDirectories(); + + LogManager::Init(&g_Config.bEnableLogging); + + // Load config up here, because those changes below would be overwritten + // if it's not loaded here first. + g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); + g_Config.Load(); + + bool debugLogLevel = false; + + g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11; + + if (debugLogLevel) { + LogManager::GetInstance()->SetAllLogLevels(LogTypes::LDEBUG); + } + + const char *argv[2] = { "fake", nullptr }; + + std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->LocalFolder->Path->Data()); + + NativeInit(1, argv, "", "", cacheFolder.c_str()); - // At this point we have main requirements initialized (Log, Config, NativeInit, Device) NativeInitGraphics(ctx_.get()); NativeResized(); @@ -91,9 +136,6 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr()); InputDevice::BeginPolling(); - - // Prepare input pane (for Xbox & touch devices) - PrepareInputPane(); } PPSSPP_UWPMain::~PPSSPP_UWPMain() { @@ -119,10 +161,18 @@ void PPSSPP_UWPMain::CreateWindowSizeDependentResources() { ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, m_deviceResources->GetBackBufferRenderTargetView()); } -void PPSSPP_UWPMain::UpdateScreenState() { - // This code was included into the render loop directly - // based on my test I don't understand why it should be called each loop - // is it better to call it on demand only, like when screen state changed? +// Renders the current frame according to the current application state. +// Returns true if the frame was rendered and is ready to be displayed. +bool PPSSPP_UWPMain::Render() { + ctx_->GetDrawContext()->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr); + NativeUpdate(); + + static bool hasSetThreadName = false; + if (!hasSetThreadName) { + SetCurrentThreadName("UWPRenderThread"); + hasSetThreadName = true; + } + auto context = m_deviceResources->GetD3DDeviceContext(); switch (m_deviceResources->ComputeDisplayRotation()) { @@ -161,20 +211,8 @@ void PPSSPP_UWPMain::UpdateScreenState() { g_display.dp_yres = g_display.pixel_yres * g_display.dpi_scale_y; context->RSSetViewports(1, &viewport); -} -// Renders the current frame according to the current application state. -// Returns true if the frame was rendered and is ready to be displayed. -bool PPSSPP_UWPMain::Render() { - static bool hasSetThreadName = false; - if (!hasSetThreadName) { - SetCurrentThreadName("UWPRenderThread"); - hasSetThreadName = true; - } - - UpdateScreenState(); - - NativeFrame(ctx_.get()); + NativeRender(ctx_.get()); return true; } @@ -191,10 +229,6 @@ void PPSSPP_UWPMain::OnDeviceRestored() { } void PPSSPP_UWPMain::OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount) { - // TODO: Look like (Ctrl, Alt, Shift) don't trigger this event - bool isDPad = (int)virtualKey >= 195 && (int)virtualKey <= 218; // DPad buttons range - DPadInputState(isDPad); - auto iter = virtualKeyCodeToNKCode.find(virtualKey); if (iter != virtualKeyCodeToNKCode.end()) { KeyInput key{}; @@ -216,22 +250,8 @@ void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKe } } -void PPSSPP_UWPMain::OnCharacterReceived(int scanCode, unsigned int keyCode) { - // This event triggered only in chars case, (Arrows, Delete..etc don't call it) - // TODO: Add ` && !IsCtrlOnHold()` once it's ready and implemented - if (isTextEditActive()) { - KeyInput key{}; - key.deviceId = DEVICE_ID_KEYBOARD; - key.keyCode = (InputKeyCode)keyCode; - // After many tests turns out for char just add `KEY_CHAR` for the flags - // any other flag like `KEY_DOWN` will cause conflict and trigger something else - key.flags = KEY_CHAR; - NativeKey(key); - } -} - void PPSSPP_UWPMain::OnMouseWheel(float delta) { - InputKeyCode key = NKCODE_EXT_MOUSEWHEEL_UP; + int key = NKCODE_EXT_MOUSEWHEEL_UP; if (delta < 0) { key = NKCODE_EXT_MOUSEWHEEL_DOWN; } else if (delta == 0) { @@ -294,10 +314,10 @@ void PPSSPP_UWPMain::OnSuspend() { UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr resources) { - std::vector adapterNames = resources->GetAdapters(); + std::vector adapterNames; draw_ = Draw::T3DCreateD3D11Context( - resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetSwapChain(), resources->GetDeviceFeatureLevel(), 0, adapterNames, g_Config.iInflightFrames); + resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetDeviceFeatureLevel(), 0, adapterNames); bool success = draw_->CreatePresets(); _assert_(success); } @@ -306,13 +326,17 @@ void UWPGraphicsContext::Shutdown() { delete draw_; } +void UWPGraphicsContext::SwapInterval(int interval) { + +} + std::string System_GetProperty(SystemProperty prop) { static bool hasCheckedGPUDriverVersion = false; switch (prop) { case SYSPROP_NAME: - return GetWindowsVersion(); + return "Windows 10 Universal"; case SYSPROP_LANGREGION: - return GetLangRegion(); + return langRegion; case SYSPROP_CLIPBOARD_TEXT: /* TODO: Need to either change this API or do this on a thread in an ugly fashion. DataPackageView ^view = Clipboard::GetContent(); @@ -323,8 +347,6 @@ std::string System_GetProperty(SystemProperty prop) { return ""; case SYSPROP_GPUDRIVER_VERSION: return ""; - case SYSPROP_BUILD_VERSION: - return PPSSPP_GIT_VERSION; default: return ""; } @@ -344,6 +366,13 @@ std::vector System_GetPropertyStringVec(SystemProperty prop) { // Need to resize off the null terminator either way. tempPath.resize(sz); result.push_back(ConvertWStringToUTF8(tempPath)); + + if (getenv("TMPDIR") && strlen(getenv("TMPDIR")) != 0) + result.push_back(getenv("TMPDIR")); + if (getenv("TMP") && strlen(getenv("TMP")) != 0) + result.push_back(getenv("TMP")); + if (getenv("TEMP") && strlen(getenv("TEMP")) != 0) + result.push_back(getenv("TEMP")); return result; } @@ -356,31 +385,17 @@ int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return winAudioBackend ? winAudioBackend->GetSampleRate() : -1; - case SYSPROP_DEVICE_TYPE: { - if (IsMobile()) { + auto ver = Windows::System::Profile::AnalyticsInfo::VersionInfo; + if (ver->DeviceFamily == "Windows.Mobile") { return DEVICE_TYPE_MOBILE; - } else if (IsXBox()) { + } else if (ver->DeviceFamily == "Windows.Xbox") { return DEVICE_TYPE_TV; } else { return DEVICE_TYPE_DESKTOP; } } - case SYSPROP_DISPLAY_XRES: - { - CoreWindow^ corewindow = CoreWindow::GetForCurrentThread(); - if (corewindow) { - return (int)corewindow->Bounds.Width; - } - } - case SYSPROP_DISPLAY_YRES: - { - CoreWindow^ corewindow = CoreWindow::GetForCurrentThread(); - if (corewindow) { - return (int)corewindow->Bounds.Height; - } - } default: return -1; } @@ -405,19 +420,15 @@ void System_Toast(const char *str) {} bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { case SYSPROP_HAS_OPEN_DIRECTORY: - { - return !IsXBox(); - } + return false; case SYSPROP_HAS_FILE_BROWSER: return true; case SYSPROP_HAS_FOLDER_BROWSER: - return true; + return false; // at least I don't know a usable one case SYSPROP_HAS_IMAGE_BROWSER: return true; // we just use the file browser case SYSPROP_HAS_BACK_BUTTON: return true; - case SYSPROP_HAS_ACCELEROMETER: - return IsMobile(); case SYSPROP_APP_GOLD: #ifdef GOLD return true; @@ -427,14 +438,7 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_CAN_JIT: return true; case SYSPROP_HAS_KEYBOARD: - { - // Do actual check - // touch devices has input pane, we need to depend on it - // I don't know any possible way to display input dialog in non-xaml apps - return isKeyboardAvailable() || isTouchAvailable(); - } - case SYSPROP_DEBUGGER_PRESENT: - return IsDebuggerPresent(); + return true; default: return false; } @@ -458,113 +462,48 @@ void System_Notify(SystemNotification notification) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { - - case SystemRequestType::EXIT_APP: - { - bool state = false; - ExecuteTask(state, Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->TryConsolidateAsync()); - if (!state) { - // Notify the user? - } - return true; - } - case SystemRequestType::RESTART_APP: - { - Windows::ApplicationModel::Core::AppRestartFailureReason error; - ExecuteTask(error, Windows::ApplicationModel::Core::CoreApplication::RequestRestartAsync(nullptr)); - if (error != Windows::ApplicationModel::Core::AppRestartFailureReason::RestartPending) { - // Shutdown - System_MakeRequest(SystemRequestType::EXIT_APP, requestId, param1, param2, param3); - } - return true; - } case SystemRequestType::BROWSE_FOR_IMAGE: - { - std::vector supportedExtensions = { ".jpg", ".png" }; - - //Call file picker - ChooseFile(supportedExtensions).then([requestId](std::string filePath) { - if (filePath.size() > 1) { - g_requestManager.PostSystemSuccess(requestId, filePath.c_str()); - } - else { - g_requestManager.PostSystemFailure(requestId); - } - }); - return true; - } case SystemRequestType::BROWSE_FOR_FILE: { - std::vector supportedExtensions = {}; - switch ((BrowseFileType)param3) { - case BrowseFileType::BOOTABLE: - supportedExtensions = { ".cso", ".bin", ".iso", ".elf", ".pbp", ".zip" }; - break; - case BrowseFileType::INI: - supportedExtensions = { ".ini" }; - break; - case BrowseFileType::DB: - supportedExtensions = { ".db" }; - break; - case BrowseFileType::SOUND_EFFECT: - supportedExtensions = { ".wav" }; - break; - case BrowseFileType::ANY: - // 'ChooseFile' will added '*' by default when there are no extensions assigned - break; - default: - ERROR_LOG(FILESYS, "Unexpected BrowseFileType: %d", param3); - return false; + auto picker = ref new Windows::Storage::Pickers::FileOpenPicker(); + picker->ViewMode = Pickers::PickerViewMode::List; + + if (type == SystemRequestType::BROWSE_FOR_IMAGE) { + picker->FileTypeFilter->Append(".jpg"); + picker->FileTypeFilter->Append(".png"); + } else { + switch ((BrowseFileType)param3) { + case BrowseFileType::BOOTABLE: + // These are single files that can be loaded directly using StorageFileLoader. + picker->FileTypeFilter->Append(".cso"); + picker->FileTypeFilter->Append(".iso"); + + // Can't load these this way currently, they require mounting the underlying folder. + picker->FileTypeFilter->Append(".bin"); + picker->FileTypeFilter->Append(".elf"); + break; + case BrowseFileType::INI: + picker->FileTypeFilter->Append(".ini"); + break; + case BrowseFileType::DB: + picker->FileTypeFilter->Append(".db"); + break; + case BrowseFileType::ANY: + picker->FileTypeFilter->Append("*"); + break; + } } - //Call file picker - ChooseFile(supportedExtensions).then([requestId](std::string filePath) { - if (filePath.size() > 1) { - g_requestManager.PostSystemSuccess(requestId, filePath.c_str()); - } - else { + picker->SuggestedStartLocation = Pickers::PickerLocationId::DocumentsLibrary; + + create_task(picker->PickSingleFileAsync()).then([requestId](StorageFile ^file) { + if (file) { + std::string path = FromPlatformString(file->Path); + g_requestManager.PostSystemSuccess(requestId, path.c_str()); + } else { g_requestManager.PostSystemFailure(requestId); } }); - - return true; - } - case SystemRequestType::BROWSE_FOR_FOLDER: - { - ChooseFolder().then([requestId](std::string folderPath) { - if (folderPath.size() > 1) { - g_requestManager.PostSystemSuccess(requestId, folderPath.c_str()); - } - else { - g_requestManager.PostSystemFailure(requestId); - } - }); - return true; - } - case SystemRequestType::NOTIFY_UI_STATE: - { - if (!param1.empty()) { - if (!strcmp(param1.c_str(), "menu")) { - CloseLaunchItem(); - } - else if (!strcmp(param1.c_str(), "popup_closed")) { - DeactivateTextEditInput(); - } - else if (!strcmp(param1.c_str(), "text_gotfocus")) { - ActivateTextEditInput(true); - } - else if (!strcmp(param1.c_str(), "text_lostfocus")) { - DeactivateTextEditInput(true); - } - } - return true; - } - case SystemRequestType::COPY_TO_CLIPBOARD: - { - auto dataPackage = ref new DataPackage(); - dataPackage->RequestedOperation = DataPackageOperation::Copy; - dataPackage->SetText(ToPlatformString(param1)); - Clipboard::SetContent(dataPackage); return true; } case SystemRequestType::TOGGLE_FULLSCREEN_STATE: @@ -583,14 +522,15 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } return true; } - case SystemRequestType::SHOW_FILE_IN_FOLDER: - OpenFolder(param1); - return true; default: return false; } } +void System_ShowFileInFolder(const char *path) { + // Unsupported +} + void System_LaunchUrl(LaunchUrlType urlType, const char *url) { auto uri = ref new Windows::Foundation::Uri(ToPlatformString(url)); @@ -675,3 +615,20 @@ std::string GetCPUBrandString() { return "Unknown"; } } + +// Emulation of TlsAlloc for Windows 10. Used by glslang. Doesn't actually seem to work, other than fixing the linking errors? + +extern "C" { +DWORD WINAPI __imp_TlsAlloc() { + return FlsAlloc(nullptr); +} +BOOL WINAPI __imp_TlsFree(DWORD index) { + return FlsFree(index); +} +BOOL WINAPI __imp_TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) { + return FlsSetValue(dwTlsIndex, lpTlsValue); +} +LPVOID WINAPI __imp_TlsGetValue(DWORD dwTlsIndex) { + return FlsGetValue(dwTlsIndex); +} +} diff --git a/UWP/PPSSPP_UWPMain.h b/UWP/PPSSPP_UWPMain.h index 09cdfbff3..3be7b25ce 100644 --- a/UWP/PPSSPP_UWPMain.h +++ b/UWP/PPSSPP_UWPMain.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include @@ -19,6 +19,8 @@ public: UWPGraphicsContext(std::shared_ptr resources); void Shutdown() override; + void SwapInterval(int interval) override; + void SwapBuffers() override {} void Resize() override {} Draw::DrawContext * GetDrawContext() override { return draw_; @@ -34,7 +36,6 @@ public: PPSSPP_UWPMain(App ^app, const std::shared_ptr& deviceResources); ~PPSSPP_UWPMain(); void CreateWindowSizeDependentResources(); - void UpdateScreenState(); bool Render(); // IDeviceNotify @@ -45,7 +46,6 @@ public: // Not sure whether this abstraction is worth it. void OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount); void OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKey); - void OnCharacterReceived(int scanCode,unsigned int keyCode); void OnTouchEvent(int touchEvent, int touchId, float x, float y, double timestamp); @@ -59,6 +59,8 @@ public: void OnSuspend(); void Close(); + void LoadStorageFile(Windows::Storage::StorageFile ^file); + private: App ^app_; @@ -68,4 +70,4 @@ private: std::unique_ptr ctx_; }; -} +} \ No newline at end of file diff --git a/UWP/Package.appxmanifest b/UWP/Package.appxmanifest index ec681ab8b..967c48e26 100644 --- a/UWP/Package.appxmanifest +++ b/UWP/Package.appxmanifest @@ -1,53 +1,36 @@ - - - - - - PPSSPP - PSP emulator - Henrik Rydgård - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - .cso - .bin - .iso - .elf - - - - - - - - - - - - - - - - - - - - + + + + + + PPSSPP - PSP emulator + Henrik Rydgård + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UWP/PackageGold.appxmanifest b/UWP/PackageGold.appxmanifest index 0396b3ee4..384fa2d9d 100644 --- a/UWP/PackageGold.appxmanifest +++ b/UWP/PackageGold.appxmanifest @@ -1,57 +1,40 @@ - - - - PPSSPP Gold - PSP emulator - Henrik Rydgård - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - - - .cso - .bin - .iso - .elf - - - - - - - - - - - - - - - - - - - + + + + PPSSPP Gold - PSP emulator + Henrik Rydgård + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UWP/PackageNormal.appxmanifest b/UWP/PackageNormal.appxmanifest new file mode 100644 index 000000000..cc6f628a2 --- /dev/null +++ b/UWP/PackageNormal.appxmanifest @@ -0,0 +1,36 @@ + + + + + + PPSSPP - PSP emulator + Henrik Rydgård + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj index e3838d4cd..4b0eeb423 100644 --- a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj +++ b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {2b2d16bd-1d37-46af-a3f8-552900951b26} @@ -43,10 +67,10 @@ StaticLibrary true - + StaticLibrary false - false + true @@ -60,7 +84,7 @@ false - + Use false @@ -74,7 +98,35 @@ false - + + + Use + false + true + pch.h + _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + true + pch.h + _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + Use false @@ -88,7 +140,7 @@ false - + Use false @@ -102,6 +154,104 @@ false + + + Use + false + true + pch.h + _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + true + pch.h + _ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + true + pch.h + _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + true + pch.h + _ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + false + pch.h + _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + true + pch.h + _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + + + + Use + false + true + pch.h + _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX + + + Console + false + false + + diff --git a/UWP/UI_UWP/UI_UWP.vcxproj b/UWP/UI_UWP/UI_UWP.vcxproj index e6940e76f..e9054bb14 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj +++ b/UWP/UI_UWP/UI_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {5fac15bd-7397-4512-99d5-66cdc03af5b7} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,7 +84,7 @@ false - + Use false @@ -76,7 +100,39 @@ false - + + + Use + false + false + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + GOLD;NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + Use false @@ -92,7 +148,7 @@ false - + Use false @@ -108,6 +164,118 @@ false + + + Use + false + false + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + GOLD;NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + GOLD;NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + + + + Use + false + false + GOLD;NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../..;../../ext/native;../../Common;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + pch.h + stdcpp17 + + + Console + false + false + + @@ -115,7 +283,6 @@ - @@ -127,8 +294,6 @@ - - @@ -153,7 +318,6 @@ - @@ -165,8 +329,6 @@ - - @@ -186,14 +348,6 @@ Create - - - {acb316ca-3ecb-48e5-be0a-91e72d5b0f12} - - - {4c9d52d0-310a-4347-8991-e3788cb22169} - - diff --git a/UWP/UI_UWP/UI_UWP.vcxproj.filters b/UWP/UI_UWP/UI_UWP.vcxproj.filters index aa3b1b3b6..56716f7b5 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj.filters +++ b/UWP/UI_UWP/UI_UWP.vcxproj.filters @@ -34,9 +34,6 @@ - - - @@ -72,8 +69,5 @@ - - - \ No newline at end of file diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 9a24e4e23..4e7b0db3b 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -1,6 +1,30 @@ + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + Debug ARM @@ -13,25 +37,13 @@ UWP Gold ARM - - Debug - ARM64 - - - Release - ARM64 - UWP Gold ARM64 - - Debug - x64 - - - Release - x64 + + UWP Gold + Win32 UWP Gold @@ -59,7 +71,7 @@ Application false - true + false true @@ -74,19 +86,17 @@ - False + True False Never + C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA False - 0 + 1 OnApplicationRun True PPSSPP_UWP_TemporaryKey.pfx - SHA256 - True - 0 - + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/ARM/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm @@ -103,13 +113,42 @@ + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) + ../ffmpeg/Windows10/ARM64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + _DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets + copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 + ../Windows/git-version-gen.cmd + EXIT 0 + + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/ARM/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm @@ -126,13 +165,42 @@ + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) + ../ffmpeg/Windows10/ARM64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets + copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 + ../Windows/git-version-gen.cmd + EXIT 0 + + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/ARM/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm @@ -150,59 +218,15 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsGold\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - - - xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) - ../ffmpeg/Windows10/ARM64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm - - - pch.h - $(IntDir)pch.pch - ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - 4453;28204 - _DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - pch.h - stdcpp17 - - - - copy AssetsNormal\*.* Assets /Y - ../Windows/git-version-gen.cmd - EXIT 0 - - - - - - xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) - ../ffmpeg/Windows10/ARM64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm - - - pch.h - $(IntDir)pch.pch - ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - 4453;28204 - NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - pch.h - stdcpp17 - - - - copy AssetsNormal\*.* Assets /Y - ../Windows/git-version-gen.cmd - EXIT 0 - - - - + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/ARM64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm @@ -220,13 +244,93 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsGold\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) + ../ffmpeg/Windows10/x86/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + _DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets + copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 + ../Windows/git-version-gen.cmd + EXIT 0 + + + + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) + ../ffmpeg/Windows10/x86/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets + copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 + ../Windows/git-version-gen.cmd + EXIT 0 + + + + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) + ../ffmpeg/Windows10/x86/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + ..;../ext/native;../ext/snappy;$(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + GOLD;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + + copy PackageGold.appxmanifest Package.appxmanifest /Y + mkdir Assets + copy AssetsGold\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 + ../Windows/git-version-gen.cmd + EXIT 0 + + + + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/x64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 @@ -243,13 +347,16 @@ + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/x64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 @@ -266,13 +373,16 @@ + copy PackageNormal.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsNormal\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + xinputuap.lib;libavcodec.a;libavformat.a;libavutil.a;libswresample.a;libswscale.a;d2d1.lib;d3d11.lib;dxgi.lib;windowscodecs.lib;dwrite.lib; %(AdditionalDependencies) ../ffmpeg/Windows10/x64/lib;%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 @@ -290,23 +400,17 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y + mkdir Assets copy AssetsGold\*.* Assets /Y + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - - Designer - Document - - - Designer - Document - - - True + + false true @@ -323,9 +427,24 @@ true + + true + true + + true + + + true + + + true + + + true + @@ -337,14 +456,8 @@ - - - - - - @@ -356,114 +469,437 @@ - - - - - Create - - + + Designer + Document + + true - Content\%(Filename)%(Extension) - - true - Content\debugger\%(Filename)%(Extension) - - + true Document - Content\%(Filename)%(Extension) - + true - Content\vfpu\%(Filename)%(Extension) - - + Document + + true - Content\debugger\%(Filename)%(Extension) - - + Document + + true - Content\debugger\%(Filename)%(Extension) - + true - Content\debugger\%(Filename)%(Extension) - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + true Content\debugger\static\css\%(Filename)%(Extension) - + true Content\debugger\static\css\%(Filename)%(Extension) - + true Content\debugger\static\js\%(Filename)%(Extension) - + true Content\debugger\static\js\%(Filename)%(Extension) - + true Content\debugger\static\media\%(Filename)%(Extension) - + true - Content\%(Filename)%(Extension) - + true - Content\themes\%(Filename)%(Extension) - + true - Content\%(Filename)%(Extension) - + true - Content\%(Filename)%(Extension) - + true - Content\flash0\font\%(Filename)%(Extension) - + true - Content\%(Filename)%(Extension) - + true - Content\%(Filename)%(Extension) - + true - Content\lang\%(Filename)%(Extension) - + true - Content\shaders\%(Filename)%(Extension) - + true - Content\shaders\%(Filename)%(Extension) - + true - Content\shaders\%(Filename)%(Extension) - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + true - Content\shaders\%(Filename)%(Extension) @@ -500,19 +936,16 @@ - + true Content\debugger\static\js\%(Filename)%(Extension) - + true - Content\%(Filename)%(Extension) - - Content\%(Filename)%(Extension) - + @@ -520,4 +953,4 @@ - \ No newline at end of file + diff --git a/UWP/UWP.vcxproj.filters b/UWP/UWP.vcxproj.filters index 0b635f0f4..5b018c149 100644 --- a/UWP/UWP.vcxproj.filters +++ b/UWP/UWP.vcxproj.filters @@ -1,91 +1,13 @@  - - 68b36d2a-4f4a-48a5-8b8f-cb15af108c93 - - - a5564d79-b131-4b27-9f5f-d80671731d94 - 0d070030-beb5-4f48-99a0-b1777297a468 - - 5964c8ad-590e-4b46-84f2-067602f4f231 + + a5564d79-b131-4b27-9f5f-d80671731d94 + bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png - - 8d1bdedf-c546-4b7a-8aa7-e490c4e8ad60 - - - {ef87b390-608f-4c6d-a0ad-88963875ed11} - wav;zim;ini;txt;ttf;png;meta - - - {0c1cdb21-de65-4a10-962e-46b9bb0ff717} - ini - - - {a861f712-3285-448d-b7a0-f6d39ac4c4b9} - vsh;fsh;csh;ini - - - {d51ae335-1279-4484-bfbf-2caa2efba6d9} - - - {d2294c79-82bd-470f-b984-f838f0fbcd25} - pgf - - - {da2113a6-e616-4fc9-8be3-ff75b963664b} - - - {55147387-68fc-487e-abed-7a763f850ef1} - json;ico;html - - - {e5d2759b-3511-4ab9-a9ca-070dd9715f3b} - - - {0fb972a9-20a9-4eba-be70-c408f9306939} - css;map - - - {47d54a48-ca53-4d57-8bfd-9c86fd97d84b} - js;map;txt - - - {83476056-57b8-409f-b729-754d6401e3d5} - - - {eebef4bc-52b6-460d-946d-c70c8a4ee337} - dat - - - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - Common @@ -95,9 +17,6 @@ Common - - Assets - Assets @@ -116,146 +35,517 @@ Assets + + {ef87b390-608f-4c6d-a0ad-88963875ed11} + + + {0c1cdb21-de65-4a10-962e-46b9bb0ff717} + + + {a861f712-3285-448d-b7a0-f6d39ac4c4b9} + + + {d51ae335-1279-4484-bfbf-2caa2efba6d9} + + + {d2294c79-82bd-470f-b984-f838f0fbcd25} + + + {da2113a6-e616-4fc9-8be3-ff75b963664b} + + + {55147387-68fc-487e-abed-7a763f850ef1} + + + {e5d2759b-3511-4ab9-a9ca-070dd9715f3b} + + + {0fb972a9-20a9-4eba-be70-c408f9306939} + + + {47d54a48-ca53-4d57-8bfd-9c86fd97d84b} + + + {83476056-57b8-409f-b729-754d6401e3d5} + + + {eebef4bc-52b6-460d-946d-c70c8a4ee337} + - - Audio - + - - Input - - - Input - - - UWPHelpers - - - UWPHelpers - - - UWPHelpers - + + - - Audio - + - - Input - - - Input - + + - - Input - - - UWPHelpers - + - + + Assets + + + Content + + + Content + + + Content + + + Content + + + Assets + + + Assets + + + Content + + + Content + + Content\debugger - - - Content - - + Content - + Content - + Content - + Content - + Content\lang - + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + + Content\lang + + Content\shaders - + Content\shaders - + Content\shaders - + Content\shaders - + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + Content\flash0\font - + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + + Content\flash0\font + + Content - + + Content + + Content\themes - + Content - + + Content + + + Content + + + Content + + + Content + + + Content + + + Content + + + Content\shaders + + + Content\shaders + + Content\debugger - + Content\debugger - + Content\debugger - + + Content\debugger + + Content\debugger\static\css - + Content\debugger\static\css - + Content\debugger\static\js - + Content\debugger\static\js - + Content\debugger\static\media - + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + + Content\vfpu + + Content\vfpu - + Content - + Content\debugger\static\js + + - + Content - \ No newline at end of file + diff --git a/UWP/UWPHelpers/InputHelpers.cpp b/UWP/UWPHelpers/InputHelpers.cpp deleted file mode 100644 index c865ff1b7..000000000 --- a/UWP/UWPHelpers/InputHelpers.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include - -#include "InputHelpers.h" -#include "UWPUtil.h" -#include "NKCodeFromWindowsSystem.h" -#include "Common/Log.h" - -#include -#include - -using namespace Windows::System; -using namespace Windows::Foundation; -using namespace Windows::UI::Core; -using namespace Windows::UI::ViewManagement; -using namespace Windows::ApplicationModel::Core; -using namespace Windows::Data::Xml::Dom; -using namespace Windows::UI::Notifications; -using namespace Windows::UI::ViewManagement; - -#pragma region Extenstions -template -bool findInList(std::list& inputList, T& str) { - return (std::find(inputList.begin(), inputList.end(), str) != inputList.end()); -}; -#pragma endregion - -#pragma region Input Devices -bool isKeyboardAvailable() { - Windows::Devices::Input::KeyboardCapabilities^ keyboardCapabilities = ref new Windows::Devices::Input::KeyboardCapabilities(); - bool hasKeyboard = keyboardCapabilities->KeyboardPresent != 0; - return hasKeyboard; -} - -bool isTouchAvailable() { - Windows::Devices::Input::TouchCapabilities^ touchCapabilities = ref new Windows::Devices::Input::TouchCapabilities(); - bool hasTouch = touchCapabilities->TouchPresent != 0; - return hasTouch; -} -#pragma endregion - -#pragma region Input Keyboard - -bool dPadInputActive = false; -bool textEditActive = false; -bool inputPaneVisible = false; -Platform::Agile inputPane = nullptr; - -void OnShowing(InputPane^ pane, InputPaneVisibilityEventArgs^ args) { - inputPaneVisible = true; -} -void OnHiding(InputPane^ pane, InputPaneVisibilityEventArgs^ args) { - inputPaneVisible = false; -} - -void PrepareInputPane() { - inputPane = InputPane::GetForCurrentView(); - inputPane->Showing += ref new Windows::Foundation::TypedEventHandler(&OnShowing); - inputPane->Hiding += ref new Windows::Foundation::TypedEventHandler(&OnHiding); -} - -// Show input pane (OSK) -bool ShowInputPane() { - return !isInputPaneVisible() ? inputPane->TryShow() : true; -} -// Hide input pane (OSK) -bool HideInputPane() { - return isInputPaneVisible() ? inputPane->TryHide() : true; -} - -// Check if input pane (OSK) visible -bool isInputPaneVisible() { - return inputPaneVisible; -} - -// Check if text edit active (got focus) -bool isTextEditActive() { - return textEditActive; -} - -// Set if the current input is DPad -void DPadInputState(bool inputState) { - dPadInputActive = inputState; -} - -// Check if the current input is DPad -bool isDPadActive() { - return dPadInputActive; -} - -void ActivateTextEditInput(bool byFocus) { - // Must be performed from UI thread - Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( - CoreDispatcherPriority::Normal, - ref new Windows::UI::Core::DispatchedHandler([=]() - { - if (byFocus) { - // Why we should delay? (Mostly happen on XBox) - // once the popup appear, UI is reporting 3 focus events for text edit (got, lost, got) - // it might be caused by the input pane it self but anyway.. - // because this has to on UI thread and async, we will end with input pane hidden - // the small delay will ensure that last recieved event is (got focus) - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - - if (!isInputPaneVisible() && (isDPadActive() || !IsXBox())) { - if (ShowInputPane()) { - DEBUG_LOG(COMMON, "Input pane: TryShow accepted"); - } - else { - DEBUG_LOG(COMMON, "Input pane: (TryShow is not accepted or not supported)"); - } - } - DEBUG_LOG(COMMON, "Text edit active"); - textEditActive = true; - })); -} - -void DeactivateTextEditInput(bool byFocus) { - // Must be performed from UI thread - Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( - CoreDispatcherPriority::Normal, - ref new Windows::UI::Core::DispatchedHandler([=]() - { - if (isInputPaneVisible()) { - if (HideInputPane()) { - DEBUG_LOG(COMMON, "Input pane: TryHide accepted"); - } - else { - DEBUG_LOG(COMMON, "Input pane: TryHide is not accepted, or not supported"); - } - } - if (isTextEditActive()) { - DEBUG_LOG(COMMON, "Text edit inactive"); - textEditActive = false; - } - })); -} - -bool IgnoreInput(int keyCode) { - // When text edit active and char is passed this function return 'true' - // it will help to prevent KeyDown from sending the same code again - bool ignoreInput = false; - // TODO: Add ` && !IsCtrlOnHold()` once it's ready and implemented - if (isTextEditActive()) { - // To avoid bothering KeyDown to check this case always - // we don't get here unless text edit is active - std::list nonCharList = { - NKCODE_CTRL_LEFT, - NKCODE_CTRL_RIGHT, - NKCODE_MOVE_HOME, - NKCODE_PAGE_UP, - NKCODE_MOVE_END, - NKCODE_PAGE_DOWN, - NKCODE_FORWARD_DEL, - NKCODE_DEL, - NKCODE_ENTER, - NKCODE_NUMPAD_ENTER, - NKCODE_EXT_MOUSEBUTTON_1, - NKCODE_EXT_MOUSEBUTTON_2, - NKCODE_EXT_MOUSEBUTTON_3, - NKCODE_EXT_MOUSEBUTTON_4, - NKCODE_EXT_MOUSEBUTTON_5, - }; - if (!isInputPaneVisible()) { - // Keyboard active but no on-screen keyboard - // allow arrow keys for navigation - nonCharList.push_back(NKCODE_DPAD_UP); - nonCharList.push_back(NKCODE_DPAD_DOWN); - nonCharList.push_back(NKCODE_DPAD_LEFT); - nonCharList.push_back(NKCODE_DPAD_RIGHT); - nonCharList.push_back(NKCODE_BACK); - nonCharList.push_back(NKCODE_ESCAPE); - } - - ignoreInput = !findInList(nonCharList, keyCode); - } - - return ignoreInput; -} -#pragma endregion - -#pragma region Keys Status -bool IsCapsLockOn() { - // TODO: Perform this on UI thread, delayed as currently `KeyDown` don't detect those anyway - auto capsLockState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::CapitalLock); - return (capsLockState == CoreVirtualKeyStates::Locked); -} -bool IsShiftOnHold() { - // TODO: Perform this on UI thread, delayed as currently `KeyDown` don't detect those anyway - auto shiftState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::Shift); - return (shiftState == CoreVirtualKeyStates::Down); -} -bool IsCtrlOnHold() { - // TODO: Perform this on UI thread, delayed as currently `KeyDown` don't detect those anyway - auto ctrlState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::Control); - return (ctrlState == CoreVirtualKeyStates::Down); -} -#pragma endregion - -#pragma region Misc -std::string GetLangRegion() { - std::string langRegion = "en_US"; - wchar_t lcCountry[256]; - - if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, lcCountry, 256) != FALSE) { - langRegion = ConvertWStringToUTF8(lcCountry); - for (size_t i = 0; i < langRegion.size(); i++) { - if (langRegion[i] == '-') - langRegion[i] = '_'; - } - } - return langRegion; -} - -bool IsXBox() { - auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo; - return deviceInfo->DeviceFamily == "Windows.Xbox"; -} - -bool IsMobile() { - auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo; - return deviceInfo->DeviceFamily == "Windows.Mobile"; -} -#pragma endregion diff --git a/UWP/UWPHelpers/InputHelpers.h b/UWP/UWPHelpers/InputHelpers.h deleted file mode 100644 index d5656e81f..000000000 --- a/UWP/UWPHelpers/InputHelpers.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once -#include - -// Input Devices -bool isKeyboardAvailable(); -bool isTouchAvailable(); - -// Input Pane -void PrepareInputPane(); -bool isInputPaneVisible(); -bool ShowInputPane(); -bool HideInputPane(); - -// Text Edit -bool isTextEditActive(); -void ActivateTextEditInput(bool byFocus = false); -void DeactivateTextEditInput(bool byFocus = false); -bool IgnoreInput(int keyCode); - -// Input DPad -void DPadInputState(bool inputState); -bool isDPadActive(); - -// Keys Status -bool IsCapsLockOn(); -bool IsShiftOnHold(); -bool IsCtrlOnHold(); - -// Misc -std::string GetLangRegion(); -bool IsXBox(); -bool IsMobile(); diff --git a/UWP/UWPHelpers/LaunchItem.cpp b/UWP/UWPHelpers/LaunchItem.cpp deleted file mode 100644 index 4f06c173d..000000000 --- a/UWP/UWPHelpers/LaunchItem.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "pch.h" -#include -#include -#include - -#include "LaunchItem.h" -#include "StorageAccess.h" - -#include "Common/Log.h" -#include "Common/System/System.h" -#include "Common/File/Path.h" -#include "UWPUtil.h" - -#include -#include - -#pragma region LaunchItemClass -class LaunchItem { -public: - LaunchItem() { - } - - ~LaunchItem() { - delete storageFile; - } - - void Activate(IStorageFile^ file) { - storageFile = file; - AddItemToFutureList(storageFile); - launchPath = std::string(); - launchOnExit = std::string(); - } - - void Activate(ProtocolActivatedEventArgs^ args) { - try { - unsigned i; - Windows::Foundation::WwwFormUrlDecoder^ query = args->Uri->QueryParsed; - - for (i = 0; i < query->Size; i++) - { - IWwwFormUrlDecoderEntry^ arg = query->GetAt(i); - - if (arg->Name == "cmd") - { - auto command = FromPlatformString(arg->Value); - DEBUG_LOG(FILESYS, "Launch command %s", command.c_str()); - - std::regex rgx("\"(.+[^\\/]+)\""); - std::smatch match; - - if (std::regex_search(command, match, rgx)) { - try - { - launchPath = match[1]; - } - catch (...) { - launchPath = match[0]; - } - DEBUG_LOG(FILESYS, "Launch target %s", launchPath.c_str()); - } - } - else if (arg->Name == "launchOnExit") { - launchOnExit = FromPlatformString(arg->Value); - DEBUG_LOG(FILESYS, "On exit URI %s", launchOnExit.c_str()); - } - } - } - catch (...) { - - } - storageFile = nullptr; - } - - void Start() { - if (IsValid()) { - concurrency::create_task([&] { - SetState(true); - std::string path = GetFilePath(); - // Delay to be able to launch on startup too - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, path); - }); - } - } - - bool IsHandled() { - return handled; - } - void SetState(bool fileHandled) { - handled = fileHandled; - } - - bool IsValid() { - return storageFile != nullptr || !launchPath.empty(); - } - - std::string GetFilePath() { - std::string path = launchPath; - if (storageFile != nullptr) { - path = FromPlatformString(storageFile->Path); - } - return path; - } - - void Close(bool callLaunchOnExit) { - storageFile = nullptr; - launchPath = std::string(); - handled = false; - - if (!launchOnExit.empty()) { - if (callLaunchOnExit) { - DEBUG_LOG(FILESYS, "Calling back %s", launchOnExit.c_str()); - auto uri = ref new Windows::Foundation::Uri(ToPlatformString(launchOnExit)); - Windows::System::Launcher::LaunchUriAsync(uri); - } - else { - DEBUG_LOG(FILESYS, "Ignoring callback %s, due to callLaunchOnExit is false", launchOnExit.c_str()); - } - } - launchOnExit = std::string(); - } - -private: - IStorageFile^ storageFile; - std::string launchPath; - std::string launchOnExit; - bool handled = false; -}; -#pragma endregion - -LaunchItem launchItemHandler; -void DetectLaunchItem(IActivatedEventArgs^ activateArgs, bool onlyActivate) { - if (activateArgs != nullptr) { - if (!launchItemHandler.IsHandled()) { - if (activateArgs->Kind == ActivationKind::File) { - FileActivatedEventArgs^ fileArgs = dynamic_cast(activateArgs); - launchItemHandler.Activate((StorageFile^)fileArgs->Files->GetAt(0)); - } - else if (activateArgs->Kind == ActivationKind::Protocol) - { - ProtocolActivatedEventArgs^ protocolArgs = dynamic_cast(activateArgs); - launchItemHandler.Activate(protocolArgs); - } - if (!onlyActivate) { - launchItemHandler.Start(); - } - } - } -} - -std::string GetLaunchItemPath(IActivatedEventArgs^ activateArgs) { - DetectLaunchItem(activateArgs, true); // Just activate - if (launchItemHandler.IsValid()) { - // Expected that 'GetLaunchItemPath' called to handle startup item - // it should be marked as handled by default - launchItemHandler.SetState(true); - } - return launchItemHandler.GetFilePath(); -} - -void CloseLaunchItem(bool launchOnExit) { - if (launchItemHandler.IsValid() && launchItemHandler.IsHandled()) { - launchItemHandler.Close(launchOnExit); - } -} diff --git a/UWP/UWPHelpers/LaunchItem.h b/UWP/UWPHelpers/LaunchItem.h deleted file mode 100644 index 36979728c..000000000 --- a/UWP/UWPHelpers/LaunchItem.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -using namespace Platform; -using namespace Windows::Storage; -using namespace Windows::Foundation; -using namespace Windows::UI::Core; -using namespace Windows::ApplicationModel; -using namespace Windows::ApplicationModel::Activation; - -// LaunchItem can detect launch items in two cases -// 1- StorageFile -// 2- URI [ppsspp:?cmd="fullpath"&launchOnExit=customURI] - -// Detect if activate args has launch item -// it will auto start the item unless 'onlyActivate' set to 'true' -void DetectLaunchItem(IActivatedEventArgs^ activateArgs, bool onlyActivate = false); - -// Get current launch item path (same as 'DetectLaunchItem' but it doesn't start) -// this function made to handle item on startup -// it will mark the item as 'Handled' by default -// consider to close it if you want to use it for other purposes -std::string GetLaunchItemPath(IActivatedEventArgs^ activateArgs); - -// Close current launch item -// it will launch back 'launchOnExit' if passed with URI 'cmd' -// if you want to ignore 'launchOnExit' call set it to 'false' -void CloseLaunchItem(bool launchOnExit = true); diff --git a/UWP/UWPHelpers/StorageAccess.cpp b/UWP/UWPHelpers/StorageAccess.cpp deleted file mode 100644 index d3075345a..000000000 --- a/UWP/UWPHelpers/StorageAccess.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "StorageAsync.h" -#include "StorageAccess.h" -#include "UWPUtil.h" -#include "Common/File/Path.h" - -using namespace Platform; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::Storage::AccessCache; -using namespace Windows::ApplicationModel; - -std::list alist; -void AppendToAccessList(Platform::String^ path) -{ - Path p(FromPlatformString(path)); - alist.push_back(p.ToString()); -} - -// Get value from app local settings -Platform::String^ GetDataFromLocalSettings(Platform::String^ key) { - ApplicationDataContainer^ localSettings{ ApplicationData::Current->LocalSettings }; - IPropertySet^ values{ localSettings->Values }; - if (key != nullptr) { - Platform::Object^ tokenRetrive = values->Lookup(key); - if (tokenRetrive != nullptr) { - Platform::String^ ConvertedToken = (Platform::String^)tokenRetrive; - return ConvertedToken; - } - } - return nullptr; -} - -std::string GetDataFromLocalSettings(std::string key) { - return FromPlatformString(GetDataFromLocalSettings(ToPlatformString(key))); -} - -// Add or replace value in app local settings -bool AddDataToLocalSettings(Platform::String^ key, Platform::String^ data, bool replace) { - ApplicationDataContainer^ localSettings{ ApplicationData::Current->LocalSettings }; - IPropertySet^ values{ localSettings->Values }; - - Platform::String^ testResult = GetDataFromLocalSettings(key); - if (testResult == nullptr) { - values->Insert(key, PropertyValue::CreateString(data)); - return true; - } - else if (replace) { - values->Remove(key); - values->Insert(key, PropertyValue::CreateString(data)); - return true; - } - - return false; -} - -bool AddDataToLocalSettings(std::string key, std::string data, bool replace) { - return AddDataToLocalSettings(ToPlatformString(key), ToPlatformString(data),replace); -} - -// Add folder to future list (to avoid request picker again) -void AddItemToFutureList(IStorageItem^ item) { - try { - if (item != nullptr) { - Platform::String^ folderToken = AccessCache::StorageApplicationPermissions::FutureAccessList->Add(item); - AppendToAccessList(item->Path); - } - } - catch (Platform::COMException^ e) { - } -} - -// Get item by key -// This function can be used when you store token in LocalSettings as custom key -IStorageItem^ GetItemByKey(Platform::String^ key) { - IStorageItem^ item; - Platform::String^ itemToken = GetDataFromLocalSettings(key); - if (itemToken != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(itemToken)) { - ExecuteTask(item, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(itemToken)); - } - - return item; -} - -std::list GetFutureAccessList() { - if (alist.empty()) { - auto AccessList = AccessCache::StorageApplicationPermissions::FutureAccessList->Entries; - for (auto it = 0; it != AccessList->Size; ++it){ - auto item = AccessList->GetAt(it); - try { - auto token = item.Token; - if (token != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(token)) { - IStorageItem^ storageItem; - ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(token)); - if (storageItem != nullptr) { - AppendToAccessList(storageItem->Path); - } - else { - AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(token); - } - } - } - catch (Platform::COMException^ e) { - } - } - - AppendToAccessList(ApplicationData::Current->LocalFolder->Path); - AppendToAccessList(ApplicationData::Current->TemporaryFolder->Path); - } - return alist; -} diff --git a/UWP/UWPHelpers/StorageAccess.h b/UWP/UWPHelpers/StorageAccess.h deleted file mode 100644 index e7b967b4f..000000000 --- a/UWP/UWPHelpers/StorageAccess.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -// This header meant to be included within the storage manager -// don't use it within PPSSPP core - -#pragma once - -#include -#include - -using namespace Windows::Storage; - -// Local settings -std::string GetDataFromLocalSettings(std::string key); -bool AddDataToLocalSettings(std::string key, std::string data, bool replace); -void AddItemToFutureList(IStorageItem^ item); -std::list GetFutureAccessList(); diff --git a/UWP/UWPHelpers/StorageAsync.cpp b/UWP/UWPHelpers/StorageAsync.cpp deleted file mode 100644 index e79152fe9..000000000 --- a/UWP/UWPHelpers/StorageAsync.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Thanks to RetroArch/Libretro team for this idea -// This is improved version of the original idea - -#include "StorageAsync.h" - -bool ActionPass(Windows::Foundation::IAsyncAction^ action) -{ - try { - return TaskHandler([&]() { - return concurrency::create_task(action).then([]() { - return true; - }); - }, false); - } - catch (...) { - return false; - } -} - -// Async action such as 'Delete' file -// @action: async action -// return false when action failed -bool ExecuteTask(Windows::Foundation::IAsyncAction^ action) -{ - return ActionPass(action); -}; diff --git a/UWP/UWPHelpers/StorageAsync.h b/UWP/UWPHelpers/StorageAsync.h deleted file mode 100644 index 3f57a2457..000000000 --- a/UWP/UWPHelpers/StorageAsync.h +++ /dev/null @@ -1,105 +0,0 @@ -// Thanks to RetroArch/Libretro team for this idea -// This is improved version of the original idea - -#pragma once - -#include "pch.h" -#include -#include -#include -#include - -#include "Common/Log.h" -#include "UWPUtil.h" - -using namespace Windows::UI::Core; - -// Don't add 'using' 'Windows::Foundation' -// it might cause confilct with some types like 'Point' - -#pragma region Async Handlers - -template -T TaskHandler(std::function()> wtask, T def) -{ - T result = def; - bool done = false; - wtask().then([&](concurrency::task t) { - try - { - result = t.get(); - } - catch (Platform::Exception^ exception_) - { - ERROR_LOG(FILESYS, FromPlatformString(exception_->Message).c_str()); - } - done = true; - }); - - CoreWindow^ corewindow = CoreWindow::GetForCurrentThread(); - while (!done) - { - try { - if (corewindow) { - corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); - } - else { - corewindow = CoreWindow::GetForCurrentThread(); - } - } - catch (...) { - - } - } - - return result; -}; - -template -T TaskPass(Windows::Foundation::IAsyncOperation^ task, T def) -{ - return TaskHandler([&]() { - return concurrency::create_task(task).then([](T res) { - return res; - }); - }, def); -} - -bool ActionPass(Windows::Foundation::IAsyncAction^ action); - -#pragma endregion - -// Now it's more simple to execute async task -// @out: output variable -// @task: async task -template -void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation^ task) -{ - try { - out = TaskPass(task, T()); - } - catch (...) { - out = T(); - } -}; - -// For specific return default value -// @out: output variable -// @task: async task -// @def: default value when fail -template -void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation^ task, T def) -{ - try{ - out = TaskPass(task, def); - } - catch (...) { - out = def; - } -}; - - -// Async action such as 'Delete' file -// @action: async action -// return false when action failed -bool ExecuteTask(Windows::Foundation::IAsyncAction^ action); diff --git a/UWP/UWPHelpers/StorageManager.cpp b/UWP/UWPHelpers/StorageManager.cpp deleted file mode 100644 index fed038b22..000000000 --- a/UWP/UWPHelpers/StorageManager.cpp +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "pch.h" -#include -#include -#include - -#include "Common/Log.h" -#include "Core/Config.h" -#include "Common/File/Path.h" -#include "Common/StringUtils.h" -#include "UWPUtil.h" - -#include "StorageManager.h" -#include "StorageAsync.h" -#include "StorageAccess.h" - - -using namespace Platform; -using namespace Windows::Storage; -using namespace Windows::Foundation; -using namespace Windows::ApplicationModel; - - -#pragma region Locations -std::string GetPSPFolder() { - if (g_Config.memStickDirectory.empty()) { - return g_Config.internalDataDirectory.ToString(); - } - else { - return g_Config.memStickDirectory.ToString(); - } -} -std::string GetInstallationFolder() { - return FromPlatformString(Package::Current->InstalledLocation->Path); -} -StorageFolder^ GetLocalStorageFolder() { - return ApplicationData::Current->LocalFolder; -} -std::string GetLocalFolder() { - return FromPlatformString(GetLocalStorageFolder()->Path); -} -std::string GetTempFolder() { - return FromPlatformString(ApplicationData::Current->TemporaryFolder->Path); -} -std::string GetTempFile(std::string name) { - StorageFile^ tmpFile; - ExecuteTask(tmpFile, ApplicationData::Current->TemporaryFolder->CreateFileAsync(ToPlatformString(name), CreationCollisionOption::GenerateUniqueName)); - if (tmpFile != nullptr) { - return FromPlatformString(tmpFile->Path); - } - else { - return ""; - } -} -std::string GetPicturesFolder() { - // Requires 'picturesLibrary' capability - return FromPlatformString(KnownFolders::PicturesLibrary->Path); -} -std::string GetVideosFolder() { - // Requires 'videosLibrary' capability - return FromPlatformString(KnownFolders::VideosLibrary->Path); -} -std::string GetDocumentsFolder() { - // Requires 'documentsLibrary' capability - return FromPlatformString(KnownFolders::DocumentsLibrary->Path); -} -std::string GetMusicFolder() { - // Requires 'musicLibrary' capability - return FromPlatformString(KnownFolders::MusicLibrary->Path); -} -std::string GetPreviewPath(std::string path) { - std::string pathView = path; - pathView = ReplaceAll(pathView, "/", "\\"); - std::string currentMemoryStick = GetPSPFolder(); - // Ensure memStick sub path replaced by 'ms:' - pathView = ReplaceAll(pathView, currentMemoryStick + "\\", "ms:\\"); - auto appData = ReplaceAll(GetLocalFolder(), "\\LocalState", ""); - pathView = ReplaceAll(pathView, appData, "AppData"); - - return pathView; -} -bool isLocalState(std::string path) { - return !_stricmp(GetPreviewPath(path).c_str(), "LocalState"); -} -#pragma endregion - -#pragma region Internal -Path PathResolver(Path path) { - auto root = path.GetDirectory(); - auto newPath = path.ToString(); - if (path.IsRoot() || !_stricmp(root.c_str(), "/") || !_stricmp(root.c_str(), "\\")) { - // System requesting file from app data - newPath = ReplaceAll(newPath, "/", (GetLocalFolder() + (path.size() > 1 ? "/" : ""))); - } - return Path(newPath); -} -Path PathResolver(std::string path) { - return PathResolver(Path(path)); -} - -std::string ResolvePathUWP(std::string path) { - return PathResolver(path).ToString(); -} -#pragma endregion - -#pragma region Functions -std::map accessState; -bool CheckDriveAccess(std::string driveName) { - bool state = false; - - HANDLE searchResults; - WIN32_FIND_DATA findDataResult; - auto keyIter = accessState.find(driveName); - if (keyIter != accessState.end()) { - state = keyIter->second; - } - else { - try { - wchar_t* filteredPath = _wcsdup(ConvertUTF8ToWString(driveName).c_str()); - wcscat_s(filteredPath, sizeof(L"\\*.*"), L"\\*.*"); - - searchResults = FindFirstFileExFromAppW( - filteredPath, FindExInfoBasic, &findDataResult, - FindExSearchNameMatch, NULL, 0); - - state = searchResults != NULL && searchResults != INVALID_HANDLE_VALUE; - if (state) { - FindClose(searchResults); - } - // Cache the state - accessState.insert(std::make_pair(driveName, state)); - } - catch (...) { - } - } - if (!state) { - state = IsRootForAccessibleItems(driveName); - } - return state; -} - -FILE* GetFileStreamFromApp(std::string path, const char* mode) { - - FILE* file{}; - - auto pathResolved = Path(ResolvePathUWP(path)); - HANDLE handle; - - DWORD dwDesiredAccess = GENERIC_READ; - DWORD dwShareMode = FILE_SHARE_READ; - DWORD dwCreationDisposition = OPEN_EXISTING; - int flags = 0; - - if (!strcmp(mode, "r") || !strcmp(mode, "rb") || !strcmp(mode, "rt")) - { - dwDesiredAccess = GENERIC_READ; - dwShareMode = FILE_SHARE_READ; - dwCreationDisposition = OPEN_EXISTING; - flags = _O_RDONLY; - } - else if (!strcmp(mode, "r+") || !strcmp(mode, "rb+") || !strcmp(mode, "r+b") || !strcmp(mode, "rt+") || !strcmp(mode, "r+t")) - { - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - dwCreationDisposition = OPEN_EXISTING; - flags = _O_RDWR; - } - else if (!strcmp(mode, "a") || !strcmp(mode, "ab") || !strcmp(mode, "at")) { - dwDesiredAccess = GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - dwCreationDisposition = OPEN_ALWAYS; - flags = _O_APPEND | _O_WRONLY | _O_CREAT; - } - else if (!strcmp(mode, "a+") || !strcmp(mode, "ab+") || !strcmp(mode, "a+b") || !strcmp(mode, "at+") || !strcmp(mode, "a+t")) { - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - dwCreationDisposition = OPEN_ALWAYS; - flags = _O_APPEND | _O_RDWR | _O_CREAT; - } - else if (!strcmp(mode, "w") || !strcmp(mode, "wb") || !strcmp(mode, "wt")) - { - dwDesiredAccess = GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - dwCreationDisposition = CREATE_ALWAYS; - flags = _O_WRONLY | _O_CREAT | _O_TRUNC; - } - else if (!strcmp(mode, "w+") || !strcmp(mode, "wb+") || !strcmp(mode, "w+b") || !strcmp(mode, "wt+") || !strcmp(mode, "w+t")) - { - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - dwCreationDisposition = CREATE_ALWAYS; - flags = _O_RDWR | _O_CREAT | _O_TRUNC; - } - - if (strpbrk(mode, "t") != nullptr) { - flags |= _O_TEXT; - } - - handle = CreateFile2FromAppW(pathResolved.ToWString().c_str(), dwDesiredAccess, dwShareMode, dwCreationDisposition, nullptr); - - if (handle != INVALID_HANDLE_VALUE) { - file = _fdopen(_open_osfhandle((intptr_t)handle, flags), mode); - } - - return file; -} - -#pragma endregion - -#pragma region FakeFolders -// Parent and child full path -std::string getSubRoot(std::string parent, std::string child) { - auto childCut = child; - childCut = ReplaceAll(childCut, (parent + "/"), ""); - size_t len = childCut.find_first_of('/', 0); - auto subRoot = childCut.substr(0, len); - - return parent + "/" + subRoot; -} - -bool isChild(std::string parent, std::string child) { - return child.find(parent) != std::string::npos; -} - -// Parent full path, child full path, child name only -bool isParent(std::string parent, std::string child, std::string childName) { - parent.append("/" + childName); - return parent == child; -} - -bool IsRootForAccessibleItems(Path path, std::list& subRoot, bool breakOnFirstMatch = false) { - path = PathResolver(path); - auto FutureAccessItems = GetFutureAccessList(); - for (auto& fItem : FutureAccessItems) { - if (isChild(path.ToString(), fItem)) { - if (breakOnFirstMatch) { - // Just checking, we don't need to loop for each item - return true; - } - auto sub = getSubRoot(path.ToString(), fItem); - - // This check can be better, but that's how I can do it in C++ - if (!endsWith(sub, ":")) { - bool alreadyAdded = false; - for each (auto sItem in subRoot) { - if (!strcmp(sItem.c_str(), sub.c_str())) { - alreadyAdded = true; - break; - } - } - if (!alreadyAdded) { - subRoot.push_back(sub); - } - } - } - } - return !subRoot.empty(); -} -bool IsRootForAccessibleItems(std::string path) -{ - std::list tmp; - return IsRootForAccessibleItems(Path(path), tmp, true); -} - -bool GetFakeFolders(Path path, std::vector* files, const char* filter, std::set filters) { - bool state = false; - std::list subRoot; - if (IsRootForAccessibleItems(path, subRoot)) { - if (!subRoot.empty()) { - for each (auto sItem in subRoot) { - auto folderPath = Path(sItem); - File::FileInfo info; - info.name = folderPath.GetFilename(); - info.fullName = folderPath; - info.exists = true; - info.size = 1; - info.isDirectory = true; - info.isWritable = true; - info.atime = 0; - info.mtime = 0; - info.ctime = 0; - info.access = 0111; - - files->push_back(info); - state = true; - } - } - } - return state; -} - -#pragma endregion - -#pragma region Helpers -bool OpenFile(std::string path) { - bool state = false; - Platform::String^ wString = ref new Platform::String(Path(path).ToWString().c_str()); - - StorageFile^ storageItem; - ExecuteTask(storageItem, StorageFile::GetFileFromPathAsync(wString)); - if (storageItem != nullptr) { - ExecuteTask(state, Windows::System::Launcher::LaunchFileAsync(storageItem), false); - } - else { - auto uri = ref new Windows::Foundation::Uri(wString); - ExecuteTask(state, Windows::System::Launcher::LaunchUriAsync(uri), false); - } - return state; -} - -bool OpenFolder(std::string path) { - bool state = false; - Path itemPath(path); - Platform::String^ wString = ref new Platform::String(itemPath.ToWString().c_str()); - StorageFolder^ storageItem; - ExecuteTask(storageItem, StorageFolder::GetFolderFromPathAsync(wString)); - if (storageItem != nullptr) { - ExecuteTask(state, Windows::System::Launcher::LaunchFolderAsync(storageItem), false); - } - else { - // Try as it's file - Path parent = Path(itemPath.GetDirectory()); - Platform::String^ wParentString = ref new Platform::String(parent.ToWString().c_str()); - - ExecuteTask(storageItem, StorageFolder::GetFolderFromPathAsync(wParentString)); - if (storageItem != nullptr) { - ExecuteTask(state, Windows::System::Launcher::LaunchFolderAsync(storageItem), false); - } - } - return state; -} - -bool GetDriveFreeSpace(Path path, int64_t& space) { - - bool state = false; - if (path.empty()) { - // This case happen on first start only - path = Path(GetPSPFolder()); - if (g_Config.memStickDirectory.empty()) { - g_Config.memStickDirectory = path; - } - } - Platform::String^ wString = ref new Platform::String(path.ToWString().c_str()); - StorageFolder^ storageItem; - ExecuteTask(storageItem, StorageFolder::GetFolderFromPathAsync(wString)); - if (storageItem != nullptr) { - Platform::String^ freeSpaceKey = ref new Platform::String(L"System.FreeSpace"); - Platform::Collections::Vector^ propertiesToRetrieve = ref new Platform::Collections::Vector(); - propertiesToRetrieve->Append(freeSpaceKey); - Windows::Foundation::Collections::IMap^ result; - ExecuteTask(result, storageItem->Properties->RetrievePropertiesAsync(propertiesToRetrieve)); - if (result != nullptr && result->Size > 0) { - try { - auto value = result->Lookup(L"System.FreeSpace"); - space = (uint64_t)value; - state = true; - } - catch (...) { - - } - } - } - - return state; -} -#pragma endregion - -#pragma region Logs -std::string GetLogFile() { - std::string logFile; - Path logFilePath = Path(GetPSPFolder() + "\\PSP\\ppsspplog.txt"); - HANDLE h = CreateFile2FromAppW(logFilePath.ToWString().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr); - if (h != INVALID_HANDLE_VALUE) { - logFile = logFilePath.ToString(); - CloseHandle(h); - } - return logFile; -} - -#pragma endregion diff --git a/UWP/UWPHelpers/StorageManager.h b/UWP/UWPHelpers/StorageManager.h deleted file mode 100644 index 4b9f2f0f4..000000000 --- a/UWP/UWPHelpers/StorageManager.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include -#include -#include - -#include "Common/File/DirListing.h" -#include "StoragePickers.h" - -// Locations -std::string GetPSPFolder(); // Where main data is, default is app data -std::string GetInstallationFolder(); -std::string GetLocalFolder(); -std::string GetTempFolder(); -std::string GetTempFile(std::string name); -std::string GetPicturesFolder(); // Requires 'picturesLibrary' capability -std::string GetVideosFolder(); // Requires 'videosLibrary' capability -std::string GetDocumentsFolder(); // Requires 'documentsLibrary' capability -std::string GetMusicFolder(); // Requires 'musicLibrary' capability -std::string GetPreviewPath(std::string path); -bool isLocalState(std::string path); - -// Management -// `GetFileStreamFromApp` Will use Windows UWP API, use it instead of fopen..etc -FILE* GetFileStreamFromApp(std::string path, const char* mode); - -// 'driveName' like C: -bool CheckDriveAccess(std::string driveName); -bool GetFakeFolders(Path path, std::vector* files, const char* filter, std::set filters); -bool IsRootForAccessibleItems(std::string path); - -// Helpers -bool OpenFile(std::string path); -bool OpenFolder(std::string path); -std::string ResolvePathUWP(std::string path); -bool GetDriveFreeSpace(Path path, int64_t& space); - -// Log helpers -std::string GetLogFile(); diff --git a/UWP/UWPHelpers/StoragePickers.cpp b/UWP/UWPHelpers/StoragePickers.cpp deleted file mode 100644 index db725834f..000000000 --- a/UWP/UWPHelpers/StoragePickers.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "pch.h" - -#include "StorageAsync.h" -#include "StorageAccess.h" - -using namespace Platform; -using namespace Windows::Storage; -using namespace Windows::Foundation; - -extern void AddItemToFutureList(IStorageItem^ folder); - -// Call folder picker (the selected folder will be added to future list) -concurrency::task PickSingleFolder() -{ - auto folderPicker = ref new Windows::Storage::Pickers::FolderPicker(); - folderPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop; - folderPicker->FileTypeFilter->Append("*"); - - return concurrency::create_task(folderPicker->PickSingleFolderAsync()).then([](StorageFolder^ folder) { - auto path = ref new Platform::String(); - if (folder != nullptr) - { - AddItemToFutureList(folder); - path = folder->Path; - } - return path; - }); -} - -// Call file picker (the selected file will be added to future list) -concurrency::task PickSingleFile(std::vector exts) -{ - auto filePicker = ref new Windows::Storage::Pickers::FileOpenPicker(); - filePicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop; - filePicker->ViewMode = Pickers::PickerViewMode::List; - - if (exts.size() > 0) { - for each (auto ext in exts) { - filePicker->FileTypeFilter->Append(ToPlatformString(ext)); - } - } - else - { - filePicker->FileTypeFilter->Append("*"); - } - return concurrency::create_task(filePicker->PickSingleFileAsync()).then([](StorageFile^ file) { - auto path = ref new Platform::String(); - if (file != nullptr) - { - AddItemToFutureList(file); - path = file->Path; - } - return path; - }); -} - - -concurrency::task ChooseFile(std::vector exts) { - return PickSingleFile(exts).then([](Platform::String^ filePath) { - return FromPlatformString(filePath); - }); -} - -concurrency::task ChooseFolder() { - return PickSingleFolder().then([](Platform::String^ folderPath) { - return FromPlatformString(folderPath); - }); - -} diff --git a/UWP/UWPHelpers/StoragePickers.h b/UWP/UWPHelpers/StoragePickers.h deleted file mode 100644 index 8d845e679..000000000 --- a/UWP/UWPHelpers/StoragePickers.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2023- PPSSPP 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 or later versions. - -// 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include -#include -#include -#include - -concurrency::task ChooseFolder(); -concurrency::task ChooseFile(std::vector exts); diff --git a/UWP/build_uwp.proj b/UWP/build_uwp.proj new file mode 100644 index 000000000..8f40df2a0 --- /dev/null +++ b/UWP/build_uwp.proj @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj index 0cf2a268a..6dcea065c 100644 --- a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj +++ b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {C249F016-7F82-45CF-BB6E-0642A988C4D3} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,7 +84,172 @@ false - + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + + + Use + false + true + pch.h + ../../ext/cpu_features/include + STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + + + Console + false + false + + + Use false @@ -107,7 +296,6 @@ - diff --git a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters index d0b95fcfe..d0acee9d4 100644 --- a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters +++ b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters @@ -110,9 +110,6 @@ Source Files - - Source Files - Source Files diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj b/UWP/glslang_UWP/glslang_UWP.vcxproj index efef2fce6..1be05c767 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {d326891e-ece4-4b94-b5e7-8aa0a8e8ecbc} @@ -39,11 +63,11 @@ 10.0 - + StaticLibrary true - + StaticLibrary false false @@ -61,7 +85,7 @@ false - + Use false @@ -76,7 +100,37 @@ false - + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + Use false @@ -91,7 +145,7 @@ false - + Use false @@ -106,6 +160,111 @@ false + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;ENABLE_HLSL;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/glslang;../../ext/glslang-build;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + diff --git a/UWP/libchdr_UWP/libchdr_UWP.vcxproj b/UWP/libchdr_UWP/libchdr_UWP.vcxproj deleted file mode 100644 index afd6fb6a3..000000000 --- a/UWP/libchdr_UWP/libchdr_UWP.vcxproj +++ /dev/null @@ -1,104 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - {191b6f52-ad66-4172-bd20-733eeeceef8c} - StaticLibrary - libchdr - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.19041.0 - 10.0 - libchdr_UWP - - - - StaticLibrary - true - - - StaticLibrary - false - false - - - - - - - - - - - - false - - - - false - false - ..\..\ext\zlib;..\..\ext\libchdr\include;..\..\ext\libchdr\deps\lzma-22.01\include;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - NotUsing - _7ZIP_ST;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) - - - Console - false - false - - - - - - \ No newline at end of file diff --git a/UWP/libchdr_UWP/libchdr_UWP.vcxproj.filters b/UWP/libchdr_UWP/libchdr_UWP.vcxproj.filters deleted file mode 100644 index 7a49828f1..000000000 --- a/UWP/libchdr_UWP/libchdr_UWP.vcxproj.filters +++ /dev/null @@ -1,67 +0,0 @@ - - - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms - - - {20de3681-6341-427f-a3a7-4ae259deb0b9} - - - - - - - - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - \ No newline at end of file diff --git a/UWP/libkirk_UWP/libkirk_UWP.vcxproj b/UWP/libkirk_UWP/libkirk_UWP.vcxproj index e33d8cc6f..045f0b48f 100644 --- a/UWP/libkirk_UWP/libkirk_UWP.vcxproj +++ b/UWP/libkirk_UWP/libkirk_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {2f911c05-b341-4291-8bf5-09edecbdd5f5} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,12 +84,13 @@ false - + NotUsing false true - + + _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -74,12 +99,43 @@ false - + NotUsing false true - + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -88,12 +144,13 @@ false - + NotUsing false true - + + _ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -102,6 +159,111 @@ false + + + NotUsing + false + true + + + _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + diff --git a/UWP/libzstd_UWP/libzstd_UWP.vcxproj b/UWP/libzstd_UWP/libzstd_UWP.vcxproj index 37e1a566d..09cbd21e9 100644 --- a/UWP/libzstd_UWP/libzstd_UWP.vcxproj +++ b/UWP/libzstd_UWP/libzstd_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,6 +25,10 @@ Release ARM64 + + Release + Win32 + Release x64 @@ -61,12 +69,95 @@ false $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + NotUsing false false - false Console diff --git a/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj b/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj index a2aec08ba..cc9ce9235 100644 --- a/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj +++ b/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {d31fd4f0-53eb-477c-9dc7-149796f628e2} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,7 +84,7 @@ false - + Use false @@ -75,14 +99,52 @@ false - - cd ..\..\ext\miniupnp\miniupnpc\msvc - genminiupnpcstrings.vbs - cd ..\..\..\..\UWP\miniupnpc_UWP - + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP - + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + Use false @@ -97,14 +159,12 @@ false - - cd ..\..\ext\miniupnp\miniupnpc\msvc - genminiupnpcstrings.vbs - cd ..\..\..\..\UWP\miniupnpc_UWP - + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP - + Use false @@ -119,11 +179,149 @@ false - - cd ..\..\ext\miniupnp\miniupnpc\msvc - genminiupnpcstrings.vbs - cd ..\..\..\..\UWP\miniupnpc_UWP - + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP + + + + + Use + false + true + pch.h + _CRT_SECURE_NO_WARNINGS;NOMINMAX;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + ../../ext/miniupnpc;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + + + Console + false + false + + + cd ..\..\ext\miniupnp\miniupnpc\msvc +genminiupnpcstrings.vbs +cd ..\..\..\..\UWP\miniupnpc_UWP diff --git a/UWP/rcheevos_UWP/rcheevos_UWP.vcxproj b/UWP/rcheevos_UWP/rcheevos_UWP.vcxproj deleted file mode 100644 index dec3e5e70..000000000 --- a/UWP/rcheevos_UWP/rcheevos_UWP.vcxproj +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {4c9d52d0-310a-4347-8991-e3788cb22169} - StaticLibrary - rcheevos - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.19041.0 - 10.0 - rcheevos_UWP - - - - StaticLibrary - true - - - StaticLibrary - false - false - - - - - - - - - - false - - - - false - true - NotUsing - ../../ext/rcheevos/include;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - RC_DISABLE_LUA;_UNICODE;UNICODE;%(PreprocessorDefinitions) - - - Console - false - false - - - - - - diff --git a/UWP/rcheevos_UWP/rcheevos_UWP.vcxproj.filters b/UWP/rcheevos_UWP/rcheevos_UWP.vcxproj.filters deleted file mode 100644 index 847b8ec38..000000000 --- a/UWP/rcheevos_UWP/rcheevos_UWP.vcxproj.filters +++ /dev/null @@ -1,159 +0,0 @@ - - - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - rapi - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rhash - - - rcheevos - - - include - - - - - {918cc87d-a38b-4e00-be13-0256398e1eec} - - - {89858679-3cc1-4b8b-b2f7-7f418d9335e9} - - - {e161d2c8-a15a-499d-96d9-fc29fb4ff78d} - - - {4e62f4d5-be01-4047-b0d6-3c0c171ff486} - - - - - rapi - - - rapi - - - rapi - - - rapi - - - rapi - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rhash - - - rhash - - - rhash - - - rcheevos - - - rcheevos - - - diff --git a/UWP/zlib_UWP/zlib_UWP.vcxproj b/UWP/zlib_UWP/zlib_UWP.vcxproj index f57dad5ff..f60d2aa01 100644 --- a/UWP/zlib_UWP/zlib_UWP.vcxproj +++ b/UWP/zlib_UWP/zlib_UWP.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -21,10 +25,30 @@ Release ARM64 + + Release + Win32 + Release x64 + + UWP Gold + ARM + + + UWP Gold + ARM64 + + + UWP Gold + Win32 + + + UWP Gold + x64 + {ddf90203-0aae-4f38-b589-2e9637658ce6} @@ -43,7 +67,7 @@ StaticLibrary true - + StaticLibrary false false @@ -60,7 +84,7 @@ false - + NotUsing false @@ -73,7 +97,33 @@ false - + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + NotUsing false @@ -86,7 +136,7 @@ false - + NotUsing false @@ -99,6 +149,97 @@ false + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + + + + NotUsing + false + true + _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + Console + false + false + + diff --git a/Windows/.gitignore b/Windows/.gitignore index 5c87205d5..8d4dba11e 100644 --- a/Windows/.gitignore +++ b/Windows/.gitignore @@ -2,4 +2,3 @@ *.VC.db *.txt enc_temp_folder -Win32 diff --git a/Windows/Debugger/BreakpointWindow.cpp b/Windows/Debugger/BreakpointWindow.cpp index d26c5f6c2..1a1b1a1d2 100644 --- a/Windows/Debugger/BreakpointWindow.cpp +++ b/Windows/Debugger/BreakpointWindow.cpp @@ -11,8 +11,7 @@ INT_PTR CALLBACK BreakpointWindow::StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wP if (iMsg == WM_INITDIALOG) { SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam); thiz = (BreakpointWindow *)lParam; - } - else { + } else { thiz = (BreakpointWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA); } @@ -41,15 +40,15 @@ INT_PTR BreakpointWindow::DlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lP EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory); EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory); EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), log); - + if (address != -1) { snprintf(str, sizeof(str), "0x%08X", address); - SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str); + SetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str); } snprintf(str, sizeof(str), "0x%08X", size); - SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str); - + SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE),str); + SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), ConvertUTF8ToWString(condition).c_str()); SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), ConvertUTF8ToWString(logFormat).c_str()); return TRUE; @@ -122,7 +121,7 @@ INT_PTR BreakpointWindow::DlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lP bool BreakpointWindow::fetchDialogData(HWND hwnd) { - char str[256], errorMessage[512]; + char str[256],errorMessage[512]; PostfixExpression exp; memory = GetCheckState(hwnd, IDC_BREAKPOINT_MEMORY); @@ -133,36 +132,36 @@ bool BreakpointWindow::fetchDialogData(HWND hwnd) onChange = GetCheckState(hwnd, IDC_BREAKPOINT_ONCHANGE); // parse address - GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str, 256); - if (cpu->initExpression(str, exp) == false) + GetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str,256); + if (cpu->initExpression(str,exp) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); + MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } - if (cpu->parseExpression(exp, address) == false) + if (cpu->parseExpression(exp,address) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); + MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (memory) { // parse size - GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str, 256); - if (cpu->initExpression(str, exp) == false) + GetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),str,256); + if (cpu->initExpression(str,exp) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); + MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } - if (cpu->parseExpression(exp, size) == false) + if (cpu->parseExpression(exp,size) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); + MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } } @@ -177,7 +176,7 @@ bool BreakpointWindow::fetchDialogData(HWND hwnd) if (cpu->initExpression(condition.c_str(), compiledCondition) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", condition.c_str(), getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); + MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } } @@ -230,17 +229,16 @@ void BreakpointWindow::addBreakpoint() { } CBreakPoints::ChangeMemCheckLogFormat(address, address + size, logFormat); - } - else { + } else { // add breakpoint - CBreakPoints::AddBreakPoint(address, false); + CBreakPoints::AddBreakPoint(address,false); if (!condition.empty()) { BreakPointCond cond; cond.debug = cpu; cond.expressionString = condition; cond.expression = compiledCondition; - CBreakPoints::ChangeBreakPointAddCond(address, cond); + CBreakPoints::ChangeBreakPointAddCond(address,cond); } CBreakPoints::ChangeBreakPoint(address, result); @@ -259,12 +257,11 @@ void BreakpointWindow::loadFromMemcheck(const MemCheck &memcheck) { enabled = (memcheck.result & BREAK_ACTION_PAUSE) != 0; address = memcheck.start; - size = memcheck.end - address; + size = memcheck.end-address; if (memcheck.hasCondition) { condition = memcheck.condition.expressionString; - } - else { + } else { condition.clear(); } @@ -281,8 +278,7 @@ void BreakpointWindow::loadFromBreakpoint(const BreakPoint& breakpoint) { if (breakpoint.hasCond) { condition = breakpoint.cond.expressionString; - } - else { + } else { condition.clear(); } diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index 946a131a1..e8d176b1b 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -18,7 +18,6 @@ #include "Windows/Debugger/Debugger_MemoryDlg.h" #include "Windows/Debugger/DebuggerShared.h" #include "Windows/Debugger/BreakpointWindow.h" -#include "Windows/Debugger/EditSymbolsWindow.h" #include "Windows/main.h" #include "Common/CommonWindows.h" @@ -303,7 +302,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) { for (int reg = 0; reg < debugger->GetNumRegsInCategory(cat); reg++) { - if (strcasecmp(debugger->GetRegName(cat,reg).c_str(), registerName.c_str()) == 0) + if (strcasecmp(debugger->GetRegName(cat,reg),registerName.c_str()) == 0) { debugger->SetRegValue(cat,reg,value); Reporting::NotifyDebugger(); @@ -979,16 +978,6 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) NopInstructions(selectRangeStart, selectRangeEnd); redraw(); break; - case ID_DISASM_EDITSYMBOLS: - { - EditSymbolsWindow esw(wnd, debugger); - if (esw.exec()) { - esw.eval(); - SendMessage(GetParent(wnd), WM_DEB_MAPLOADED, 0, 0); - redraw(); - } - } - break; case ID_DISASM_SETPCTOHERE: debugger->setPC(curAddress); redraw(); diff --git a/Windows/Debugger/CtrlRegisterList.cpp b/Windows/Debugger/CtrlRegisterList.cpp index 2a5bc7a6c..7f442650e 100644 --- a/Windows/Debugger/CtrlRegisterList.cpp +++ b/Windows/Debugger/CtrlRegisterList.cpp @@ -251,7 +251,7 @@ void CtrlRegisterList::onPaint(WPARAM wParam, LPARAM lParam) if (iGetNumRegsInCategory(category)) { char temp[256]; - int temp_len = snprintf(temp, sizeof(temp), "%s", cpu->GetRegName(category, i).c_str()); + int temp_len = snprintf(temp, sizeof(temp), "%s", cpu->GetRegName(category, i)); SetTextColor(hdc,0x600000); TextOutA(hdc,17,rowY1,temp,temp_len); SetTextColor(hdc,0x000000); diff --git a/Windows/Debugger/EditSymbolsWindow.cpp b/Windows/Debugger/EditSymbolsWindow.cpp deleted file mode 100644 index 607b67e3d..000000000 --- a/Windows/Debugger/EditSymbolsWindow.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include "EditSymbolsWindow.h" -#include "../resource.h" - - -bool EditSymbolsWindow::GetCheckState(HWND hwnd, int dlgItem) { - return SendMessage(GetDlgItem(hwnd, dlgItem), BM_GETCHECK, 0, 0) != 0; -} - -bool EditSymbolsWindow::fetchDialogData(HWND hwnd) -{ - char str[256], errorMessage[512]; - PostfixExpression exp; - - scan_ = GetCheckState(hwnd, IDC_EDITSYMBOLS_SCAN); - - // Parse the address - GetWindowTextA(GetDlgItem(hwnd, IDC_EDITSYMBOLS_ADDRESS), str, 256); - - if (cpu->initExpression(str, exp) == false) - { - snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); - return false; - } - if (cpu->parseExpression(exp, address_) == false) - { - snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); - return false; - } - - // Parse the size - GetWindowTextA(GetDlgItem(hwnd, IDC_EDITSYMBOLS_SIZE), str, 256); - - if (cpu->initExpression(str, exp) == false) - { - snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); - return false; - } - if (cpu->parseExpression(exp, size_) == false) - { - snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); - MessageBoxA(hwnd, errorMessage, "Error", MB_OK); - return false; - } - - // Now let's validate the range - if (!Memory::IsValidRange(address_, size_)) { - MessageBoxA(hwnd, "Invalid range", "Error", MB_OK); - return false; - } - - return true; -} - -INT_PTR CALLBACK EditSymbolsWindow::StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { - EditSymbolsWindow *thiz; - if (iMsg == WM_INITDIALOG) { - SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam); - thiz = (EditSymbolsWindow *)lParam; - } - else { - thiz = (EditSymbolsWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - } - - if (!thiz) - return FALSE; - return thiz->DlgFunc(hWnd, iMsg, wParam, lParam); -} - -INT_PTR EditSymbolsWindow::DlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - char str[128]; - - switch (iMsg) - { - case WM_INITDIALOG: - - // Set the radiobutton values - SendMessage(GetDlgItem(hwnd, IDC_EDITSYMBOLS_SCAN), BM_SETCHECK, scan_ ? BST_CHECKED : BST_UNCHECKED, 0); - SendMessage(GetDlgItem(hwnd, IDC_EDITSYMBOLS_REMOVE), BM_SETCHECK, scan_ ? BST_UNCHECKED : BST_CHECKED, 0); - - // Set the text in the textboxes - if (address_ != -1) { - snprintf(str, sizeof(str), "0x%08X", address_); - SetWindowTextA(GetDlgItem(hwnd, IDC_EDITSYMBOLS_ADDRESS), str); - } - snprintf(str, sizeof(str), "0x%08X", size_); - SetWindowTextA(GetDlgItem(hwnd, IDC_EDITSYMBOLS_SIZE), str); - - return TRUE; - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_EDITSYMBOLS_SCAN: - switch (HIWORD(wParam)) - { - case BN_CLICKED: - scan_ = true; - break; - } - break; - case IDC_EDITSYMBOLS_REMOVE: - switch (HIWORD(wParam)) - { - case BN_CLICKED: - scan_ = false; - break; - } - break; - case IDC_EDITSYMBOLS_OK: - switch (HIWORD(wParam)) - { - case BN_CLICKED: - if (fetchDialogData(hwnd)) { - EndDialog(hwnd, true); - } - break; - }; - break; - case IDC_EDITSYMBOLS_CANCEL: - switch (HIWORD(wParam)) - { - case BN_CLICKED: - EndDialog(hwnd, false); - break; - }; - break; - case IDOK: - if (fetchDialogData(hwnd)) { - EndDialog(hwnd, true); - } - break; - case IDCANCEL: - EndDialog(hwnd, false); - break; - } - } - - return FALSE; -} - -bool EditSymbolsWindow::exec() { - return DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_EDITSYMBOLS), parentHwnd, StaticDlgFunc, (LPARAM)this) != 0; -} - -void EditSymbolsWindow::Scan() { - bool insertSymbols = MIPSAnalyst::ScanForFunctions(address_, address_ + size_ - 1, true); - MIPSAnalyst::FinalizeScan(insertSymbols); -} - -void EditSymbolsWindow::Remove() { - u32 func_address = g_symbolMap->GetFunctionStart(address_); - if (func_address == SymbolMap::INVALID_ADDRESS) { - func_address = g_symbolMap->GetNextSymbolAddress(address_, SymbolType::ST_FUNCTION); - } - - u32 counter = 0; - while (func_address < address_ + size_ && func_address != SymbolMap::INVALID_ADDRESS) { - g_symbolMap->RemoveFunction(func_address, true); - ++counter; - func_address = g_symbolMap->GetNextSymbolAddress(address_, SymbolType::ST_FUNCTION); - } - - if (counter) { - MIPSAnalyst::ForgetFunctions(address_, address_ + size_ - 1); - - // The following was copied from hle.func.remove: - g_symbolMap->SortSymbols(); - - MIPSAnalyst::UpdateHashMap(); - MIPSAnalyst::ApplyHashMap(); - - if (g_Config.bFuncReplacements) { - MIPSAnalyst::ReplaceFunctions(); - } - - // Clear cache for branch lines and such. - DisassemblyManager manager; - manager.clear(); - } -} - -void EditSymbolsWindow::eval() { - if (scan_) { - Scan(); - } - else { - Remove(); - } -} diff --git a/Windows/Debugger/EditSymbolsWindow.h b/Windows/Debugger/EditSymbolsWindow.h deleted file mode 100644 index cc5baa975..000000000 --- a/Windows/Debugger/EditSymbolsWindow.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include -#include "Common/CommonWindows.h" -#include "Common/CommonTypes.h" -#include "Core/Config.h" -#include "Core/Debugger/DebugInterface.h" -#include "Core/Debugger/SymbolMap.h" -#include "Core/MIPS/MIPSAnalyst.h" -#include "Core/Debugger/DisassemblyManager.h" -#include "Core/MemMap.h" - -class EditSymbolsWindow { - HWND parentHwnd; - DebugInterface* cpu; - - bool scan_; - u32 address_; - u32 size_; - - void Scan(); - void Remove(); - - bool GetCheckState(HWND hwnd, int dlgItem); - bool fetchDialogData(HWND hwnd); - - static INT_PTR CALLBACK StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam); - INT_PTR DlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam); - -public: - EditSymbolsWindow(HWND parent, DebugInterface* cpu) : cpu(cpu) { - parentHwnd = parent; - scan_ = true; - address_ = -1; - size_ = 1; - } - - bool exec(); - void eval(); -}; diff --git a/Windows/DinputDevice.cpp b/Windows/DinputDevice.cpp index 0581f522e..43a2340f2 100644 --- a/Windows/DinputDevice.cpp +++ b/Windows/DinputDevice.cpp @@ -39,7 +39,7 @@ std::vector DinputDevice::devices; bool DinputDevice::needsCheck_ = true; // In order from 0. There can be 128, but most controllers do not have that many. -static const InputKeyCode dinput_buttons[] = { +static const int dinput_buttons[] = { NKCODE_BUTTON_1, NKCODE_BUTTON_2, NKCODE_BUTTON_3, @@ -145,7 +145,7 @@ DinputDevice::DinputDevice(int devnum) { return; } - getDevices(needsCheck_); + getDevices(false); if ( (devnum >= (int)devices.size()) || FAILED(getPDI()->CreateDevice(devices.at(devnum).guidInstance, &pJoystick, NULL))) { return; @@ -203,12 +203,12 @@ DinputDevice::~DinputDevice() { } } -void SendNativeAxis(InputDeviceID deviceId, int value, int &lastValue, InputAxis axisId) { +void SendNativeAxis(int deviceId, int value, int &lastValue, int axisId) { AxisInput axis; axis.deviceId = deviceId; axis.axisId = axisId; - axis.value = (float)value * (1.0f / 10000.0f); // Convert axis to normalised float - NativeAxis(&axis, 1); + axis.value = (float)value / 10000.0f; // Convert axis to normalised float + NativeAxis(axis); lastValue = value; } @@ -241,7 +241,6 @@ int DinputDevice::UpdateState() { ApplyButtons(js); if (analog) { - // TODO: Use the batched interface. AxisInput axis; axis.deviceId = DEVICE_ID_PAD_0 + pDevNum; diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index e0ae53822..71af97e68 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -335,8 +335,6 @@ shutdown: g_graphicsContext->Shutdown(); - delete g_graphicsContext; - UpdateConsolePosition(); NativeShutdown(); diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 15869fb24..c96643cc3 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -29,7 +29,6 @@ #include "Common/Data/Text/Parsers.h" #include "Common/StringUtils.h" #include "Common/System/System.h" -#include "Common/System/Request.h" #include "Core/Config.h" #include "Core/Screenshot.h" @@ -1212,10 +1211,11 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { break; case IDC_GEDBG_RECORD: - GPURecord::RecordNextFrame([](const Path &path) { - // Opens a Windows Explorer window with the file, when done. - System_ShowFileInFolder(path); + GPURecord::SetCallback([](const Path &path) { + // Opens a Windows Explorer window with the file. + System_ShowFileInFolder(path.c_str()); }); + GPURecord::Activate(); break; case IDC_GEDBG_FLUSH: diff --git a/Windows/GEDebugger/TabState.cpp b/Windows/GEDebugger/TabState.cpp index 5719d2a34..0a50b4fd1 100644 --- a/Windows/GEDebugger/TabState.cpp +++ b/Windows/GEDebugger/TabState.cpp @@ -15,7 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "Common/CommonWindows.h" #include #include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp index 4304084a4..35ab37e49 100644 --- a/Windows/GEDebugger/TabVertices.cpp +++ b/Windows/GEDebugger/TabVertices.cpp @@ -15,7 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "Common/CommonWindows.h" #include #include "Common/CommonTypes.h" #include "Common/Data/Encoding/Utf8.h" diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index d24c42255..ed503ab2f 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -33,6 +33,21 @@ #error This file should not be compiled for UWP. #endif +D3D11Context::D3D11Context() : draw_(nullptr), adapterId(-1), hDC(nullptr), hWnd_(nullptr), hD3D11(nullptr) { +} + +D3D11Context::~D3D11Context() { +} + +void D3D11Context::SwapBuffers() { + swapChain_->Present(swapInterval_, 0); + draw_->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr); +} + +void D3D11Context::SwapInterval(int interval) { + swapInterval_ = interval; +} + HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) { bool windowed = true; // D3D11 has no need for display rotation. @@ -44,6 +59,13 @@ HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) { UINT createDeviceFlags = 0; #endif + static const D3D_DRIVER_TYPE driverTypes[] = { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + const UINT numDriverTypes = ARRAYSIZE(driverTypes); + static const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, @@ -66,6 +88,13 @@ HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) { return hr; } +static void GetRes(HWND hWnd, int &xres, int &yres) { + RECT rc; + GetClientRect(hWnd, &rc); + xres = rc.right - rc.left; + yres = rc.bottom - rc.top; +} + bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { hWnd_ = wnd; LoadD3D11Error result = LoadD3D11(); @@ -149,15 +178,19 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { } #endif + draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames); + SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName); + bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. + _assert_msg_(success, "Failed to compile preset shaders"); int width; int height; - W32Util::GetWindowRes(hWnd_, &width, &height); + GetRes(hWnd_, width, height); // Obtain DXGI factory from device (since we used nullptr for pAdapter above) - IDXGIFactory1 *dxgiFactory = nullptr; - IDXGIDevice *dxgiDevice = nullptr; - IDXGIAdapter *adapter = nullptr; + IDXGIFactory1* dxgiFactory = nullptr; + IDXGIDevice* dxgiDevice = nullptr; + IDXGIAdapter* adapter = nullptr; hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice)); if (SUCCEEDED(hr)) { hr = dxgiDevice->GetAdapter(&adapter); @@ -189,11 +222,6 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { dxgiFactory->MakeWindowAssociation(hWnd_, DXGI_MWA_NO_ALT_ENTER); dxgiFactory->Release(); - draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, swapChain_, featureLevel_, hWnd_, adapterNames, g_Config.iInflightFrames); - SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName); - bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. - _assert_msg_(success, "Failed to compile preset shaders"); - GotBackbuffer(); return true; } @@ -228,7 +256,7 @@ void D3D11Context::Resize() { LostBackbuffer(); int width; int height; - W32Util::GetWindowRes(hWnd_, &width, &height); + GetRes(hWnd_, width, height); swapChain_->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, 0); GotBackbuffer(); } diff --git a/Windows/GPU/D3D11Context.h b/Windows/GPU/D3D11Context.h index f3d8ff4d8..07d551b7d 100644 --- a/Windows/GPU/D3D11Context.h +++ b/Windows/GPU/D3D11Context.h @@ -28,8 +28,12 @@ class DrawContext; class D3D11Context : public WindowsGraphicsContext { public: + D3D11Context(); + ~D3D11Context(); bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; void Shutdown() override; + void SwapInterval(int interval) override; + void SwapBuffers() override; void Resize() override; @@ -55,12 +59,13 @@ private: ID3D11Debug *d3dDebug_ = nullptr; ID3D11InfoQueue *d3dInfoQueue_ = nullptr; #endif + D3D_FEATURE_LEVEL featureLevel_ = D3D_FEATURE_LEVEL_11_0; - int adapterId = -1; - HDC hDC = nullptr; // Private GDI Device Context - HWND hWnd_ = nullptr; // Holds Our Window Handle - HMODULE hD3D11 = nullptr; - int width = 0; - int height = 0; + int adapterId; + HDC hDC; // Private GDI Device Context + HWND hWnd_; // Holds Our Window Handle + HMODULE hD3D11; + int width; + int height; int swapInterval_ = 0; }; diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index 11ce38367..7ffe7f79f 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -21,8 +21,31 @@ #include "Common/GPU/thin3d_create.h" #include "Common/GPU/D3D9/D3DCompilerLoader.h" +void D3D9Context::SwapBuffers() { + if (has9Ex_) { + deviceEx_->EndScene(); + deviceEx_->PresentEx(NULL, NULL, NULL, NULL, 0); + deviceEx_->BeginScene(); + } else { + device_->EndScene(); + device_->Present(NULL, NULL, NULL, NULL); + device_->BeginScene(); + } +} + typedef HRESULT (__stdcall *DIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**); +static void GetRes(HWND hWnd, int &xres, int &yres) { + RECT rc; + GetClientRect(hWnd, &rc); + xres = rc.right - rc.left; + yres = rc.bottom - rc.top; +} + +void D3D9Context::SwapInterval(int interval) { + swapInterval_ = interval; +} + bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { bool windowed = true; hWnd_ = wnd; @@ -103,7 +126,7 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; int xres, yres; - W32Util::GetWindowRes(hWnd_, &xres, &yres); + GetRes(hWnd_, xres, yres); presentParams_ = {}; presentParams_.BackBufferWidth = xres; @@ -160,8 +183,8 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { void D3D9Context::Resize() { // This should only be called from the emu thread. int xres, yres; - W32Util::GetWindowRes(hWnd_, &xres, &yres); - uint32_t newInterval = swapInterval_ == 1 ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + GetRes(hWnd_, xres, yres); + uint32_t newInterval = swapInterval_ == 1 ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;; bool w_changed = presentParams_.BackBufferWidth != xres; bool h_changed = presentParams_.BackBufferHeight != yres; bool i_changed = presentParams_.PresentationInterval != newInterval; diff --git a/Windows/GPU/D3D9Context.h b/Windows/GPU/D3D9Context.h index b9c40fdd9..9ad836d33 100644 --- a/Windows/GPU/D3D9Context.h +++ b/Windows/GPU/D3D9Context.h @@ -34,6 +34,8 @@ public: bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; void Shutdown() override; + void SwapInterval(int interval) override; + void SwapBuffers() override; void Resize() override; diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 026d70f29..a1bbe2dfc 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -22,7 +22,7 @@ #include "Common/GPU/OpenGL/GLFeatures.h" #include "Common/GPU/thin3d_create.h" #include "Common/GPU/OpenGL/GLRenderManager.h" -#include "Common/System/OSD.h" +#include "Common/System/System.h" #include "GL/gl.h" #include "GL/wglew.h" #include "Core/Config.h" @@ -39,7 +39,7 @@ // Currently, just compile time for debugging. May be NVIDIA only. static const int simulateGLES = false; -void WindowsGLContext::Poll() { +void WindowsGLContext::SwapBuffers() { // We no longer call RenderManager::Swap here, it's handled by the render thread, which // we're not on here. @@ -412,7 +412,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { resumeRequested = false; CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(wglSwapIntervalEXT != nullptr); + draw_ = Draw::T3DCreateGLContext(); bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these. if (!success) { delete draw_; @@ -422,7 +422,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { } draw_->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) { - g_OSD.Show(OSDType::MESSAGE_ERROR, details, 0.0f, "error_callback"); + System_NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback"); }, nullptr); // These are auto-reset events. @@ -432,7 +432,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); - renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }); + renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }, true); if (wglSwapIntervalEXT) { // glew loads wglSwapIntervalEXT if available renderManager_->SetSwapIntervalFunction([&](int interval) { @@ -443,6 +443,11 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { return true; // Success } +void WindowsGLContext::SwapInterval(int interval) { + // Delegate to the render manager to make sure it's done on the right thread. + renderManager_->SwapInterval(interval); +} + void WindowsGLContext::Shutdown() { glslang::FinalizeProcess(); } diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index eacc6709d..2909be60f 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -17,8 +17,8 @@ public: void ShutdownFromRenderThread() override; void Shutdown() override; - - void Poll() override; + void SwapInterval(int interval) override; + void SwapBuffers() override; // Used during window resize. Must be called from the window thread, // not the rendering thread or CPU thread. diff --git a/Windows/GPU/WindowsGraphicsContext.h b/Windows/GPU/WindowsGraphicsContext.h index 41efb96a2..db022e9b5 100644 --- a/Windows/GPU/WindowsGraphicsContext.h +++ b/Windows/GPU/WindowsGraphicsContext.h @@ -7,3 +7,4 @@ class WindowsGraphicsContext : public GraphicsContext { public: virtual bool Init(HINSTANCE hInst, HWND window, std::string *error_message) = 0; }; + diff --git a/Windows/GPU/WindowsVulkanContext.cpp b/Windows/GPU/WindowsVulkanContext.cpp index 71347e8e5..818f39842 100644 --- a/Windows/GPU/WindowsVulkanContext.cpp +++ b/Windows/GPU/WindowsVulkanContext.cpp @@ -131,12 +131,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m return false; } - bool useMultiThreading = g_Config.bRenderMultiThreading; - if (g_Config.iInflightFrames == 1) { - useMultiThreading = false; - } - - draw_ = Draw::T3DCreateVulkanContext(vulkan_, useMultiThreading); + draw_ = Draw::T3DCreateVulkanContext(vulkan_); SetGPUBackend(GPUBackend::VULKAN, vulkan_->GetPhysicalDeviceProperties(deviceNum).properties.deviceName); bool success = draw_->CreatePresets(); _assert_msg_(success, "Failed to compile preset shaders"); diff --git a/Windows/GPU/WindowsVulkanContext.h b/Windows/GPU/WindowsVulkanContext.h index f71522c69..49e6613e3 100644 --- a/Windows/GPU/WindowsVulkanContext.h +++ b/Windows/GPU/WindowsVulkanContext.h @@ -29,6 +29,8 @@ public: WindowsVulkanContext() : draw_(nullptr) {} bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override; void Shutdown() override; + void SwapInterval(int interval) override {} + void SwapBuffers() override {} void Resize() override; void Poll() override; diff --git a/Windows/InputBox.cpp b/Windows/InputBox.cpp index 49cb2eb4e..632a8134f 100644 --- a/Windows/InputBox.cpp +++ b/Windows/InputBox.cpp @@ -1,18 +1,13 @@ -#include "Common/Common.h" #include "Common/CommonTypes.h" #include "Common/CommonWindows.h" #include "Windows/InputBox.h" #include "Windows/resource.h" -#include "Windows/W32Util/Misc.h" #include "Common/Data/Encoding/Utf8.h" static std::wstring textBoxContents; -static std::wstring passwordContents; static std::wstring out; static std::wstring windowTitle; static bool defaultSelected; -static std::string g_userName; -static std::string g_passWord; static INT_PTR CALLBACK InputBoxFunc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -20,31 +15,34 @@ static INT_PTR CALLBACK InputBoxFunc(HWND hDlg, UINT message, WPARAM wParam, LPA case WM_INITDIALOG: SetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), textBoxContents.c_str()); SetWindowText(hDlg, windowTitle.c_str()); - if (defaultSelected == false) - PostMessage(GetDlgItem(hDlg,IDC_INPUTBOX),EM_SETSEL,-1,-1); - W32Util::CenterWindow(hDlg); + if (defaultSelected == false) PostMessage(GetDlgItem(hDlg,IDC_INPUTBOX),EM_SETSEL,-1,-1); return TRUE; case WM_COMMAND: - switch (wParam) { + switch (wParam) + { case IDOK: { - wchar_t temp[512]; - GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, ARRAY_SIZE(temp) - 1); + wchar_t temp[256]; + GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, 255); out = temp; - EndDialog(hDlg, IDOK); - return TRUE; } + EndDialog(hDlg, IDOK); + return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; - default: - return FALSE; } default: return FALSE; } } +template +void InputBoxFunc() +{ + +} + bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultValue, std::string &outvalue, bool selected) { defaultSelected = selected; @@ -140,51 +138,3 @@ bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t* title, u32 de return false; } } - -static INT_PTR CALLBACK UserPasswordBoxFunc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INITDIALOG: - SetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), L""); - SetWindowText(GetDlgItem(hDlg, IDC_PASSWORDBOX), L""); - SetWindowText(hDlg, windowTitle.c_str()); - PostMessage(GetDlgItem(hDlg, IDC_INPUTBOX), EM_SETSEL, -1, -1); - PostMessage(GetDlgItem(hDlg, IDC_PASSWORDBOX), EM_SETSEL, -1, -1); - W32Util::CenterWindow(hDlg); - return TRUE; - case WM_COMMAND: - switch (wParam) - { - case IDOK: - { - wchar_t temp[256]; - GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, 255); - g_userName = ConvertWStringToUTF8(temp); - GetWindowText(GetDlgItem(hDlg, IDC_PASSWORDBOX), temp, 255); - g_passWord = ConvertWStringToUTF8(temp); - EndDialog(hDlg, IDOK); - return TRUE; - } - case IDCANCEL: - EndDialog(hDlg, IDCANCEL); - return TRUE; - default: - return FALSE; - } - default: - return FALSE; - } -} - -bool UserPasswordBox_GetStrings(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string *username, std::string *password) { - windowTitle = title; - INT_PTR value = DialogBox(hInst, (LPCWSTR)IDD_USERPASSWORDBOX, hParent, UserPasswordBoxFunc); - - if (value == IDOK) { - *username = g_userName; - *password = g_passWord; - return true; - } else { - return false; - } -} diff --git a/Windows/InputBox.h b/Windows/InputBox.h index 4617b1323..e82c785e5 100644 --- a/Windows/InputBox.h +++ b/Windows/InputBox.h @@ -3,10 +3,9 @@ #include #include "Common/CommonWindows.h" + // All I/O is in UTF-8 bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultvalue, std::string &outvalue, bool selected); bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultvalue, std::string &outvalue); bool InputBox_GetWString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue); bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t *title, u32 defaultvalue, u32 &outvalue); - -bool UserPasswordBox_GetStrings(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string *username, std::string *password); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 0b7f1afe5..b37bcbf48 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -87,7 +87,6 @@ #define MOUSEEVENTF_FROMTOUCH_NOPEN 0xFF515780 //http://msdn.microsoft.com/en-us/library/windows/desktop/ms703320(v=vs.85).aspx #define MOUSEEVENTF_MASK_PLUS_PENTOUCH 0xFFFFFF80 -// See https://github.com/unknownbrackets/verysleepy/commit/fc1b1b3bd6081fae3566cdb542d896e413238b71 int verysleepy__useSendMessage = 1; const UINT WM_VERYSLEEPY_MSG = WM_APP + 0x3117; @@ -241,7 +240,7 @@ namespace MainWindow g_Config.iInternalResolution = 0; } - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_renderResized", ""); } void CorrectCursor() { @@ -268,25 +267,28 @@ namespace MainWindow } void ReleaseMouseWheel() { - // For simplicity release both wheel events - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.flags = KEY_UP; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - NativeKey(key); - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - NativeKey(key); + // For simplicity release both wheel events + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + key.flags = KEY_UP; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; + NativeKey(key); + key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; + NativeKey(key); } static void HandleSizeChange(int newSizingType) { SavePosition(); Core_NotifyWindowHidden(false); if (!g_Config.bPauseWhenMinimized) { - System_PostUIMessage(UIMessage::WINDOW_MINIMIZED, "false"); + NativeMessageReceived("window minimized", "false"); } - int width, height; - W32Util::GetWindowRes(hwndMain, &width, &height); + int width = 0, height = 0; + RECT rc; + GetClientRect(hwndMain, &rc); + width = rc.right - rc.left; + height = rc.bottom - rc.top; // Moves the internal display window to match the inner size of the main window. MoveWindow(hwndDisplay, 0, 0, width, height, TRUE); @@ -302,8 +304,8 @@ namespace MainWindow DEBUG_LOG(SYSTEM, "Pixel width/height: %dx%d", PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); if (UpdateScreenScale(width, height)) { - System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED); - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); + NativeMessageReceived("gpu_displayResized", ""); + NativeMessageReceived("gpu_renderResized", ""); } // Don't save the window state if fullscreen. @@ -655,22 +657,15 @@ namespace MainWindow // Simulate doubleclick, doesn't work with RawInput enabled static double lastMouseDown; - static float lastMouseDownX = -1.0f; - static float lastMouseDownY = -1.0f; double now = time_now_d(); if ((now - lastMouseDown) < 0.001 * GetDoubleClickTime()) { - float dx = lastMouseDownX - x; - float dy = lastMouseDownY - y; - float distSq = dx * dx + dy * dy; - if (distSq < 3.0f*3.0f && !g_Config.bShowTouchControls && !g_Config.bMouseControl && GetUIState() == UISTATE_INGAME && g_Config.bFullscreenOnDoubleclick) { + if (!g_Config.bShowTouchControls && !g_Config.bMouseControl && GetUIState() == UISTATE_INGAME && g_Config.bFullscreenOnDoubleclick) { SendToggleFullscreen(!g_Config.UseFullScreen()); } lastMouseDown = 0.0; } else { lastMouseDown = now; } - lastMouseDownX = x; - lastMouseDownY = y; } break; @@ -853,12 +848,12 @@ namespace MainWindow } if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { - System_PostUIMessage(UIMessage::GOT_FOCUS); + NativeMessageReceived("got_focus", ""); hasFocus = true; trapMouse = true; } if (wParam == WA_INACTIVE) { - System_PostUIMessage(UIMessage::LOST_FOCUS); + NativeMessageReceived("lost_focus", ""); WindowsRawInput::LoseFocus(); InputDevice::LoseFocus(); hasFocus = false; @@ -905,7 +900,7 @@ namespace MainWindow case SIZE_MINIMIZED: Core_NotifyWindowHidden(true); if (!g_Config.bPauseWhenMinimized) { - System_PostUIMessage(UIMessage::WINDOW_MINIMIZED, "true"); + NativeMessageReceived("window minimized", "true"); } InputDevice::LoseFocus(); break; @@ -1029,7 +1024,7 @@ namespace MainWindow TCHAR filename[512]; if (DragQueryFile(hdrop, 0, filename, 512) != 0) { const std::string utf8_filename = ReplaceAll(ConvertWStringToUTF8(filename), "\\", "/"); - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, utf8_filename); + NativeMessageReceived("boot", utf8_filename.c_str()); Core_EnableStepping(false); } } diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index fa6c7a8bc..c7ff2deab 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -14,7 +14,6 @@ #include "Common/Data/Text/I18n.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/System/NativeApp.h" #include "Common/System/Request.h" #include "Common/File/FileUtil.h" @@ -51,7 +50,6 @@ #include "Core/HLE/sceUmd.h" #include "Core/SaveState.h" #include "Core/Core.h" -#include "Core/RetroAchievements.h" extern bool g_TakeScreenshot; @@ -70,28 +68,14 @@ namespace MainWindow { LRESULT CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); void SetIngameMenuItemStates(HMENU menu, const GlobalUIState state) { - bool menuEnableBool = state == UISTATE_INGAME || state == UISTATE_EXCEPTION; - - bool loadStateEnableBool = menuEnableBool; - bool saveStateEnableBool = menuEnableBool; - if (Achievements::ChallengeModeActive()) { - loadStateEnableBool = false; - if (!g_Config.bAchievementsSaveStateInChallengeMode) { - saveStateEnableBool = false; - } - } - - UINT menuEnable = menuEnableBool ? MF_ENABLED : MF_GRAYED; - UINT loadStateEnable = loadStateEnableBool ? MF_ENABLED : MF_GRAYED; - UINT saveStateEnable = saveStateEnableBool ? MF_ENABLED : MF_GRAYED; + UINT menuEnable = state == UISTATE_INGAME || state == UISTATE_EXCEPTION ? MF_ENABLED : MF_GRAYED; UINT menuInGameEnable = state == UISTATE_INGAME ? MF_ENABLED : MF_GRAYED; UINT umdSwitchEnable = state == UISTATE_INGAME && getUMDReplacePermit() ? MF_ENABLED : MF_GRAYED; - EnableMenuItem(menu, ID_FILE_SAVESTATE_SLOT_MENU, saveStateEnable); - EnableMenuItem(menu, ID_FILE_SAVESTATEFILE, saveStateEnable); - EnableMenuItem(menu, ID_FILE_LOADSTATEFILE, loadStateEnable); - EnableMenuItem(menu, ID_FILE_QUICKSAVESTATE, saveStateEnable); - EnableMenuItem(menu, ID_FILE_QUICKLOADSTATE, loadStateEnable); + EnableMenuItem(menu, ID_FILE_SAVESTATEFILE, menuEnable); + EnableMenuItem(menu, ID_FILE_LOADSTATEFILE, menuEnable); + EnableMenuItem(menu, ID_FILE_QUICKSAVESTATE, menuEnable); + EnableMenuItem(menu, ID_FILE_QUICKLOADSTATE, menuEnable); EnableMenuItem(menu, ID_EMULATION_PAUSE, menuEnable); EnableMenuItem(menu, ID_EMULATION_STOP, menuEnable); EnableMenuItem(menu, ID_EMULATION_RESET, menuEnable); @@ -295,6 +279,7 @@ namespace MainWindow { TranslateMenuItem(menu, ID_TEXTURESCALING_HYBRID_BICUBIC); TranslateMenuItem(menu, ID_TEXTURESCALING_DEPOSTERIZE); TranslateMenuItem(menu, ID_OPTIONS_HARDWARETRANSFORM); + TranslateMenuItem(menu, ID_OPTIONS_VERTEXCACHE); TranslateMenuItem(menu, ID_EMULATION_SOUND); TranslateMenuItem(menu, ID_EMULATION_CHEATS, g_Config.bSystemControls ? L"\tCtrl+T" : L""); TranslateMenuItem(menu, ID_EMULATION_CHAT, g_Config.bSystemControls ? L"\tCtrl+C" : L""); @@ -321,6 +306,12 @@ namespace MainWindow { void BrowseAndBootDone(std::string filename); void BrowseAndBoot(std::string defaultPath, bool browseDirectory) { + static std::wstring filter = L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"; + for (int i = 0; i < (int)filter.length(); i++) { + if (filter[i] == '|') + filter[i] = '\0'; + } + browsePauseAfter = false; if (GetUIState() == UISTATE_INGAME) { browsePauseAfter = Core_IsStepping(); @@ -347,20 +338,27 @@ namespace MainWindow { Core_EnableStepping(false); } filename = ReplaceAll(filename, "\\", "/"); - System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, filename); + NativeMessageReceived("boot", filename.c_str()); W32Util::MakeTopMost(GetHWND(), g_Config.bTopMost); } static void UmdSwitchAction() { - auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFile(mm->T("Switch UMD"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { - __UmdReplace(Path(value)); - }); + std::string fn; + std::string filter = "PSP ROMs (*.iso *.cso *.pbp *.elf)|*.pbp;*.elf;*.iso;*.cso;*.prx|All files (*.*)|*.*||"; + + for (int i = 0; i < (int)filter.length(); i++) { + if (filter[i] == '|') + filter[i] = '\0'; + } + + if (W32Util::BrowseForFileName(true, GetHWND(), L"Switch UMD", 0, ConvertUTF8ToWString(filter).c_str(), L"*.pbp;*.elf;*.iso;*.cso;", fn)) { + __UmdReplace(Path(fn)); + } } static void SaveStateActionFinished(SaveState::Status status, const std::string &message, void *userdata) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { - g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); + osm.Show(message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); } PostMessage(MainWindow::GetHWND(), WM_USER_SAVESTATE_FINISH, 0, 0); } @@ -368,17 +366,17 @@ namespace MainWindow { // not static void setTexScalingMultiplier(int level) { g_Config.iTexScalingLevel = level; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } static void setTexScalingType(int type) { g_Config.iTexScalingType = type; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } static void setSkipBufferEffects(bool skip) { g_Config.bSkipBufferEffects = skip; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } static void setFrameSkipping(int framesToSkip = -1) { @@ -399,7 +397,7 @@ namespace MainWindow { else messageStream << g_Config.iFrameSkip; - g_OSD.Show(OSDType::MESSAGE_INFO, messageStream.str()); + osm.Show(messageStream.str()); } static void setFrameSkippingType(int fskipType = -1) { @@ -419,11 +417,11 @@ namespace MainWindow { else messageStream << gr->T("Percent of FPS"); - g_OSD.Show(OSDType::MESSAGE_INFO, messageStream.str()); + osm.Show(messageStream.str()); } static void RestartApp() { - if (System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) { + if (IsDebuggerPresent()) { PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0); } else { g_Config.bRestartRequired = true; @@ -461,8 +459,8 @@ namespace MainWindow { case ID_TOGGLE_BREAK: if (GetUIState() == UISTATE_PAUSEMENU) { - // Causes hang (outdated comment?) - // System_PostUIMessage(UIMessage::REQUEST_GAME_RUN, ""); + // Causes hang + //NativeMessageReceived("run", ""); if (disasmWindow) SendMessage(disasmWindow->GetDlgHandle(), WM_COMMAND, IDC_STOPGO, 0); @@ -481,7 +479,7 @@ namespace MainWindow { break; case ID_EMULATION_PAUSE: - System_PostUIMessage(UIMessage::REQUEST_GAME_PAUSE); + NativeMessageReceived("pause", ""); break; case ID_EMULATION_STOP: @@ -489,12 +487,12 @@ namespace MainWindow { Core_EnableStepping(false); Core_Stop(); - System_PostUIMessage(UIMessage::REQUEST_GAME_STOP); + NativeMessageReceived("stop", ""); Core_WaitInactive(); break; case ID_EMULATION_RESET: - System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); + NativeMessageReceived("reset", ""); Core_EnableStepping(false); break; @@ -509,102 +507,85 @@ namespace MainWindow { case ID_EMULATION_CHEATS: g_Config.bEnableCheats = !g_Config.bEnableCheats; - g_OSD.ShowOnOff(gr->T("Cheats"), g_Config.bEnableCheats); + osm.ShowOnOff(gr->T("Cheats"), g_Config.bEnableCheats); break; case ID_EMULATION_CHAT: if (GetUIState() == UISTATE_INGAME) { - System_PostUIMessage(UIMessage::SHOW_CHAT_SCREEN); + NativeMessageReceived("chat screen", ""); } break; case ID_FILE_LOADSTATEFILE: - if (!Achievements::WarnUserIfChallengeModeActive(false)) { - if (W32Util::BrowseForFileName(true, hWnd, L"Load state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) { - SetCursor(LoadCursor(0, IDC_WAIT)); - SaveState::Load(Path(fn), -1, SaveStateActionFinished); - } + if (W32Util::BrowseForFileName(true, hWnd, L"Load state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) { + SetCursor(LoadCursor(0, IDC_WAIT)); + SaveState::Load(Path(fn), -1, SaveStateActionFinished); } break; case ID_FILE_SAVESTATEFILE: - if (!Achievements::WarnUserIfChallengeModeActive(true)) { - if (W32Util::BrowseForFileName(false, hWnd, L"Save state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) { - SetCursor(LoadCursor(0, IDC_WAIT)); - SaveState::Save(Path(fn), -1, SaveStateActionFinished); - } + if (W32Util::BrowseForFileName(false, hWnd, L"Save state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) { + SetCursor(LoadCursor(0, IDC_WAIT)); + SaveState::Save(Path(fn), -1, SaveStateActionFinished); } break; case ID_FILE_SAVESTATE_NEXT_SLOT: { - if (!Achievements::WarnUserIfChallengeModeActive(true)) { - SaveState::NextSlot(); - System_PostUIMessage(UIMessage::SAVESTATE_DISPLAY_SLOT); - } + SaveState::NextSlot(); + NativeMessageReceived("savestate_displayslot", ""); break; } case ID_FILE_SAVESTATE_NEXT_SLOT_HC: { - if (!Achievements::WarnUserIfChallengeModeActive(true)) { - if (!KeyMap::PspButtonHasMappings(VIRTKEY_NEXT_SLOT)) { - SaveState::NextSlot(); - System_PostUIMessage(UIMessage::SAVESTATE_DISPLAY_SLOT); - } + if (!KeyMap::PspButtonHasMappings(VIRTKEY_NEXT_SLOT)) { + SaveState::NextSlot(); + NativeMessageReceived("savestate_displayslot", ""); } break; } - case ID_FILE_SAVESTATE_SLOT_1: - case ID_FILE_SAVESTATE_SLOT_2: - case ID_FILE_SAVESTATE_SLOT_3: - case ID_FILE_SAVESTATE_SLOT_4: - case ID_FILE_SAVESTATE_SLOT_5: - if (!Achievements::WarnUserIfChallengeModeActive(true)) { - g_Config.iCurrentStateSlot = wmId - ID_FILE_SAVESTATE_SLOT_1; - } - break; + case ID_FILE_SAVESTATE_SLOT_1: g_Config.iCurrentStateSlot = 0; break; + case ID_FILE_SAVESTATE_SLOT_2: g_Config.iCurrentStateSlot = 1; break; + case ID_FILE_SAVESTATE_SLOT_3: g_Config.iCurrentStateSlot = 2; break; + case ID_FILE_SAVESTATE_SLOT_4: g_Config.iCurrentStateSlot = 3; break; + case ID_FILE_SAVESTATE_SLOT_5: g_Config.iCurrentStateSlot = 4; break; case ID_FILE_QUICKLOADSTATE: - if (!Achievements::WarnUserIfChallengeModeActive(false)) { - SetCursor(LoadCursor(0, IDC_WAIT)); - SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); - } + { + SetCursor(LoadCursor(0, IDC_WAIT)); + SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); break; + } case ID_FILE_QUICKLOADSTATE_HC: { - if (!Achievements::WarnUserIfChallengeModeActive(false)) { - if (!KeyMap::PspButtonHasMappings(VIRTKEY_LOAD_STATE)) { - SetCursor(LoadCursor(0, IDC_WAIT)); - SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); - } + if (!KeyMap::PspButtonHasMappings(VIRTKEY_LOAD_STATE)) + { + SetCursor(LoadCursor(0, IDC_WAIT)); + SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); } break; } case ID_FILE_QUICKSAVESTATE: { - if (!Achievements::WarnUserIfChallengeModeActive(true)) { - SetCursor(LoadCursor(0, IDC_WAIT)); - SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); - } + SetCursor(LoadCursor(0, IDC_WAIT)); + SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); break; } case ID_FILE_QUICKSAVESTATE_HC: { - if (!Achievements::WarnUserIfChallengeModeActive(true)) { - if (!KeyMap::PspButtonHasMappings(VIRTKEY_SAVE_STATE)) - { - SetCursor(LoadCursor(0, IDC_WAIT)); - SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); - break; - } + if (!KeyMap::PspButtonHasMappings(VIRTKEY_SAVE_STATE)) + { + SetCursor(LoadCursor(0, IDC_WAIT)); + SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished); + break; } break; } case ID_OPTIONS_LANGUAGE: - System_PostUIMessage(UIMessage::SHOW_LANGUAGE_SCREEN); + NativeMessageReceived("language screen", ""); break; case ID_OPTIONS_IGNOREWINKEY: @@ -649,7 +630,7 @@ namespace MainWindow { g_Config.bAutoFrameSkip = !g_Config.bAutoFrameSkip; if (g_Config.bAutoFrameSkip && g_Config.bSkipBufferEffects) { g_Config.bSkipBufferEffects = false; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); } break; @@ -666,7 +647,7 @@ namespace MainWindow { case ID_TEXTURESCALING_DEPOSTERIZE: g_Config.bTexDeposterize = !g_Config.bTexDeposterize; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); + NativeMessageReceived("gpu_configChanged", ""); break; case ID_OPTIONS_DIRECT3D9: @@ -695,29 +676,23 @@ namespace MainWindow { case ID_OPTIONS_SKIP_BUFFER_EFFECTS: g_Config.bSkipBufferEffects = !g_Config.bSkipBufferEffects; - System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); - g_OSD.ShowOnOff(gr->T("Skip Buffer Effects"), g_Config.bSkipBufferEffects); + NativeMessageReceived("gpu_renderResized", ""); + osm.ShowOnOff(gr->T("Skip Buffer Effects"), g_Config.bSkipBufferEffects); break; case ID_DEBUG_SHOWDEBUGSTATISTICS: - // This is still useful as a shortcut to tell users to use. - // So let's fake the enum. - if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS) { - g_Config.iDebugOverlay = (int)DebugOverlay::OFF; - } else { - g_Config.iDebugOverlay = (int)DebugOverlay::DEBUG_STATS; - } - System_PostUIMessage(UIMessage::REQUEST_CLEAR_JIT); + g_Config.bShowDebugStats = !g_Config.bShowDebugStats; + NativeMessageReceived("clear jit", ""); break; case ID_OPTIONS_HARDWARETRANSFORM: g_Config.bHardwareTransform = !g_Config.bHardwareTransform; - System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); - g_OSD.ShowOnOff(gr->T("Hardware Transform"), g_Config.bHardwareTransform); + NativeMessageReceived("gpu_configChanged", ""); + osm.ShowOnOff(gr->T("Hardware Transform"), g_Config.bHardwareTransform); break; case ID_OPTIONS_DISPLAY_LAYOUT: - System_PostUIMessage(UIMessage::SHOW_DISPLAY_LAYOUT_EDITOR); + NativeMessageReceived("display layout editor", ""); break; @@ -748,7 +723,7 @@ namespace MainWindow { break; case ID_DEBUG_DUMPNEXTFRAME: - System_PostUIMessage(UIMessage::REQUEST_GPU_DUMP_NEXT_FRAME); + NativeMessageReceived("gpu dump next frame", ""); break; case ID_DEBUG_LOADMAPFILE: @@ -863,6 +838,9 @@ namespace MainWindow { SendToggleFullscreen(!g_Config.UseFullScreen()); break; + case ID_OPTIONS_VERTEXCACHE: + g_Config.bVertexCache = !g_Config.bVertexCache; + break; case ID_OPTIONS_TEXTUREFILTERING_AUTO: g_Config.iTexFiltering = TEX_FILTER_AUTO; break; case ID_OPTIONS_NEARESTFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_NEAREST; break; case ID_OPTIONS_LINEARFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_LINEAR; break; @@ -881,11 +859,11 @@ namespace MainWindow { break; case ID_OPTIONS_CONTROLS: - System_PostUIMessage(UIMessage::SHOW_CONTROL_MAPPING); + NativeMessageReceived("control mapping", ""); break; case ID_OPTIONS_MORE_SETTINGS: - System_PostUIMessage(UIMessage::SHOW_SETTINGS); + NativeMessageReceived("settings", ""); break; case ID_EMULATION_SOUND: @@ -952,9 +930,10 @@ namespace MainWindow { HMENU menu = GetMenu(GetHWND()); #define CHECKITEM(item,value) CheckMenuItem(menu,item,MF_BYCOMMAND | ((value) ? MF_CHECKED : MF_UNCHECKED)); CHECKITEM(ID_DEBUG_IGNOREILLEGALREADS, g_Config.bIgnoreBadMemAccess); - CHECKITEM(ID_DEBUG_SHOWDEBUGSTATISTICS, (DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS); + CHECKITEM(ID_DEBUG_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform); CHECKITEM(ID_DEBUG_BREAKONLOAD, !g_Config.bAutoRun); + CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache); CHECKITEM(ID_OPTIONS_FRAMESKIP_AUTO, g_Config.bAutoFrameSkip); CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != FRAMESKIP_OFF); CHECKITEM(ID_OPTIONS_FRAMESKIPTYPE_COUNT, g_Config.iFrameSkipType == FRAMESKIPTYPE_COUNT); @@ -988,6 +967,13 @@ namespace MainWindow { CheckMenuItem(menu, displayrotationitems[i], MF_BYCOMMAND | ((i + 1) == g_Config.iInternalScreenRotation ? MF_CHECKED : MF_UNCHECKED)); } + // Disable Vertex Cache when HW T&L is disabled. + if (!g_Config.bHardwareTransform) { + EnableMenuItem(menu, ID_OPTIONS_VERTEXCACHE, MF_GRAYED); + } else { + EnableMenuItem(menu, ID_OPTIONS_VERTEXCACHE, MF_ENABLED); + } + static const int zoomitems[11] = { ID_OPTIONS_SCREENAUTO, ID_OPTIONS_SCREEN1X, diff --git a/Windows/PPSSPP.sln b/Windows/PPSSPP.sln index 93a9d22c6..877e13aff 100644 --- a/Windows/PPSSPP.sln +++ b/Windows/PPSSPP.sln @@ -1,19 +1,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.6.33801.468 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1082 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPPWindows", "PPSSPP.vcxproj", "{567AF8DB-42C1-4D08-96CD-D70A2DFEFC6B}" ProjectSection(ProjectDependencies) = postProject {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} = {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} + {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {D8A71225-178B-424E-96C1-CC3BE2C1B047} {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} - {31694510-A8C0-40F6-B09B-E8DF825ADEFA} = {31694510-A8C0-40F6-B09B-E8DF825ADEFA} - {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} = {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} - {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} - {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} {533F1D30-D04D-47CC-AD71-20F658907E36} = {533F1D30-D04D-47CC-AD71-20F658907E36} {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} - {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {D8A71225-178B-424E-96C1-CC3BE2C1B047} {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} + {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} = {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} + {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} + {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\Common\Common.vcxproj", "{3FCDBAE2-5103-4350-9A8E-848CE9C73195}" @@ -26,28 +25,28 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\ext\zlib\zlib.vc EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GPU", "..\GPU\GPU.vcxproj", "{457F45D2-556F-47BC-A31D-AFF0D15BEAED}" ProjectSection(ProjectDependencies) = postProject - {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} {4328A62C-F1E9-47ED-B816-A1A81DAF4363} = {4328A62C-F1E9-47ED-B816-A1A81DAF4363} {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} + {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\Core\Core.vcxproj", "{533F1D30-D04D-47CC-AD71-20F658907E36}" ProjectSection(ProjectDependencies) = postProject {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} - {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} - {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} + {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} + {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPPHeadless", "..\headless\Headless.vcxproj", "{EE9BD869-CAA3-447D-8328-294D90DE2C1F}" ProjectSection(ProjectDependencies) = postProject - {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} - {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} = {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} - {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} - {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} - {533F1D30-D04D-47CC-AD71-20F658907E36} = {533F1D30-D04D-47CC-AD71-20F658907E36} {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {D8A71225-178B-424E-96C1-CC3BE2C1B047} + {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} + {533F1D30-D04D-47CC-AD71-20F658907E36} = {533F1D30-D04D-47CC-AD71-20F658907E36} {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} + {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} = {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} + {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} + {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libkirk", "..\ext\libkirk\libkirk.vcxproj", "{3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE}" @@ -55,18 +54,17 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "..\unittest\UnitTests.vcxproj", "{37CBC214-7CE7-4655-B619-F7CEE16E3313}" ProjectSection(ProjectDependencies) = postProject {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} = {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} + {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {D8A71225-178B-424E-96C1-CC3BE2C1B047} {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} {533F1D30-D04D-47CC-AD71-20F658907E36} = {533F1D30-D04D-47CC-AD71-20F658907E36} - {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {D8A71225-178B-424E-96C1-CC3BE2C1B047} {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UI", "..\UI\UI.vcxproj", "{004B8D11-2BE3-4BD9-AB40-2BE04CF2096F}" ProjectSection(ProjectDependencies) = postProject - {31694510-A8C0-40F6-B09B-E8DF825ADEFA} = {31694510-A8C0-40F6-B09B-E8DF825ADEFA} - {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} - {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} {533F1D30-D04D-47CC-AD71-20F658907E36} = {533F1D30-D04D-47CC-AD71-20F658907E36} + {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} + {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libarmips", "..\ext\libarmips.vcxproj", "{129E5E2B-39C1-4D84-96FE-DFD22DBB4A25}" @@ -91,10 +89,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "..\ext\libzstd.v EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu_features", "..\ext\cpu_features.vcxproj", "{C249F016-7F82-45CF-BB6E-0642A988C4D3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcheevos", "..\ext\rcheevos-build\rcheevos.vcxproj", "{31694510-A8C0-40F6-B09B-E8DF825ADEFA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchdr", "..\ext\libchdr.vcxproj", "{956F1F48-B612-46D8-89EE-96996DCD9383}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -381,38 +375,6 @@ Global {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.Build.0 = Release|Win32 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.ActiveCfg = Release|x64 {C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.Build.0 = Release|x64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|ARM.ActiveCfg = Debug|ARM - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|ARM.Build.0 = Debug|ARM - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|ARM64.Build.0 = Debug|ARM64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|Win32.Build.0 = Debug|Win32 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|x64.ActiveCfg = Debug|x64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Debug|x64.Build.0 = Debug|x64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|ARM.ActiveCfg = Release|ARM - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|ARM.Build.0 = Release|ARM - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|ARM64.ActiveCfg = Release|ARM64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|ARM64.Build.0 = Release|ARM64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|Win32.ActiveCfg = Release|Win32 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|Win32.Build.0 = Release|Win32 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|x64.ActiveCfg = Release|x64 - {31694510-A8C0-40F6-B09B-E8DF825ADEFA}.Release|x64.Build.0 = Release|x64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM.ActiveCfg = Debug|ARM - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM.Build.0 = Debug|ARM - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|ARM64.Build.0 = Debug|ARM64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|Win32.ActiveCfg = Debug|Win32 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|Win32.Build.0 = Debug|Win32 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|x64.ActiveCfg = Debug|x64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Debug|x64.Build.0 = Debug|x64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM.ActiveCfg = Release|ARM - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM.Build.0 = Release|ARM - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM64.ActiveCfg = Release|ARM64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|ARM64.Build.0 = Release|ARM64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|Win32.ActiveCfg = Release|Win32 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|Win32.Build.0 = Release|Win32 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|x64.ActiveCfg = Release|x64 - {956F1F48-B612-46D8-89EE-96996DCD9383}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -429,8 +391,6 @@ Global {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} {C249F016-7F82-45CF-BB6E-0642A988C4D3} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} - {31694510-A8C0-40F6-B09B-E8DF825ADEFA} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} - {956F1F48-B612-46D8-89EE-96996DCD9383} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2FD47774-A031-48F4-B645-A49A3140A29B} diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index 01128f75f..cd23a3b70 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -249,7 +249,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86/lib true Windows @@ -289,7 +289,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86_64/lib true $(OutDir)$(ProjectName).pdb @@ -325,7 +325,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/aarch64/lib true $(OutDir)$(ProjectName).pdb @@ -359,7 +359,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/arm/lib true $(OutDir)$(ProjectName).pdb @@ -397,7 +397,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86/lib;%(AdditionalLibraryDirectories) $(OutDir)$(TargetName)$(TargetExt) true @@ -446,7 +446,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/x86_64/lib;%(AdditionalLibraryDirectories) true Windows @@ -489,7 +489,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/aarch64/lib;%(AdditionalLibraryDirectories) true Windows @@ -530,7 +530,7 @@ stdcpp17 - winhttp.lib;uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) + uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies) ../ffmpeg/Windows/arm/lib;%(AdditionalLibraryDirectories) true Windows @@ -844,7 +844,6 @@ - @@ -1273,7 +1272,6 @@ true true - true true @@ -1334,7 +1332,6 @@ true true - true true @@ -1401,7 +1398,6 @@ - @@ -1651,16 +1647,6 @@ - - true - true - true - true - true - true - true - true - true @@ -1683,16 +1669,6 @@ true - - true - true - true - true - true - true - true - true - @@ -1721,9 +1697,6 @@ {edfa2e87-8ac1-4853-95d4-d7594ff81947} - - {956f1f48-b612-46d8-89ee-96996dcd9383} - {3baae095-e0ab-4b0e-b5df-ce39c8ae31de} diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index 1c228494e..b3195e189 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -62,9 +62,6 @@ {e6f1a7f6-807b-484e-9595-bdb58ecaa2ae} - - {e2dd8951-ccb6-4575-996a-69c6832fafbf} - @@ -280,9 +277,6 @@ Windows\Debugger - - Windows\Debugger - @@ -571,15 +565,6 @@ Windows\Debugger - - Windows\Debugger - - - Other Platforms\Mac - - - Other Platforms\Mac - @@ -809,12 +794,6 @@ Build\CMake - - Other Platforms\Mac - - - Other Platforms\Mac - diff --git a/Windows/RawInput.cpp b/Windows/RawInput.cpp index 486c20e62..db8b8518c 100644 --- a/Windows/RawInput.cpp +++ b/Windows/RawInput.cpp @@ -57,7 +57,7 @@ #endif namespace WindowsRawInput { - static std::set keyboardKeysDown; + static std::set keyboardKeysDown; static void *rawInputBuffer; static size_t rawInputBufferSize; static bool menuActive; @@ -68,7 +68,7 @@ namespace WindowsRawInput { // TODO: More keys need to be added, but this is more than // a fair start. - static std::map windowsTransTable = { + static std::map windowsTransTable = { { 'A', NKCODE_A }, { 'B', NKCODE_B }, { 'C', NKCODE_C }, @@ -213,7 +213,7 @@ namespace WindowsRawInput { return menuActive; } - static InputKeyCode GetTrueVKey(const RAWKEYBOARD &kb) { + static int GetTrueVKey(const RAWKEYBOARD &kb) { int vKey = kb.VKey; switch (kb.VKey) { case VK_SHIFT: @@ -275,7 +275,8 @@ namespace WindowsRawInput { if (key.keyCode) { NativeKey(key); - auto keyDown = keyboardKeysDown.find(key.keyCode); + + auto keyDown = std::find(keyboardKeysDown.begin(), keyboardKeysDown.end(), key.keyCode); if (keyDown != keyboardKeysDown.end()) keyboardKeysDown.erase(keyDown); } @@ -284,7 +285,7 @@ namespace WindowsRawInput { LRESULT ProcessChar(HWND hWnd, WPARAM wParam, LPARAM lParam) { KeyInput key; - key.unicodeChar = (int)wParam; // Note that this is NOT a NKCODE but a Unicode character! + key.keyCode = (int)wParam; // Note that this is NOT a NKCODE but a Unicode character! key.flags = KEY_CHAR; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); diff --git a/Windows/W32Util/DarkMode.h b/Windows/W32Util/DarkMode.h index 0ad97a877..50ac9498d 100644 --- a/Windows/W32Util/DarkMode.h +++ b/Windows/W32Util/DarkMode.h @@ -1,7 +1,9 @@ #pragma once -#include "Common/CommonWindows.h" -#include +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include #include #include #include diff --git a/Windows/W32Util/IatHook.h b/Windows/W32Util/IatHook.h index 2319e3cea..1f259a5f2 100644 --- a/Windows/W32Util/IatHook.h +++ b/Windows/W32Util/IatHook.h @@ -5,10 +5,6 @@ #pragma once -#include "Common/CommonWindows.h" -#include -#include - template constexpr T RVA2VA(T1 base, T2 rva) { diff --git a/Windows/W32Util/Misc.cpp b/Windows/W32Util/Misc.cpp index 0583c5963..97f4e475e 100644 --- a/Windows/W32Util/Misc.cpp +++ b/Windows/W32Util/Misc.cpp @@ -4,12 +4,9 @@ #include #include #include -#include #include "Misc.h" #include "Common/Data/Encoding/Utf8.h" -#include "Common/StringUtils.h" -#include "Common/File/FileUtil.h" bool KeyDownAsync(int vkey) { #if PPSSPP_PLATFORM(UWP) @@ -90,28 +87,6 @@ namespace W32Util SetWindowPos(hwnd, style, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); } - void GetWindowRes(HWND hWnd, int *xres, int *yres) { - RECT rc; - GetClientRect(hWnd, &rc); - *xres = rc.right - rc.left; - *yres = rc.bottom - rc.top; - } - - void ShowFileInFolder(const std::string &path) { - // SHParseDisplayName can't handle relative paths, so normalize first. - std::string resolved = ReplaceAll(File::ResolvePath(path), "/", "\\"); - - SFGAOF flags{}; - PIDLIST_ABSOLUTE pidl = nullptr; - HRESULT hr = SHParseDisplayName(ConvertUTF8ToWString(resolved).c_str(), nullptr, &pidl, 0, &flags); - - if (pidl) { - if (SUCCEEDED(hr)) - SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0); - CoTaskMemFree(pidl); - } - } - static const wchar_t *RemoveExecutableFromCommandLine(const wchar_t *cmdline) { if (!cmdline) { return L""; @@ -168,34 +143,6 @@ namespace W32Util ExitProcess(0); } - bool ExecuteAndGetReturnCode(const wchar_t *executable, const wchar_t *cmdline, const wchar_t *currentDirectory, DWORD *exitCode) { - PROCESS_INFORMATION processInformation = { 0 }; - STARTUPINFO startupInfo = { 0 }; - startupInfo.cb = sizeof(startupInfo); - - std::wstring cmdlineW; - cmdlineW += L"PPSSPP "; // could also put the executable name as first argument, but concerned about escaping. - cmdlineW += cmdline; - - // Create the process - bool result = CreateProcess(executable, (LPWSTR)cmdlineW.c_str(), - NULL, NULL, FALSE, - NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, - NULL, currentDirectory, &startupInfo, &processInformation); - - if (!result) { - // We failed. - return false; - } - - // Successfully created the process. Wait for it to finish. - WaitForSingleObject(processInformation.hProcess, INFINITE); - result = GetExitCodeProcess(processInformation.hProcess, exitCode); - CloseHandle(processInformation.hProcess); - CloseHandle(processInformation.hThread); - return result != 0; - } - void SpawnNewInstance(bool overrideArgs, const std::string &args) { // This preserves arguments (for example, config file) and working directory. std::wstring workingDirectory; diff --git a/Windows/W32Util/Misc.h b/Windows/W32Util/Misc.h index cd20db75e..ddfaa0a89 100644 --- a/Windows/W32Util/Misc.h +++ b/Windows/W32Util/Misc.h @@ -3,7 +3,6 @@ #include #include #include - #include "Common/CommonWindows.h" namespace W32Util @@ -14,12 +13,8 @@ namespace W32Util void MakeTopMost(HWND hwnd, bool topMost); void ExitAndRestart(bool overrideArgs = false, const std::string &args = ""); void SpawnNewInstance(bool overrideArgs = false, const std::string &args = ""); - bool ExecuteAndGetReturnCode(const wchar_t *executable, const wchar_t *cmdline, const wchar_t *currentDirectory, DWORD *exitCode); void GetSelfExecuteParams(std::wstring &workingDirectory, std::wstring &moduleFilename); - void GetWindowRes(HWND hWnd, int *xres, int *yres); - void ShowFileInFolder(const std::string &path); - struct ClipboardData { ClipboardData(const char *format, size_t sz); ClipboardData(UINT format, size_t sz); diff --git a/Windows/W32Util/ShellUtil.cpp b/Windows/W32Util/ShellUtil.cpp index e6d007862..df770e64d 100644 --- a/Windows/W32Util/ShellUtil.cpp +++ b/Windows/W32Util/ShellUtil.cpp @@ -192,7 +192,6 @@ HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathL psl->SetPath(lpszPathObj); psl->SetArguments(lpszArguments); psl->SetDescription(lpszDesc); - // psl->SetIconLocation(..) // Query IShellLink for the IPersistFile interface, used for saving the // shortcut in persistent storage. @@ -211,8 +210,12 @@ HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathL } bool CreateDesktopShortcut(const std::string &argumentPath, std::string gameTitle) { + // TODO: not working correctly + return false; + // Get the desktop folder - wchar_t *pathbuf = new wchar_t[4096]; + // TODO: Not long path safe. + wchar_t *pathbuf = new wchar_t[MAX_PATH + gameTitle.size() + 100]; SHGetFolderPath(0, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, pathbuf); // Sanitize the game title for banned characters. @@ -228,7 +231,6 @@ bool CreateDesktopShortcut(const std::string &argumentPath, std::string gameTitl wcscat(pathbuf, L"\\"); wcscat(pathbuf, ConvertUTF8ToWString(gameTitle).c_str()); - wcscat(pathbuf, L".lnk"); std::wstring moduleFilename; size_t sz; @@ -239,20 +241,7 @@ bool CreateDesktopShortcut(const std::string &argumentPath, std::string gameTitl } while (sz >= moduleFilename.size()); moduleFilename.resize(sz); - // Need to flip the slashes in the filename. - - std::string sanitizedArgument = argumentPath; - for (size_t i = 0; i < sanitizedArgument.size(); i++) { - if (sanitizedArgument[i] == '/') { - sanitizedArgument[i] = '\\'; - } - } - - sanitizedArgument = "\"" + sanitizedArgument + "\""; - - CreateLink(moduleFilename.c_str(), ConvertUTF8ToWString(sanitizedArgument).c_str(), pathbuf, ConvertUTF8ToWString(gameTitle).c_str()); - - // TODO: Also extract the game icon and convert to .ico, put it somewhere under Memstick, and set it. + CreateLink(moduleFilename.c_str(), ConvertUTF8ToWString(argumentPath).c_str(), pathbuf, ConvertUTF8ToWString(gameTitle).c_str()); delete[] pathbuf; return false; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index ef0e71574..8a2d877bf 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -107,16 +107,17 @@ void WindowsInputManager::PollControllers() { float mx = std::max(-1.0f, std::min(1.0f, mouseDeltaX_ * scaleFactor_x)); float my = std::max(-1.0f, std::min(1.0f, mouseDeltaY_ * scaleFactor_y)); - AxisInput axis[2]; - axis[0].axisId = JOYSTICK_AXIS_MOUSE_REL_X; - axis[0].deviceId = DEVICE_ID_MOUSE; - axis[0].value = mx; - axis[1].axisId = JOYSTICK_AXIS_MOUSE_REL_Y; - axis[1].deviceId = DEVICE_ID_MOUSE; - axis[1].value = my; + AxisInput axisX{}, axisY{}; + axisX.axisId = JOYSTICK_AXIS_MOUSE_REL_X; + axisX.deviceId = DEVICE_ID_MOUSE; + axisX.value = mx; + axisY.axisId = JOYSTICK_AXIS_MOUSE_REL_Y; + axisY.deviceId = DEVICE_ID_MOUSE; + axisY.value = my; if (GetUIState() == UISTATE_INGAME || g_Config.bMapMouse) { - NativeAxis(axis, 2); + NativeAxis(axisX); + NativeAxis(axisY); } } diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 8d65b3fe2..3e8201592 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -16,6 +16,8 @@ #include "Core/KeyMap.h" #include "Core/HLE/sceCtrl.h" +static double newVibrationTime = 0.0; + // Utilities to dynamically load XInput. Adapted from SDL. #if !PPSSPP_PLATFORM(UWP) @@ -124,7 +126,7 @@ static void UnloadXInputDLL() {} // Permanent map. Actual mapping happens elsewhere. -static const struct { int from; InputKeyCode to; } xinput_ctrl_map[] = { +static const struct {int from, to;} xinput_ctrl_map[] = { {XINPUT_GAMEPAD_A, NKCODE_BUTTON_A}, {XINPUT_GAMEPAD_B, NKCODE_BUTTON_B}, {XINPUT_GAMEPAD_X, NKCODE_BUTTON_X}, @@ -142,6 +144,8 @@ static const struct { int from; InputKeyCode to; } xinput_ctrl_map[] = { {XINPUT_GUIDE_BUTTON, NKCODE_HOME}, }; +static const unsigned int xinput_ctrl_map_size = sizeof(xinput_ctrl_map) / sizeof(xinput_ctrl_map[0]); + XinputDevice::XinputDevice() { if (LoadXInputDLL() != 0) { WARN_LOG(SCECTRL, "Failed to load XInput! DLL missing"); @@ -156,6 +160,19 @@ XinputDevice::~XinputDevice() { UnloadXInputDLL(); } +struct Stick { + Stick (float x_, float y_, float scale) : x(x_ * scale), y(y_ * scale) {} + float x; + float y; +}; + +bool NormalizedDeadzoneDiffers(u8 x1, u8 x2, const u8 thresh) { + if (x1 > thresh || x2 > thresh) { + return x1 != x2; + } + return false; +} + int XinputDevice::UpdateState() { #if !PPSSPP_PLATFORM(UWP) if (!s_pXInputDLL) @@ -164,8 +181,10 @@ int XinputDevice::UpdateState() { bool anySuccess = false; for (int i = 0; i < XUSER_MAX_COUNT; i++) { - XINPUT_STATE state{}; - XINPUT_VIBRATION vibration{}; + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + XINPUT_VIBRATION vibration; + ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION)); if (check_delay[i]-- > 0) continue; DWORD dwResult = PPSSPP_XInputGetState(i, &state); @@ -183,8 +202,9 @@ int XinputDevice::UpdateState() { } void XinputDevice::UpdatePad(int pad, const XINPUT_STATE &state, XINPUT_VIBRATION &vibration) { - if (!notified_[pad]) { - notified_[pad] = true; + static bool notified[XUSER_MAX_COUNT]{}; + if (!notified[pad]) { + notified[pad] = true; #if !PPSSPP_PLATFORM(UWP) XINPUT_CAPABILITIES_EX caps{}; if (PPSSPP_XInputGetCapabilitiesEx != nullptr && PPSSPP_XInputGetCapabilitiesEx(1, pad, 0, &caps) == ERROR_SUCCESS) { @@ -199,29 +219,25 @@ void XinputDevice::UpdatePad(int pad, const XINPUT_STATE &state, XINPUT_VIBRATIO ApplyButtons(pad, state); ApplyVibration(pad, vibration); - AxisInput axis[6]; - int axisCount = 0; - for (int i = 0; i < ARRAY_SIZE(axis); i++) { - axis[i].deviceId = (InputDeviceID)(DEVICE_ID_XINPUT_0 + pad); - } - auto sendAxis = [&](InputAxis axisId, float value, int axisIndex) { - if (value != prevAxisValue_[pad][axisIndex]) { - prevAxisValue_[pad][axisIndex] = value; - axis[axisCount].axisId = axisId; - axis[axisCount].value = value; - axisCount++; - } + AxisInput axis; + axis.deviceId = DEVICE_ID_XINPUT_0 + pad; + auto sendAxis = [&](AndroidJoystickAxis axisId, float value) { + axis.axisId = axisId; + axis.value = value; + NativeAxis(axis); }; - sendAxis(JOYSTICK_AXIS_X, (float)state.Gamepad.sThumbLX / 32767.0f, 0); - sendAxis(JOYSTICK_AXIS_Y, (float)state.Gamepad.sThumbLY / 32767.0f, 1); - sendAxis(JOYSTICK_AXIS_Z, (float)state.Gamepad.sThumbRX / 32767.0f, 2); - sendAxis(JOYSTICK_AXIS_RZ, (float)state.Gamepad.sThumbRY / 32767.0f, 3); - sendAxis(JOYSTICK_AXIS_LTRIGGER, (float)state.Gamepad.bLeftTrigger / 255.0f, 4); - sendAxis(JOYSTICK_AXIS_RTRIGGER, (float)state.Gamepad.bRightTrigger / 255.0f, 5); + sendAxis(JOYSTICK_AXIS_X, (float)state.Gamepad.sThumbLX / 32767.0f); + sendAxis(JOYSTICK_AXIS_Y, (float)state.Gamepad.sThumbLY / 32767.0f); + sendAxis(JOYSTICK_AXIS_Z, (float)state.Gamepad.sThumbRX / 32767.0f); + sendAxis(JOYSTICK_AXIS_RZ, (float)state.Gamepad.sThumbRY / 32767.0f); - if (axisCount) { - NativeAxis(axis, axisCount); + if (NormalizedDeadzoneDiffers(prevState[pad].Gamepad.bLeftTrigger, state.Gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) { + sendAxis(JOYSTICK_AXIS_LTRIGGER, (float)state.Gamepad.bLeftTrigger / 255.0f); + } + + if (NormalizedDeadzoneDiffers(prevState[pad].Gamepad.bRightTrigger, state.Gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) { + sendAxis(JOYSTICK_AXIS_RTRIGGER, (float)state.Gamepad.bRightTrigger / 255.0f); } prevState[pad] = state; @@ -229,13 +245,13 @@ void XinputDevice::UpdatePad(int pad, const XINPUT_STATE &state, XINPUT_VIBRATIO } void XinputDevice::ApplyButtons(int pad, const XINPUT_STATE &state) { - const u32 buttons = state.Gamepad.wButtons; + u32 buttons = state.Gamepad.wButtons; - const u32 downMask = buttons & (~prevButtons_[pad]); - const u32 upMask = (~buttons) & prevButtons_[pad]; - prevButtons_[pad] = buttons; + u32 downMask = buttons & (~prevButtons[pad]); + u32 upMask = (~buttons) & prevButtons[pad]; + prevButtons[pad] = buttons; - for (int i = 0; i < ARRAY_SIZE(xinput_ctrl_map); i++) { + for (int i = 0; i < xinput_ctrl_map_size; i++) { if (downMask & xinput_ctrl_map[i].from) { KeyInput key; key.deviceId = DEVICE_ID_XINPUT_0 + pad; @@ -256,11 +272,11 @@ void XinputDevice::ApplyButtons(int pad, const XINPUT_STATE &state) { void XinputDevice::ApplyVibration(int pad, XINPUT_VIBRATION &vibration) { if (PSP_IsInited()) { - newVibrationTime_ = time_now_d(); + newVibrationTime = time_now_d(); // We have to run PPSSPP_XInputSetState at time intervals // since it bugs otherwise with very high fast-forward speeds // and freezes at constant vibration or no vibration at all. - if (newVibrationTime_ - prevVibrationTime >= 1.0 / 64.0) { + if (newVibrationTime - prevVibrationTime >= 1.0 / 64.0) { if (GetUIState() == UISTATE_INGAME) { vibration.wLeftMotorSpeed = sceCtrlGetLeftVibration(); // use any value between 0-65535 here vibration.wRightMotorSpeed = sceCtrlGetRightVibration(); // use any value between 0-65535 here @@ -273,7 +289,7 @@ void XinputDevice::ApplyVibration(int pad, XINPUT_VIBRATION &vibration) { PPSSPP_XInputSetState(pad, &vibration); prevVibration[pad] = vibration; } - prevVibrationTime = newVibrationTime_; + prevVibrationTime = newVibrationTime; } } else { DWORD dwResult = PPSSPP_XInputSetState(pad, &vibration); @@ -282,3 +298,4 @@ void XinputDevice::ApplyVibration(int pad, XINPUT_VIBRATION &vibration) { } } } + diff --git a/Windows/XinputDevice.h b/Windows/XinputDevice.h index af8f43c4f..93347a672 100644 --- a/Windows/XinputDevice.h +++ b/Windows/XinputDevice.h @@ -18,8 +18,5 @@ private: XINPUT_STATE prevState[4]{}; XINPUT_VIBRATION prevVibration[4]{}; double prevVibrationTime = 0.0; - float prevAxisValue_[4][6]{}; - bool notified_[XUSER_MAX_COUNT]{}; - u32 prevButtons_[4]{}; - double newVibrationTime_ = 0.0; + u32 prevButtons[4]{}; }; diff --git a/Windows/main.cpp b/Windows/main.cpp index 762d5a747..c1e9b1177 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -26,10 +26,10 @@ #include "Common/GPU/Vulkan/VulkanLoader.h" #include "ppsspp_config.h" -#include -#include #include +#include #include +#include #include "Common/System/Display.h" #include "Common/System/NativeApp.h" @@ -43,7 +43,6 @@ #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/Net/Resolve.h" -#include "Common/TimeUtil.h" #include "W32Util/DarkMode.h" #include "W32Util/ShellUtil.h" @@ -116,11 +115,20 @@ WindowsInputManager g_inputManager; int g_lastNumInstances = 0; -static double g_lastActivity = 0.0; -static double g_lastKeepAwake = 0.0; -// Time until we stop considering the core active without user input. -// Should this be configurable? 2 hours currently. -static const double ACTIVITY_IDLE_TIMEOUT = 2.0 * 3600.0; +void System_ShowFileInFolder(const char *path) { + // SHParseDisplayName can't handle relative paths, so normalize first. + std::string resolved = ReplaceAll(File::ResolvePath(path), "/", "\\"); + + SFGAOF flags{}; + PIDLIST_ABSOLUTE pidl = nullptr; + HRESULT hr = SHParseDisplayName(ConvertUTF8ToWString(resolved).c_str(), nullptr, &pidl, 0, &flags); + + if (pidl) { + if (SUCCEEDED(hr)) + SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0); + CoTaskMemFree(pidl); + } +} void System_LaunchUrl(LaunchUrlType urlType, const char *url) { ShellExecute(NULL, L"open", ConvertUTF8ToWString(url).c_str(), NULL, NULL, SW_SHOWNORMAL); @@ -226,10 +234,6 @@ std::string System_GetProperty(SystemProperty prop) { gpuDriverVersion = GetVideoCardDriverVersion(); } return gpuDriverVersion; - case SYSPROP_BUILD_VERSION: - return PPSSPP_GIT_VERSION; - case SYSPROP_USER_DOCUMENTS_DIR: - return Path(W32Util::UserDocumentsPath()).ToString(); // this'll reverse the slashes. default: return ""; } @@ -283,28 +287,20 @@ static int ScreenDPI() { #endif static int ScreenRefreshRateHz() { - static int rate = 0; - static double lastCheck = 0.0; - double now = time_now_d(); - if (!rate || lastCheck < now - 10.0) { - lastCheck = now; - DEVMODE lpDevMode{}; - lpDevMode.dmSize = sizeof(DEVMODE); - lpDevMode.dmDriverExtra = 0; + DEVMODE lpDevMode; + memset(&lpDevMode, 0, sizeof(DEVMODE)); + lpDevMode.dmSize = sizeof(DEVMODE); + lpDevMode.dmDriverExtra = 0; - // TODO: Use QueryDisplayConfig instead (Win7+) so we can get fractional refresh rates correctly. - - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &lpDevMode) == 0) { - rate = 60; // default value + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &lpDevMode) == 0) { + return 60; // default value + } else { + if (lpDevMode.dmFields & DM_DISPLAYFREQUENCY) { + return lpDevMode.dmDisplayFrequency > 60 ? lpDevMode.dmDisplayFrequency : 60; } else { - if (lpDevMode.dmFields & DM_DISPLAYFREQUENCY) { - rate = lpDevMode.dmDisplayFrequency > 60 ? lpDevMode.dmDisplayFrequency : 60; - } else { - rate = 60; - } + return 60; } } - return rate; } int System_GetPropertyInt(SystemProperty prop) { @@ -357,16 +353,11 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_HAS_FILE_BROWSER: case SYSPROP_HAS_FOLDER_BROWSER: case SYSPROP_HAS_OPEN_DIRECTORY: - case SYSPROP_HAS_TEXT_INPUT_DIALOG: - case SYSPROP_CAN_CREATE_SHORTCUT: - case SYSPROP_CAN_SHOW_FILE: return true; case SYSPROP_HAS_IMAGE_BROWSER: return true; case SYSPROP_HAS_BACK_BUTTON: return true; - case SYSPROP_HAS_LOGIN_DIALOG: - return true; case SYSPROP_APP_GOLD: #ifdef GOLD return true; @@ -379,10 +370,6 @@ bool System_GetPropertyBool(SystemProperty prop) { return true; case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor - case SYSPROP_SUPPORTS_HTTPS: - return !g_Config.bDisableHTTPS; - case SYSPROP_DEBUGGER_PRESENT: - return IsDebuggerPresent(); default: return false; } @@ -450,29 +437,6 @@ void System_Notify(SystemNotification notification) { case SystemNotification::TOGGLE_DEBUG_CONSOLE: MainWindow::ToggleDebugConsoleVisibility(); break; - - case SystemNotification::ACTIVITY: - g_lastActivity = time_now_d(); - break; - - case SystemNotification::KEEP_SCREEN_AWAKE: - { - // Keep the system awake for longer than normal for cutscenes and the like. - const double now = time_now_d(); - if (now < g_lastActivity + ACTIVITY_IDLE_TIMEOUT) { - // Only resetting it ever prime number seconds in case the call is expensive. - // Using a prime number to ensure there's no interaction with other periodic events. - if (now - g_lastKeepAwake > 89.0 || now < g_lastKeepAwake) { - // Note that this needs to be called periodically. - // It's also possible to set ES_CONTINUOUS but let's not, for simplicity. -#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) - SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); -#endif - g_lastKeepAwake = now; - } - } - break; - } } } @@ -496,7 +460,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string restartArgs = param1; if (!restartArgs.empty()) AddDebugRestartArgs(); - if (System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) { + if (IsDebuggerPresent()) { PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); } else { g_Config.bRestartRequired = true; @@ -534,17 +498,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } }).detach(); return true; - case SystemRequestType::ASK_USERNAME_PASSWORD: - std::thread([=] { - std::string username; - std::string password; - if (UserPasswordBox_GetStrings(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), &username, &password)) { - g_requestManager.PostSystemSuccess(requestId, (username + '\n' + password).c_str()); - } else { - g_requestManager.PostSystemFailure(requestId); - } - }).detach(); - return true; case SystemRequestType::BROWSE_FOR_IMAGE: std::thread([=] { std::string out; @@ -562,7 +515,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string std::wstring filter; switch (type) { case BrowseFileType::BOOTABLE: - filter = MakeFilter(L"All supported file types (*.iso *.cso *.chd *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.chd;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.chd *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.chd;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"); + filter = MakeFilter(L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"); break; case BrowseFileType::INI: filter = MakeFilter(L"Ini files (*.ini)|*.ini|All files (*.*)|*.*||"); @@ -570,9 +523,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case BrowseFileType::DB: filter = MakeFilter(L"Cheat db files (*.db)|*.db|All files (*.*)|*.*||"); break; - case BrowseFileType::SOUND_EFFECT: - filter = MakeFilter(L"WAVE files (*.wav)|*.wav|All files (*.*)|*.*||"); - break; case BrowseFileType::ANY: filter = MakeFilter(L"All files (*.*)|*.*||"); break; @@ -602,11 +552,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string }).detach(); return true; } - - case SystemRequestType::SHOW_FILE_IN_FOLDER: - W32Util::ShowFileInFolder(param1); - return true; - case SystemRequestType::TOGGLE_FULLSCREEN_STATE: { bool flag = !MainWindow::IsFullscreen(); @@ -628,6 +573,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return true; } case SystemRequestType::CREATE_GAME_SHORTCUT: + // This is not actually working, but ported it to the request framework anyway. return W32Util::CreateDesktopShortcut(param1, param2); default: return false; @@ -696,13 +642,28 @@ static bool DetectVulkanInExternalProcess() { const wchar_t *cmdline = L"--vulkan-available-check"; - DWORD exitCode = 0; - if (W32Util::ExecuteAndGetReturnCode(moduleFilename.c_str(), cmdline, workingDirectory.c_str(), &exitCode)) { - return exitCode == EXIT_CODE_VULKAN_WORKS; - } else { - ERROR_LOG(G3D, "Failed to detect Vulkan in external process somehow"); + SHELLEXECUTEINFO info{ sizeof(SHELLEXECUTEINFO) }; + info.fMask = SEE_MASK_NOCLOSEPROCESS; + info.lpFile = moduleFilename.c_str(); + info.lpParameters = cmdline; + info.lpDirectory = workingDirectory.c_str(); + info.nShow = SW_HIDE; + if (ShellExecuteEx(&info) != TRUE) { return false; } + if (info.hProcess == nullptr) { + return false; + } + + DWORD result = WaitForSingleObject(info.hProcess, 10000); + DWORD exitCode = 0; + if (result == WAIT_FAILED || GetExitCodeProcess(info.hProcess, &exitCode) == 0) { + CloseHandle(info.hProcess); + return false; + } + CloseHandle(info.hProcess); + + return exitCode == EXIT_CODE_VULKAN_WORKS; } #endif @@ -724,65 +685,6 @@ std::vector GetWideCmdLine() { return wideArgs; } -static void InitMemstickDirectory() { - if (!g_Config.memStickDirectory.empty() && !g_Config.flash0Directory.empty()) - return; - - const Path &exePath = File::GetExeDirectory(); - // Mount a filesystem - g_Config.flash0Directory = exePath / "assets/flash0"; - - // Caller sets this to the Documents folder. - const Path rootMyDocsPath = g_Config.internalDataDirectory; - const Path myDocsPath = rootMyDocsPath / "PPSSPP"; - const Path installedFile = exePath / "installed.txt"; - const bool installed = File::Exists(installedFile); - - // If installed.txt exists(and we can determine the Documents directory) - if (installed && !rootMyDocsPath.empty()) { - FILE *fp = File::OpenCFile(installedFile, "rt"); - if (fp) { - char temp[2048]; - char *tempStr = fgets(temp, sizeof(temp), fp); - // Skip UTF-8 encoding bytes if there are any. There are 3 of them. - if (tempStr && strncmp(tempStr, "\xEF\xBB\xBF", 3) == 0) { - tempStr += 3; - } - std::string tempString = tempStr ? tempStr : ""; - if (!tempString.empty() && tempString.back() == '\n') - tempString.resize(tempString.size() - 1); - - g_Config.memStickDirectory = Path(tempString); - fclose(fp); - } - - // Check if the file is empty first, before appending the slash. - if (g_Config.memStickDirectory.empty()) - g_Config.memStickDirectory = myDocsPath; - } else { - g_Config.memStickDirectory = exePath / "memstick"; - } - - // Create the memstickpath before trying to write to it, and fall back on Documents yet again - // if we can't make it. - if (!File::Exists(g_Config.memStickDirectory)) { - if (!File::CreateDir(g_Config.memStickDirectory)) - g_Config.memStickDirectory = myDocsPath; - INFO_LOG(COMMON, "Memstick directory not present, creating at '%s'", g_Config.memStickDirectory.c_str()); - } - - Path testFile = g_Config.memStickDirectory / "_writable_test.$$$"; - - // If any directory is read-only, fall back to the Documents directory. - // We're screwed anyway if we can't write to Documents, or can't detect it. - if (!File::CreateEmptyFile(testFile)) - g_Config.memStickDirectory = myDocsPath; - - // Clean up our mess. - if (File::Exists(testFile)) - File::Delete(testFile); -} - static void WinMainInit() { CoInitializeEx(NULL, COINIT_MULTITHREADED); net::Init(); // This needs to happen before we load the config. So on Windows we also run it in Main. It's fine to call multiple times. @@ -815,36 +717,11 @@ static void WinMainCleanup() { CoUninitialize(); if (g_Config.bRestartRequired) { - // TODO: ExitAndRestart prevents the Config::~Config destructor from running, - // which normally would have done this instance counter update. - // ExitAndRestart calls ExitProcess which really bad, we should do something better that - // allows us to fall out of main() properly. - if (g_Config.bUpdatedInstanceCounter) { - ShutdownInstanceCounter(); - } W32Util::ExitAndRestart(!restartArgs.empty(), restartArgs); } } int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { - std::vector wideArgs = GetWideCmdLine(); - - // Check for the Vulkan workaround before any serious init. - for (size_t i = 1; i < wideArgs.size(); ++i) { - if (wideArgs[i][0] == L'-') { - // This should only be called by DetectVulkanInExternalProcess(). - if (wideArgs[i] == L"--vulkan-available-check") { - // Just call it, this way it will crash here if it doesn't work. - // (this is an external process.) - bool result = VulkanMayBeAvailable(); - - LogManager::Shutdown(); - WinMainCleanup(); - return result ? EXIT_CODE_VULKAN_WORKS : EXIT_FAILURE; - } - } - } - SetCurrentThreadName("Main"); WinMainInit(); @@ -868,6 +745,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin std::string controlsConfigFilename = ""; const std::wstring controlsOption = L"--controlconfig="; + std::vector wideArgs = GetWideCmdLine(); for (size_t i = 1; i < wideArgs.size(); ++i) { if (wideArgs[i][0] == L'\0') @@ -890,9 +768,23 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin // On Win32 it makes more sense to initialize the system directories here // because the next place it was called was in the EmuThread, and it's too late by then. g_Config.internalDataDirectory = Path(W32Util::UserDocumentsPath()); - InitMemstickDirectory(); - CreateSysDirectories(); + InitSysDirectories(); + // Check for the Vulkan workaround before any serious init. + for (size_t i = 1; i < wideArgs.size(); ++i) { + if (wideArgs[i][0] == L'-') { + // This should only be called by DetectVulkanInExternalProcess(). + if (wideArgs[i] == L"--vulkan-available-check") { + // Just call it, this way it will crash here if it doesn't work. + // (this is an external process.) + bool result = VulkanMayBeAvailable(); + + LogManager::Shutdown(); + WinMainCleanup(); + return result ? EXIT_CODE_VULKAN_WORKS : EXIT_FAILURE; + } + } + } // Load config up here, because those changes below would be overwritten // if it's not loaded here first. @@ -973,7 +865,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin LogManager::GetInstance()->GetConsoleListener()->Init(showLog, 150, 120, "PPSSPP Debug Console"); if (debugLogLevel) { - LogManager::GetInstance()->SetAllLogLevels(LogLevel::LDEBUG); + LogManager::GetInstance()->SetAllLogLevels(LogTypes::LDEBUG); } // This still seems to improve performance noticeably. diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index f3c48d74c..fcfa2278e 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -92,7 +92,7 @@ BEGIN VK_F10, ID_DEBUG_STEPOVER, VIRTKEY, NOINVERT VK_F11, ID_DEBUG_STEPINTO, VIRTKEY, NOINVERT VK_F11, ID_DEBUG_STEPOUT, VIRTKEY, SHIFT, NOINVERT - "H", ID_DEBUG_HIDEBOTTOMTABS, VIRTKEY, CONTROL, NOINVERT + "X", ID_DEBUG_HIDEBOTTOMTABS, VIRTKEY, CONTROL, NOINVERT "Y", ID_DEBUG_TOGGLEBOTTOMTABTITLES, VIRTKEY, CONTROL, NOINVERT END @@ -322,28 +322,15 @@ BEGIN CONTROL "",IDC_MEMVIEW_STATUS,"msctls_statusbar32",WS_CHILD | WS_VISIBLE,0,286,700,24 END -IDD_INPUTBOX DIALOGEX 0, 0, 223, 55 +IDD_INPUTBOX DIALOGEX 0, 0, 163, 55 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Input value" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Value",IDC_VALUENAME,7,7,89,8 - EDITTEXT IDC_INPUTBOX,7,16,209,13,ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,111,34,50,14 - PUSHBUTTON "Cancel",IDCANCEL,166,34,50,14 -END - -IDD_USERPASSWORDBOX DIALOGEX 0, 0, 223, 95 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Login" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN -LTEXT "Username", IDC_VALUENAME, 7, 7, 89, 8 -EDITTEXT IDC_INPUTBOX, 7, 17, 209, 13, ES_AUTOHSCROLL -LTEXT "Password", IDC_PASSWORDNAME, 7, 34, 89, 8 -EDITTEXT IDC_PASSWORDBOX, 7, 46, 209, 13, ES_AUTOHSCROLL | ES_PASSWORD -DEFPUSHBUTTON "OK", IDOK, 111, 74, 50, 14 -PUSHBUTTON "Cancel", IDCANCEL, 166, 74, 50, 14 + EDITTEXT IDC_INPUTBOX,7,16,149,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,51,34,50,14 + PUSHBUTTON "Cancel",IDCANCEL,106,34,50,14 END IDD_VFPU DIALOGEX 0, 0, 250, 420 @@ -380,21 +367,6 @@ BEGIN PUSHBUTTON "Cancel",IDC_BREAKPOINT_CANCEL,186,98,42,14 END -IDD_EDITSYMBOLS DIALOGEX 0, 0, 236, 72 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Edit symbols" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - LTEXT "Address",IDC_STATIC,7,8,27,8 - EDITTEXT IDC_EDITSYMBOLS_ADDRESS,41,7,69,14,ES_AUTOHSCROLL - CONTROL "Scan in range",IDC_EDITSYMBOLS_SCAN,"Button",BS_AUTORADIOBUTTON,144,8,70,10 - CONTROL "Remove in range",IDC_EDITSYMBOLS_REMOVE,"Button",BS_AUTORADIOBUTTON,144,27,70,10 - LTEXT "Size",IDC_STATIC,7,27,14,8 - EDITTEXT IDC_EDITSYMBOLS_SIZE,41,25,69,14,ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDC_EDITSYMBOLS_OK,144,51,41,14 - PUSHBUTTON "Cancel",IDC_EDITSYMBOLS_CANCEL,186,51,42,14 -END - IDD_DUMPMEMORY DIALOGEX 0, 0, 230, 100 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Dump memory" @@ -685,6 +657,7 @@ BEGIN MENUITEM "Deposterize", ID_TEXTURESCALING_DEPOSTERIZE END MENUITEM "Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM + MENUITEM "Vertex Cache", ID_OPTIONS_VERTEXCACHE MENUITEM "", 0, MFT_SEPARATOR MENUITEM "Enable Sound", ID_EMULATION_SOUND MENUITEM "", 0, MFT_SEPARATOR @@ -769,7 +742,6 @@ BEGIN MENUITEM "Remove Function", ID_DISASM_REMOVEFUNCTION MENUITEM "Add Function Here", ID_DISASM_ADDFUNCTION MENUITEM "NOP instruction(s)", ID_DISASM_NOPINSTRUCTION - MENUITEM "Edit symbols...", ID_DISASM_EDITSYMBOLS END POPUP "reglist" BEGIN diff --git a/Windows/resource.h b/Windows/resource.h index efec1f414..1e42ad07e 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -36,7 +36,6 @@ #define ID_DEBUG_RESETSYMBOLTABLE 212 #define IDI_STOP 223 #define IDD_INPUTBOX 226 -#define IDD_USERPASSWORDBOX 227 #define IDD_VFPU 231 #define IDD_BREAKPOINT 233 #define ID_FILE_LOAD_DIR 234 @@ -61,7 +60,6 @@ #define IDD_GEDBG_TAB_MATRICES 255 #define IDD_GEDBG_STEPCOUNT 256 #define IDD_CPUWATCH 257 -#define IDD_EDITSYMBOLS 258 #define IDC_STOPGO 1001 #define IDC_ADDRESS 1002 @@ -77,12 +75,10 @@ #define IDC_INPUTBOX 1098 #define IDC_MODENORMAL 1099 #define IDC_MODESYMBOLS 1100 -#define IDC_PASSWORDBOX 1101 #define IDC_SEARCH_RESULTS 1102 #define IDC_REGIONS 1142 #define IDC_REGLIST 1146 #define IDC_VALUENAME 1148 -#define IDC_PASSWORDNAME 1149 #define IDC_SHOWVFPU 1161 #define IDC_BREAKPOINTLIST 1164 #define IDC_DEBUGMEMVIEW 1165 @@ -123,12 +119,6 @@ #define IDC_SHOWOFFSETS 1200 #define IDC_GEDBG_PRIMCOUNTER 1201 #define IDC_BUTTON_SEARCH 1204 -#define IDC_EDITSYMBOLS_SCAN 1205 -#define IDC_EDITSYMBOLS_REMOVE 1206 -#define IDC_EDITSYMBOLS_ADDRESS 1207 -#define IDC_EDITSYMBOLS_SIZE 1208 -#define IDC_EDITSYMBOLS_OK 1209 -#define IDC_EDITSYMBOLS_CANCEL 1210 #define ID_FILE_EXIT 40000 #define ID_DEBUG_SAVEMAPFILE 40001 @@ -169,6 +159,7 @@ #define ID_OPTIONS_CONTROLS 40038 #define ID_DEBUG_BREAKONLOAD 40039 #define ID_DEBUG_DUMPNEXTFRAME 40040 +#define ID_OPTIONS_VERTEXCACHE 40041 #define ID_OPTIONS_FRAMESKIP 40044 #define IDC_MEMCHECK 40045 #define ID_FILE_MEMSTICK 40046 @@ -352,7 +343,6 @@ #define IDC_DISASM_FMT_INT 40233 #define IDC_DISASM_FMT_FLOAT 40234 #define IDC_DISASM_FMT_STR 40235 -#define ID_DISASM_EDITSYMBOLS 40236 // Dummy option to let the buffered rendering hotkey cycle through all the options. diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 38853da07..8d3c19009 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -79,9 +79,6 @@ - - - @@ -94,9 +91,6 @@ - - - diff --git a/android/VRManifest.xml b/android/VRManifest.xml index dc1a3aa1e..4dfda7647 100644 --- a/android/VRManifest.xml +++ b/android/VRManifest.xml @@ -3,7 +3,6 @@ - = 14000000) { @@ -62,8 +63,8 @@ android { new File("versionname.txt").write(androidGitVersion.name()) new File("versioncode.txt").write(androidGitVersion.code().toString()) - minSdk 9 - targetSdk 33 + minSdkVersion 9 + targetSdkVersion 33 if (project.hasProperty("ANDROID_VERSION_CODE") && project.hasProperty("ANDROID_VERSION_NAME")) { versionCode ANDROID_VERSION_CODE versionName ANDROID_VERSION_NAME @@ -132,7 +133,7 @@ android { } } ndk { - abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64' + abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } gold { @@ -151,7 +152,7 @@ android { } } ndk { - abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64' + abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } vr { diff --git a/android/gold/res/mipmap-hdpi/ic_launcher.png b/android/gold/res/mipmap-hdpi/ic_launcher.png index 662362974..3b6eb4487 100644 Binary files a/android/gold/res/mipmap-hdpi/ic_launcher.png and b/android/gold/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/gold/res/mipmap-hdpi/ic_launcher_round.png b/android/gold/res/mipmap-hdpi/ic_launcher_round.png index 662362974..0bab70e86 100644 Binary files a/android/gold/res/mipmap-hdpi/ic_launcher_round.png and b/android/gold/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/gold/res/mipmap-mdpi/ic_launcher.png b/android/gold/res/mipmap-mdpi/ic_launcher.png index d2df261ba..defe49449 100644 Binary files a/android/gold/res/mipmap-mdpi/ic_launcher.png and b/android/gold/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/gold/res/mipmap-mdpi/ic_launcher_round.png b/android/gold/res/mipmap-mdpi/ic_launcher_round.png index d2df261ba..59ac6fd56 100644 Binary files a/android/gold/res/mipmap-mdpi/ic_launcher_round.png and b/android/gold/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/gold/res/mipmap-xhdpi/ic_launcher.png b/android/gold/res/mipmap-xhdpi/ic_launcher.png index c8e6e7d3d..1ac24a174 100644 Binary files a/android/gold/res/mipmap-xhdpi/ic_launcher.png and b/android/gold/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/gold/res/mipmap-xhdpi/ic_launcher_round.png b/android/gold/res/mipmap-xhdpi/ic_launcher_round.png index c8e6e7d3d..545f37de1 100644 Binary files a/android/gold/res/mipmap-xhdpi/ic_launcher_round.png and b/android/gold/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/gold/res/mipmap-xxhdpi/ic_launcher.png b/android/gold/res/mipmap-xxhdpi/ic_launcher.png index f1d666718..b9595acf2 100644 Binary files a/android/gold/res/mipmap-xxhdpi/ic_launcher.png and b/android/gold/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/gold/res/mipmap-xxhdpi/ic_launcher_round.png b/android/gold/res/mipmap-xxhdpi/ic_launcher_round.png index f1d666718..0b0f5e648 100644 Binary files a/android/gold/res/mipmap-xxhdpi/ic_launcher_round.png and b/android/gold/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/gold/res/mipmap-xxxhdpi/ic_launcher.png b/android/gold/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..61c0d3398 Binary files /dev/null and b/android/gold/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/gold/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/gold/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..c11c07b09 Binary files /dev/null and b/android/gold/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/gold/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/gold/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..45b824286 Binary files /dev/null and b/android/gold/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 70fda2601..07aa70657 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -4,45 +4,9 @@ SRC := ../.. include $(CLEAR_VARS) include $(LOCAL_PATH)/Locals.mk -LOCAL_CFLAGS += -D_7ZIP_ST -D__SWITCH__ - -LZMA_FILES := \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Alloc.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bcj2.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bcj2Enc.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bra.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Bra86.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/CpuArch.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Delta.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzFind.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzFindOpt.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzmaDec.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzmaEnc.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Lzma86Dec.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Lzma86Enc.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/LzmaLib.c \ - $(SRC)/ext/libchdr/deps/lzma-22.01/src/Sort.c - -CHDR_FILES := \ - ${LZMA_FILES} \ - $(SRC)/ext/libchdr/src/libchdr_bitstream.c \ - $(SRC)/ext/libchdr/src/libchdr_cdrom.c \ - $(SRC)/ext/libchdr/src/libchdr_chd.c \ - $(SRC)/ext/libchdr/src/libchdr_flac.c \ - $(SRC)/ext/libchdr/src/libchdr_huffman.c - -LOCAL_MODULE := libchdr -LOCAL_SRC_FILES := $(CHDR_FILES) -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) -include $(LOCAL_PATH)/Locals.mk - LOCAL_C_INCLUDES += \ - $(LOCAL_PATH)/../../ext/cpu_features/include \ - $(LOCAL_PATH)/../../ext/rcheevos/include - -LOCAL_CFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DHAVE_DLFCN_H -DRC_DISABLE_LUA -D_7ZIP_ST + $(LOCAL_PATH)/../../ext/cpu_features/include +LOCAL_CFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DHAVE_DLFCN_H # http://software.intel.com/en-us/articles/getting-started-on-optimizing-ndk-project-for-multiple-cpu-architectures @@ -79,11 +43,15 @@ NATIVE_FILES :=\ $(SRC)/Common/GPU/OpenGL/GLSLProgram.cpp \ $(SRC)/Common/GPU/OpenGL/GLFeatures.cpp \ $(SRC)/Common/GPU/OpenGL/GLFrameData.cpp \ - $(SRC)/Common/GPU/OpenGL/GLMemory.cpp \ $(SRC)/Common/GPU/OpenGL/GLRenderManager.cpp \ $(SRC)/Common/GPU/OpenGL/GLQueueRunner.cpp \ $(SRC)/Common/GPU/OpenGL/DataFormatGL.cpp +EGL_FILES := \ + $(SRC)/Common/GL/GLInterface/EGL.cpp \ + $(SRC)/Common/GL/GLInterface/EGLAndroid.cpp \ + $(SRC)/Common/GL/GLInterface/GLInterface.cpp + VULKAN_FILES := \ $(SRC)/Common/GPU/Vulkan/thin3d_vulkan.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanQueueRunner.cpp \ @@ -95,7 +63,6 @@ VULKAN_FILES := \ $(SRC)/Common/GPU/Vulkan/VulkanImage.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanFramebuffer.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanMemory.cpp \ - $(SRC)/Common/GPU/Vulkan/VulkanDescSet.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanProfiler.cpp \ $(SRC)/Common/GPU/Vulkan/VulkanBarrier.cpp @@ -110,36 +77,6 @@ SPIRV_CROSS_FILES := \ $(SRC)/ext/SPIRV-Cross/spirv_parser.cpp \ $(SRC)/ext/SPIRV-Cross/spirv_cross_parsed_ir.cpp -NAETT_FILES := \ - ${SRC}/ext/naett/naett.c - -RCHEEVOS_FILES := \ - ${SRC}/ext/rcheevos/src/rapi/rc_api_common.c \ - ${SRC}/ext/rcheevos/src/rapi/rc_api_editor.c \ - ${SRC}/ext/rcheevos/src/rapi/rc_api_info.c \ - ${SRC}/ext/rcheevos/src/rapi/rc_api_runtime.c \ - ${SRC}/ext/rcheevos/src/rapi/rc_api_user.c \ - ${SRC}/ext/rcheevos/src/rcheevos/alloc.c \ - ${SRC}/ext/rcheevos/src/rcheevos/condition.c \ - ${SRC}/ext/rcheevos/src/rcheevos/condset.c \ - ${SRC}/ext/rcheevos/src/rcheevos/consoleinfo.c \ - ${SRC}/ext/rcheevos/src/rcheevos/format.c \ - ${SRC}/ext/rcheevos/src/rcheevos/lboard.c \ - ${SRC}/ext/rcheevos/src/rcheevos/memref.c \ - ${SRC}/ext/rcheevos/src/rcheevos/operand.c \ - ${SRC}/ext/rcheevos/src/rc_client.c \ - ${SRC}/ext/rcheevos/src/rc_util.c \ - ${SRC}/ext/rcheevos/src/rc_compat.c \ - ${SRC}/ext/rcheevos/src/rcheevos/rc_validate.c \ - ${SRC}/ext/rcheevos/src/rcheevos/richpresence.c \ - ${SRC}/ext/rcheevos/src/rcheevos/runtime.c \ - ${SRC}/ext/rcheevos/src/rcheevos/runtime_progress.c \ - ${SRC}/ext/rcheevos/src/rcheevos/trigger.c \ - ${SRC}/ext/rcheevos/src/rcheevos/value.c \ - ${SRC}/ext/rcheevos/src/rhash/cdreader.c \ - ${SRC}/ext/rcheevos/src/rhash/hash.c \ - ${SRC}/ext/rcheevos/src/rhash/md5.c - VR_FILES := \ $(SRC)/Common/VR/OpenXRLoader.cpp \ $(SRC)/Common/VR/PPSSPPVR.cpp \ @@ -206,12 +143,11 @@ EXT_FILES := \ EXEC_AND_LIB_FILES := \ $(ARCH_FILES) \ + $(EGL_FILES) \ $(VULKAN_FILES) \ $(VR_FILES) \ $(VMA_FILES) \ $(SPIRV_CROSS_FILES) \ - $(RCHEEVOS_FILES) \ - $(NAETT_FILES) \ $(EXT_FILES) \ $(NATIVE_FILES) \ $(SRC)/Common/Buffer.cpp \ @@ -252,7 +188,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/File/DirListing.cpp \ $(SRC)/Common/File/FileDescriptor.cpp \ $(SRC)/Common/GPU/thin3d.cpp \ - $(SRC)/Common/GPU/GPUBackendCommon.cpp \ $(SRC)/Common/GPU/Shader.cpp \ $(SRC)/Common/GPU/ShaderWriter.cpp \ $(SRC)/Common/GPU/ShaderTranslation.cpp \ @@ -272,8 +207,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Math/lin/matrix4x4.cpp.arm \ $(SRC)/Common/Net/HTTPClient.cpp \ $(SRC)/Common/Net/HTTPHeaders.cpp \ - $(SRC)/Common/Net/HTTPRequest.cpp \ - $(SRC)/Common/Net/HTTPNaettRequest.cpp \ $(SRC)/Common/Net/HTTPServer.cpp \ $(SRC)/Common/Net/NetBuffer.cpp \ $(SRC)/Common/Net/Resolve.cpp \ @@ -283,7 +216,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Profiler/Profiler.cpp \ $(SRC)/Common/System/Display.cpp \ $(SRC)/Common/System/Request.cpp \ - $(SRC)/Common/System/OSD.cpp \ $(SRC)/Common/Thread/ThreadUtil.cpp \ $(SRC)/Common/Thread/ThreadManager.cpp \ $(SRC)/Common/Thread/ParallelLoop.cpp \ @@ -294,7 +226,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/UI/Context.cpp \ $(SRC)/Common/UI/UIScreen.cpp \ $(SRC)/Common/UI/Tween.cpp \ - $(SRC)/Common/UI/IconCache.cpp \ $(SRC)/Common/UI/View.cpp \ $(SRC)/Common/UI/ViewGroup.cpp \ $(SRC)/Common/UI/ScrollView.cpp \ @@ -324,9 +255,25 @@ include $(BUILD_STATIC_LIBRARY) # Next up, Core, GPU, and other core parts shared by headless. include $(CLEAR_VARS) include $(LOCAL_PATH)/Locals.mk -LOCAL_WHOLE_STATIC_LIBRARIES += ppsspp_common libchdr +LOCAL_WHOLE_STATIC_LIBRARIES += ppsspp_common -ifeq ($(TARGET_ARCH_ABI),x86_64) +ifeq ($(TARGET_ARCH_ABI),x86) +ARCH_FILES := \ + $(SRC)/Core/MIPS/x86/CompALU.cpp \ + $(SRC)/Core/MIPS/x86/CompBranch.cpp \ + $(SRC)/Core/MIPS/x86/CompFPU.cpp \ + $(SRC)/Core/MIPS/x86/CompLoadStore.cpp \ + $(SRC)/Core/MIPS/x86/CompVFPU.cpp \ + $(SRC)/Core/MIPS/x86/CompReplace.cpp \ + $(SRC)/Core/MIPS/x86/Asm.cpp \ + $(SRC)/Core/MIPS/x86/Jit.cpp \ + $(SRC)/Core/MIPS/x86/JitSafeMem.cpp \ + $(SRC)/Core/MIPS/x86/RegCache.cpp \ + $(SRC)/Core/MIPS/x86/RegCacheFPU.cpp \ + $(SRC)/GPU/Common/VertexDecoderX86.cpp \ + $(SRC)/GPU/Software/DrawPixelX86.cpp \ + $(SRC)/GPU/Software/SamplerX86.cpp +else ifeq ($(TARGET_ARCH_ABI),x86_64) ARCH_FILES := \ $(SRC)/Core/MIPS/x86/CompALU.cpp \ $(SRC)/Core/MIPS/x86/CompBranch.cpp \ @@ -339,15 +286,6 @@ ARCH_FILES := \ $(SRC)/Core/MIPS/x86/JitSafeMem.cpp \ $(SRC)/Core/MIPS/x86/RegCache.cpp \ $(SRC)/Core/MIPS/x86/RegCacheFPU.cpp \ - $(SRC)/Core/MIPS/x86/X64IRAsm.cpp \ - $(SRC)/Core/MIPS/x86/X64IRCompALU.cpp \ - $(SRC)/Core/MIPS/x86/X64IRCompBranch.cpp \ - $(SRC)/Core/MIPS/x86/X64IRCompFPU.cpp \ - $(SRC)/Core/MIPS/x86/X64IRCompLoadStore.cpp \ - $(SRC)/Core/MIPS/x86/X64IRCompSystem.cpp \ - $(SRC)/Core/MIPS/x86/X64IRCompVec.cpp \ - $(SRC)/Core/MIPS/x86/X64IRJit.cpp \ - $(SRC)/Core/MIPS/x86/X64IRRegCache.cpp \ $(SRC)/GPU/Common/VertexDecoderX86.cpp \ $(SRC)/GPU/Software/DrawPixelX86.cpp \ $(SRC)/GPU/Software/SamplerX86.cpp @@ -379,21 +317,12 @@ ARCH_FILES := \ $(SRC)/Core/MIPS/ARM64/Arm64Jit.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64RegCache.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRAsm.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRCompALU.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRCompBranch.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRCompFPU.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRCompLoadStore.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRCompSystem.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRCompVec.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRJit.cpp \ - $(SRC)/Core/MIPS/ARM64/Arm64IRRegCache.cpp \ $(SRC)/Core/Util/DisArm64.cpp \ $(SRC)/GPU/Common/VertexDecoderArm64.cpp \ Arm64EmitterTest.cpp endif -GPU_VULKAN_FILES := \ +VULKAN_FILES := \ $(SRC)/GPU/Vulkan/DrawEngineVulkan.cpp \ $(SRC)/GPU/Vulkan/FramebufferManagerVulkan.cpp \ $(SRC)/GPU/Vulkan/GPU_Vulkan.cpp \ @@ -406,7 +335,7 @@ GPU_VULKAN_FILES := \ EXEC_AND_LIB_FILES := \ $(ARCH_FILES) \ - $(GPU_VULKAN_FILES) \ + $(VULKAN_FILES) \ $(SRC)/ext/xxhash.c \ TestRunner.cpp \ $(SRC)/Core/MIPS/MIPS.cpp.arm \ @@ -422,7 +351,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/MIPS/MIPSVFPUFallbacks.cpp.arm \ $(SRC)/Core/MIPS/MIPSCodeUtils.cpp.arm \ $(SRC)/Core/MIPS/MIPSDebugInterface.cpp \ - $(SRC)/Core/MIPS/IR/IRAnalysis.cpp \ $(SRC)/Core/MIPS/IR/IRFrontend.cpp \ $(SRC)/Core/MIPS/IR/IRJit.cpp \ $(SRC)/Core/MIPS/IR/IRCompALU.cpp \ @@ -432,7 +360,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/MIPS/IR/IRCompVFPU.cpp \ $(SRC)/Core/MIPS/IR/IRInst.cpp \ $(SRC)/Core/MIPS/IR/IRInterpreter.cpp \ - $(SRC)/Core/MIPS/IR/IRNativeCommon.cpp \ $(SRC)/Core/MIPS/IR/IRPassSimplify.cpp \ $(SRC)/Core/MIPS/IR/IRRegCache.cpp \ $(SRC)/GPU/Math3D.cpp \ @@ -517,7 +444,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/ConfigSettings.cpp \ $(SRC)/Core/CoreTiming.cpp \ $(SRC)/Core/CwCheat.cpp \ - $(SRC)/Core/FrameTiming.cpp \ $(SRC)/Core/HDRemaster.cpp \ $(SRC)/Core/Instance.cpp \ $(SRC)/Core/KeyMap.cpp \ @@ -535,7 +461,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/MemMapFunctions.cpp \ $(SRC)/Core/Reporting.cpp \ $(SRC)/Core/Replay.cpp \ - $(SRC)/Core/RetroAchievements.cpp \ $(SRC)/Core/SaveState.cpp \ $(SRC)/Core/Screenshot.cpp \ $(SRC)/Core/System.cpp \ @@ -549,7 +474,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/Debugger/WebSocket.cpp \ $(SRC)/Core/Debugger/WebSocket/BreakpointSubscriber.cpp \ $(SRC)/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp \ - $(SRC)/Core/Debugger/WebSocket/ClientConfigSubscriber.cpp \ $(SRC)/Core/Debugger/WebSocket/DisasmSubscriber.cpp \ $(SRC)/Core/Debugger/WebSocket/GameBroadcaster.cpp \ $(SRC)/Core/Debugger/WebSocket/GameSubscriber.cpp \ @@ -664,7 +588,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/MIPS/JitCommon/JitState.cpp \ $(SRC)/Core/Util/AudioFormat.cpp \ $(SRC)/Core/Util/PortManager.cpp \ - $(SRC)/Core/Util/GameDB.cpp \ $(SRC)/Core/Util/GameManager.cpp \ $(SRC)/Core/Util/BlockAllocator.cpp \ $(SRC)/Core/Util/PPGeDraw.cpp \ @@ -798,12 +721,10 @@ LOCAL_SRC_FILES := \ $(SRC)/UI/BackgroundAudio.cpp \ $(SRC)/UI/DiscordIntegration.cpp \ $(SRC)/UI/ChatScreen.cpp \ - $(SRC)/UI/DebugOverlay.cpp \ $(SRC)/UI/DevScreens.cpp \ $(SRC)/UI/DisplayLayoutScreen.cpp \ $(SRC)/UI/EmuScreen.cpp \ $(SRC)/UI/MainScreen.cpp \ - $(SRC)/UI/TabbedDialogScreen.cpp \ $(SRC)/UI/MemStickScreen.cpp \ $(SRC)/UI/MiscScreens.cpp \ $(SRC)/UI/RemoteISOScreen.cpp \ @@ -827,8 +748,7 @@ LOCAL_SRC_FILES := \ $(SRC)/UI/ProfilerDraw.cpp \ $(SRC)/UI/NativeApp.cpp \ $(SRC)/UI/Theme.cpp \ - $(SRC)/UI/CustomButtonMappingScreen.cpp \ - $(SRC)/UI/RetroAchievementScreens.cpp + $(SRC)/UI/CustomButtonMappingScreen.cpp ifneq ($(SKIPAPP),1) include $(BUILD_SHARED_LIBRARY) diff --git a/android/jni/AndroidJavaGLContext.cpp b/android/jni/AndroidJavaGLContext.cpp index 84010df9c..a2cada60f 100644 --- a/android/jni/AndroidJavaGLContext.cpp +++ b/android/jni/AndroidJavaGLContext.cpp @@ -22,7 +22,7 @@ bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int g_display.rotation = DisplayRotation::ROTATE_0; g_display.rot_matrix.setIdentity(); - draw_ = Draw::T3DCreateGLContext(false); // Can't fail + draw_ = Draw::T3DCreateGLContext(); // Can't fail renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); diff --git a/android/jni/AndroidJavaGLContext.h b/android/jni/AndroidJavaGLContext.h index b89c41d0f..4b4ff95d1 100644 --- a/android/jni/AndroidJavaGLContext.h +++ b/android/jni/AndroidJavaGLContext.h @@ -15,6 +15,8 @@ public: void ShutdownFromRenderThread() override; void Shutdown() override {} + void SwapBuffers() override {} + void SwapInterval(int interval) override {} void Resize() override {} Draw::DrawContext *GetDrawContext() override { diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 319f41346..d12832a7f 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -13,27 +13,6 @@ #include "Core/ConfigValues.h" #include "Core/System.h" - -#ifdef _DEBUG -static const bool g_Validate = true; -#else -static const bool g_Validate = false; -#endif - -// TODO: Share this between backends. -static uint32_t FlagsFromConfig() { - uint32_t flags; - if (g_Config.bVSync) { - flags = VULKAN_FLAG_PRESENT_FIFO; - } else { - flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_IMMEDIATE; - } - if (g_Validate) { - flags |= VULKAN_FLAG_VALIDATE; - } - return flags; -} - AndroidVulkanContext::AndroidVulkanContext() {} AndroidVulkanContext::~AndroidVulkanContext() { @@ -41,6 +20,20 @@ AndroidVulkanContext::~AndroidVulkanContext() { g_Vulkan = nullptr; } +static uint32_t FlagsFromConfig() { + uint32_t flags; + + if (g_Config.bVSync) { + flags = VULKAN_FLAG_PRESENT_FIFO; + } else { + flags = VULKAN_FLAG_PRESENT_MAILBOX | VULKAN_FLAG_PRESENT_FIFO_RELAXED; + } +#ifdef _DEBUG + flags |= VULKAN_FLAG_VALIDATE; +#endif + return flags; +} + bool AndroidVulkanContext::InitAPI() { INFO_LOG(G3D, "AndroidVulkanContext::Init"); init_glslang(); @@ -89,7 +82,7 @@ bool AndroidVulkanContext::InitAPI() { g_Vulkan->ChooseDevice(physicalDevice); - INFO_LOG(G3D, "Creating Vulkan device (flags: %08x)", info.flags); + INFO_LOG(G3D, "Creating Vulkan device"); if (g_Vulkan->CreateDevice() != VK_SUCCESS) { INFO_LOG(G3D, "Failed to create vulkan device: %s", g_Vulkan->InitError().c_str()); System_Toast("No Vulkan driver found. Using OpenGL instead."); @@ -120,11 +113,7 @@ bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredB bool success = true; if (g_Vulkan->InitSwapchain()) { - bool useMultiThreading = g_Config.bRenderMultiThreading; - if (g_Config.iInflightFrames == 1) { - useMultiThreading = false; - } - draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, useMultiThreading); + draw_ = Draw::T3DCreateVulkanContext(g_Vulkan); SetGPUBackend(GPUBackend::VULKAN); success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler. _assert_msg_(success, "Failed to compile preset shaders"); @@ -168,6 +157,9 @@ void AndroidVulkanContext::Shutdown() { INFO_LOG(G3D, "AndroidVulkanContext::Shutdown completed"); } +void AndroidVulkanContext::SwapBuffers() { +} + void AndroidVulkanContext::Resize() { INFO_LOG(G3D, "AndroidVulkanContext::Resize begin (oldsize: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); @@ -182,3 +174,6 @@ void AndroidVulkanContext::Resize() { draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); INFO_LOG(G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight()); } + +void AndroidVulkanContext::SwapInterval(int interval) { +} diff --git a/android/jni/AndroidVulkanContext.h b/android/jni/AndroidVulkanContext.h index 7da96fbd9..31d88c1a2 100644 --- a/android/jni/AndroidVulkanContext.h +++ b/android/jni/AndroidVulkanContext.h @@ -15,6 +15,8 @@ public: void ShutdownFromRenderThread() override; // Inverses InitFromRenderThread. void Shutdown() override; + void SwapInterval(int interval) override; + void SwapBuffers() override; void Resize() override; void *GetAPIContext() override { return g_Vulkan; } diff --git a/android/jni/Application.mk b/android/jni/Application.mk index 9282f31bd..ab283e0a4 100644 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -1,5 +1,5 @@ APP_STL := c++_static APP_PLATFORM := android-9 -APP_ABI := arm64-v8a armeabi-v7a x86_64 +APP_ABI := arm64-v8a armeabi-v7a x86 x86_64 APP_GNUSTL_CPP_FEATURES := exceptions NDK_TOOLCHAIN_VERSION := clang diff --git a/android/jni/Locals.mk b/android/jni/Locals.mk index e176a2bdc..beed00858 100644 --- a/android/jni/Locals.mk +++ b/android/jni/Locals.mk @@ -20,8 +20,6 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/../../ext/armips \ $(LOCAL_PATH)/../../ext/armips/ext/filesystem/include \ $(LOCAL_PATH)/../../ext/armips/ext/tinyformat \ - $(LOCAL_PATH)/../../ext/libchdr/deps/lzma-22.01/include \ - $(LOCAL_PATH)/../../ext/libchdr/include \ $(LOCAL_PATH) LOCAL_STATIC_LIBRARIES := libzip glslang-build miniupnp-build @@ -55,6 +53,16 @@ ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_ARCH_32 -march=armv6 endif +ifeq ($(TARGET_ARCH_ABI),x86) + LOCAL_LDLIBS += $(LOCAL_PATH)/../../ffmpeg/android/x86/lib/libavformat.a + LOCAL_LDLIBS += $(LOCAL_PATH)/../../ffmpeg/android/x86/lib/libavcodec.a + LOCAL_LDLIBS += $(LOCAL_PATH)/../../ffmpeg/android/x86/lib/libswresample.a + LOCAL_LDLIBS += $(LOCAL_PATH)/../../ffmpeg/android/x86/lib/libswscale.a + LOCAL_LDLIBS += $(LOCAL_PATH)/../../ffmpeg/android/x86/lib/libavutil.a + LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ffmpeg/android/x86/include + + LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_ARCH_32 -D_M_IX86 -fomit-frame-pointer -mtune=atom -mfpmath=sse -mssse3 -mstackrealign +endif ifeq ($(TARGET_ARCH_ABI),x86_64) LOCAL_LDLIBS += $(LOCAL_PATH)/../../ffmpeg/android/x86_64/lib/libavformat.a diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index d4bfb28a2..1084252a1 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -61,7 +61,6 @@ struct JNIEnv {}; #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/System/Request.h" #include "Common/Thread/ThreadUtil.h" #include "Common/File/Path.h" @@ -90,7 +89,6 @@ struct JNIEnv {}; #include "Core/ConfigValues.h" #include "Core/Loaders.h" #include "Core/FileLoaders/LocalFileLoader.h" -#include "Core/KeyMap.h" #include "Core/System.h" #include "Core/HLE/sceUsbCam.h" #include "Core/HLE/sceUsbGps.h" @@ -148,8 +146,8 @@ static int deviceType; // Should only be used for display detection during startup (for config defaults etc) // This is the ACTUAL display size, not the hardware scaled display size. // Exposed so it can be displayed on the touchscreen test. -static int display_xres; -static int display_yres; +int display_xres; +int display_yres; static int display_dpi_x; static int display_dpi_y; static int backbuffer_format; // Android PixelFormat enum @@ -158,8 +156,7 @@ static int desiredBackbufferSizeX; static int desiredBackbufferSizeY; // Cache the class loader so we can use it from native threads. Required for TextAndroid. -extern JavaVM *gJvm; - +static JavaVM* gJvm = nullptr; static jobject gClassLoader; static jmethodID gFindClassMethod; @@ -202,10 +199,10 @@ int utimensat(int fd, const char *path, const struct timespec times[2]) { void AndroidLogger::Log(const LogMessage &message) { int mode; switch (message.level) { - case LogLevel::LWARNING: + case LogTypes::LWARNING: mode = ANDROID_LOG_WARN; break; - case LogLevel::LERROR: + case LogTypes::LERROR: mode = ANDROID_LOG_ERROR; break; default: @@ -252,7 +249,7 @@ void Android_AttachThreadToJNI() { JNIEnv *env; int status = gJvm->GetEnv((void **)&env, JNI_VERSION_1_6); if (status < 0) { - DEBUG_LOG(SYSTEM, "Attaching thread '%s' (not already attached) to JNI.", GetCurrentThreadName()); + INFO_LOG(SYSTEM, "Attaching thread '%s' (not already attached) to JNI.", GetCurrentThreadName()); JavaVMAttachArgs args{}; args.version = JNI_VERSION_1_6; args.name = GetCurrentThreadName(); @@ -269,7 +266,7 @@ void Android_AttachThreadToJNI() { void Android_DetachThreadFromJNI() { if (gJvm->DetachCurrentThread() == JNI_OK) { - DEBUG_LOG(SYSTEM, "Detached thread from JNI: '%s'", GetCurrentThreadName()); + INFO_LOG(SYSTEM, "Detached thread from JNI: '%s'", GetCurrentThreadName()); } else { WARN_LOG(SYSTEM, "Failed to detach thread '%s' from JNI - never attached?", GetCurrentThreadName()); } @@ -295,11 +292,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) { // Only used in OpenGL mode. static void EmuThreadFunc() { + JNIEnv *env; + SetCurrentThreadName("EmuThread"); // Name the thread in the JVM, because why not (might result in better debug output in Play Console). // TODO: Do something clever with getEnv() and stored names from SetCurrentThreadName? - JNIEnv *env; JavaVMAttachArgs args{}; args.version = JNI_VERSION_1_6; args.name = "EmuThread"; @@ -310,7 +308,7 @@ static void EmuThreadFunc() { // Wait for render loop to get started. INFO_LOG(SYSTEM, "Runloop: Waiting for displayInit..."); while (!graphicsContext || graphicsContext->GetState() == GraphicsContextState::PENDING) { - sleep_ms(5); + sleep_ms(20); } // Check the state of the graphics context before we try to feed it into NativeInitGraphics. @@ -370,7 +368,7 @@ static void EmuThreadJoin() { static void ProcessFrameCommands(JNIEnv *env); -static void PushCommand(std::string cmd, std::string param) { +void PushCommand(std::string cmd, std::string param) { std::lock_guard guard(frameCommandLock); frameCommands.push(FrameCommand(cmd, param)); } @@ -390,6 +388,10 @@ void System_Vibrate(int length_ms) { PushCommand("vibrate", temp); } +void System_ShowFileInFolder(const char *path) { + // Unsupported +} + void System_LaunchUrl(LaunchUrlType urlType, const char *url) { switch (urlType) { case LaunchUrlType::BROWSER_URL: PushCommand("launchBrowser", url); break; @@ -408,8 +410,6 @@ std::string System_GetProperty(SystemProperty prop) { return mogaVersion; case SYSPROP_BOARDNAME: return boardName; - case SYSPROP_BUILD_VERSION: - return PPSSPP_GIT_VERSION; default: return ""; } @@ -480,8 +480,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } case SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE: return sustainedPerfSupported; // 7.0 introduced sustained performance mode as an optional feature. - case SYSPROP_HAS_TEXT_INPUT_DIALOG: - return true; case SYSPROP_HAS_OPEN_DIRECTORY: return false; case SYSPROP_HAS_ADDITIONAL_STORAGE: @@ -530,12 +528,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } case SYSPROP_HAS_KEYBOARD: return deviceType != DEVICE_TYPE_VR; - case SYSPROP_HAS_ACCELEROMETER: - return deviceType == DEVICE_TYPE_MOBILE; -#ifndef HTTPS_NOT_AVAILABLE - case SYSPROP_SUPPORTS_HTTPS: - return !g_Config.bDisableHTTPS; -#endif default: return false; } @@ -689,9 +681,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init EARLY_LOG("NativeApp.init() -- begin"); PROFILE_INIT(); - std::lock_guard guard(renderLock); + std::lock_guard guard(renderLock); // Note: This is held for the rest of this function - intended? renderer_inited = false; - exitRenderLoop = false; androidVersion = jAndroidVersion; deviceType = jdeviceType; @@ -865,7 +856,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_resume(JNIEnv *, jclass) { INFO_LOG(SYSTEM, "NativeApp.resume() - resuming audio"); AndroidAudio_Resume(g_audioState); - System_PostUIMessage(UIMessage::APP_RESUMED); + NativeMessageReceived("app_resumed", ""); } extern "C" void Java_org_ppsspp_ppsspp_NativeApp_pause(JNIEnv *, jclass) { @@ -874,14 +865,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_pause(JNIEnv *, jclass) { } extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { - INFO_LOG(SYSTEM, "NativeApp.shutdown() -- begin"); - if (renderer_inited && useCPUThread && graphicsContext) { // Only used in Java EGL path. - - // We can't lock renderLock here because the emu thread will be in NativeFrame - // which locks renderLock already, and only gets out once we call ThreadFrame() - // in a loop before, to empty the queue. EmuThreadStop("shutdown"); INFO_LOG(SYSTEM, "BeginAndroidShutdown"); graphicsContext->BeginAndroidShutdown(); @@ -899,19 +884,19 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { EmuThreadJoin(); } + INFO_LOG(SYSTEM, "NativeApp.shutdown() -- begin"); + if (renderer_inited) { + INFO_LOG(G3D, "Shutting down renderer"); + graphicsContext->Shutdown(); + delete graphicsContext; + graphicsContext = nullptr; + renderer_inited = false; + } else { + INFO_LOG(G3D, "Not shutting down renderer - not initialized"); + } + { std::lock_guard guard(renderLock); - - if (graphicsContext) { - INFO_LOG(G3D, "Shutting down renderer"); - graphicsContext->Shutdown(); - delete graphicsContext; - graphicsContext = nullptr; - renderer_inited = false; - } else { - INFO_LOG(G3D, "Not shutting down renderer - not initialized"); - } - NativeShutdown(); g_VFS.Clear(); } @@ -961,7 +946,7 @@ extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, } graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) { - g_OSD.Show(OSDType::MESSAGE_ERROR, details, 5.0); + System_NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback"); }, nullptr); EmuThreadStart(); @@ -977,14 +962,14 @@ extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, } graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) { - g_OSD.Show(OSDType::MESSAGE_ERROR, details, 5.0); + System_NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback"); }, nullptr); graphicsContext->ThreadStart(); renderer_inited = true; } - System_PostUIMessage(UIMessage::RECREATE_VIEWS); + NativeMessageReceived("recreateviews", ""); if (IsVREnabled()) { EnterVR(firstStart, graphicsContext->GetAPIContext()); @@ -1048,9 +1033,6 @@ void System_Notify(SystemNotification notification) { case SystemNotification::SUSTAINED_PERF_CHANGE: PushCommand("sustainedPerfMode", ""); break; - case SystemNotification::TEST_JAVA_EXCEPTION: - PushCommand("testException", "This is a test exception"); - break; default: break; } @@ -1077,18 +1059,8 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string PushCommand("browse_image", StringFromFormat("%d", requestId)); return true; case SystemRequestType::BROWSE_FOR_FILE: - { - BrowseFileType fileType = (BrowseFileType)param3; - switch (fileType) { - case BrowseFileType::SOUND_EFFECT: - PushCommand("browse_file_audio", StringFromFormat("%d", requestId)); - break; - default: - PushCommand("browse_file", StringFromFormat("%d", requestId)); - break; - } + PushCommand("browse_file", StringFromFormat("%d", requestId)); return true; - } case SystemRequestType::BROWSE_FOR_FOLDER: PushCommand("browse_folder", StringFromFormat("%d", requestId)); return true; @@ -1114,8 +1086,16 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendRequestResult(JNIEnv *env, jclass, jint jrequestID, jboolean result, jstring jvalue, jint jintValue) { - std::string value = jvalue ? GetJavaString(env, jvalue) : "(no value)"; - INFO_LOG(SYSTEM, "Received result of request %d from Java: %d: %d '%s'", jrequestID, (int)result, jintValue, value.c_str()); + std::string value = GetJavaString(env, jvalue); + + static jint lastSeqID = -1; + if (lastSeqID == jrequestID) { + // We send this on dismiss, so twice in many cases. + WARN_LOG(SYSTEM, "Ignoring duplicate sendInputBox"); + return; + } + lastSeqID = jrequestID; + if (result) { g_requestManager.PostSystemSuccess(jrequestID, value.c_str()); } else { @@ -1125,7 +1105,8 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendRequestResult(JNIEn void LockedNativeUpdateRender() { std::lock_guard renderGuard(renderLock); - NativeFrame(graphicsContext); + NativeUpdate(); + NativeRender(graphicsContext); } void UpdateRunLoopAndroid(JNIEnv *env) { @@ -1143,9 +1124,6 @@ void UpdateRunLoopAndroid(JNIEnv *env) { } extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { - // This doesn't get called on the Vulkan path. - _assert_(useCPUThread); - static bool hasSetThreadName = false; if (!hasSetThreadName) { hasSetThreadName = true; @@ -1155,9 +1133,13 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, if (IsVREnabled() && !StartVRRender()) return; - // This is the "GPU thread". Call ThreadFrame. - if (!graphicsContext || !graphicsContext->ThreadFrame()) { - return; + if (useCPUThread) { + // This is the "GPU thread". Call ThreadFrame. + if (!graphicsContext || !graphicsContext->ThreadFrame()) { + return; + } + } else { + UpdateRunLoopAndroid(env); } if (IsVREnabled()) { @@ -1184,22 +1166,23 @@ PermissionStatus System_GetPermissionStatus(SystemPermission permission) { extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - if (!renderer_inited) - return; + + float scaledX = x * g_display.dpi_scale_x; + float scaledY = y * g_display.dpi_scale_y; + TouchInput touch; touch.id = pointerId; - touch.x = x * g_display.dpi_scale_x; - touch.y = y * g_display.dpi_scale_y; + touch.x = scaledX; + touch.y = scaledY; touch.flags = code; + NativeTouch(touch); } extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key, jboolean isRepeat) { - if (!renderer_inited) - return false; KeyInput keyInput; - keyInput.deviceId = (InputDeviceID)deviceId; - keyInput.keyCode = (InputKeyCode)key; + keyInput.deviceId = deviceId; + keyInput.keyCode = key; keyInput.flags = KEY_DOWN; if (isRepeat) { keyInput.flags |= KEY_IS_REPEAT; @@ -1208,33 +1191,31 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_keyDown(JNIEnv *, jclass, j } extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { - if (!renderer_inited) - return false; KeyInput keyInput; - keyInput.deviceId = (InputDeviceID)deviceId; - keyInput.keyCode = (InputKeyCode)key; + keyInput.deviceId = deviceId; + keyInput.keyCode = key; keyInput.flags = KEY_UP; return NativeKey(keyInput); } -// TODO: Make a batched interface, since we get these in batches on the Java side. extern "C" void Java_org_ppsspp_ppsspp_NativeApp_joystickAxis( JNIEnv *env, jclass, jint deviceId, jint axisId, jfloat value) { if (!renderer_inited) return; - // These are dirty-filtered on the Java side. AxisInput axis; - axis.deviceId = (InputDeviceID)deviceId; - axis.axisId = (InputAxis)axisId; + axis.axisId = axisId; + axis.deviceId = deviceId; axis.value = value; - NativeAxis(&axis, 1); + + NativeAxis(axis); } extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_mouseWheelEvent( JNIEnv *env, jclass, jint stick, jfloat x, jfloat y) { if (!renderer_inited) return false; + // TODO: Support mousewheel for android return true; } @@ -1242,16 +1223,27 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_mouseWheelEvent( extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { if (!renderer_inited) return; - NativeAccelerometer(x, y, z); + + AxisInput axis; + axis.deviceId = DEVICE_ID_ACCELEROMETER; + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; + axis.value = x; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; + axis.value = y; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; + axis.value = z; + NativeAxis(axis); } -extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNIEnv *env, jclass, jstring message, jstring param) { +extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); - // A bit ugly, see InputDeviceState.java. - static InputDeviceID nextInputDeviceID = DEVICE_ID_ANY; - // Some messages are caught by app-android. TODO: Should be all. if (msg == "moga") { mogaVersion = prm; @@ -1259,16 +1251,12 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNI INFO_LOG(SYSTEM, "STORAGE PERMISSION: PENDING"); // TODO: Add support for other permissions permissions[SYSTEM_PERMISSION_STORAGE] = PERMISSION_STATUS_PENDING; - // Don't need to send along, nothing else is listening. } else if (msg == "permission_denied") { INFO_LOG(SYSTEM, "STORAGE PERMISSION: DENIED"); permissions[SYSTEM_PERMISSION_STORAGE] = PERMISSION_STATUS_DENIED; - // Don't need to send along, nothing else is listening. } else if (msg == "permission_granted") { INFO_LOG(SYSTEM, "STORAGE PERMISSION: GRANTED"); permissions[SYSTEM_PERMISSION_STORAGE] = PERMISSION_STATUS_GRANTED; - // Send along. - System_PostUIMessage(UIMessage::PERMISSION_GRANTED, prm); } else if (msg == "sustained_perf_supported") { sustainedPerfSupported = true; } else if (msg == "safe_insets") { @@ -1281,17 +1269,20 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNI g_safeInsetTop = (float)top * g_display.dpi_scale_y; g_safeInsetBottom = (float)bottom * g_display.dpi_scale_y; } - } else if (msg == "inputDeviceConnectedID") { - nextInputDeviceID = (InputDeviceID)parseLong(prm); - } else if (msg == "inputDeviceConnected") { - KeyMap::NotifyPadConnected(nextInputDeviceID, prm); - } else if (msg == "core_powerSaving") { - // Forward. - System_PostUIMessage(UIMessage::POWER_SAVING, prm); - } else if (msg == "exception") { - g_OSD.Show(OSDType::MESSAGE_ERROR, std::string("Java Exception"), prm, 10.0f); - } else { - ERROR_LOG(SYSTEM, "Got unexpected message from Java, ignoring: %s / %s", msg.c_str(), prm.c_str()); + } + + // Ensures that the receiver can handle it on a sensible thread. + NativeMessageReceived(msg.c_str(), prm.c_str()); +} + +extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_requestExitVulkanRenderLoop(JNIEnv *env, jobject obj) { + if (!renderLoopRunning) { + ERROR_LOG(SYSTEM, "Render loop already exited"); + return; + } + exitRenderLoop = true; + while (renderLoopRunning) { + sleep_ms(10); } } @@ -1442,13 +1433,8 @@ static void ProcessFrameCommands(JNIEnv *env) { } } -std::thread g_vulkanRenderLoopThread; - -static void VulkanEmuThread(ANativeWindow *wnd); - // This runs in Vulkan mode only. -// This handles the entire lifecycle of the Vulkan context, init and exit. -extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runVulkanRenderLoop(JNIEnv * env, jobject obj, jobject _surf) { +extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runVulkanRenderLoop(JNIEnv *env, jobject obj, jobject _surf) { _assert_(!useCPUThread); if (!graphicsContext) { @@ -1456,13 +1442,15 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runVulkanRenderLoo return false; } - if (g_vulkanRenderLoopThread.joinable()) { - ERROR_LOG(G3D, "runVulkanRenderLoop: Already running"); - return false; - } + exitRenderLoop = false; + // This is up here to prevent race conditions, in case we pause during init. + renderLoopRunning = true; ANativeWindow *wnd = _surf ? ANativeWindow_fromSurface(env, _surf) : nullptr; + WARN_LOG(G3D, "runVulkanRenderLoop. display_xres=%d display_yres=%d desiredBackbufferSizeX=%d desiredBackbufferSizeY=%d", + display_xres, display_yres, desiredBackbufferSizeX, desiredBackbufferSizeY); + if (!wnd) { // This shouldn't ever happen. ERROR_LOG(G3D, "Error: Surface is null."); @@ -1470,49 +1458,6 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runVulkanRenderLoo return false; } - g_vulkanRenderLoopThread = std::thread(VulkanEmuThread, wnd); - return true; -} - -extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_requestExitVulkanRenderLoop(JNIEnv * env, jobject obj) { - if (!renderLoopRunning) { - ERROR_LOG(SYSTEM, "Render loop already exited"); - return; - } - _assert_(g_vulkanRenderLoopThread.joinable()); - exitRenderLoop = true; - g_vulkanRenderLoopThread.join(); - _assert_(!g_vulkanRenderLoopThread.joinable()); - g_vulkanRenderLoopThread = std::thread(); -} - -// TODO: Merge with the Win32 EmuThread and so on, and the Java EmuThread? -static void VulkanEmuThread(ANativeWindow *wnd) { - SetCurrentThreadName("EmuThread"); - - AndroidJNIThreadContext ctx; - JNIEnv *env = getEnv(); - - if (!graphicsContext) { - ERROR_LOG(G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context."); - renderLoopRunning = false; - exitRenderLoop = false; - return; - } - - if (exitRenderLoop) { - WARN_LOG(G3D, "runVulkanRenderLoop: ExitRenderLoop requested at start, skipping the whole thing."); - renderLoopRunning = false; - exitRenderLoop = false; - return; - } - - // This is up here to prevent race conditions, in case we pause during init. - renderLoopRunning = true; - - WARN_LOG(G3D, "runVulkanRenderLoop. display_xres=%d display_yres=%d desiredBackbufferSizeX=%d desiredBackbufferSizeY=%d", - display_xres, display_yres, desiredBackbufferSizeX, desiredBackbufferSizeY); - if (!graphicsContext->InitFromRenderThread(wnd, desiredBackbufferSizeX, desiredBackbufferSizeY, backbuffer_format, androidVersion)) { // On Android, if we get here, really no point in continuing. // The UI is supposed to render on any device both on OpenGL and Vulkan. If either of those don't work @@ -1523,7 +1468,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) { delete graphicsContext; graphicsContext = nullptr; renderLoopRunning = false; - return; + return false; } if (!exitRenderLoop) { @@ -1534,12 +1479,20 @@ static void VulkanEmuThread(ANativeWindow *wnd) { graphicsContext->ThreadStart(); renderer_inited = true; - while (!exitRenderLoop) { - LockedNativeUpdateRender(); - ProcessFrameCommands(env); + static bool hasSetThreadName = false; + if (!hasSetThreadName) { + hasSetThreadName = true; + SetCurrentThreadName("AndroidRender"); } } + while (!exitRenderLoop) { + LockedNativeUpdateRender(); + graphicsContext->SwapBuffers(); + + ProcessFrameCommands(env); + } + INFO_LOG(G3D, "Leaving EGL/Vulkan render loop."); NativeShutdownGraphics(); @@ -1551,9 +1504,9 @@ static void VulkanEmuThread(ANativeWindow *wnd) { INFO_LOG(G3D, "Shutting down graphics context from render thread..."); graphicsContext->ShutdownFromRenderThread(); renderLoopRunning = false; - exitRenderLoop = false; WARN_LOG(G3D, "Render loop function exited."); + return true; } // NOTE: This is defunct and not working, due to how the Android storage functions currently require diff --git a/android/res/drawable-ldpi/ic_launcher.png b/android/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 000000000..4ba6d0b71 Binary files /dev/null and b/android/res/drawable-ldpi/ic_launcher.png differ diff --git a/android/res/mipmap-hdpi/ic_launcher.png b/android/res/mipmap-hdpi/ic_launcher.png index 982b0e34b..e4861f356 100644 Binary files a/android/res/mipmap-hdpi/ic_launcher.png and b/android/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/res/mipmap-hdpi/ic_launcher_round.png b/android/res/mipmap-hdpi/ic_launcher_round.png index 982b0e34b..33e11da64 100644 Binary files a/android/res/mipmap-hdpi/ic_launcher_round.png and b/android/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-mdpi/ic_launcher.png b/android/res/mipmap-mdpi/ic_launcher.png index badd38dc0..78762e0a1 100644 Binary files a/android/res/mipmap-mdpi/ic_launcher.png and b/android/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/res/mipmap-mdpi/ic_launcher_round.png b/android/res/mipmap-mdpi/ic_launcher_round.png index badd38dc0..20aa16737 100644 Binary files a/android/res/mipmap-mdpi/ic_launcher_round.png and b/android/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-xhdpi/ic_launcher.png b/android/res/mipmap-xhdpi/ic_launcher.png index 33d7274e9..f86cb15b8 100644 Binary files a/android/res/mipmap-xhdpi/ic_launcher.png and b/android/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/res/mipmap-xhdpi/ic_launcher_round.png b/android/res/mipmap-xhdpi/ic_launcher_round.png index 33d7274e9..0fb5a8c0d 100644 Binary files a/android/res/mipmap-xhdpi/ic_launcher_round.png and b/android/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-xxhdpi/ic_launcher.png b/android/res/mipmap-xxhdpi/ic_launcher.png index 79863e370..5c08e8fe6 100644 Binary files a/android/res/mipmap-xxhdpi/ic_launcher.png and b/android/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/res/mipmap-xxhdpi/ic_launcher_round.png b/android/res/mipmap-xxhdpi/ic_launcher_round.png index 79863e370..792f90ca0 100644 Binary files a/android/res/mipmap-xxhdpi/ic_launcher_round.png and b/android/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher.png b/android/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..dc6461c73 Binary files /dev/null and b/android/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..25516d315 Binary files /dev/null and b/android/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..7c3741b28 Binary files /dev/null and b/android/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/src/org/ppsspp/ppsspp/InputDeviceState.java b/android/src/org/ppsspp/ppsspp/InputDeviceState.java index 6961ee6fb..b221032cd 100644 --- a/android/src/org/ppsspp/ppsspp/InputDeviceState.java +++ b/android/src/org/ppsspp/ppsspp/InputDeviceState.java @@ -18,7 +18,6 @@ public class InputDeviceState { private InputDevice mDevice; private int[] mAxes; - private float[] mAxisPrevValue; private int sources; @@ -95,12 +94,6 @@ public class InputDeviceState { return str; } - public static boolean inputSourceIsJoystick(int source) { - return (source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || - (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || - (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD; - } - public InputDeviceState(InputDevice device) { sources = device.getSources(); // First, anything that's a gamepad is a gamepad, even if it has a keyboard or pointer. @@ -108,7 +101,8 @@ public class InputDeviceState { this.deviceId = NativeApp.DEVICE_ID_PAD_0; } else if ((sources & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD && device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { this.deviceId = NativeApp.DEVICE_ID_KEYBOARD; - } else if (inputSourceIsJoystick(sources)) { + } else if ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || + (sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) { this.deviceId = NativeApp.DEVICE_ID_PAD_0; } else if ((sources & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) { this.deviceId = NativeApp.DEVICE_ID_MOUSE; @@ -124,7 +118,6 @@ public class InputDeviceState { } mAxes = new int[numAxes]; - mAxisPrevValue = new float[numAxes]; int i = 0; for (MotionRange range : device.getMotionRanges()) { @@ -135,35 +128,29 @@ public class InputDeviceState { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { logAdvanced(device); } - NativeApp.sendMessageFromJava("inputDeviceConnectedID", String.valueOf(this.deviceId)); - NativeApp.sendMessageFromJava("inputDeviceConnected", device.getName()); + NativeApp.sendMessage("inputDeviceConnectedID", String.valueOf(this.deviceId)); + NativeApp.sendMessage("inputDeviceConnected", device.getName()); } - // This is called from dispatchKeyEvent. public boolean onKeyDown(KeyEvent event) { int keyCode = event.getKeyCode(); boolean repeat = event.getRepeatCount() > 0; return NativeApp.keyDown(deviceId, keyCode, repeat); } - // This is called from dispatchKeyEvent. public boolean onKeyUp(KeyEvent event) { int keyCode = event.getKeyCode(); return NativeApp.keyUp(deviceId, keyCode); } public boolean onJoystickMotion(MotionEvent event) { - if (!inputSourceIsJoystick(event.getSource())) { - Log.i(TAG, "Not a joystick event: source = " + event.getSource()); + if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) { return false; } for (int i = 0; i < mAxes.length; i++) { int axisId = mAxes[i]; float value = event.getAxisValue(axisId); - if (value != mAxisPrevValue[i]) { - NativeApp.joystickAxis(deviceId, axisId, value); - mAxisPrevValue[i] = value; - } + NativeApp.joystickAxis(deviceId, axisId, value); } return true; } diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index cf93e4b28..740eef13b 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -62,12 +62,13 @@ public abstract class NativeActivity extends Activity { // Allows us to skip a lot of initialization on secondary calls to onCreate. private static boolean initialized = false; - // False to use Vulkan, queried from C++ after NativeApp.init. + // False to use C++ EGL, queried from C++ after NativeApp.init. private static boolean javaGL = true; - // Graphics and audio interfaces for Vulkan (javaGL = false) + // Graphics and audio interfaces for EGL (javaGL = false) private NativeSurfaceView mSurfaceView; private Surface mSurface; + private Thread mRenderLoopThread = null; // Graphics and audio interfaces for Java EGL (javaGL = true) private NativeGLView mGLSurfaceView; @@ -100,9 +101,14 @@ public abstract class NativeActivity extends Activity { // switched-away from or rotated etc. private boolean shuttingDown; - private static final int RESULT_LOAD_IMAGE = 101; - private static final int RESULT_OPEN_DOCUMENT = 102; - private static final int RESULT_OPEN_DOCUMENT_TREE = 103; + private static final int RESULT_LOAD_IMAGE = 1; + private static final int RESULT_OPEN_DOCUMENT = 2; + private static final int RESULT_OPEN_DOCUMENT_TREE = 3; + + // These can probably be merged, but conceptually nice to have them separate. + private int imageRequestId = -1; + private int fileRequestId = -1; + private int folderRequestId = -1; // Allow for multiple connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. @@ -194,9 +200,9 @@ public abstract class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Let's start out granted if it was granted already. if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - NativeApp.sendMessageFromJava("permission_granted", "storage"); + NativeApp.sendMessage("permission_granted", "storage"); } else { - NativeApp.sendMessageFromJava("permission_denied", "storage"); + NativeApp.sendMessage("permission_denied", "storage"); } } } @@ -214,9 +220,9 @@ public abstract class NativeActivity extends Activity { switch (requestCode) { case REQUEST_CODE_STORAGE_PERMISSION: if (permissionsGranted(permissions, grantResults)) { - NativeApp.sendMessageFromJava("permission_granted", "storage"); + NativeApp.sendMessage("permission_granted", "storage"); } else { - NativeApp.sendMessageFromJava("permission_denied", "storage"); + NativeApp.sendMessage("permission_denied", "storage"); } break; case REQUEST_CODE_LOCATION_PERMISSION: @@ -358,7 +364,7 @@ public abstract class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (powerManager != null && powerManager.isSustainedPerformanceModeSupported()) { sustainedPerfSupported = true; - NativeApp.sendMessageFromJava("sustained_perf_supported", "1"); + NativeApp.sendMessage("sustained_perf_supported", "1"); } } @@ -422,7 +428,6 @@ public abstract class NativeActivity extends Activity { additionalStorageDirs = s.toString(); } catch (Exception e) { - NativeApp.reportException(e, null); Log.e(TAG, "Failed to get SD storage dirs: " + e.toString()); } @@ -567,6 +572,19 @@ public abstract class NativeActivity extends Activity { } } + private final Runnable mEmulationRunner = new Runnable() { + @Override + public void run() { + Log.i(TAG, "Starting the render loop: " + mSurface); + // Start emulation using the provided Surface. + if (!runVulkanRenderLoop(mSurface)) { + // Shouldn't happen. + Log.e(TAG, "Failed to start up OpenGL/Vulkan - runVulkanRenderLoop returned false"); + } + Log.i(TAG, "Left the render loop: " + mSurface); + } + }; + public native boolean runVulkanRenderLoop(Surface surface); // Tells the render loop thread to exit, so we can restart it. public native void requestExitVulkanRenderLoop(); @@ -648,7 +666,7 @@ public abstract class NativeActivity extends Activity { Log.i(TAG, "setcontentview before"); setContentView(mSurfaceView); Log.i(TAG, "setcontentview after"); - startRenderLoopThread(); + ensureRenderLoop(); } } @@ -663,47 +681,55 @@ public abstract class NativeActivity extends Activity { public void notifySurface(Surface surface) { mSurface = surface; - - if (!initialized) { - Log.e(TAG, "Can't deal with surfaces while not initialized"); - return; - } - if (!javaGL) { // If we got a surface, this starts the thread. If not, it doesn't. if (mSurface == null) { joinRenderLoopThread(); } else { - startRenderLoopThread(); + ensureRenderLoop(); } } updateSustainedPerformanceMode(); } - // The render loop thread (EmuThread) is now spawned from the native side. - protected synchronized void startRenderLoopThread() { + // Invariants: After this, mRenderLoopThread will be set, and the thread will be running, + // if in Vulkan mode. + protected synchronized void ensureRenderLoop() { if (javaGL) { - Log.e(TAG, "JavaGL mode - should not get into startRenderLoopThread."); + Log.e(TAG, "JavaGL mode - should not get into ensureRenderLoop."); return; } if (mSurface == null) { - Log.w(TAG, "startRenderLoopThread - not starting thread, needs surface"); + Log.w(TAG, "ensureRenderLoop - not starting thread, needs surface"); return; } - - Log.w(TAG, "startRenderLoopThread: Starting thread"); - runVulkanRenderLoop(mSurface); + if (mRenderLoopThread == null) { + Log.w(TAG, "ensureRenderLoop: Starting thread"); + mRenderLoopThread = new Thread(mEmulationRunner); + mRenderLoopThread.start(); + } } + // Invariants: After this, mRenderLoopThread will be null, and the thread has exited. private synchronized void joinRenderLoopThread() { if (javaGL) { Log.e(TAG, "JavaGL - should not get into joinRenderLoopThread."); return; } - // This will wait until the thread has exited. - Log.i(TAG, "requestExitVulkanRenderLoop"); - requestExitVulkanRenderLoop(); + if (mRenderLoopThread != null) { + // This will wait until the thread has exited. + Log.i(TAG, "requestExitVulkanRenderLoop"); + requestExitVulkanRenderLoop(); + try { + Log.i(TAG, "joining render loop thread..."); + mRenderLoopThread.join(); + Log.w(TAG, "Joined render loop thread."); + mRenderLoopThread = null; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } @TargetApi(Build.VERSION_CODES.KITKAT) @@ -717,37 +743,33 @@ public abstract class NativeActivity extends Activity { navigationCallbackView = decorView; } + @Override + protected void onStop() { + super.onStop(); + Log.i(TAG, "onStop - do nothing special"); + } + @Override protected void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy"); if (javaGL) { - if (nativeRenderer != null) { - if (nativeRenderer.isRenderingFrame()) { - Log.i(TAG, "Waiting for renderer to finish."); - int tries = 200; - do { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - } - tries--; - } while (nativeRenderer.isRenderingFrame() && tries > 0); - } else { - Log.i(TAG, "nativerenderer done."); - nativeRenderer = null; - } - } - if (mGLSurfaceView != null) { - mGLSurfaceView.onDestroy(); - mGLSurfaceView = null; + if (nativeRenderer != null && nativeRenderer.isRenderingFrame()) { + Log.i(TAG, "Waiting for renderer to finish."); + int tries = 200; + do { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + tries--; + } while (nativeRenderer.isRenderingFrame() && tries > 0); } + mGLSurfaceView.onDestroy(); + mGLSurfaceView = null; } else { - if (mSurfaceView != null) { - mSurfaceView.onDestroy(); - mSurfaceView = null; - } - mSurface = null; + mSurfaceView.onDestroy(); + mSurfaceView = null; } // Probably vain attempt to help the garbage collector... @@ -763,7 +785,7 @@ public abstract class NativeActivity extends Activity { // TODO: Can we ensure that the GL thread has stopped rendering here? // I've seen crashes that seem to indicate that sometimes it hasn't... NativeApp.audioShutdown(); - if (shuttingDown) { + if (shuttingDown || isFinishing()) { NativeApp.shutdown(); unregisterCallbacks(); initialized = false; @@ -781,7 +803,6 @@ public abstract class NativeActivity extends Activity { super.onPause(); Log.i(TAG, "onPause"); loseAudioFocus(this.audioManager, this.audioFocusChangeListener); - sizeManager.setPaused(true); NativeApp.pause(); if (!javaGL) { mSurfaceView.onPause(); @@ -817,7 +838,6 @@ public abstract class NativeActivity extends Activity { protected void onResume() { super.onResume(); updateSustainedPerformanceMode(); - sizeManager.setPaused(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { updateSystemUiVisibility(); } @@ -846,7 +866,7 @@ public abstract class NativeActivity extends Activity { if (!javaGL) { // Restart the render loop. - startRenderLoopThread(); + ensureRenderLoop(); } } @@ -964,7 +984,11 @@ public abstract class NativeActivity extends Activity { // XInput device on Android returns source 1281 or 0x501, which equals GAMEPAD | KEYBOARD. // Shield Remote returns 769 or 0x301 which equals DPAD | KEYBOARD. - if (InputDeviceState.inputSourceIsJoystick(sources)) { + // Don't disable passthrough if app at top level. + if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD || + (sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || + (sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD)) + { passThrough = false; } @@ -1006,7 +1030,7 @@ public abstract class NativeActivity extends Activity { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) public boolean onGenericMotionEvent(MotionEvent event) { // Log.d(TAG, "onGenericMotionEvent: " + event); - if (InputDeviceState.inputSourceIsJoystick(event.getSource())) { + if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { InputDeviceState state = getInputDeviceState(event); if (state == null) { @@ -1059,7 +1083,7 @@ public abstract class NativeActivity extends Activity { case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_RIGHT: // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && InputDeviceState.inputSourceIsJoystick(event.getSource())) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { // Pass through / ignore return super.onKeyDown(keyCode, event); } @@ -1097,7 +1121,7 @@ public abstract class NativeActivity extends Activity { case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_RIGHT: // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && InputDeviceState.inputSourceIsJoystick(event.getSource())) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { return super.onKeyUp(keyCode, event); } // Fall through @@ -1108,36 +1132,19 @@ public abstract class NativeActivity extends Activity { } } - static int packResultCode(int requestCode, int requestId) { - return (requestCode << 16) | (requestId & 0xFFFF); - } - static int getRequestCode(int packedResult) { - return packedResult >> 16; // This will sign-extend, just like we want. - } - static int getRequestId(int packedResult) { - return packedResult & 0xFFFF; // The requestID is unsigned, so this is fine. - } - @Override - protected void onActivityResult(int packedRequest, int resultCode, Intent data) { - super.onActivityResult(packedRequest, resultCode, data); - - int requestCode = getRequestCode(packedRequest); - int requestId = getRequestId(packedRequest); - - Log.i(TAG, "onActivityResult: requestCode=" + requestCode + " requestId = " + requestId + " resultCode = " + resultCode); - - if (resultCode != RESULT_OK || data == null) { - NativeApp.sendRequestResult(requestId, false, "", resultCode); - return; - } - - try { - if (requestCode == RESULT_LOAD_IMAGE) { + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == RESULT_LOAD_IMAGE) { + if (resultCode != RESULT_OK || data == null) { + NativeApp.sendRequestResult(imageRequestId, false, "", 0); + return; + } + try { Uri selectedImage = data.getData(); if (selectedImage != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - NativeApp.sendRequestResult(requestId, true, selectedImage.toString(), 0); + NativeApp.sendRequestResult(imageRequestId, true, selectedImage.toString(), 0); } else { String[] filePathColumn = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null); @@ -1146,54 +1153,69 @@ public abstract class NativeActivity extends Activity { int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); - NativeApp.sendRequestResult(requestId, true, picturePath, 0); + NativeApp.sendRequestResult(imageRequestId, true, picturePath, 0); } } + } else { + NativeApp.sendRequestResult(imageRequestId, false, "", 0); } - } else if (requestCode == RESULT_OPEN_DOCUMENT) { - Uri selectedFile = data.getData(); - if (selectedFile != null) { - try { - // Grab permanent permission so we can show it in recents list etc. - if (Build.VERSION.SDK_INT >= 19) { - getContentResolver().takePersistableUriPermission(selectedFile, Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - } catch (Exception e) { - Log.w(TAG, "Exception getting permissions for document: " + e.toString()); - NativeApp.sendRequestResult(requestId, false, "", 0); - NativeApp.reportException(e, selectedFile.toString()); - return; - } - Log.i(TAG, "Browse file finished:" + selectedFile.toString()); - NativeApp.sendRequestResult(requestId, true, selectedFile.toString(), 0); - } - } else if (requestCode == RESULT_OPEN_DOCUMENT_TREE) { - Uri selectedDirectoryUri = data.getData(); - if (selectedDirectoryUri != null) { - String path = selectedDirectoryUri.toString(); - Log.i(TAG, "Browse folder finished: " + path); - try { - if (Build.VERSION.SDK_INT >= 19) { - getContentResolver().takePersistableUriPermission(selectedDirectoryUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - } - } catch (Exception e) { - Log.w(TAG, "Exception getting permissions for document: " + e.toString()); - NativeApp.reportException(e, selectedDirectoryUri.toString()); - // Even if we got an exception getting permissions, continue and try to pass along the file. Maybe this version of Android - // doesn't need it. If we can't access it, we'll fail in some other way later. - } - DocumentFile documentFile = DocumentFile.fromTreeUri(this, selectedDirectoryUri); - Log.i(TAG, "Chosen document name: " + documentFile.getUri()); - NativeApp.sendRequestResult(requestId, true, documentFile.getUri().toString(), 0); - } - } else { - Toast.makeText(getApplicationContext(), "Bad request code: " + requestCode, Toast.LENGTH_LONG).show(); - NativeApp.sendRequestResult(requestId, false, null, resultCode); - // Can't send a sensible request result back to the app without a requestCode + } catch (Exception e) { + Log.w(TAG, "Exception receiving image: " + e); } - } catch (Exception e) { - NativeApp.reportException(e, "(function level)"); - NativeApp.sendRequestResult(requestId, false, null, resultCode); + imageRequestId = -1; + } else if (requestCode == RESULT_OPEN_DOCUMENT) { + if (resultCode != RESULT_OK || data == null) { + NativeApp.sendRequestResult(fileRequestId, false, "", 0); + return; + } + Uri selectedFile = data.getData(); + if (selectedFile != null) { + try { + // Grab permanent permission so we can show it in recents list etc. + if (Build.VERSION.SDK_INT >= 19) { + getContentResolver().takePersistableUriPermission(selectedFile, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } catch (Exception e) { + Log.w(TAG, "Exception getting permissions for document: " + e.toString()); + NativeApp.sendRequestResult(fileRequestId, false, "", 0); + return; + } + // Even if we got an exception getting permissions, try to pass along the file. Maybe this version of Android + // doesn't need it. + Log.i(TAG, "Browse file finished:" + selectedFile.toString()); + NativeApp.sendRequestResult(fileRequestId, true, selectedFile.toString(), 0); + } + fileRequestId = -1; + } else if (requestCode == RESULT_OPEN_DOCUMENT_TREE) { + if (resultCode != RESULT_OK || data == null) { + NativeApp.sendRequestResult(folderRequestId, false, "", 0); + return; + } + Uri selectedDirectoryUri = data.getData(); + if (selectedDirectoryUri != null) { + String path = selectedDirectoryUri.toString(); + Log.i(TAG, "Browse folder finished: " + path); + try { + if (Build.VERSION.SDK_INT >= 19) { + getContentResolver().takePersistableUriPermission(selectedDirectoryUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } + } catch (Exception e) { + Log.w(TAG, "Exception getting permissions for document: " + e.toString()); + } + // Even if we got an exception getting permissions, try to pass along the file. Maybe this version of Android + // doesn't need it. If we can't access it, we'll fail in some other way later. + DocumentFile documentFile = DocumentFile.fromTreeUri(this, selectedDirectoryUri); + Log.i(TAG, "Document name: " + documentFile.getUri()); + /* + // Old debug log + DocumentFile[] children = documentFile.listFiles(); + for (DocumentFile child : children) { + Log.i(TAG, "Child: " + child.getUri() + " " + child.getName()); + } + */ + NativeApp.sendRequestResult(folderRequestId, true, documentFile.getUri().toString(), 0); + } + folderRequestId = -1; } } @@ -1270,15 +1292,13 @@ public abstract class NativeActivity extends Activity { .setPositiveButton(defaultAction, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int which) { - Log.i(TAG, "input box successful"); NativeApp.sendRequestResult(requestId, true, input.getText().toString(), 0); - d.dismiss(); // It's OK that this will cause an extra dismiss message. It'll be ignored since the request number has already been processed. + d.dismiss(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int which) { - Log.i(TAG, "input box cancelled"); NativeApp.sendRequestResult(requestId, false, "", 0); d.cancel(); } @@ -1287,7 +1307,6 @@ public abstract class NativeActivity extends Activity { builder.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface d) { - Log.i(TAG, "input box dismissed"); NativeApp.sendRequestResult(requestId, false, "", 0); updateSystemUiVisibility(); } @@ -1323,7 +1342,6 @@ public abstract class NativeActivity extends Activity { startActivity(i); return true; } catch (Exception e) { - NativeApp.reportException(e, params); // No browser? Log.e(TAG, e.toString()); return false; @@ -1340,57 +1358,50 @@ public abstract class NativeActivity extends Activity { startActivity(Intent.createChooser(send, "E-mail the app author!")); return true; } catch (Exception e) { // For example, android.content.ActivityNotFoundException - NativeApp.reportException(e, params); Log.e(TAG, e.toString()); return false; } } else if (command.equals("browse_image")) { try { - int requestId = Integer.parseInt(params); - int packedResultCode = packResultCode(RESULT_LOAD_IMAGE, requestId); - Log.i(TAG, "image request ID: " + requestId + " packed: " + packedResultCode); + imageRequestId = Integer.parseInt(params); + Log.i(TAG, "image request ID: " + imageRequestId); Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); - startActivityForResult(i, packedResultCode); + startActivityForResult(i, RESULT_LOAD_IMAGE); return true; } catch (Exception e) { // For example, android.content.ActivityNotFoundException - NativeApp.reportException(e, params); + imageRequestId = -1; Log.e(TAG, e.toString()); return false; } - } else if (command.equals("browse_file") || command.equals("browse_file_audio")) { + } else if (command.equals("browse_file")) { try { - int requestId = Integer.parseInt(params); - int packedResultCode = packResultCode(RESULT_OPEN_DOCUMENT, requestId); - Log.i(TAG, "browse_file request ID: " + requestId + " packed: " + packedResultCode); + fileRequestId = Integer.parseInt(params); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); - if (command.equals("browse_file_audio")) { - intent.setType("audio/x-wav"); - } else { - intent.setType("*/*"); - } + intent.setType("*/*"); intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); - startActivityForResult(intent, packedResultCode); + // Possible alternative approach: + // String[] mimeTypes = {"application/octet-stream", "/x-iso9660-image"}; + // intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes); + startActivityForResult(intent, RESULT_OPEN_DOCUMENT); // intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri); } catch (Exception e) { - NativeApp.reportException(e, params); + fileRequestId = -1; Log.e(TAG, e.toString()); return false; } } else if (command.equals("browse_folder")) { try { - int requestId = Integer.parseInt(params); - int packedResultCode = packResultCode(RESULT_OPEN_DOCUMENT_TREE, requestId); - Log.i(TAG, "browse_folder request ID: " + requestId + " packed: " + packedResultCode); + folderRequestId = Integer.parseInt(params); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); // Only allow local folders. - startActivityForResult(intent, packedResultCode); + startActivityForResult(intent, RESULT_OPEN_DOCUMENT_TREE); return true; } catch (Exception e) { - NativeApp.reportException(e, params); + folderRequestId = -1; Log.e(TAG, e.toString()); return false; } @@ -1404,7 +1415,6 @@ public abstract class NativeActivity extends Activity { startActivity(shareIntent); return true; } catch (Exception e) { // For example, android.content.ActivityNotFoundException - NativeApp.reportException(e, params); Log.e(TAG, e.toString()); return false; } @@ -1505,9 +1515,9 @@ public abstract class NativeActivity extends Activity { recreate(); } else if (command.equals("ask_permission") && params.equals("storage")) { if (askForPermissions(permissionsForStorage, REQUEST_CODE_STORAGE_PERMISSION)) { - NativeApp.sendMessageFromJava("permission_pending", "storage"); + NativeApp.sendMessage("permission_pending", "storage"); } else { - NativeApp.sendMessageFromJava("permission_granted", "storage"); + NativeApp.sendMessage("permission_granted", "storage"); } } else if (command.equals("gps_command")) { if (params.equals("open")) { @@ -1552,12 +1562,6 @@ public abstract class NativeActivity extends Activity { // Only keep the screen bright ingame. window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } - } else if (command.equals("testException")) { - try { - throw new Exception(); - } catch (Exception e) { - NativeApp.reportException(e, params); - } } return false; } diff --git a/android/src/org/ppsspp/ppsspp/NativeApp.java b/android/src/org/ppsspp/ppsspp/NativeApp.java index d155ddc22..00ee71d57 100644 --- a/android/src/org/ppsspp/ppsspp/NativeApp.java +++ b/android/src/org/ppsspp/ppsspp/NativeApp.java @@ -50,7 +50,7 @@ public class NativeApp { public static native void accelerometer(float x, float y, float z); - public static native void sendMessageFromJava(String msg, String arg); + public static native void sendMessage(String msg, String arg); public static native void sendRequestResult(int seqID, boolean result, String value, int iValue); public static native String queryConfig(String queryName); @@ -58,27 +58,4 @@ public class NativeApp { public static native void setGpsDataAndroid(long time, float hdop, float latitude, float longitude, float altitude, float speed, float bearing); public static native void setSatInfoAndroid(short index, short id, short elevation, short azimuth, short snr, short good); public static native void pushCameraImageAndroid(byte[] image); - - // Wrappers - public static void reportException(Exception e, String data) { - String str = e.toString() + "\n" + e.getMessage() + "\n"; - if (data != null) { - str += data + "\n"; - } - // could also use import android.util.Log; String stackTrace = Log.getStackTraceString(exception); - int count = 0; - for (StackTraceElement ste : e.getStackTrace()) { - str += ste + "\n"; - // Only bother with the top of the stack. - if (count > 3) { - break; - } - count++; - } - NativeApp.sendMessageFromJava("exception", str); - } - - public static void reportError(String errorStr) { - NativeApp.sendMessageFromJava("exception", errorStr); - } } diff --git a/android/src/org/ppsspp/ppsspp/NativeGLView.java b/android/src/org/ppsspp/ppsspp/NativeGLView.java index d6a67ab00..6dbf91974 100644 --- a/android/src/org/ppsspp/ppsspp/NativeGLView.java +++ b/android/src/org/ppsspp/ppsspp/NativeGLView.java @@ -189,11 +189,11 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, case StateEvent.ACTION_CONNECTED: Log.i(TAG, "Moga Connected"); if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) == Controller.ACTION_VERSION_MOGA) { - NativeApp.sendMessageFromJava("moga", "Moga"); + NativeApp.sendMessage("moga", "Moga"); } else { Log.i(TAG, "MOGA Pro detected"); isMogaPro = true; - NativeApp.sendMessageFromJava("moga", "MogaPro"); + NativeApp.sendMessage("moga", "MogaPro"); } break; case StateEvent.ACTION_CONNECTING: @@ -201,7 +201,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, break; case StateEvent.ACTION_DISCONNECTED: Log.i(TAG, "Moga Disconnected (or simply Not connected)"); - NativeApp.sendMessageFromJava("moga", ""); + NativeApp.sendMessage("moga", ""); break; } break; diff --git a/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java b/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java index 81625b3f9..fa70f96cc 100644 --- a/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java +++ b/android/src/org/ppsspp/ppsspp/NativeSurfaceView.java @@ -186,11 +186,11 @@ public class NativeSurfaceView extends SurfaceView implements SensorEventListene case StateEvent.ACTION_CONNECTED: Log.i(TAG, "Moga Connected"); if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) == Controller.ACTION_VERSION_MOGA) { - NativeApp.sendMessageFromJava("moga", "Moga"); + NativeApp.sendMessage("moga", "Moga"); } else { Log.i(TAG, "MOGA Pro detected"); isMogaPro = true; - NativeApp.sendMessageFromJava("moga", "MogaPro"); + NativeApp.sendMessage("moga", "MogaPro"); } break; case StateEvent.ACTION_CONNECTING: @@ -198,7 +198,7 @@ public class NativeSurfaceView extends SurfaceView implements SensorEventListene break; case StateEvent.ACTION_DISCONNECTED: Log.i(TAG, "Moga Disconnected (or simply Not connected)"); - NativeApp.sendMessageFromJava("moga", ""); + NativeApp.sendMessage("moga", ""); break; } break; diff --git a/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java b/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java index b480c9e90..38649b873 100644 --- a/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java +++ b/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java @@ -108,9 +108,9 @@ public class PowerSaveModeReceiver extends BroadcastReceiver { try { if (isBatteryLow || isPowerSaving) { - NativeApp.sendMessageFromJava("core_powerSaving", "true"); + NativeApp.sendMessage("core_powerSaving", "true"); } else { - NativeApp.sendMessageFromJava("core_powerSaving", "false"); + NativeApp.sendMessage("core_powerSaving", "false"); } } catch (Exception e) { Log.e(TAG, "Exception in sendPowerSaving: " + e.toString()); diff --git a/android/src/org/ppsspp/ppsspp/SizeManager.java b/android/src/org/ppsspp/ppsspp/SizeManager.java index af81f640d..174396f86 100644 --- a/android/src/org/ppsspp/ppsspp/SizeManager.java +++ b/android/src/org/ppsspp/ppsspp/SizeManager.java @@ -39,18 +39,10 @@ public class SizeManager implements SurfaceHolder.Callback { private Point desiredSize = new Point(); private int badOrientationCount = 0; - - private boolean paused = false; - public SizeManager(final NativeActivity a) { activity = a; } - - public void setPaused(boolean p) { - paused = p; - } - @TargetApi(Build.VERSION_CODES.P) public void setSurfaceView(SurfaceView view) { surfaceView = view; @@ -115,11 +107,7 @@ public class SizeManager implements SurfaceHolder.Callback { NativeApp.backbufferResize(width, height, format); updateDisplayMeasurements(); - if (!paused) { - activity.notifySurface(holder.getSurface()); - } else { - Log.i(TAG, "Skipping notifySurface while paused"); - } + activity.notifySurface(holder.getSurface()); } @Override @@ -215,7 +203,7 @@ public class SizeManager implements SurfaceHolder.Callback { safeInsetTop = 0; safeInsetBottom = 0; } - NativeApp.sendMessageFromJava("safe_insets", safeInsetLeft + ":" + safeInsetRight + ":" + safeInsetTop + ":" + safeInsetBottom); + NativeApp.sendMessage("safe_insets", safeInsetLeft + ":" + safeInsetRight + ":" + safeInsetTop + ":" + safeInsetBottom); } } } diff --git a/android/src/org/ppsspp/ppsspp/TextRenderer.java b/android/src/org/ppsspp/ppsspp/TextRenderer.java index 60b18912c..6e753c873 100644 --- a/android/src/org/ppsspp/ppsspp/TextRenderer.java +++ b/android/src/org/ppsspp/ppsspp/TextRenderer.java @@ -14,7 +14,7 @@ public class TextRenderer { p = new Paint(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); p.setColor(Color.WHITE); bg = new Paint(); - bg.setColor(0); + bg.setColor(Color.BLACK); } public static void init(Context ctx) { @@ -61,10 +61,10 @@ public class TextRenderer { total.x = 1; if (total.y < 1) total.y = 1; - if (total.x > 4096) - total.x = 4096; - if (total.y > 4096) - total.y = 4096; + if (total.x > 2048) + total.x = 2048; + if (total.y > 2048) + total.y = 2048; return total; } diff --git a/assets/compat.ini b/assets/compat.ini index c0c1da77f..e21f9e748 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -79,11 +79,6 @@ NPJH50579 = true ULJS19069 = true NPJH50579 = true -# After Burner: Black Falcon (#8514, only affects video) -ULUS10244 = true -ULES00753 = true -ULES00785 = true - [PixelDepthRounding] # Heroes Phantasia requires pixel depth rounding. #6485 (flickering overlaid sprites) NPJH50558 = true @@ -265,11 +260,10 @@ ULJM06365 = true # This hacks separates each mipmap to independent textures to display wrong-size mipmaps. # For example this requires games like Tactics Ogre(Japanese) to display multi bytes fonts stored in mipmaps. # See issue #5350. -# Tactics Ogre (Japanese) +# Tactics Ogre(Japanese) ULJM05753 = true NPJH50348 = true ULJM06009 = true -# We handle the US/EU versions by detecting its weird use of two identical mipmaps and treating it as a normal 2D texture (#17491 / #17980) [RequireBufferedRendering] # Warn the user that the game will not work and have issue, if buffered rendering is not enabled. @@ -300,9 +294,6 @@ ULJM05359 = true ULJM05885 = true NPJH50825 = true ULKS46157 = true -# Sindacco Chronicles total conversion -ULUS01826 = true - # GOW : Ghost of Sparta UCUS98737 = true UCAS40323 = true @@ -796,14 +787,6 @@ ULJM05687 = true ULJM05440 = true ULKS46164 = true -# Qix++ (see issue #13724) -ULJM05617 = true -NPJH50199 = true - -# Mahou Shoujo Madoka Magica Portable #6557 -ULJS00430 = true -ULJS00429 = true - [GoWFramerateHack60] # Replaces ForceMax60FPS for GOW games, should provide smoother experience # Also works around softlock in GOW:GOS , see #8299 @@ -1082,10 +1065,6 @@ ULJM08022 = true NPJH50126 = true ULJM08052 = true ULAS42316 = true -# Doko Demo Issho - issue #18420 -UCJS10002 = true -UCJS10039 = true -UCJS18012 = true [MemstickFixedFree] ULJM05571 = true @@ -1158,12 +1137,7 @@ ULKS46087 = true # Burnout Dominator - lens flare effect (issue #11100) ULUS10236 = true -ULES00750 = true -ULJM05242 = true -ULJM05371 = true -NPJH50304 = true ULES00703 = true -ULAS42095 = true # Need for Speed - Shift (same as Burnout Dominator) ULUS10462 = true @@ -1317,12 +1291,7 @@ ULKS46087 = true # Burnout Dominator - lens flare effect (issue #11100) # Some of the steps don't work at high resolution yet. ULUS10236 = true -ULES00750 = true -ULJM05242 = true -ULJM05371 = true -NPJH50304 = true ULES00703 = true -ULAS42095 = true # Need for Speed - Shift (same as Burnout Dominator) ULUS10462 = true @@ -1509,14 +1478,6 @@ ULJM05160 = true NPJH50717 = true ULJM06223 = true -# Danball Senki, issue #17622 -ULJS00361 = true -# Danball Senki Boost -ULJM05990 = true - -# Shining Blade -NPJH50530 = true - [DisallowFramebufferAtOffset] # Little Big Planet, see #16030 UCUS98744 = true @@ -1525,21 +1486,6 @@ UCJS10107 = true NPJG00073 = true UCAS40262 = true -# WWE Smackdown vs RAW 2006 : See #13797 -ULES00227 = true -ULKS46057 = true -ULUS10050 = true - -# WWE Smackdown vs RAW 2007 -ULUS10199 = True -ULES00631 = True -ULJM05233 = True - -# Rainbow Six: Vegas: See #9324 -# Replaces a heuristic we added in #16971, which broke Castlevania - Symphony of the Night. -ULES00584 = true -ULUS10206 = true - [RockmanDash2SoundFix] # Rockman Dash 2, see #11442 ULJM05037 = true @@ -1632,59 +1578,3 @@ NPEG90024 = true # demo UCJS10102 = true NPJG00035 = true NPJG90068 = true # demo - -[Fontltn12Hack] -# optimumFont do not return ltn12.pgf see #11055 -NPJH00052 = true - -[LoadCLUTFromCurrentFrameOnly] -# Helps Syphon Filter: Logan's Shadow color issue, # where we accidentally load a CLUT from an outdated framebuffer. -# Perhaps this should be the default. -UCUS98606 = true -UCES00710 = true -NPUG80173 = true -NPUA80013 = true # Demo -UCUS98704 = true # Demo -NPEG90002 = true # Demo -SYPH04036 = true # Prototype? - -[ForceUMDReadSpeed] -# Aces of War required slow read speed (even in Real PSP), see #11062 -ULES00590 = true -ULJM05075 = true -# Sengoku Musou 3Z Special DLC see #9993 -ULJM06024 = true - -# Bejeweled 2. This shouldn't really fix anything since it's a PSN game that didn't run from UMD, -# but apparently it does work around the timing error. See issue #15304 . -NPUG30038 = true -NPEG00036 = true - -# Doko Demo Issho, load savedata error see #18420 -UCJS10002 = true -UCJS18002 = true - -# Driver 76, see #16904 #12054 -ULUS10235 = true -ULES00740 = true - -# Harukanaru Toki no Naka de 3 with Izayoiki Aizouban, see #6127 -ULJM05441 = true -KOEIP0167 = true -ULJM06245 = true - -# Ace Combat: Joint Assault #12434 -ULUS10511 = true -ULES01408 = true - -# Ace Combat X2: Joint Assault #5545 -ULJS00290 = true -ULKS46254 = true -ULJS19057 = true -NPJH50263 = true - -[AllowDelayedReadbacks] -# NOTE: This only affects Vulkan currently. -# Added for easy experimentation. Many games using readbacks do not work well delaying them, though. -# For example, Motorstorm lighting adaptation goes into self-oscillation (!) -# UCES01250 = true diff --git a/assets/compatvr.ini b/assets/compatvr.ini index 015a9e1cf..ce24b5cbb 100644 --- a/assets/compatvr.ini +++ b/assets/compatvr.ini @@ -75,16 +75,9 @@ UCJS10104 = true UCKS45124 = true UCUS98743 = true -# Ultimate Ghosts 'n Goblins -NPJH50235 = true -UCKS45037 = true -ULJM05147 = true -ULES00419 = true -ULUS10105 = true - [IdentityViewHack] -# Disables head tracking for render passes where view matrix is identity +# Disables head tracking for render passes where view matrix is Identity # Sonic Rivals 1 ULES00622 = true @@ -95,16 +88,6 @@ ULES00940 = true ULUS10323 = true -[MirroringVariant] -# Forces mirroring of the view matrix - -# Tony Hawk's Underground 2 Remix -ULES00033 = 3 -ULES00034 = 3 -ULES00035 = 3 -ULUS10014 = 3 - - [Skyplane] # Workaround to remove the background skyplane and add clearing framebuffer with a fog color. @@ -118,8 +101,6 @@ ULJM05255 = true ULJM05359 = true ULJM05885 = true ULUS10041 = true -# Sindacco Chronicles total conversion -ULUS01826 = true # Grand Theft Auto: Vice City Stories NPJH50827 = true @@ -443,8 +424,6 @@ ULJM05255 = 0.5 ULJM05359 = 0.5 ULJM05885 = 0.5 ULUS10041 = 0.5 -# Sindacco Chronicles total conversion -ULUS01826 = 0.5 # Hatsune Miku: Project Diva NPJH50494 = 3.6 diff --git a/assets/gamecontrollerdb.txt b/assets/gamecontrollerdb.txt index 1cc65709a..1c45e96ff 100644 --- a/assets/gamecontrollerdb.txt +++ b/assets/gamecontrollerdb.txt @@ -1,1854 +1,3 @@ -# Game Controller DB for SDL in 2.0.16 format -# Source: https://github.com/gabomdq/SDL_GameControllerDB - -# Windows -03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, -03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, -03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, -03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, -03000000d0160000060d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, -03000000d0160000070d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, -03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, -03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows, -03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00002090000000000000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows, -03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows, -03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, -03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, -03000000c82d00006928000000000000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows, -03000000c82d00002590000000000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows, -03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000131000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows, -03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, -030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows, -030000006f0e00008801000000000000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, -03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows, -03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows, -03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows, -03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, -03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, -030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows, -030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000bc2000000055000000000000,Betop BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000790000000700000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, -03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows, -030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, -030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, -030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, -030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, -030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows, -030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000a306000022f6000000000000,Cyborg V.3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows, -030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000c0160000e105000000000000,Dual Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows, -030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, -03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows, -030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, -03000000317300000100000000000000,DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows, -03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, -03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, -030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, -030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, -030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows, -03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, -03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00008101000000000000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows, -03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows, -03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows, -03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows, -03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows, -03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows, -0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, -03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, -03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows, -03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows, -03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000ac0500004d04000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000ac0500001a06000000000000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows, -030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000c9110000f055000000000000,GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, -030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows, -03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, -030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00008800000000000000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows, -030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows, -030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows, -030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002301000000000000,Hori PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -030000000d0f00001100000000000000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, -030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows, -030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows, -03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows, -03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, -03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows, -03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, -03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows, -03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows, -03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, -03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, -03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, -03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows, -03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, -03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows, -03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, -03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, -030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows, -030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, -03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows, -03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, -03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows, -03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, -030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, -030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows, -030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, -03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, -030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, -030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, -0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, -03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows, -030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, -03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows, -0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows, -030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows, -030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, -030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, -030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows, -03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows, -03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows, -03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, -03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, -03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows, -03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows, -030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows, -0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows, -03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, -03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, -03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, -03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows, -03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows, -03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows, -030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows, -030000007e0500001720000000000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Windows, -03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows, -03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows, -030000005509000000b4000000000000,NVIDIA Virtual,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000004b120000014d000000000000,Nyko Airflo,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, -03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows, -030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows, -03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows, -03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows, -03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000632500002306000000000000,PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, -03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d620000013a7000000000000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000250900000088000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000151a00006222000000000000,PS2 Dual Plus Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000250900000218000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, -030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows, -030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, -03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, -030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, -030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows, -03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, -030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, -030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, -03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows, -03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, -03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, -03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows, -03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, -03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, -030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, -030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, -030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows, -030000009b2800006200000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, -030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, -030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, -030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows, -030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, -030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows, -030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows, -030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, -030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, -030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, -030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows, -030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, -030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, -030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, -03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows, -03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows, -03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, -03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, -03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Windows, -0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows, -030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e00008701000000000000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, -03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, -03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, -03000000050b0000181a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, -03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, -03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, -030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000a306000023f6000000000000,Saitek Cyborg V.1 Game,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows, -03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows, -03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, -03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows, -03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001001000000000000,Saitek P480 Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows, -03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000a30600002106000000000000,Saitek PS1000 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows, -03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows, -03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows, -03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, -03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows, -03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, -03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, -0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, -03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, -03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, -030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, -03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, -03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, -03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, -03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows, -030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, -03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, -03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows, -03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, -030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows, -03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows, -030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows, -03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows, -03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, -03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, -03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows, -030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004f04000008d0000000000000,ThrustMaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, -030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -030000004f04000003d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004f04000009d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000571d00002100000000000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows, -03000000571d00002000000000000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, -03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, -03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, -03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows, -03000000300f00000701000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000341a00002308000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000666600000188000000000000,USB Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -030000006b1400000203000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000790000000a00000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -03000000b404000081c6000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, -03000000b50700001503000000000000,USB Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, -03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, -03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, -03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows, -03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows, -03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, -030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000450c00002043000000000000,Xeox SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, -03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, -xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows, -03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, -03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, - -# Mac OS X -030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, -03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X, -03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, -03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X, -03000000c82d00002590000000010000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00002690000000010000,8BitDo NEOGEOa:b0,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,b:b1,back:b10,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X, -03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001130000000020000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001330000001000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001330000000020000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X, -03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X, -03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, -03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, -03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, -03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X, -03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, -03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, -03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X, -030000006f0e00008401000003010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X, -03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, -03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X, -030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X, -030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X, -030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f0000aa00000072050000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X, -03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X, -03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, -03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X, -03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X, -030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, -030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000006d04000019c2000000000000,Logitech Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000016c2000000000000,Logitech F310,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X, -03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, -03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, -0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008f0e00001030000011010000,Mayflash Saturn Adapter,a:b0,b:b2,dpdown:b28,dpleft:b30,dpright:b26,dpup:b24,leftshoulder:b10,lefttrigger:b14,rightshoulder:b12,righttrigger:b4,start:b18,x:b6,y:b8,platform:Mac OS X, -0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, -03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X, -03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, -03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, -030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X, -030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X, -030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X, -030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, -03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, -03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X, -030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X, -030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,platform:Mac OS X, -030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X, -030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, -030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X, -030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000666600006706000088020000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X, -030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000d620000011a7000010050000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, -030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, -050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, -050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, -030000005e040000e002000001000000,PXN P30 Pro Mobile,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, -03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, -030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, -0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -030000000d0f0000c100000072050000,Retro Bit Sega Genesis 6B Controller,a:b2,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b8,rightshoulder:b6,righttrigger:b7,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X, -03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X, -03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X, -030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X, -030000006f0e00008701000005010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000e804000000a000001b010000,Samsung EIGP20,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b11,leftx:a1,lefty:a3,rightshoulder:b12,rightx:a4,righty:a5,start:b16,x:b7,y:b9,platform:Mac OS X, -03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X, -03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X, -03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, -03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, -030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, -030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, -030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, -03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, -03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, -05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, -050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, -03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, -03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, -030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, -03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X, -030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, -030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, -03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X, -03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, -030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, -03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X, -030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, -030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000c62400003a54000000000000,Xbox One PowerA Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, -03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, - -# Linux -030000005e0400008e02000020010000,8BitDo Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, -03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Linux, -05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00002090000011010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, -03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux, -05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, -05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, -03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux, -05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, -030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00000631000014010000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, -03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, -05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00003901000013020000,Afterglow Prismatic Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00001302000000010000,Afterglow Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000100000008200000011010000,Akishop Customs PS360,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000007c1800000006000010010000,Alienware Dual Compatible Game PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux, -05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, -05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, -03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, -03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, -05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, -05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, -03000000050b00000579000011010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000503200000110000000000000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, -03000000503200000110000011010000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, -05000000503200000110000000000000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, -05000000503200000110000044010000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, -05000000503200000110000046010000,Atari Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, -03000000503200000210000000000000,Atari Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, -03000000503200000210000011010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, -05000000503200000210000000000000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, -05000000503200000210000045010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, -05000000503200000210000046010000,Atari Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, -05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, -03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000bc2000004d50000011010000,BEITONG A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000bc2000000055000001000000,BETOP AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, -03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, -030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux, -03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, -19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux, -190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux, -190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b2,y:b3,platform:Linux, -0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, -0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000632500002605000010010000,HJDX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux, -030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux, -030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f0000aa00000011010000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux, -03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux, -03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux, -03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, -03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, -03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, -03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, -0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, -050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, -030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, -050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, -03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000242f00002d00000011010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, -030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001ec2000019200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux, -03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000380700001888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700003888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux, -03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, -0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000008f0e00001030000010010000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, -0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, -03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, -03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, -030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux, -030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, -030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, -030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux, -030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000ea02000008040000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, -050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -05000000e80400006e0400001b010000,Mocute 053X M59,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000d6200000e589000001000000,Moga 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, -05000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, -03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux, -03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, -030000009b2800008000000020020000,Nintendo Classic Controller,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, -030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, -03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, -060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, -060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, -050000004c69632050726f20436f6e00,Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux, -030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux, -030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, -050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, -050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux, -030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux, -030000007e0500001920000011810000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux, -050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux, -050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux, -030000007e0500001720000011810000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, -050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux, -050000007e0500001720000001800000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, -03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, -05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, -19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, -19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux, -03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:Linux, -05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux, -03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux, -030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00008501000011010000,PDP Fightpad Pro Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000666600006706000000010000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, -030000004c050000da0c000011010000,PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, -03000000d9040000160f000000010000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d620000013a7000011010000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000d620000014a7000011010000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, -03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000005f1400003102000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, -030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, -050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, -050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, -03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, -03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, -03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, -030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux, -030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, -030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, -03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, -190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux, -00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux, -03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Linux, -030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00008701000011010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux, -03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux, -03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux, -03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000a30600000b04000000010000,Saitek P990 Dual Analog,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, -03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux, -03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux, -03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux, -03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, -03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, -030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, -03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000632500007505000010010000,Shanwan PS3 PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000bc2000000055000010010000,Shanwan PS3 PC ,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, -03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -05000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, -03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, -03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, -03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000de2800000512000010010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux, -050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux, -03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux, -030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux, -03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, -03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, -030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f0400000ed0000011010000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux, -030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux, -030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000680a00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, -03000000780300000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, -03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, -03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, -030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, -03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, -030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, -030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000000010000,Xbox 360 EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, -030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000ea02000001030000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000007050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, -03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, -xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000120c0000100e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000120c0000101e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, - -# Android -38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, -34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, -38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, -32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, -38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, -64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, -66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, -66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, -38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, -61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, -62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, -33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, -38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, -05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, -38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, -32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android, -38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android, -38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, -61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, -05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android, -33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, -63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, -35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,start:b6,platform:Android, -32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, -05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, -05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android, -66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, -65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android, -31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -30306539356238653637313730656134,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, -62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, -31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android, -5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android, -64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android, -532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android, -65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, -33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, -38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, -64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, -6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android, -436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, -37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, -30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, -39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android, -31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, -37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, -64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, -33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, -30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, -32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, -050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, -34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android, -36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, -4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, -534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, -050000005509000003720000cf7f3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005509000010720000ffff3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005509000014720000df7f3f00,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, -050000005509000014720000df7f3f80,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android, -37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, -4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, -506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, -62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, -536f6e7920496e746572616374697665,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -576972656c65737320436f6e74726f6c,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, -32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, -050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android, -050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android, -31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, -050000004c050000e60c0000fffe3f80,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android, -050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, -64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, -36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android, -32417865732031314b6579732047616d,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, -526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android, -61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, -38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -526574726f696420506f636b65742043,Retroid Pocket Flip,a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -582d426f7820436f6e74726f6c6c6572,Retroid Pocket Flip,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, -37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, -5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, -526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, -64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, -37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, -33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, -36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android, -32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, -38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, -61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, -30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, -66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, -62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, -38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, -5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, -5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, -63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, -63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, -476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -5374616469614e3848532d6532633400,Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, -05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, -0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, -35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android, -54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android, -38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android, -050000004f0400000ed00000fffe3f00,ThrustMaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, -30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, -33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, -050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -65353331386662343338643939643636,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -65613532386633373963616462363038,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e04000091020000ff073f00,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -050000005e04000091020000ff073f80,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000e00200000ffe3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, -050000005e040000e00200000ffe3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android, -050000005e040000e0020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, -050000005e040000e0020000ffff3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android, -050000005e040000fd020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, -35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, -050000005e040000120b000000783f80,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -050000001727000044310000ffff3f00,XiaoMi Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, - -# iOS -05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, -05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, -05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, -05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, -05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, -050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, -4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, -050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS, -050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS, -050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, -050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+rightx:h0.4,+righty:h0.8,-rightx:h0.1,-righty:h0.2,a:b1,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b2,platform:iOS, -050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, -050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS, -050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,platform:iOS, -050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS, -05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, -05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, -05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, -05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, -050000005e040000050b0000df070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000005e040000050b0000ff070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000005e040000e0020000df070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000005e040000e0020000ff070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -# The below is from PPSSPP's old gamecontrollerdb.txt. # Windows - DINPUT 8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2, 341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 410f5b148..bc97b2502 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -6,69 +6,10 @@ # perl -CSAD -p -i -e 's/(.* = )(?!\x{200e})(.*\p{Arabic}.*)/\1\x{200e}\2/g' ar_AE.ini -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = ‎(إعادة التشغيل مطلوبة) الخلفية الصوتية Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = ‎معادلة مصادقة البلوتوث (بطئ) Auto = Auto Device = Device @@ -103,7 +44,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = ‎معايرة Calibrated = Calibrated Calibration = ‎المعايرة -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = ‎كلاسيكي Confine Mouse = ‎حجز مؤشر الماوس في حدود نافذة البرنامج @@ -116,10 +56,8 @@ Deadzone radius = ‎مساحة المنطقة الميتة Disable D-Pad diagonals (4-way touch) = ‎(4طرق للمس)تعطيل أقطار D-Pad Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -148,7 +86,6 @@ OnScreen = ‎تحكم لمس الشاشة Portrait = ‎طولية Portrait Reversed = ‎طولية معكوسة PSP Action Buttons = ‎PSP أزرار الأفعال الخاصة بـ -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -157,7 +94,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = ‎الحساسية Shape = Shape Show Touch Pause Menu Button = ‎أظهر زر قائمة التوقف المؤقت -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -238,7 +174,6 @@ Log Console = ‎&سجل الكونسول Memory View... = ‎عرض الرام... More Settings... = ‎&إعدادات إضافية... Nearest = ‎&الأقرب -Recent = &Recent Skip Buffer Effects = ‎&تخطي تأثيرات الصقل (غير مصقول, أسرع) Off = ‎&مغلق Open Chat = Open Chat @@ -277,6 +212,7 @@ Texture Filtering = Te&xture filtering Texture Scaling = ‎&تكبير الرسوم Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = ‎&مخزن الفريتكس VSync = VS&ync Vulkan = ‎فولكان Window Size = ‎&حجم النافذة @@ -290,11 +226,8 @@ Backspace = Backspace Block address = Block address By Address = ‎بالعنوان Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = ‎الحالي -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = ‎أدوات التطوير DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -305,11 +238,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = ‎تفعيل سجل التصحيح Enter address = ‎أدخل العنوان FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -319,10 +249,8 @@ Log Dropped Frame Statistics = ‎سجل التفاصيل للفريمات ال Log Level = ‎مستوي السجل Log View = ‎أظهر السجل Logging Channels = ‎قنوات التسجيل -Multi-threaded rendering = Multi-threaded rendering Next = ‎التالي No block = ‎لا بوك -Off = Off Prev = ‎السابق Random = ‎عشوائي Replace textures = ‎إستبدال الرسوم @@ -340,12 +268,10 @@ Stats = ‎الحالات System Information = ‎معلومات النظام Texture ini file created = Texture ini file created Texture Replacement = ‎إستبدال الرسوم -Audio Debug = ‎تفعيل تصحيح الصوت -Control Debug = Control Debug +Toggle Audio Debug = ‎تفعيل تصحيح الصوت +Toggle Control Debug = Toggle Control Debug Toggle Freeze = ‎تفعيل الإيقاف Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -353,14 +279,10 @@ VFPU = VFPU * PSP res = ‎* PSP حجم Active = Active Back = ‎رجوع -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = ‎إلغاء Center = ‎المركز -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = ‎تغيير واجهة معالجة من كرت الشاشة يتطلب إعادة التشغيل. إعادة تشغيل الأن؟ +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = ‎إختر PPSSPP مجلد الحفظ الخاص بـ Confirm Overwrite = ‎هل تريد الكتابة علي هذه البيانات? @@ -380,46 +302,33 @@ DeleteConfirmGameConfig = ‎هل تود حقاً مسح الإعدادات له DeleteFailed = ‎غير قادر علي مسح البيانات. Deleting = ‎يمسح\nمن فضلك إنتظر... Disable All = ‎عطل الكل -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = ‎فعل الكل -Enabled = Enabled Enter = ‎إدخال -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = ‎إنهاء GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = ‎تحميل Load completed = ‎التحميل إكتمل. Loading = ‎تحميل\nمن فضلك إنتظر... LoadingFailed = ‎غير قادر علي تحميل البيانات. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = ‎تحريك Move Down = Move Down Move Up = Move Up Network Connection = ‎إتصال الشبكة NEW DATA = ‎بيانات جديدة No = ‎لا -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = ‎حسناً Old savedata detected = ‎بيانات حفظ قديمة قد إكتشفت Options = ‎إعدادات -Password = Password Remove = Remove Reset = ‎إستعادة Resize = ‎تغيير الحجم -Restart = Restart Retry = ‎حاول مجدداً Save = ‎حفظ Save completed = ‎الحفظ إكتمل. @@ -428,7 +337,6 @@ SavingFailed = ‎غير قادر علي حفظ البيانات. Search = Search seconds, 0:off = إطارات, 0 = ‎مُغلق Select = ‎حدد -Settings = Settings Shift = ‎شفت Skip = Skip Snap = Snap @@ -439,11 +347,7 @@ Supported = Supported There is no data = ‎ليس هناك بيانات. Toggle All = ‎تبديل الكل Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = ‎نعم @@ -509,23 +413,18 @@ ZIP file detected (Require WINRAR) = ‎الملف مضغوط (ZIP).\nمن فض [Game] Asia = ‎أسيا Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = ‎مسح -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = ‎أنشي إعدادت للعبة Create Shortcut = ‎إصنع إختصار Delete Game = ‎إمسح اللعبة Delete Game Config = ‎مسح إعدادات اللعبة Delete Save Data = ‎مسح بيانات الحفظ Europe = ‎أروبا -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = ‎اللعبة -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = ‎إعدادات اللعبة Homebrew = ‎الصفحة الرئيسية Hong Kong = ‎هونج كونج InstallData = ‎تثبيت البيانات -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = ‎اليابان Korea = Korea MB = ‎ميجا @@ -535,8 +434,6 @@ Remove From Recent = ‎مسح من "الحالي" SaveData = ‎بيانات الحفظ Setting Background = ‎إعدادات الخلفية Show In Folder = ‎أظهر في المجلد -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = ‎أمريكا Use UI background = ‎إستخدم خلفية الواجهة @@ -631,7 +528,6 @@ Must Restart = ‎يجب عليك إعادة تشغيل البرنامج لكي Native device resolution = ‎حجم الجهاز الأساسي Nearest = Nearest No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -666,7 +562,6 @@ Stereo rendering = Stereo rendering Stretch = ‎المط Texture Filter = ‎منقي الرسوم Texture Filtering = ‎مفلتر الرسوم -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = ‎تكبير الرسوم Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -677,6 +572,8 @@ Upscale Level = ‎مستوي التكبير Upscale Type = ‎نوع التكبير UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex cache +VertexCache Tip = ‎أسرع, لكن ربما يسبب تميع مؤقت VSync = VSync Vulkan = ‎فولكان Window Size = ‎حجم النافذة @@ -693,12 +590,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = ‎ضبط تلقائي Autoconfigure for device = ‎إعداد تلقائي للعبة Bind All = Bind All Clear All = ‎إخلاء الكل -Combo mappings are not enabled = Combo mappings are not enabled Default All = ‎إرجاع للإفتراضي Map a new key for = ‎خريطة مفتاح جديدة لـ Map Key = ‎خريطة مفتاح @@ -755,7 +650,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = ‎الدائرة Cross = ‎الأكس -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -768,7 +672,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Down Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -781,7 +684,6 @@ None = None Note = Note OpenChat = Open chat Pause = ‎توقف مؤقت -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -811,7 +713,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = ‎تفعيل وضع الشاشة الكاملة Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = ‎مثلث Fast-forward = Fast-forward Up = Dpad Up @@ -821,7 +722,6 @@ Wlan = ‎الواي فاي [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -854,6 +754,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = ‎MAC تغيير عنوان الـ Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -887,6 +792,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = ‎الشبكة تُطلق +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset (0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -897,9 +803,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -909,23 +817,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = ‎الشفرات Continue = ‎إكمال @@ -952,7 +843,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = ‎كرتوني CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -960,7 +850,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = ‎CRT خطوط الفحص -FakeReflections = FakeReflections FXAA = ‎FXAA منعم الحواف Gamma = Gamma GreenLevel = Green level @@ -981,7 +870,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1185,11 +1073,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1198,9 +1085,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1212,7 +1097,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1295,7 +1180,6 @@ Record Audio = ‎تسجيل الصوت Record Display = ‎سجل الفيديو Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = ‎إلي الإفتراضي PPSSPP's إعادة إعدادات -RetroAchievements = RetroAchievements Rewind Snapshot Interval = ‎ترجيع تردد اللقطة (يأكل الذاكرة) Save path in installed.txt = ‎installed.txt مسار الحفظ في Save path in My Documents = ‎مسار الحفظ في مستنداتي @@ -1308,7 +1192,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = ‎UMD محاكاة تأخر -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1363,11 +1246,12 @@ Download = ‎تحميل New version of PPSSPP available = ‎تتوفر نسخة جديدة من البرنامج [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 2e4b3cecc..53f114aff 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classic Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Ekran Kontrolları Açıq Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Log Console Memory View... = Memory &View... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xture Filtering Texture Scaling = &Texture Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window Size @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Enable debug logging Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = System information Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Geri -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Cancel Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Do you want to overwrite the data? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = Silinir\nZəhmət Olmasa Gözləyin... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Gir -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Bitir GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = Yükləmə Tamamlandı Loading = Yüklənir\nZəhmət Olmasa Gözləyin... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = NEW DATA No = Xeyir -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = Qeyd edildi @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = Seç -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Veri yoxdur Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Bəli @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Create shortcut Delete Game = Delete game Delete Game Config = Delete game config Delete Save Data = Delete savedata Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Game -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Game settings Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = Savedata Setting Background = Setting background Show In Folder = Show in folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = Nearest No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Texture filtering Texture Filtering = Texture filtering -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Texture scaling Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Upscale level Upscale Type = Upscale type UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex Keş +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Window size @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Clear all -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restore defaults Map a new key for = Map a new key for Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Down Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Up @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = Dəvam @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = New version of PPSSPP available [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index 99a0f244a..99e209c46 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Класик Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone радиус Disable D-Pad diagonals (4-way touch) = Изключи D-Pad диагонали (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Управление с докосване на екрана Portrait = Портрет Portrait Reversed = Обърнат портрет PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Чувствителност Shape = Shape Show Touch Pause Menu Button = Покажи бутон „Пауза“ -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Log Console Memory View... = Памет изглед... More Settings... = Още настройки... Nearest = &Най-близко -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Изключено Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Текстурно филтриране Texture Scaling = Текстурно мащабиране Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Размер на прозореца @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Enable debug logging Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Системна информация Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Назад -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Отмени Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Искате ли да презапишете данните? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = Изтриване\nМоля изчакайте... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Край GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Зареди Load completed = Зареждането завършено. Loading = Зареждане\nМоля изчакайте... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Преместване Move Down = Move Down Move Up = Move Up Network Connection = Мрежова връзка NEW DATA = Нови данни No = Не -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Преоразмеряване -Restart = Restart Retry = Нов опит Save = Запази Save completed = Съхраняването завършено. @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = Select -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Няма данни. Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Да @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Файла е архивиран (ZIP).\nМ [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Изтрий -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Създай пряк път Delete Game = Изтрий игра Delete Game Config = Delete game config Delete Save Data = Изтрий записа Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Игра -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Настройки Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Премахни от „Скорошни“ SaveData = Savedata Setting Background = Setting background Show In Folder = Покажи в папка -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = Най-близко No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Текстурно филтриране Texture Filtering = Текстурно филтриране -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Текстурно мащабиране Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Upscale level Upscale Type = Upscale type UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex cache +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Размер на прозореца @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Изчисти всички -Combo mappings are not enabled = Combo mappings are not enabled Default All = Първоначални Map a new key for = Избери нов клавиш за Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Надолу Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Пауза -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Нагоре @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = чийтове Continue = Продължи @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Анимация CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Възстанови първоначалните настройки на PPSSPP -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind snapshot честота („яде“ памет) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Свали New version of PPSSPP available = Налична е нова версия на PPSSPP [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 276cb2903..c3a8fb2a6 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternar velocitat del soroll Audio backend = Motor d'àudio (requereix reiniciar) Audio Error = Error d'àudio -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Memòria intermèdia en Bluetooth (lent) Auto = Automàtic Device = Dispositiu @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrar Calibrated = Calibrat Calibration = Calibració -Circular low end radius = Ràdio inferior circular Circular stick input = Entrada de stick circular Classic = Clàssic Confine Mouse = Fixar el ratolí a l'àrea de la finestra/pantalla @@ -108,10 +48,8 @@ Deadzone radius = Ràdio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonals de creueta Disable diagonal input = Desactivar mov. diagonal Double tap = Doble toc -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Habilitar gestos Enable standard shortcut keys = Habilitar les tecles de drecera -frames = frames Gesture = Gestos Gesture mapping = Configuració de gestos Glowing borders = Vores brillants @@ -140,7 +78,6 @@ OnScreen = Controls tàctils a la pantalla Portrait = Vertical Portrait Reversed = Vertical invertit PSP Action Buttons = Botons d'acció -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Mode repetició Reset to defaults = Restaurar paràmetres @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensibilitat (escala) Sensitivity = Sensibilitat Shape = Forma Show Touch Pause Menu Button = Mostrar botó del menú -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Lliscar cap a Swipe sensitivity = Sensibilitat de lliscament Swipe smoothing = Fluïdesa del lliscat @@ -230,7 +166,6 @@ Log Console = Consola de re&gistres Memory View... = Visor de &memòria... More Settings... = Més &paràmetres... Nearest = &El més proper -Recent = &Recent Skip Buffer Effects = &Renderitzat sense memòria intermèdia (més ràpid) Off = &No Open Chat = Obrir xat @@ -269,6 +204,7 @@ Texture Filtering = Filtrat de te&xtura Texture Scaling = Escalat de &textura Use Lossless Video Codec (FFV1) = Fes servir còdec de vídeo sense pèrdua (FFV1) Use output buffer for video = Utilitzar sortida de búfer per a vídeo +Vertex Cache = &Memòria cau de vèrtexs VSync = Sincronització vertical (VS&ync) Vulkan = Vulkan Window Size = Mida de la &finestra @@ -282,11 +218,8 @@ Backspace = Esborra Block address = Bloca l'adreça By Address = Per adreça Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Crear/Obrir fitxer «textures.ini» per al joc actual Current = Actual -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Activa el registre Enter address = Inseriu adreça FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Amidar el rendiment -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Registra estadístiques de caigudes de quadres Log Level = Nivell del registre Log View = Veure el registre Logging Channels = Canals del registre -Multi-threaded rendering = Multi-threaded rendering Next = Següent No block = No bloquis -Off = Off Prev = Anterior Random = Aleatori Replace textures = Reemplaçar textures @@ -332,12 +260,10 @@ Stats = Estadístiques System Information = Informació del sistema Texture ini file created = Texture ini file created Texture Replacement = Reemplaçament de textures -Audio Debug = Depuració d'àudio -Control Debug = Control Debug +Toggle Audio Debug = Commuta la depuració d'àudio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Commuta la imatge Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * resolució PSP Active = Actiu Back = Enrere -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Cancel·lar Center = Centre -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Canvar aquesta configuració requereix reiniciar PPSSPP.\nReiniciar ara? +ChangingGPUBackends = Canviar el motor gràfic requereix reiniciar PPSSPP.\nReiniciar ara? +ChangingInflightFrames = Canvar el búfer de comanda de gràfics requereix reiniciar PPSSPP.\nReiniciar ara? Channel: = Canal: Choose PPSSPP save folder = Tria la carpeta de guardat de PPSSPP. Confirm Overwrite = Vols sobreescriure les dades? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Estàs segur que vols esborrar la configuración d'aqu DeleteFailed = Les dades no s'han pogut borrar. Deleting = Esborrant\nEspera un moment... Disable All = Desactivar tot -Disabled = Disabled Dumps = Volcats Edit = Editar Enable All = Activar tot -Enabled = Enabled Enter = Confirmar -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filtrar Finish = Finalitzar GE Frame Dumps = Volcats de fotograma GE Grid = Quadrícula Inactive = Inactiu -Installing... = Installing... InternalError = Un error intern ha ocorregut. -Links = Links Load = Carregar Load completed = Càrrega completada Loading = Carregant\nEspera un moment... LoadingFailed = Les dadess del joc no s'ha pogut carregar. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Moure Move Down = Baixar Move Up = Pujar Network Connection = Connexión de xarxa NEW DATA = NOVES DADES DE PARTIDA No = No -None = None ObtainingIP = Obtenint direcció IP.\nPer favor espera... OK = Acceptar Old savedata detected = S'han detectar dades del joc antigues. Options = Opcions -Password = Password Remove = Borrar Reset = Reiniciar Resize = Canviar la mida -Restart = Restart Retry = Reintentar Save = Guardar Save completed = Guardat completat @@ -420,7 +329,6 @@ SavingFailed = Les dades no s'han pogut guardar. Search = Cercar seconds, 0:off = segons, 0 = off Select = Seleccionar -Settings = Settings Shift = Canviar Skip = Saltar Snap = Capturar @@ -431,11 +339,7 @@ Supported = Suportat There is no data = No hi han dades Toggle All = Canviar tot Toggle List = Veure llista -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = No suportat -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Quant guardis, la partida carregarà a una PSP, però no en versions antigues de PPSSPP. When you save, it will not work on outdated PSP Firmware anymore = Quant guardis, no tornarà a funcionar a un firmware de PSP antic. Yes = Sí @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Àsia Calculate CRC = Calcular valor CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Confirmar esborrat -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Crear config. del joc Create Shortcut = Crear accés directe Delete Game = Esborrar joc Delete Game Config = Esborrar config. del joc Delete Save Data = Esborrar dades guardades Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Joc -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Paràmetres del joc Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instal·lació de dades -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japó Korea = Corea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = Dades guardades Setting Background = Imatge de fons Show In Folder = Mostrar en carpeta -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = EEUU Use UI background = Utilitzar imatge de fons de l'interfície d'usuari @@ -623,7 +520,6 @@ Must Restart = Heu de reiniciar PPSSPP per aplicar aquest canvi. Native device resolution = Resolució nativa del dispositiu Nearest = Més proper No buffer = Sense memòria intermèdia -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Saltar efectes del memòria intermèdia @@ -658,7 +554,6 @@ Stereo rendering = Renderitzat estèreo Stretch = Estirar Texture Filter = Filtre de textures Texture Filtering = Filtrat de textures -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Escalat de textures Texture Shader = Shader de textura Turn off Hardware Tessellation - unsupported = Desactivant tessel·lat per maquinari: no suportat. @@ -669,6 +564,8 @@ Upscale Level = Nivell d'escalat Upscale Type = Tipus d'escalat UpscaleLevel Tip = Exigeix consum de CPU, alguns escalats es poden retardar per evitar estrebades. Use all displays = Usar totes les pantalles +Vertex Cache = Memòria cau de vèrtexs +VertexCache Tip = Ràpid, però pot causar parpelleig temporal. VSync = Sincronització vertical (VSync) Vulkan = Vulkan Window Size = Mida de la finestra @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autoconfigurar Autoconfigure for device = Autoconfigurar per a dispositiu Bind All = Assignar tots Clear All = Esborrar tot -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restaurar Map a new key for = Prem una tecla per Map Key = Mapejar tecla @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Down Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Up @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Trucs Continue = Continuar @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Descarregar New version of PPSSPP available = Nova versió de PPSSPP disponible [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index bfbce0ebb..d12d87503 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Zvukové jádro (vyžaduje restart) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibrovat Calibrated = Calibrated Calibration = Kalibrace -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasický Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Poloměr mrtvé zóny Disable D-Pad diagonals (4-way touch) = Zakázat diagonální D-Pad (čtyřsměrný dotek) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Dotykové ovládání na obrazovce Portrait = Na výšku Portrait Reversed = Na výšku obráceně PSP Action Buttons = Tlačítka činností PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Citlivost Shape = Shape Show Touch Pause Menu Button = Zobrazit tlačítko Nabídky při pozastavení -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Konzole záznamu Memory View... = &Zobrazení paměti... More Settings... = D&alší nastavení... Nearest = &Nejbližší -Recent = &Recent Skip Buffer Effects = &Přeskočit efekty vyrovnávací paměti Off = &Vypnuto Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = &Filtrování textur Texture Scaling = &Změna velikosti textur Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = Mezipaměť verte&xů VSync = Vertikální S&ynchronizace Vulkan = Vulkan Window Size = &Velikost okna @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Adresa bloku By Address = Podle adresy Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Současný -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Povolit záznam při ladění Enter address = Zadejte adresu FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Profilovač snímku -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Úroveň záznamu Log View = Zobrazení záznamu Logging Channels = Kanály záznamu -Multi-threaded rendering = Multi-threaded rendering Next = Další No block = Žádný blok -Off = Off Prev = Předchozí Random = Náhodné Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Statistiky System Information = Informace o systému Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Přepnout ladění zvuku -Control Debug = Control Debug +Toggle Audio Debug = Přepnout ladění zvuku +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Přepnout zamrznutí Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP rozlišení Active = Active Back = Zpět -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Zrušit Center = Na střed -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Změna grafického jádra vyžaduje restart PPSSPP. Chcete tak učinit nyní?? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Zvolit složku pro ukládání dat PPSSPP Confirm Overwrite = Chcete tato data přepsat?? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Opravdu chcete smazat nastavení této hry? DeleteFailed = Nelze smazat data. Deleting = Probíhá mazání\nČekejte prosím... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Potvrdit -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Potvrdit GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Načíst Load completed = Načítání dokončeno. Loading = Načítání\nČekejte prosím... LoadingFailed = Nelze načíst data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Přesunout Move Down = Move Down Move Up = Move Up Network Connection = Síťové připojení NEW DATA = NOVÁ DATA No = Ne -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Zjištěna stará uložená data Options = Volby -Password = Password Remove = Remove Reset = Resetovat Resize = Velikost -Restart = Restart Retry = Zkusit znovu Save = Uložit Save completed = Ukládání dokončeno. @@ -420,7 +329,6 @@ SavingFailed = Nelze uložit data. Search = Search seconds, 0:off = sekundy, 0 = vypnuto Select = Vybrat -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Žádná data k dispozici. Toggle All = Přepnout vše Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Pokud uložíte, můžete hru načíst na PSP, ale ne na starší verzi PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Ano @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Soubor je komprimován (ZIP).\nNejdříve h [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Smazat -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Vytvořit nastavení hry Create Shortcut = Vytvořit zkratku Delete Game = Smazat hru Delete Game Config = Smazat nastavení hry Delete Save Data = Smazat uložená data Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Hra -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Nastavení hry Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instalace dat -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Odstranit z "Nedávné" SaveData = Uložená data Setting Background = Setting background Show In Folder = Zobrazit ve složce -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = Aby došlo k použití těchto změn, je nutné PPSSPP restartova Native device resolution = Původní rozlišení zařízení Nearest = Nejbližší No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Přeskočit efekty vyrovnávací paměti @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Roztažení Texture Filter = Filtr textur Texture Filtering = Filtrování textur -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Změna velikosti textur Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Úroveň zvětšení Upscale Type = Typ zvětšení UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Mezipaměť vertexů +VertexCache Tip = Faster, but may cause temporary flicker VSync = Vertikální synchronizace Vulkan = Vulkan Window Size = Velikost okna @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Automatické nastavení Autoconfigure for device = Automaticky nastavit pro zařízení Bind All = Bind All Clear All = Vše vyčistit -Combo mappings are not enabled = Combo mappings are not enabled Default All = Obnovit výchozí Map a new key for = Mapovat novou klávesu pro Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Výměna osy Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Dolů Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pauza -Previous Slot = Previous Slot R = R RapidFire = Rychlá palba Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Rychle vpřed Up = Dpad Nahoru @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Změnit MAC adresu Change proAdhocServer Address = Změnit IP adresu serveru PRO ad hoc (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Síť zavedena +None = None Please change your Port Offset = Please change your port offset Port offset = Odchylka portu (0 = Kompatibilita s PSP) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheaty Continue = Pokračovat @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Animák CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = Skenovací řádky CRT -FakeReflections = FakeReflections FXAA = Vyhlazování hran FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Zvyšovač rozlišení Spline36 VideoSmoothingAA = VideoSmoothingAA Vignette = Viněta @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Obnovit výchozí nastavení PPSSPP -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Četnost snímků přetočení (žrout paměti) Save path in installed.txt = Cesta pro uložení dat je installed.txt Save path in My Documents = Cesta pro uložení dat je v Dokumentech @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulovat zpoždění UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Stáhnout New version of PPSSPP available = Je dostupná nová verze PPSSPP [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 6e0bb9d68..01beec70e 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Lyd backend Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-venlig buffer (langsommere) Auto = Automatisk Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibrer Calibrated = Calibrated Calibration = Kalibrering -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klassisk Confine Mouse = Begræns mus indenfor vindue/skærmområde @@ -108,10 +48,8 @@ Deadzone radius = Dødzone radius Disable D-Pad diagonals (4-way touch) = Deaktiver D-Pad diagonaler (4-vejs touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Touch billedskærmsknapper Portrait = Portræt Portrait Reversed = Omvendt portræt PSP Action Buttons = PSP action knapper -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Følsomhed Shape = Shape Show Touch Pause Menu Button = Vis pause menu knap -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Log konsol Memory View... = Hukommelseso&versigt... More Settings... = &Flere indstillinger... Nearest = &Nærmest -Recent = &Recent Skip Buffer Effects = &Skip buffer effekter Off = &Slukket Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xturfilter Texture Scaling = &Texturskalering Use Lossless Video Codec (FFV1) = Brug Tabsfri Video Codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertexcache VSync = VS&ync Vulkan = Vulkan Window Size = &Vinduesstørrelse @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Bloker adresse By Address = Efter adresse Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Opret/Åben textures.ini fil for aktuelle spil Current = Aktuelle -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Aktiver fejlfindingslogning Enter address = Indtast adresse FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log Droppede Frames Statistik Log Level = Logniveau Log View = Log visning Logging Channels = Logkanaler -Multi-threaded rendering = Multi-threaded rendering Next = Næste No block = Ingen blokering -Off = Off Prev = Forrige Random = Tilfældig Replace textures = Erstat textures @@ -332,12 +260,10 @@ Stats = Stats System Information = System information Texture ini file created = Texture ini file created Texture Replacement = Texture Erstatning -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Skift freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Tilbage -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Annuler Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Det er nødvendigt at genstarte PPSSPP for at ændre GPU backend. Genstart nu? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Vælg hvilken folder PPSSPP gemmer i Confirm Overwrite = Vil du overskrive dette data? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Vil du virkelig slette opsætningen for dette spil? DeleteFailed = Ikke muligt at slette data. Deleting = Sletter\nVent venligst... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Slut GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Hent Load completed = Hentet. Loading = Henter\nVent venligst... LoadingFailed = Ikke muligt at indlæse data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Flyt Move Down = Move Down Move Up = Move Up Network Connection = Netværksforbindelse NEW DATA = NY DATA No = Nej -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Gamle savedata fundet Options = Optioner -Password = Password Remove = Remove Reset = Nulstil Resize = Størrelse -Restart = Restart Retry = Prøv igen Save = Gem Save completed = Gemt. @@ -420,7 +329,6 @@ SavingFailed = Ikke muligt at gemme data. Search = Search seconds, 0:off = sekunder, 0 = off Select = Vælg -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Der findes ingen data. Toggle All = Skift alle Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Når du gemmer vil det kunne hentes på en PSP men ikke på en ældre PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Ja @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Fil er pakket (ZIP).\nPak venligst ud førs [Game] Asia = Asien Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Slet -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Opret data konfiguration Create Shortcut = Opret genvej Delete Game = Slet spil Delete Game Config = Slet data konfiguration Delete Save Data = Slet gemt data Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Spil -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Spilindstillinger Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Fjern fra "Nylige" SaveData = Gem data Setting Background = Setting background Show In Folder = Vis i katalog -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Brug UI baggrund @@ -623,7 +520,6 @@ Must Restart = Du må genstarte PPSSPP for at aktivere denne ændring. Native device resolution = Standard enheds opløsning Nearest = Nærmest No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effekter @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Texturfilter Texture Filtering = Texturfiltrering -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Texturskalering Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Opskaleringsniveau Upscale Type = Opskaleringstype UpscaleLevel Tip = CPU tung - noget skallering kan belive forsinket for at undgå flimmer Use all displays = Use all displays +Vertex Cache = Vertexcache +VertexCache Tip = Hurtigere, men kan medføre midlertidig flimmer VSync = VSync Vulkan = Vulkan Window Size = Vinduesstørrelse @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autokonfigration Autoconfigure for device = Autokonfiguration af enhed Bind All = Bind All Clear All = Slet alt -Combo mappings are not enabled = Combo mappings are not enabled Default All = Sæt til standard Map a new key for = Map en ny taste for Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Ombyt akser Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad ned Dpad = Dpad -Exit App = Exit App Frame Advance = Frame Fremad Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Hurtigskydning Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Turbo Up = Dpad op @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Ændre MAC adressen Change proAdhocServer Address = Ændre PRO ad hoc server IP adresse (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Netværk er initialiseret +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP kompatibilitet) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Snyd Continue = Fortsæt @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Tegnefilm CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlinier -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 opskalere VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Optag lyd Record Display = Optag skærm Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Sæt PPSSPP's indstillinger tilbage til standard -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Tilbagespol snapshot frekvens (mem hog) Save path in installed.txt = Gem sti i installed.txt Save path in My Documents = Gem sti i Mine Dokumenter @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simuler UMD forsinkelser -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = Ny version af PPSSPP tilgængelig [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index c83b277be..bfc6c7492 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Lautstärke für wechselnde Geschwindigkeit/Turbo Audio backend = Ton-Backend (Neustart erforderlich) Audio Error = Audio Fehler -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-freundliche Pufferung (langsamer) Auto = Automatisch Device = Gerät @@ -95,7 +36,6 @@ Calibrate Analog Stick = Kalibriere Analog Stick Calibrate = Kalibriere Steuerkreuz Calibrated = Kalibriert Calibration = Kalibrierung -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klassisch Confine Mouse = Maus in Fenster/sichtbaren Bereich einsperren @@ -108,10 +48,8 @@ Deadzone radius = Radius für tote Zone Disable D-Pad diagonals (4-way touch) = Deaktiviere D-Pad Diagonalen (4-Wege-Touch) Disable diagonal input = Deaktiviere Diagonale Eingabe Double tap = Doppelklick -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Aktiviere Gestenkontrolle Enable standard shortcut keys = Aktiviere standard shortcut keys -frames = frames Gesture = Geste Gesture mapping = Gesten mapping Glowing borders = Leuchtende Ränder @@ -140,7 +78,6 @@ OnScreen = Touch Bildschirmtasten Portrait = Hochformat Portrait Reversed = Hochformat umgekehrt PSP Action Buttons = PSP Aktionstasten -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Empfindlichkeit Shape = Shape Show Touch Pause Menu Button = Zeige Pause-Taste -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Logkonsole Memory View... = Speicheransicht... More Settings... = Mehr Einstellungen... Nearest = Nächster Nachbar -Recent = &Recent Skip Buffer Effects = Überspringe Puffereffekte Off = Aus Open Chat = Öffne Chat @@ -269,6 +204,7 @@ Texture Filtering = Texturfilter Texture Scaling = Texturskalierung Use Lossless Video Codec (FFV1) = Benutze verlustfreien Videocodec (FFV1) Use output buffer for video = Benutze Ausgabepuffer für Video +Vertex Cache = Vertex-Cache VSync = V-Sync Vulkan = Vulkan Window Size = Fenstergröße @@ -282,11 +218,8 @@ Backspace = Rücktaste Block address = Blockadresse By Address = Per Adresse Copy savestates to memstick root = Kopiere Speicherstände ins Memstick Rootverzeichnis -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Erstelle/Öffne textures.ini für aktuelles Spiel Current = Aktuell -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Entwicklungswerkzeuge DevMenu = Entwicklermenü Disabled JIT functionality = Deaktivierte JIT Funktionalität @@ -297,11 +230,8 @@ Enable driver bug workarounds = Aktiviere Driver-Fehler workarounds Enable Logging = Aktiviere Logging Enter address = Adresse eingeben FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame Profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU Treibertest GPU log profiler = GPU log profiler GPU Profile = GPU Profil @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Statistik für fehlende Einzelbilder loggen Log Level = Loglevel Log View = Logbuch Logging Channels = Logkanäle -Multi-threaded rendering = Multi-threaded rendering Next = Nächstes No block = Kein Block -Off = Off Prev = Vorheriges Random = Zufall Replace textures = Texturen ersetzen @@ -332,12 +260,10 @@ Stats = Statistiken System Information = Systeminformationen Texture ini file created = Texture ini file created Texture Replacement = Austausch von Texturen -Audio Debug = Ton-Debugging -Control Debug = Control Debug +Toggle Audio Debug = Ton-Debugging umschalten +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Bild einfrieren an/aus Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP Auflösung Active = Aktiv Back = Zurück -Bottom Center = Mitte unten -Bottom Left = links unten -Bottom Right = rechts unten Cancel = Abbrechen Center = Zentriert -Center Left = Mitte links -Center Right = Mitte rechts -Changing this setting requires PPSSPP to restart. = Wenn Sie diese Einstellung ändern muss PPSSPP neu gestartet werden. +ChangingGPUBackends = Um das Grafik-Backend zu wechseln, muss PPSSPP neu gestartet werden. Wollen Sie jetzt neustarten? +ChangingInflightFrames = Das Ändern der Pufferung von Grafikbefehlen erfordert einen Neustart von PPSSPP. Wollen Sie jetzt neustarten? Channel: = Kanal: Choose PPSSPP save folder = Wähle PPSSPP Speicherpfad Confirm Overwrite = Wollen Sie diese Daten überschreiben? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Wollen Sie wirklich die spielspezifischen Einstellunge DeleteFailed = Daten konnten nicht gelöscht werden. Deleting = Löschen\nBitte warten... Disable All = Alle deaktivieren -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Alle aktivieren -Enabled = Enabled Enter = Eingabe -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Fertig GE Frame Dumps = GE Frame Dumps Grid = Gitter Inactive = Inaktiv -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Laden Load completed = Laden abgeschlossen Loading = Laden\nBitte warten... LoadingFailed = Daten konnten nicht geladen werden. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Bewegen Move Down = Move Down Move Up = Move Up Network Connection = Netzwerkverbindung NEW DATA = Neue Daten No = Nein -None = Nichts ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Alter Speicherstand entdeckt Options = Optionen -Password = Password Remove = Remove Reset = Zurücksetzen Resize = Größe ändern -Restart = Restart Retry = Wiederholen Save = Speichern Save completed = Speichern abgeschlossen @@ -420,7 +329,6 @@ SavingFailed = Daten konnten nicht gespeichert werden. Search = Search seconds, 0:off = seconds, 0 = Aus Select = Auswahl -Settings = Settings Shift = Umschalt Skip = Skip Snap = Einrasten @@ -431,11 +339,7 @@ Supported = Unterstützt There is no data = Keine Daten vorhanden Toggle All = Alle umschalten Toggle List = Toggle list -Top Center = Mitte oben -Top Left = Links oben -Top Right = Rechts oben Unsupported = Nicht unterstützt -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Wenn Sie speichern, kann es von einer PSP gelesen werden, aber nicht von einem älteren PPSSPP When you save, it will not work on outdated PSP Firmware anymore = Wenn Sie speichern, wird es auf veralteter PSP Firmware nicht mehr funktionieren Yes = Ja @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Datei ist komprimiert (ZIP).\nBitte zuerst [Game] Asia = Asien Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Löschen -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Erstelle Spielkonfig. Create Shortcut = Verknüpfung erstellen Delete Game = Spiel löschen Delete Game Config = Lösche Spielkonfig. Delete Save Data = Spielstand löschen Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Spiel -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Spieleinstellungen Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Dateninstallation -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Aus der Liste entfernen SaveData = Speicherdaten Setting Background = Einstellungshintergrund Show In Folder = Ordner öffnen -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Benutze UI Hintergrund @@ -623,7 +520,6 @@ Must Restart = Sie müssen PPSSPP neustarten, damit die Änderungen wirksam werd Native device resolution = Native Auflösung Nearest = Nächster Nachbar No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Über&springe Puffereffekte @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Strecken Texture Filter = Texturfilter Texture Filtering = Texturfilterung -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Texturskalierung Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = "Hardware Tessellierung" ausschalten: Nicht unterstützt @@ -669,6 +564,8 @@ Upscale Level = Skalierungsgrad Upscale Type = Skalierungsart UpscaleLevel Tip = CPU-lastig - einige Skalierungen könnten verzögert sein um Stottern zu vermeiden Use all displays = Benutze alle Bildschirme +Vertex Cache = Vertex-Cache +VertexCache Tip = Schneller, kann temporäres Flackern verursachen VSync = V-Sync Vulkan = Vulkan Window Size = Fenstergröße @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP Archiv beschädigt Zip file does not contain PSP software = ZIP Datei beinhaltet keine PSP Software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autokonfiguration Autoconfigure for device = Autokonfiguration für Gerät Bind All = Bind All Clear All = Alle löschen -Combo mappings are not enabled = Combo mappings are not enabled Default All = Zurücksetzen Map a new key for = Drücke zuzuweisende Taste für Map Key = Taste zuweisen @@ -747,7 +642,16 @@ Audio/Video Recording = Ton/Video Aufnahme AxisSwap = Achsen invertieren Circle = Kreis Cross = Kreuz -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Steuerkreuz Runter Dpad = Steuerkreuz -Exit App = Exit App Frame Advance = Einzelbildaufnahme Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Schnellfeuer Record = Aufnehmen @@ -803,7 +705,6 @@ Texture Dumping = Texturspeicherung Texture Replacement = Texturersetzung Toggle Fullscreen = Vollbild umschalten Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Dreieck Fast-forward = Turbo Up = Steuerkreuz Hoch @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Enthält bereits PSP Daten -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Daten können mit PPSSPP Regulär/Gold geteilt werden! @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server verbinden von Port fehlgeschlagen AM: Data from Unknown Port = AM: Dateien von Unbekannten Port Auto = Auto +Bottom Center = Mitte unten +Bottom Left = links unten +Bottom Right = rechts unten +Center Left = Mitte links +Center Right = Mitte rechts Change Mac Address = MAC-Adresse ändern Change proAdhocServer Address = proAdhocServer IP-Adresse ändern (localhost = mehrere Instanzen) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Ungültige IP oder Hostnamen Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Netzwerk initialisiert +None = Nichts Please change your Port Offset = Bitte ändern sie Ihren Port-Offset Port offset = Portverschiebung (0 = PSP Kompatibilität) Open PPSSPP Multiplayer Wiki Page = PPSSPP Ad-Hoc Wiki Seite @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Senden Send Discord Presence information = Sende Discord "Rich Presence" Information +Top Center = Mitte oben +Top Left = Links oben +Top Right = Rechts oben Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validiere Adresse... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = Fortsetzen @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT Scanlines -FakeReflections = FakeReflections FXAA = FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = UpscaleSpline36 VideoSmoothingAA = Video Bildglättung Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU Information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Sprache/Region Memory Page Size = Seitengröße des Speichers -Native resolution = Native Auflösung +Native Resolution = Native Auflösung No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL Erweiterungen OpenGL ES 2.0 Extensions = OpenGL ES 2.0 Erweiterungen @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL Erweiterungen Optimal frames per buffer = Optimale Bilder pro Zwischenspeicher Optimal sample rate = Optimale Abtastrate OS Information = Betriebssystem Information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Wiederholungsrate Release = Release RW/RX exclusive = RW/RX exklusiv @@ -1204,7 +1089,7 @@ System Information = System Information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Hersteller Vendor (detected) = Hersteller (erkannt) Version Information = Version Information @@ -1287,7 +1172,6 @@ Record Audio = Ton aufzeichnen Record Display = Bildschirm aufzeichnen Reset Recording on Save/Load State = Zurücksetzen der Aufnahme bei Laden/Speichern eines Standes Restore Default Settings = Auf Standardeinstellungen zurücksetzen -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Zurückspulen-Snapshot Frequenz (Speicherfresser) Save path in installed.txt = Speicherpfad in installed.txt Save path in My Documents = Speicherpfad in "Meine Dokumente" @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simuliere UMD Verzögerungen -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Herunterladen New version of PPSSPP available = Neue PPSSPP Version verfügbar [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 9cb388ae4..8fc3923b4 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classic Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Tobolo'na jo layar sentu Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Konsol log Memory View... = Pempakitan &Memory... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Mate Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xture Filtering Texture Scaling = &Texture Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window Size @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Padenni Log Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Pempakitan to sistem dipake Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Poleboko' -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Ah edda pole' Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Eda na ciapa dipasi toppo' te' data? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = Dihapusmi\nTajammi... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Mangkami GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = Tibukka'mi. Loading = Dibukka'i\nTajammi... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = DATA baru No = Edda mane -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = Okemi mane Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = Mangkami dianna. @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = Pillei -Settings = Settings Shift = Angka'i Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Ai edda data mane. Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Iyo mane @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Garaganni shortcut Delete Game = Delete game Delete Game Config = Delete game config Delete Save Data = Delete savedata Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Paningoan -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Pangngaturan Paningoan Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = Pangsave Setting Background = Setting background Show In Folder = Show in folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = To paling mandoppi' No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Panyaring Texture Texture Filtering = Saring i Texture -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Petonggoi Texture Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Patonggoi skala Upscale Type = Skala apa mane? UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Pangnganna Vertex +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Window size @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Paccingngi nasan -Combo mappings are not enabled = Combo mappings are not enabled Default All = Poleboko' nasan Map a new key for = Garaganni tombol baru Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Jiong Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Paus -Previous Slot = Previous Slot R = R RapidFire = RapidFire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Jaoh @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = Patarruh @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = New version of PPSSPP available [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 009cd70e5..f354d7cb8 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -22,68 +22,9 @@ # # Happy translating. -[Achievements] -%1 achievements, %2 points = %1 achievements, %2 points -%1: Attempt started = %1: Attempt started -%1: Attempt failed = %1: Attempt failed -Account = Account -Achievement unlocked = Achievement unlocked -Achievement progress = Achievement progress -Achievements = Achievements -Achievements enabled = Achievements enabled -Achievements are disabled = Achievements are disabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboards = Leaderboards -Leaderboard tracker = Leaderboard tracker -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Around me = Around me -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unsupported achievements = Unsupported achievements -Unofficial achievements = Unofficial achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. Audio Error = Audio Error AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto @@ -119,7 +60,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classic Confine Mouse = Trap mouse within window/display area @@ -132,10 +72,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -164,7 +102,6 @@ OnScreen = On-screen touch controls Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Reset to defaults = Reset to defaults Screen Rotation = Screen rotation @@ -172,7 +109,6 @@ Sensitivity = Sensitivity Sensitivity (scale) = Sensitivity (scale) Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -293,6 +229,7 @@ Texture Filtering = Te&xture filtering Texture Scaling = &Texture scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window size @@ -302,17 +239,12 @@ xBRZ = &xBRZ [Developer] Allocator Viewer = Allocator viewer (Vulkan) Allow remote debugger = Allow remote debugger -Audio Debug = Audio Debug Backspace = Backspace Block address = Block address By Address = By address -Control Debug = Control Debug Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -322,12 +254,9 @@ Dump next frame to log = Dump next frame to log Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Enable debug logging Enter address = Enter address -Fragment = Fragment FPU = FPU Framedump tests = Framedump tests Frame Profiler = Frame profiler -Frame timing = Frame timing -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU Profile = GPU profile GPU log profiler = GPU log profiler @@ -337,10 +266,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -358,10 +285,10 @@ Stats = Stats System Information = System information Texture ini file created = Texture ini file created Texture Replacement = Texture replacement +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -369,15 +296,11 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Back -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Cancel Center = Center -Center Left = Center left -Center Right = Center right +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Do you want to overwrite the data? Confirm Save = Do you want to save this data? @@ -396,46 +319,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = Deleting\nPlease wait... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Enter -Failed to log in, check your username and password. = Failed to log in, check your username and password. -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. Filter = Filter Finish = Finish GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = Load completed. Loading = Loading\nPlease Wait... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logging in... = Logging in... -Logged in! = Logged in! Move = Move Move Up = Move Up Move Down = Move Down Network Connection = Network Connection NEW DATA = NEW DATA No = No -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = Save completed. @@ -444,7 +354,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = Select -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -455,11 +364,7 @@ Supported = Supported There is no data = There is no data. Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Yes @@ -525,23 +430,18 @@ ZIP file detected (Require WINRAR) = File is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Create shortcut Delete Game = Delete game Delete Game Config = Delete game config Delete Save Data = Delete savedata Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Game -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Game settings Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -551,8 +451,6 @@ Remove From Recent = Remove from "Recent" SaveData = Savedata Setting Background = Setting background Show In Folder = Show in folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -660,7 +558,6 @@ Percent of FPS = Percent of FPS Performance = Performance Postprocessing shaders = Postprocessing shaders Recreate Activity = Recreate activity -Render all frames = Render all frames Render duplicate frames to 60hz = Render duplicate frames to 60 Hz RenderDuplicateFrames Tip = Can make framerate smoother in games that run at lower framerates Rendering Mode = Rendering mode @@ -682,7 +579,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Texture filtering Texture Filtering = Texture filtering -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Texture scaling Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -693,6 +589,8 @@ Upscale Level = Upscale level Upscale Type = Upscale type UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex cache +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Window size @@ -709,12 +607,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Clear all -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restore defaults Map a new key for = Map a new key for Map Key = Map key @@ -771,7 +667,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 +Custom 10 = Custom 10 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -780,7 +685,6 @@ DevMenu = DevMenu Double tap button = Double tap button Down = Dpad Down Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -793,7 +697,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -823,7 +726,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Up @@ -840,6 +742,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address ChangeMacSaveConfirm = Generate a new MAC address? ChangeMacSaveWarning = Some games verify the MAC address when loading savedata, so this may break old saves. @@ -873,6 +780,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset (0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -883,9 +791,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -920,7 +830,6 @@ Amount = Amount Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon ColorCorrection = Color correction @@ -930,7 +839,6 @@ CRT = CRT scanlines FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level -FakeReflections = FakeReflections Intensity = Intensity LCDPersistence = LCD Persistence Natural = Natural Colors @@ -947,7 +855,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = Video Smoothing AA Vignette = Vignette @@ -997,7 +904,6 @@ written = Written in C++ for speed and portability [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -1025,23 +931,6 @@ Use PSP folder at root of storage = Use PSP folder at root of storage Welcome to PPSSPP! = Welcome to PPSSPP! WhatsThis = What's this? -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [RemoteISO] Browse Games = Browse games Local Server Port = Local server port @@ -1192,11 +1081,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1205,9 +1093,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1219,7 +1105,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1301,7 +1187,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1313,7 +1198,6 @@ Set UI background... = Set UI background... Show ID = Show ID Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1380,12 +1264,13 @@ Progress: %1% = Progress: %1% Screen representation = Screen representation [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Heads-up display scale = Heads-up display scale Heads-up display detection = Heads-up display detection diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index dac9d446d..353c790cd 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1,66 +1,7 @@ -[Achievements] -%1 achievements, %2 points = %1 logros, %2 puntos -%1: Attempt started = %1: intento para el leaderboard iniciado -%1: Attempt failed = %1: intento para el leaderboard fallido -Account = Cuenta -Achievement progress = Progreso del logro -Achievement unlocked = Logro desbloqueado -Achievements = Logros -Achievements are disabled = Los logros están desactivados -Achievements enabled = Los logros están activados -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Alrededor mio -Can't log in to RetroAchievements right now = No se pudo iniciar sesión a RetroAchievements en estos momentos -Challenge indicator = Indicador de desafio -Contacting RetroAchievements server... = Contactando al servidor de RetroAchievements... -Customize = Customizar -Earned = Has obtenido %1 de %2 logros y %3 de %4 puntos -Encore Mode = Modo Encore -Failed logging in to RetroAchievements = No se pudo iniciar sesión a RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Modo Desafío (Sin estados) -Hardcore Mode = Modo Desafío -How to use RetroAchievements = Como usar RetroAchievements -In Encore mode - listings may be wrong below = En el modo Encore - las listas de abajo pueden estar equivocadas -Leaderboard attempt started or failed = Intento de leaderboard intentado o fracasado -Leaderboard result submitted = Resultado de leaderboard enviado -Leaderboard score submission = Subir puntos al leaderboard -Leaderboard submission is enabled = Se ha activado la subida de puntos al leaderboard -Leaderboard tracker = Rastreador de leaderboards -Leaderboards = Leaderboards -Links = Enlaces -Locked achievements = Logros bloqueados -Log bad memory accesses = Registrar malos accesos a la memoría -Mastered %1 = Completaste %1 -Notifications = Notificaciones -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Registrate en www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements no está disponible para este juego -RetroAchievements website = Página web de RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = Estado guardado sin información de los logros -Save states not available in Hardcore Mode = Los estados no están disponibles en el modo desafío -Sound Effects = Efectos de sonido -Statistics = Estadísticas -Submitted %1 for %2 = Se subió %1 para %2 -Syncing achievements data... = Sincronizando información de logros... -Test Mode = Modo prueba -This feature is not available in Hardcore Mode = Esta opción no está disponible en el modo desafío -This game has no achievements = Este juego no tiene logros -Top players = Top jugadores -Unlocked achievements = Logros desbloqueados -Unofficial achievements = Logros no oficiales -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternar velocidad de sonido Audio backend = Motor de audio (requiere reiniciar) Audio Error = Error de audio -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Búfer compatible con bluetooth (lento) Auto = Automático Device = Dispositivo @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrar stick Calibrate = Calibrar Calibrated = Calibrado Calibration = Calibración -Circular low end radius = Circular low end radius Circular stick input = Entrada de stick circular Classic = Clásico Confine Mouse = Fijar el ratón al área de la ventana/pantalla @@ -108,10 +48,8 @@ Deadzone radius = Radio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonales de cruceta Disable diagonal input = Deshabilitar mov. diagonal Double tap = Doble toque -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Habilitar gestos Enable standard shortcut keys = Habilitar teclas de atajo -frames = frames Gesture = Gestos Gesture mapping = Ajustes de gestos Glowing borders = Bordes brillantes @@ -140,7 +78,6 @@ OnScreen = Controles táctiles en pantalla Portrait = Vertical Portrait Reversed = Vertical invertido PSP Action Buttons = Botones de acción -Rapid fire interval = Rapid fire interval Raw input = Entrada raw Repeat mode = Repeat mode Reset to defaults = Restaurar ajustes @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensibilidad (escala) Sensitivity = Sensibilidad Shape = Forma Show Touch Pause Menu Button = Mostrar botón del menú -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Deslizar hacia Swipe sensitivity = Sensibilidad del deslizado Swipe smoothing = Fluidez del deslizado @@ -195,7 +131,7 @@ Direct3D9 = &Direct3D9 Direct3D11 = Direct3D &11 Disassembly = &Desensamblador... Discord = Discord -Display Layout && Effects = Editar pantalla y Shaders... +Display Layout && Effects = Editar posición de botones... Display Rotation = Rotación de pantalla Dump Next Frame to Log = &Volcar siguiente cuadro a registro Emulation = &Emulación @@ -230,7 +166,6 @@ Log Console = Consola de re&gistros... Memory View... = Visor de &memoria... More Settings... = Más &opciones... Nearest = &Cercano -Recent = &Reciente Skip Buffer Effects = &Saltar efectos del búfer (rápido) Off = &No Open Chat = Abrir ventana de chat @@ -269,6 +204,7 @@ Texture Filtering = &Filtrado de texturas Texture Scaling = &Escalado de texturas Use Lossless Video Codec (FFV1) = Usar códec de vídeo sin pérdida (&FFV1) Use output buffer for video = Usar salida de búfer para vídeo +Vertex Cache = &Caché de vértices VSync = Sincronización &vertical Vulkan = &Vulkan Window Size = &Tamaño de ventana @@ -282,11 +218,8 @@ Backspace = Borrar Block address = Bloquear dirección By Address = Por dirección Copy savestates to memstick root = Copiar estados guardados en la raíz de la Memory Stick -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Crear/Abrir archivo "textures.ini" para el juego actual Current = Actual -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Herramientas de desarrollo DevMenu = DevMenu Disabled JIT functionality = Desactivar funcionalidad JIT @@ -297,11 +230,8 @@ Enable driver bug workarounds = Activar arreglos alternativos para fallos de dri Enable Logging = Activar registro Enter address = Insertar dirección FPU = FPU -Fragment = Fragment Frame Profiler = Medir rendimiento -Frame timing = Frame timing Framedump tests = Tests de volcado de cuadros -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Test de controlador GPU GPU log profiler = log de perfiles GPU GPU Profile = Perfil GPU @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Registrar estadísticas de caídas de fotogramas Log Level = Nivel de registro Log View = Ver el registro Logging Channels = Canales de registro -Multi-threaded rendering = Renderizado multihilo Next = Siguiente No block = No bloquear -Off = Off Prev = Anterior Random = Aleatorio Replace textures = remplazar texturas @@ -332,12 +260,10 @@ Stats = Estadísticas System Information = Información del sistema Texture ini file created = Archivo ini de texturas creado Texture Replacement = Reemplazo de texturas -Audio Debug = Depuración de audio -Control Debug = Control Debug +Toggle Audio Debug = Parar/Reanudar depuración de audio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Parar/Reanudar imagen Touchscreen Test = Test de pantalla táctil -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * resolución PSP Active = Activo Back = Atrás -Bottom Center = Inferior centrado -Bottom Left = Inferior izquierda -Bottom Right = Inferior derecha Cancel = Cancelar Center = Centrar -Center Left = Centrado izquierdo -Center Right = Centrado derecho -Changing this setting requires PPSSPP to restart. = Cambiar esta opción requiere reiniciar PPSSPP.\n¿Reiniciar ahora? +ChangingGPUBackends = Cambiar el motor gráfico requiere reiniciar PPSSPP.\n¿Reiniciar ahora? +ChangingInflightFrames = Cambiar el búfer de comando de gráficos requiere reiniciar PPSSPP.\n¿Reiniciar ahora? Channel: = Canal: Choose PPSSPP save folder = Elige la carpeta de guardado de PPSSPP. Confirm Overwrite = ¿Deseas sobreescribir los datos? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = ¿Seguro que quieres borrar la configuración de este DeleteFailed = los datos no se pudieron borrar. Deleting = Borrando\nEspera un momento... Disable All = Desactivar todo -Disabled = Disabled Dumps = Volcados Edit = Editar Enable All = Activar todo -Enabled = Enabled Enter = Intro -Failed to connect to server, check your internet connection. = No se ha podido conectar con el servidor, revisa tu conexión a internet. -Failed to log in, check your username and password. = Error de log in, revisa tu username y password. Filter = Filtrar Finish = Terminar GE Frame Dumps = Volcados de fotogramas GE Grid = Cuadrícula Inactive = Inactivo -Installing... = Installing... InternalError = Ha ocurrido un error interno. -Links = Links Load = Cargar Load completed = Carga completada. Loading = Cargando\nEspera un momento... LoadingFailed = Los datos del juego no se pudieron cargar. -Log in = Log in -Log out = Log out -Logged in! = ¡Sesión iniciada! -Logging in... = Iniciando sesión... Move = Posición Move Down = Bajar Move Up = Subir Network Connection = Conexión de red NEW DATA = NUEVOS DATOS DE PARTIDA No = No -None = Ninguno ObtainingIP = Obteniendo direcciónnn IP.\nPor favor espera... OK = Aceptar Old savedata detected = Se han detectado datos del juego antiguos. Options = Opciones -Password = Password Remove = Quitar Reset = Reiniciar Resize = Tamaño -Restart = Reiniciar Retry = Reintentar Save = Guardar Save completed = Los datos del juego han sido almacenados. @@ -420,7 +329,6 @@ SavingFailed = Los datos del juego no se pudieron guardar. Search = Buscar seconds, 0:off = segundos, 0 = no Select = Seleccionar -Settings = Settings Shift = Alternar Skip = Saltar Snap = Capturar @@ -431,11 +339,7 @@ Supported = Soportado There is no data = La tarjeta de memoria está vacía. Toggle All = Cambiar todo Toggle List = Ver lista -Top Center = Superior centrado -Top Left = Superior izquierda -Top Right = Superior derecha Unsupported = No soportado -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Cuando guardes, la partida cargará en una PSP, pero no en versiones antiguas de PPSSPP. When you save, it will not work on outdated PSP Firmware anymore = Cuando guardes, no volverá a funcionar en un firmware de PSP antiguo. Yes = Sí @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Es un archivo comprimido (en ZIP).\nPor lo [Game] Asia = Asia Calculate CRC = Calcular valor CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Confirmar -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Crear config. del juego Create Shortcut = Crear acceso directo Delete Game = Borrar juego Delete Game Config = Borrar config. del juego Delete Save Data = Borrar datos Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Juego -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Ajustes de juego Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instalación de datos -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japón Korea = Corea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Borrar de recientes SaveData = Datos Setting Background = Ajustar imagen de fondo Show In Folder = Mostrar en carpeta -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = América Use UI background = Usar imagen de fondo @@ -588,7 +485,7 @@ Device = Dispositivo Direct3D 9 = Direct3D 9 Direct3D 11 = Direct3D 11 Disabled = Desactivado -Display Layout && Effects = Editar pantalla y Shaders +Display Layout && Effects = Editor del área de pantalla Display Resolution (HW scaler) = Resolución de pantalla (escalado por hardware) Enable Cardboard VR = Activar Cardboard VR FPS = FPS @@ -623,7 +520,6 @@ Must Restart = Debes reiniciar PPSSPP para aplicar este cambio. Native device resolution = Resolución nativa del dispositivo Nearest = Pixelado No buffer = Sin búfer -Render all frames = Render all frames Show Battery % = Ver % de batería Show Speed = Ver velocidad Skip Buffer Effects = Saltar efectos del búfer @@ -658,7 +554,6 @@ Stereo rendering = Renderizado estéreo Stretch = Estirar Texture Filter = Filtro de texturas Texture Filtering = Filtrado de texturas -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Escalado de texturas Texture Shader = Shader de textura Turn off Hardware Tessellation - unsupported = Desactivando teselado por hardware: no soportado. @@ -669,6 +564,8 @@ Upscale Level = Nivel de escalado Upscale Type = Tipo de escalado UpscaleLevel Tip = Exige consumo de CPU, algunos escalados se pueden retrasar para evitar tirones. Use all displays = Usar todas las pantallas +Vertex Cache = Caché de vértices +VertexCache Tip = Rápido, pero puede causar parpadeo temporal. VSync = Sincronía vertical (VSync) Vulkan = Vulkan Window Size = Tamaño de ventana @@ -685,12 +582,10 @@ Zip archive corrupt = El archivo ZIP está dañado. Zip file does not contain PSP software = El archivo ZIP no contiene software de PSP. [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autoconfigurar Autoconfigure for device = Autoconfigurar para dispositivo Bind All = Asignar todos Clear All = Borrar todo -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restaurar Map a new key for = Pulsa una tecla para Map Key = Mapear tecla @@ -748,7 +643,16 @@ Audio/Video Recording = Grabar Audio/Vídeo AxisSwap = Invertir ejes Circle = Círculo Cross = Equis -Custom %d = Personalizado %d +Custom 1 = Personalizado 1 +Custom 10 = Personalizado 10 +Custom 2 = Personalizado 2 +Custom 3 = Personalizado 3 +Custom 4 = Personalizado 4 +Custom 5 = Personalizado 5 +Custom 6 = Personalizado 6 +Custom 7 = Personalizado 7 +Custom 8 = Personalizado 8 +Custom 9 = Personalizado 9 D-pad down = D-pad abajo D-pad left = D-pad izquierda D-pad right = D-pad derecha @@ -761,7 +665,6 @@ Display Portrait Reversed = Pantalla vertical invertida Double tap button = Botón de doble toque Down = Cruceta abajo Dpad = Cruceta -Exit App = Exit App Frame Advance = Avanzar fotograma Hold = Mantener Home = Inicio @@ -774,7 +677,6 @@ None = Ninguno Note = Nota OpenChat = Abrir Chat Pause = Pausa -Previous Slot = Previous Slot R = R RapidFire = Fuego rápido Record = Grabar @@ -804,7 +706,6 @@ Texture Dumping = Volcar texturas Texture Replacement = remplazar texturas Toggle Fullscreen = Pantalla completa Toggle mode = Alternar modo -Toggle WLAN = Toggle WLAN Triangle = Triángulo Fast-forward = Modo turbo Up = Cruceta arriba @@ -814,7 +715,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Ya contiene datos de PSP -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Crear o elegir la carpeta PSP Current = Actual DataCanBeShared = Los datos se pueden compartir entre PPSSPP regular/Gold @@ -847,6 +747,11 @@ AdHoc Server = Servidor AdHoc AdhocServer Failed to Bind Port = Servidor Adhoc falló al unir puerto. AM: Data from Unknown Port = AM: Datos de puerto desconocido Auto = Automático +Bottom Center = Inferior centrado +Bottom Left = Inferior izquierda +Bottom Right = Inferior derecha +Center Left = Centrado izquierdo +Center Right = Centrado derecho Change Mac Address = Cambiar dirección MAC Change proAdhocServer Address = Cambiar dirección de proAdhocServer (localhost = varias instancias) ChangeMacSaveConfirm = Generar una nueva dirección MAC? @@ -880,6 +785,7 @@ Invalid IP or hostname = IP o nombre del host inválido Minimum Timeout = Tiempo de espera mínimo (en ms, 0 por defecto) Misc = Otros ajustes (por defecto = compatibilidad) Network Initialized = Juego en red iniciado +None = Ninguno Please change your Port Offset = Por favor cambia el offset del puerto. Port offset = Variar puerto de red (0 = compatible con PSP) Open PPSSPP Multiplayer Wiki Page = Página wiki sobre PPSSPP Ad-Hoc @@ -890,9 +796,11 @@ Quick Chat 3 = Chat rápido 3 Quick Chat 4 = Chat rápido 4 Quick Chat 5 = Chat rápido 5 QuickChat = Chat rápido -Randomize = Randomize Send = Enviar Send Discord Presence information = Enviar información a Discord "Rich Presence" +Top Center = Superior centrado +Top Left = Superior izquierda +Top Right = Superior derecha Unable to find UPnP device = Dispositivo UPnP no encontrado UPnP (port-forwarding) = UPnP (redirección de puertos) UPnP need to be reinitialized = La función de UPnP debe reinicializarse. @@ -902,23 +810,6 @@ Validating address... = Validando dirección... WLAN Channel = Canal WLAN You're in Offline Mode, go to lobby or online hall = Estás en modo offline, ve al lobby o a la sala online -[PSPSettings] -Auto = Automático -Chinese (simplified) = Chino (Simplificado) -Chinese (traditional) = Chino (Tradicional) -Dutch = Neerlandés -English = Inglés -French = Francés -Game language = Lenguaje del juego -German = Alemán -Italian = Italiano -Japanese = Japones -Korean = Coreano -Games often don't support all languages = Los juegos usualmente no pueden usar todos los lenguajes -Portuguese = Portugués -Russian = Ruso -Spanish = Castellano - [Pause] Cheats = Trucos Continue = Continuar @@ -945,7 +836,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Bordes negros Bloom = Resplandor -BloomNoBlur = Bloom (no blur) Brightness = Brillo Cartoon = Dibujos animados CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -953,7 +843,6 @@ ColorCorrection = Corrección de color ColorPreservation = Color preservation Contrast = Contraste CRT = Pantalla de tubo (CRT) -FakeReflections = FakeReflections FXAA = Antialiasing por FXAA Gamma = Gamma GreenLevel = Green level @@ -974,7 +863,6 @@ SSAA(Gauss) = Super muestreo AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Escalado en Spline36 VideoSmoothingAA = Suavizado de vídeo AA Vignette = Viñeta @@ -1129,7 +1017,7 @@ Filter = Filtro Filtering settings by '%1' = Ajustes de filtrado por '%1' Find settings = Ajustes de búsqueda No settings matched '%1' = Ningún ajuste coincide '%1' -Search term = Buscar término +Search term = Search term [Store] Already Installed = Ya instalado @@ -1178,11 +1066,10 @@ GPU Flags = GPU Flags GPU Information = Información de la GPU High precision float range = Rango de alta precisión (flotante) High precision int range = Rango de alta precisión (enteros) -Icon cache = Icon cache JIT available = JIT available Lang/Region = Idioma/Región Memory Page Size = Tamaño de página de memoria -Native resolution = Resolución nativa +Native Resolution = Resolución nativa No GPU driver bugs detected = No se han detectado error del controlador GPU OGL Extensions = Extensiones OGL OpenGL ES 2.0 Extensions = Extensiones OpenGL 2.0 @@ -1191,9 +1078,7 @@ OpenGL Extensions = Extensiones OpenGL Optimal frames per buffer = Cuadros por búfer óptimos Optimal sample rate = Frecuencia de muestreo óptima OS Information = Información del Sistema Operativo -Pixel resolution = Pixel resolution PPSSPP build = Compilación de PPSSPP -Present modes = Present modes Refresh rate = frecuencia de actualización Release = Estable RW/RX exclusive = RW/RX exclusivo @@ -1205,7 +1090,7 @@ System Information = Información del sistema System Name = Nombre System Version = Versión del sistema Threads = Cantidad hilos -UI resolution = Resolución de interfaz +UI Resolution = Resolución de interfaz Vendor = Modelo Vendor (detected) = Proveedor Version Information = Información de la versión @@ -1288,7 +1173,6 @@ Record Audio = Grabar audio Record Display = Grabar pantalla Reset Recording on Save/Load State = Reiniciar grabación al cargar/guardar estado Restore Default Settings = Reestablecer ajustes -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Intervalo de rebobinado Save path in installed.txt = Carpeta de guardado en "installed.txt" Save path in My Documents = Carpeta de guardado en "Mis documentos" @@ -1301,7 +1185,6 @@ Show ID = Mostrar ID Show Memory Stick folder = Mostrar directorio Memory Stick Show region flag = Mostrar bandera de región Simulate UMD delays = Simular retraso del UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Ranura 1 Slot 2 = Ranura 2 Slot 3 = Ranura 3 @@ -1357,11 +1240,12 @@ Download = Descargar New version of PPSSPP available = Nueva versión de PPSSPP disponible [VR] +% of native FoV = % de campo de visión nativo 6DoF movement = Movimiento 6DoF Camera type = Camera type Distance to 2D menus and scenes = Distancia de los menús y escenas 2D -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Escala de campo de visión Force 72Hz update = Forzar actualizar a 72Hz Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index dd8d824bc..fc50d9e02 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1,66 +1,7 @@ -[Achievements] -%1 achievements, %2 points = %1 logros, %2 puntos -%1: Attempt started = %1: intento para el leaderboard iniciado -%1: Attempt failed = %1: intento para el leaderboard fallido -Account = Cuenta -Achievement progress = Achievement progress -Achievement unlocked = Logro Desbloqueado -Achievements = Logros -Achievements are disabled = Los logros están desactivados -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = No se pudo iniciar sesión a RetroAchievements -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contactando al servidor de RetroAchievements... -Customize = Customizar -Earned = Has obtenido %1 de %2 logros y %3 de %4 puntos -Encore Mode = Modo Encore -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Modo Desafío (Sin estados) -Hardcore Mode = Modo Desafío -How to use RetroAchievements = Como usar RetroAchievements -In Encore mode - listings may be wrong below = En el modo Encore - las listas de abajo pueden estar equivocadas -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Subir puntos al leaderboard -Leaderboard submission is enabled = Se ha activado la subida de puntos al leaderboard -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Logros bloqueados -Log bad memory accesses = Registrar malos accesos a la memoría -Mastered %1 = Completaste %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Registrate en www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements no está disponible para este juego -RetroAchievements website = Página web de RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = Estado guardado sin información de los logros -Save states not available in Hardcore Mode = Los estados no están disponibles en el modo desafío -Sound Effects = Efectos de sonido -Statistics = Estadísticas -Submitted %1 for %2 = Se subió %1 para %2 -Syncing achievements data... = Sincronizando información de logros... -Test Mode = Modo prueba -This feature is not available in Hardcore Mode = Esta opción no está disponible en el modo desafío -This game has no achievements = Este juego no tiene logros -Top players = Top players -Unlocked achievements = Logros desbloqueados -Unofficial achievements = Logros no oficiales -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternar velocidad de volumen Audio backend = Motor de audio (req. reiniciar) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Búfer amigable con Bluetooth (enlentece) Auto = Automático Device = Dispositivo @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrar análogo Calibrate = Calibrar Calibrated = Calibrado Calibration = Calibración -Circular low end radius = Circular low end radius Circular stick input = Entrada del stick circular Classic = Clásico Confine Mouse = Fijar el ratón al área de la ventana/pantalla @@ -108,10 +48,8 @@ Deadzone radius = Radio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonales de la cruceta Disable diagonal input = Deshabilitar mov. diagonal Double tap = Doble toque -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Habilitar gestos Enable standard shortcut keys = Habilitar teclas de atajo -frames = frames Gesture = Gestos Gesture mapping = Configurac. de gestos Glowing borders = Bordes brillantes @@ -140,7 +78,6 @@ OnScreen = Controles en pantalla Portrait = Retrato Portrait Reversed = Retrato invertido PSP Action Buttons = Botones de acción PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Restaurar config. @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensibilidad (escala) Sensitivity = Sensibilidad Shape = Forma Show Touch Pause Menu Button = Mostrar botón del menú -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Deslizar hacia Swipe sensitivity = Sensibilidad del deslizado Swipe smoothing = Fluidez del deslizado @@ -195,7 +131,7 @@ Direct3D9 = &Direct3D 9 Direct3D11 = Direct3D &11 Disassembly = &Desensamblador... Discord = Discord -Display Layout && Effects = Editar pantalla y Shaders... +Display Layout && Effects = Editar posición de botones... Display Rotation = Rotación de pantalla Dump Next Frame to Log = &Volcar siguiente cuadro a registro Emulation = &Emulación @@ -230,7 +166,6 @@ Log Console = Consola de re&gistros... Memory View... = Visor de &memoria... More Settings... = Más &opciones... Nearest = &Cercano -Recent = &Recent Skip Buffer Effects = &Saltar efectos por búfer (rápido) Off = &No Open Chat = Abrir ventana de chat @@ -269,6 +204,7 @@ Texture Filtering = &Filtrado de texturas Texture Scaling = &Escalado de texturas Use Lossless Video Codec (FFV1) = Usar codec de vídeo sin pérdida (&FFV1) Use output buffer for video = Usar salida de búfer para vídeo +Vertex Cache = &Caché de vértices VSync = Sincronización &vertical Vulkan = Vulkan Window Size = &Tamaño de ventana @@ -282,11 +218,8 @@ Backspace = Borrar Block address = Bloquear dirección By Address = Por dirección Copy savestates to memstick root = Copiar estados de guardado a la ruta inicial de Memory Stick -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Crear/Abrir archivo textures.ini para el juego actual Current = Actual -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Herramientas de\ndesarrollador DevMenu = Menú Depuración Disabled JIT functionality = Apagar funcionalidad de JIT @@ -297,11 +230,8 @@ Enable driver bug workarounds = Activar arreglos alternativos para fallos de dri Enable Logging = Activar registro Enter address = Insertar dirección FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Pruebas de volcado de frames Frame Profiler = Perfilado de frame -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Probar controlador GPU GPU log profiler = GPU log profiler GPU Profile = Perfil de GPU @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Registrar estadísticas de frames caídos Log Level = Nivel de registro Log View = Ver el registro Logging Channels = Canales de registro -Multi-threaded rendering = Multi-threaded rendering Next = Siguiente No block = No bloquear -Off = Off Prev = Atras Random = Aleatorio Replace textures = Remplazar texturas @@ -332,12 +260,10 @@ Stats = Estadísticas System Information = Información del sistema Texture ini file created = Texture ini file created Texture Replacement = Remplazar texturas -Audio Debug = Depuración de audio -Control Debug = Control Debug +Toggle Audio Debug = Parar/Reanudar depuración de audio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Parar/Reanudar imagen Touchscreen Test = Probar pantalla táctil -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Activo Back = Atrás -Bottom Center = Abajo -Bottom Left = Abajo Izquierda -Bottom Right = Abajo Derecha Cancel = Cancelar Center = Centrar -Center Left = Izquierda -Center Right = Derecha -Changing this setting requires PPSSPP to restart. = Cambiar esta opción requiere que PPSSPP se reinicie.\n¿Reiniciar ahora? +ChangingGPUBackends = Cambiar el GPU requiere reiniciar PPSSPP.\n¿Reiniciar ahora? +ChangingInflightFrames = Cambiar el almacenamiento en búfer de comandos gráficos requiere que PPSSPP se reinicie.\n¿Reiniciar ahora? Channel: = Canal: Choose PPSSPP save folder = Elige la carpeta de guardado de PPSSPP. Confirm Overwrite = Hay archivos existentes,\n¿Deseas sobreescribirlos? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = ADVERTENCIA:\nLos archivos de preferencias de este jue DeleteFailed = Los archivos no se pudieron borrar. Deleting = Borrando\nPor favor espere... Disable All = Apagar todo -Disabled = Disabled Dumps = Volcados Edit = Editar Enable All = Activar todo -Enabled = Enabled Enter = Confirmar -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filtrar Finish = Terminar GE Frame Dumps = Volcados de cuadros GE Grid = Cuadrícula Inactive = Inactivo -Installing... = Installing... InternalError = Ha ocurrido una falla interna. -Links = Links Load = Abrir Load completed = Datos cargados. Loading = Cargando\nPor favor espere... LoadingFailed = Los datos del juego no se pudieron cargar. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Mover Move Down = Move Down Move Up = Move Up Network Connection = Conexión de red NEW DATA = CREAR DATOS No = No -None = None ObtainingIP = Obteniendo dirección IP.\nEspera un momento... OK = OK Old savedata detected = Se han detectado datos del juego antiguos. Options = Opciones -Password = Password Remove = Remove Reset = Reiniciar Resize = Tamaño -Restart = Reiniciar Retry = Reintentar Save = Guardar Save completed = Los datos del juego han sido almacenados. @@ -420,7 +329,6 @@ SavingFailed = Los datos del juego no se pudieron guardar. Search = Buscar seconds, 0:off = seconds, 0 = No Select = Seleccionar -Settings = Settings Shift = Alternar Skip = Saltar Snap = Capturar @@ -431,11 +339,7 @@ Supported = Soportado There is no data = No se han encontrado datos del juego. Toggle All = Cambiar todo Toggle List = Cambiar lista -Top Center = Arriba -Top Left = Arriba Izquierda -Top Right = Arriba Derecha Unsupported = No es soportado -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Cuando guardes, la partida cargará en una PSP, pero no en versiones antiguas de PPSSPP. When you save, it will not work on outdated PSP Firmware anymore = Cuando guardes, la partida puede no funcionar en una PSP con firmware desactualizado. Yes = Sí @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Se ha detectado un archivo ZIP.\nUtiliza co [Game] Asia = Asia Calculate CRC = Calcular valor CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Borrar -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Crear config. del juego Create Shortcut = Crear acceso directo Delete Game = Borrar juego Delete Game Config = Borrar config. del juego Delete Save Data = Borrar datos Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Juego -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Ajustes de juego Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instalación de datos -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japón Korea = Corea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Borrar de recientes SaveData = Datos Setting Background = Configurar fondo Show In Folder = Mostrar en carpeta -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = América Use UI background = Usar fondo como interfaz @@ -588,7 +485,7 @@ Device = Dispositivo Direct3D 9 = Direct3D 9 Direct3D 11 = Direct3D 11 Disabled = Apagado -Display Layout && Effects = Editar pantalla y Shaders +Display Layout && Effects = Editor del área de pantalla Display Resolution (HW scaler) = Resolución de pantalla (escalado por HW) Enable Cardboard VR = Activar Cardboard VR FPS = FPS @@ -623,7 +520,6 @@ Must Restart = Debes reiniciar PPSSPP para aplicar este cambio. Native device resolution = Resolución nativa del dispositivo Nearest = Pixelado No buffer = No hay búfer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Saltar efectos por búfer (Desactiva búfer, rápido) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Estirar Texture Filter = Filtro de texturas Texture Filtering = Filtrado de texturas -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Escalado de texturas Texture Shader = Shader de texturas Turn off Hardware Tessellation - unsupported = Desactivando Teselado por Hardware: no es soportado. @@ -669,6 +564,8 @@ Upscale Level = Nivel de escalado Upscale Type = Tipo de escalado UpscaleLevel Tip = Consume tanta CPU. Cierto escalado se retrasa para evitar caídas de frames. Use all displays = Usar todas las muestras +Vertex Cache = Caché con Vértices +VertexCache Tip = Acelera, pero puede causar parpadeos en ocasiones. VSync = Sincronía vertical (VSync) Vulkan = Vulkan Window Size = Tamaño de ventana @@ -685,12 +582,10 @@ Zip archive corrupt = El archivo ZIP está dañado. Zip file does not contain PSP software = El archivo ZIP no contiene software de PSP. [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autoconfigurar Autoconfigure for device = Autoconfigurar para dispositivo Bind All = Ocultar todo Clear All = Borrar todo -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restaurar Map a new key for = Presiona una tecla para Map Key = Asignar tecla @@ -747,7 +642,16 @@ Audio/Video Recording = Grabar audio/video AxisSwap = Invertir ejes Circle = ○ Cross = × -Custom %d = Personal %d +Custom 1 = Personal 1 +Custom 2 = Personal 2 +Custom 3 = Personal 3 +Custom 4 = Personal 4 +Custom 5 = Personal 5 +Custom 6 = Personal 6 +Custom 7 = Personal 7 +Custom 8 = Personal 8 +Custom 9 = Personal 9 +Custom 10 = Personal 10 D-pad down = PDM Abajo D-pad left = PDM Izquierda D-pad right = PDM Derecha @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Botón de doble toque Down = Abajo Dpad = Punto de mira -Exit App = Exit App Frame Advance = Avanzar Frame Hold = Mantener Home = PSHome @@ -773,7 +676,6 @@ None = Ninguno Note = Sonido OpenChat = Abrir chat Pause = Pausa -Previous Slot = Previous Slot R = R RapidFire = Disparo rápido Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Dumpear textura Texture Replacement = Remplazo de textura Toggle Fullscreen = Alternar pantalla completa Toggle mode = Alternar modo -Toggle WLAN = Toggle WLAN Triangle = △ Fast-forward = Modo turbo Up = Arriba @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Actualmente contiene datos de PSP -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Seleccionar o crear carpeta PSP Current = Actual DataCanBeShared = Datos pueden moverse entre PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Servidor Adhoc AdhocServer Failed to Bind Port = Servidor Adhoc falló al unir puerto. AM: Data from Unknown Port = AM: Datos de puerto desconocido Auto = Auto +Bottom Center = Abajo +Bottom Left = Abajo Izquierda +Bottom Right = Abajo Derecha +Center Left = Izquierda +Center Right = Derecha Change Mac Address = Cambiar dirección MAC Change proAdhocServer Address = Cambiar dirección IP de\nservidor PRO Adhoc (localhost = multiples instancias) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = IP o nombre de host no válido Minimum Timeout = Tiempo de espera mínimo (en ms, 0 = por defecto) Misc = Otros ajustes (por defecto = compatibilidad con PSP) Network Initialized = Juego en red iniciado +None = None Please change your Port Offset = Por favor cambia el offset del puerto. Port offset = Variar puerto de red (0 = compatibilidad con PSP) Open PPSSPP Multiplayer Wiki Page = Página wiki sobre PPSSPP Ad-Hoc @@ -889,9 +795,11 @@ Quick Chat 3 = Chat rápido 3 Quick Chat 4 = Chat rápido 4 Quick Chat 5 = Chat rápido 5 QuickChat = Chat rápido -Randomize = Randomize Send = Enviar Send Discord Presence information = Enviar información al Discord "Rich Presence" +Top Center = Arriba +Top Left = Arriba Izquierda +Top Right = Arriba Derecha Unable to find UPnP device = No se encuentra el dispositivo UPnP UPnP (port-forwarding) = UPnP (redirección de puertos) UPnP need to be reinitialized = La función de UPnP debe reinicializarse. @@ -901,23 +809,6 @@ Validating address... = Validando dirección ... WLAN Channel = Canal WLAN You're in Offline Mode, go to lobby or online hall = Estás en modo fuera de línea, ve al lobby o sala en línea -[PSPSettings] -Auto = Automático -Chinese (simplified) = Chino (Simplificado) -Chinese (traditional) = Chino (Tradicional) -Dutch = Neerlandés -English = Inglés -French = Francés -Game language = Lenguaje del juego -German = Alemán -Italian = Italiano -Japanese = Japones -Korean = Coreano -Games often don't support all languages = Los juegos usualmente no pueden usar todos los lenguajes -Portuguese = Portugués -Russian = Ruso -Spanish = Español - [Pause] Cheats = Trampas Continue = Continuar @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Borde negro Bloom = Resplandor -BloomNoBlur = Bloom (no blur) Brightness = Brillo Cartoon = Caricaturas CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Corrección de color ColorPreservation = Color preservation Contrast = Contraste CRT = Pantalla de tubo (CRT) -FakeReflections = FakeReflections FXAA = Antialiasing por FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Super muestreo AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Escalado en Spline36 VideoSmoothingAA = Suavizado de vídeo AA Vignette = Viñeta @@ -1018,8 +906,6 @@ Twitter @PPSSPP_emu = Twitter @PPSSPP_emu website = Sitio web oficial written = Escrito en lenguaje C++ para una mejor portabilidad y velocidad -[PSPSettings] - [RemoteISO] Browse Games = Buscar juegos Local Server Port = Puerto del servidor local @@ -1179,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = Info de GPU High precision float range = Rango de alta precisión (flotante) High precision int range = Rango de alta precisión (enteros) -Icon cache = Icon cache JIT available = JIT available Lang/Region = Idioma/Región Memory Page Size = Tamaño de página de memoria -Native resolution = Resolución nativa +Native Resolution = Resolución nativa No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Extensiones OGL OpenGL ES 2.0 Extensions = Extensiones OpenGL ES 2.0 @@ -1192,9 +1077,7 @@ OpenGL Extensions = Extensiones OpenGL Optimal frames per buffer = Cuadros por búfer óptimos Optimal sample rate = Frecuencia de muestreo óptima OS Information = Info de sistema -Pixel resolution = Pixel resolution PPSSPP build = Compilación de PPSSPP -Present modes = Present modes Refresh rate = Tasa de refresco Release = Estable RW/RX exclusive = Exclusivo de RW/RX @@ -1206,7 +1089,7 @@ System Information = Información del sistema System Name = Nombre System Version = Versión del sistema Threads = Cantidad hilos -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detectado) Version Information = Info de versión @@ -1289,10 +1172,9 @@ Record Audio = Grabar Audio Record Display = Grabar pantalla Reset Recording on Save/Load State = Reiniciar grabación al abrir/guardar estados Restore Default Settings = Reestablecer ajustes -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Frecuencia de rebobinado\n(consume memoria) Save path in installed.txt = Guardar ruta en installed.txt -Save path in My Documents = Guardar ruta en "C:/Users/(tu usuario)/Documents" +Save path in My Documents = Guardar ruta en\n"C:/Users/(tu usuario)/Documents" Savestate Slot = Ranura de estado guardado Savestate slot backups = Copias de seguridad de estado guardado Screenshots as PNG = Capturas en PNG @@ -1302,7 +1184,6 @@ Show ID = Mostrar ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Mostrar bandera de región Simulate UMD delays = Simular retraso del UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Ranura 1 Slot 2 = Ranura 2 Slot 3 = Ranura 3 @@ -1357,11 +1238,12 @@ Download = Descargar New version of PPSSPP available = Nueva versión de PPSSPP disponible [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 8121cd951..9a4120ffe 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = حجم سرعت متناوب Audio backend = ‎صدا (نیاز به ریستارت) API Audio Error = خطای صدا -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = ‎بافر مناسب هندزفری بلوتوث (کند تر) Auto = ‎اتوماتیک Device = سیستم @@ -95,7 +36,6 @@ Calibrate Analog Stick = دسته آنالوگ را کالیبراسیون کن Calibrate = ‎کالیبره کردن Calibrated = کالیبراسیون شد Calibration = ‎کالیبره کردن -Circular low end radius = Circular شعاع کم پایان Circular stick input = ورودی دایره ای Classic = ‎کلاسیک Confine Mouse = ‎محدود کردن موس به ناحیه درون پنجره @@ -108,10 +48,8 @@ Deadzone radius = ‎شعاع ناحیه غیر فعال Disable D-Pad diagonals (4-way touch) = ‎غیر فعال کردن جهت های قطری (تاچ ۴ جهته) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = ‎نمایش کنترل های لمسی Portrait = ‎عمودی Portrait Reversed = ‎عمودی وارونه PSP Action Buttons = ‎اکشن دکمه های -Rapid fire interval = Rapid fire interval Raw input = ورودی راو Repeat mode = حالت تکرار Reset to defaults = ریست کردن پیشفرض @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = ‎حساسیت Shape = اشیا Show Touch Pause Menu Button = ‎نمایش دکمه توقف بازی -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = حساسیت Swipe sensitivity = حساسیت کش رفتن Swipe smoothing = ضربه تند وشدید زدن @@ -230,7 +166,6 @@ Log Console = ‎کنسول لاگ Memory View... = ‎...نمایش مموری More Settings... = ‎...تنظیمات بیشتر Nearest = ‎نزدیک ترین -Recent = &Recent Skip Buffer Effects = ‎رد کردن اثرات بافر (سریع تر) Off = ‎خاموش Open Chat = باز کردن چت @@ -269,6 +204,7 @@ Texture Filtering = ‎فیلتر تکسچر Texture Scaling = ‎تغییر سایز تکسچر Use Lossless Video Codec (FFV1) = ‎(FFV1) استفاده از کدک بدون دستکاری Use output buffer for video = Use output buffer for video +Vertex Cache = ‎Vertex کش کردن VSync = VS&ync Vulkan = والکمن Window Size = ‎سایز پنجره @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = ساختن یا باز کردن تکسچر ini برای بازی شما Current = جاری کردن -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = ابزارهای توسعه DevMenu = منوتوسعه دهنده Disabled JIT functionality = قابلیت جت غیر فعال @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = ‎روشن کردن لاگ باگ ها Enter address = وارد کردن ادرس FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = تست کردن جی پی یو سخت افزار GPU log profiler = GPU log profiler GPU Profile = پروفایل سخت افراری؟ @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = ورود آمار کادر کاهش یافته ا Log Level = سطح خطا Log View = مشاهده خطا Logging Channels = رکورد خطا چنل ها -Multi-threaded rendering = Multi-threaded rendering Next = بعدی No block = بدون بلوک -Off = Off Prev = قبلی Random = شانسی Replace textures = جایگزین کردن تکسچر @@ -332,12 +260,10 @@ Stats = Stats System Information = ‎اطلاعات سیستم Texture ini file created = ایجاد کنید یک فایل بافت با فرمت ini Texture Replacement = جایگزینی بافت -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = ‎برگشت -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = ‎انصراف Center = وسط -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = تغییر دستور گرافیک گرافیک نیاز به PPSSPP برای راه اندازی مجدد دارد. راه اندازی مجدد حالا؟ +ChangingGPUBackends = تغییر Backends GPU نیاز به PPSSPP برای راه اندازی مجدد. راه اندازی مجدد حالا؟ +ChangingInflightFrames = تغییر دستور گرافیک گرافیک نیاز به PPSSPP برای راه اندازی مجدد دارد. راه اندازی مجدد حالا؟ Channel: = کانال: Choose PPSSPP save folder = انتخاب پوشه برای PPSSSPP Confirm Overwrite = ‎آیا می خواهید که دیتا ها را بازنویسی کنید؟ @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = آیا واقعا میخواهید تنظیمات ای DeleteFailed = Unable to delete data. Deleting = ‎در حال حذف کردن\n...منتظر بمانید Disable All = غیر فعال کردن همه؟ -Disabled = Disabled Dumps = Dumps Edit = ویرایش Enable All = فعال کردن همه؟ -Enabled = Enabled Enter = ‎ورود -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = فیلتر Finish = ‎پایان GE Frame Dumps = GE Frame Dumps Grid = چهارچوب Inactive = Inactive -Installing... = Installing... InternalError = خطای داخلی رخ داده است. -Links = Links Load = ‎بارگیری Load completed = ‎.بارگیری نکمیل شد Loading = ‎درحال بارگیری\n...منتظر بمانید LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = حرکت Move Down = حرکت به پایین Move Up = حرکت به بالا Network Connection = Network Connection NEW DATA = ‎دیتای جدید No = ‎خیر -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = ‎تایید Old savedata detected = Old savedata detected Options = تنظیمات -Password = Password Remove = حذف Reset = بازیابی Resize = اندازه گیری -Restart = Restart Retry = تلاش مجدد Save = ‎ذخیره Save completed = ‎.ذخیره تکمیل شد @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = جستجو seconds, 0:off = ‎تعداد فریم، 0 : ثانیه Select = ‎انتخاب -Settings = Settings Shift = ‎تغییر Skip = رد کردن Snap = Snap @@ -431,11 +339,7 @@ Supported = حمایت میشود There is no data = ‎.دیتایی وجود ندارد Toggle All = تغییر وضعیت همه Toggle List = تغییر وضعیت لیست -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = ساپورت نمیشود -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = ‎بله @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = ‎\n.فشرده سازی شده است ZIP [Game] Asia = اسیا Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = حذف -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = ایجاد کانفیگ بازی Create Shortcut = ‎ساخت میانبر Delete Game = حذف بازی Delete Game Config = حذف تنظیمات دستی Delete Save Data = حذف دیتای بازی؟ Europe = اروپا -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = ‎بازی -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = ‎تنظیمات بازی Homebrew = صفحه اصلی Hong Kong = هونگ کونگ InstallData = تصب دیتا؟ -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = ژاپن Korea = کره MB = مگابایت @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = ‎دیتای ذخیره Setting Background = تنظیمات پس زمینا Show In Folder = نمایش پوشه -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = آمریکا Use UI background = استفاده به عنوان پس زمینه؟ @@ -623,7 +520,6 @@ Must Restart = ‎برای اعمال این تنظیم باید برنامه ر Native device resolution = ‎رزولوشن دستگاه Nearest = ‎نزدیک ترین No buffer = بدون بافر -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = ‎رد کردن اثر بافر (سریع تر) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = ‎کشیدن Texture Filter = ‎فیلتر تکسچر Texture Filtering = ‎فیلتر کردن تکسچر -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = ‎تغییر سایز تکسچر ها Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = ‎میزان افزایش سایز Upscale Type = ‎نوع افزایش سایز UpscaleLevel Tip = ‎زیاد کار میکشد CPU از Use all displays = ‎استفاده از همه نمایشگر ها +Vertex Cache = ‎Vertex کش +VertexCache Tip = ‎سریع تر، اما ممکن است باعث لرزش موقتی شود VSync = VSync Vulkan = والکمن Window Size = ‎سایز پنجره @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = ‎پاکسازی همه -Combo mappings are not enabled = Combo mappings are not enabled Default All = ‎پیشفرض همه Map a new key for = ‎برای این دکمه یک کلید انتخاب کنید Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Down Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = RapidFire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Up @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = ‎کد تقلب Continue = ‎ادامه بازی @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = روشنایی Cartoon = کارتون CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = گاما GreenLevel = سطح سبز @@ -973,7 +862,6 @@ SSAA(Gauss) = نمونه برداری فوق العاده AA (گوس) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = اسپلین 36 تا اسکلهر VideoSmoothingAA = صاف کردن ویدئو AA Vignette = شکل @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = ‎ضبط صدا Record Display = ‎ضبط صفحه Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = ‎به حالت اولیه PPSSPP بازگشت تنظیمات -RetroAchievements = RetroAchievements Rewind Snapshot Interval = ‎تعداد فریم ذخیره شده برای به عقب رفتن (مصرف زیاد رم) Save path in installed.txt = Save path in installed.txt Save path in My Documents = ذخیره در داکیومنت ها @@ -1300,7 +1184,6 @@ Show ID = ایدی Show Memory Stick folder = نمایش پوشه حافظه Show region flag = Show region flag Simulate UMD delays = ‎شبیه سازی تاخیر خواندن دیسک -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = دانلود New version of PPSSPP available = ورژن جدیدی از ppsspp موجود است [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 956c2e996..9485c1040 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 saavutusta, %2 pistettä -Account = Tili -Achievement progress = Achievement progress -Achievement unlocked = Saavutus avattu -Achievements = Saavutukset -Achievements are disabled = Saavutukset ovat pois käytöstä -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = RetroAchievements:iin ei voida kirjautua juuri nyt -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Yhdistetään RetroAchievements:in palvelimelle... -Customize = Mukauta -Earned = Olet ansainnut %1/%2 saavutusta, ja %3/%4 pistettä -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Haastetila (ei tilatallennuksia) -Hardcore Mode = Haastetila -How to use RetroAchievements = Kuinka käyttää RetroAchievements:ia -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Sijoituslistan pisteiden lähetys -Leaderboard submission is enabled = Sijoituslistan lähetys on käytössä -Leaderboard tracker = Leaderboard tracker -Leaderboards = Sijoituslista -Links = Linkit -Locked achievements = Lukitut saavutukset -Log bad memory accesses = Kirjaa virheelliset muistipääsyt -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Rekisteröidy osoitteessa www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements eivät ole käytössä tälle pelille -RetroAchievements website = RetroAchievements verkkosivu -Rich Presence = Rich Presence -Save state loaded without achievement data = Tilatallennus ladattu, ilman saavutuksen tietoja -Save states not available in Hardcore Mode = Tilatallennukset eivät ole käytössä haastetilassa -Sound Effects = Äänimerkit -Statistics = Tilastot -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Synkoronoidaan saavutusten tietoja... -Test Mode = Testitila -This feature is not available in Hardcore Mode = Tämä ominaisuus ei ole käytettävissä haastetilassa -This game has no achievements = Tällä pelillä ei ole saavutuksia -Top players = Top players -Unlocked achievements = Avatut saavutukset -Unofficial achievements = Epäviralliset saavutukset -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Vaihtoehtoisen nopeuden äänenvoimakkuus Audio backend = Äänen taustajärjestelmä (uudelleenkäynnistä) Audio Error = Äänivirhe -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-ystävällinen puskuri (hitaampi) Auto = Automaattinen Device = Laite @@ -77,94 +18,89 @@ Use global volume = Käytä yleistä äänenvoimakkuutta WASAPI (fast) = WASAPI (nopea) [Controls] -Analog Binding = Analoginen kartoitus -Analog Limiter = Analoginen rajoitin -Analog Settings = Analogisen asetukset -Analog Stick = Analoginen sauva -Analog Style = Analogisen tyyli -AnalogLimiter Tip = Kun analogisen rajoittimen näppäintä painetaan -Auto = Automaattinen -Auto-centering analog stick = Automaattisesti keskittävä analoginen sauva -Auto-hide buttons after delay = Piilota näppäimet automaattisesti viiveen jälkeen +Analog Binding = Analog Binding +Analog Limiter = Analog limiter +Analog Settings = Analog Settings +Analog Stick = Analog stick +Analog Style = Analog Style +AnalogLimiter Tip = When the analog limiter button is pressed +Auto = Auto +Auto-centering analog stick = Auto-centering analog stick +Auto-hide buttons after delay = Auto-hide buttons after delay Auto-rotation speed = Auto-rotation speed -Binds = Sidokset -Button Binding = Näppäinten sidokset -Button Opacity = Näppäinten peittävyys -Button style = Näppäinten tyyli -Calibrate Analog Stick = Kalibroi analoginen sauva -Calibrate = Kalibroi -Calibrated = Kalibroitu -Calibration = Kalibraatio -Circular low end radius = Circular low end radius +Binds = Binds +Button Binding = Button Binding +Button Opacity = Painikkeiden peittävyys +Button style = Button style +Calibrate Analog Stick = Calibrate Analog Stick +Calibrate = Calibrate +Calibrated = Calibrated +Calibration = Calibration Circular stick input = Circular stick input Classic = Klassinen -Confine Mouse = Kaappaa hiiri ikkunan/näytön sisälle -Control Mapping = Ohjauksen kartoitus +Confine Mouse = Trap mouse within window/display area +Control Mapping = Control mapping Custom Key Setting = Custom Key Setting -Customize = Mukauta -Customize Touch Controls = Muokkaa kosketusohjauksen asetelmaa... -D-PAD = Ristiohjain -Deadzone radius = Katvealueen säde -Disable D-Pad diagonals (4-way touch) = Poista käytöstä ristiohjaimen vinottainen syöte (nelisuuntainen syöte) -Disable diagonal input = Poista vinottainen syöte käytöstä -Double tap = Kaksinkertainen napautus -Enable analog stick gesture = Enable analog stick gesture -Enable gesture control = Ota eleohjaukset käyttöön +Customize = Customize +Customize Touch Controls = Edit touch control layout... +D-PAD = D-Pad +Deadzone radius = Deadzone radius +Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) +Disable diagonal input = Disable diagonal input +Double tap = Double tap +Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = kuvat -Gesture = Eleet -Gesture mapping = Eleiden kartoitus -Glowing borders = Hohtavat rajat -HapticFeedback = Haptinen palaute (värinä) -Hide touch analog stick background circle = Piiloita kosketettavan analogisen sauvan taustaympyrä -Icon = Kuvake -Ignore gamepads when not focused = Älä huomioi ohjaimia, kun ohjelma ei keskitettynä -Ignore Windows Key = Poista Windows-näppäin käytöstä -Invert Axes = Käännä akselit -Invert Tilt along X axis = Käännä kallistus X-akselilla -Invert Tilt along Y axis = Käännä kallistus Y-akselilla +Gesture = Gesture +Gesture mapping = Gesture mapping +Glowing borders = Glowing borders +HapticFeedback = Haptic feedback (vibration) +Hide touch analog stick background circle = Hide touch analog stick background circle +Icon = Icon +Ignore gamepads when not focused = Ignore gamepads when not focused +Ignore Windows Key = Disable Windows key +Invert Axes = Invert axes +Invert Tilt along X axis = Invert tilt along X axis +Invert Tilt along Y axis = Invert tilt along Y axis Keep this button pressed when right analog is pressed = Keep this button pressed when right analog is pressed -Keyboard = Näppäimistöohjauksen asetukset -L/R Trigger Buttons = L/R-liipaisimen näppäimet +Keyboard = Keyboard control settings +L/R Trigger Buttons = L/R trigger buttons Landscape = Landscape Landscape Auto = Landscape auto Landscape Reversed = Landscape reversed Low end radius = Low end radius Mouse = Mouse settings -Mouse sensitivity = Hiiren herkkyys -Mouse smoothing = Hiiren tasoitus +Mouse sensitivity = Mouse sensitivity +Mouse smoothing = Mouse smoothing MouseControl Tip = You can now map mouse in control mapping screen by pressing the 'M' icon. None (Disabled) = None (disabled) -Off = Pois +Off = Off OnScreen = Kosketusnäytön kontrollit Portrait = Portrait Portrait Reversed = Portrait reversed -PSP Action Buttons = PSP-toiminta näppäimet -Rapid fire interval = Rapid fire interval +PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode -Reset to defaults = Palauta oletukset -Screen Rotation = Näytön kierto -Sensitivity (scale) = Herkkyys (skaala) -Sensitivity = Herkkyys +Reset to defaults = Reset to defaults +Screen Rotation = Screen rotation +Sensitivity (scale) = Sensitivity (scale) +Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) -Swipe = Pyyhkäise -Swipe sensitivity = Pyyhkäisyn herkkyys -Swipe smoothing = Pyyhkäisyn tasoitus -Thin borders = Ohuet rajat -Tilt control setup = Kallistusohjauksen asetus -Tilt Input Type = Kallistusohjauksen tyyppi -Tilt Sensitivity along X axis = Kallistuksen herkkyys X-akselilla -Tilt Sensitivity along Y axis = Kallistuksen herkkyys Y-akselilla -To Calibrate = Pidä laitettasi halutussa kulmassa, ja paina 'Kalibroi'. -Toggle mode = Vaihto tila -Touch Control Visibility = Kosketusohjauksen näkyvyys -Use custom right analog = Käytä mukautettua oikeaa analogista -Use Mouse Control = Käytä hiiriohjausta -Visibility = Näkyvyys -Visible = Näkyvä +Swipe = Swipe +Swipe sensitivity = Swipe sensitivity +Swipe smoothing = Swipe smoothing +Thin borders = Thin borders +Tilt control setup = Tilt control setup +Tilt Input Type = Tilt input type +Tilt Sensitivity along X axis = Tilt sensitivity along X axis +Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis +To Calibrate = Hold device at your preferred angle and press "Calibrate". +Toggle mode = Toggle mode +Touch Control Visibility = Touch control visibility +Use custom right analog = Use custom right analog +Use Mouse Control = Use mouse control +Visibility = Visibility +Visible = Visible X = X Y = Y @@ -179,41 +115,41 @@ Refresh Rate = Ruudunpäivitysnopeus # If your language does not show well with the default font, you can use Font to specify a different one. # Just add it to your language's ini file and uncomment it (remove the # by Font). #Font = Trebuchet MS -About PPSSPP... = &Tietoa PPSSPP:stä... -Auto = &Automaattinen -Auto Max Quality = Automaattinen maksimi &laatu -Backend = Renderöinnin taustaraja&pinta (PPSSPP uudelleenkäynnistyy) +About PPSSPP... = &About PPSSPP... +Auto = &Auto +Auto Max Quality = Auto Max &Quality +Backend = Rendering &Backend (Restarts PPSSPP) Bicubic = &Bicubic Break = Break Break on Load = Break on load -Buy Gold = Osta &Gold -Control Mapping... = &Ohjauksen kartoitus... -Copy PSP memory base address = Kopioi PSP:n muistin &perusosoite -Debugging = &Vianetsintä -Deposterize = &Häiriöiden korjaus +Buy Gold = Buy &Gold +Control Mapping... = C&ontrol Mapping... +Copy PSP memory base address = Copy PSP memory base &address +Debugging = &Debug +Deposterize = &Deposterize Direct3D9 = &Direct3D9 Direct3D11 = Direct3D &11 Disassembly = &Disassembly... Discord = Discord -Display Layout && Effects = Näyttöasettelu ja -&efektit -Display Rotation = Näytön kierto -Dump Next Frame to Log = Tallenna seuraava &kuva -Emulation = &Emulaatio -Enable Cheats = Ota &huijaukset käyttöön -Enable Sound = Ota &ääni käyttöön -Exit = &Poistu -Extract File... = &Pura tiedosto... -File = &Tiedosto -Frame Skipping = &Kuvan ohitus -Frame Skipping Type = Kuvan ohituksen tyyppi -Fullscreen = &Koko näyttö -Game Settings = &Pelin asetukset +Display Layout && Effects = Display layout && effects... +Display Rotation = Display rotation +Dump Next Frame to Log = D&ump Next Frame to Log +Emulation = &Emulation +Enable Cheats = Enable &Cheats +Enable Sound = Enable S&ound +Exit = E&xit +Extract File... = E&xtract File... +File = &File +Frame Skipping = &Frame skipping +Frame Skipping Type = Frame skipping type +Fullscreen = Fu&llscreen +Game Settings = &Game Settings GE Debugger... = GE Debugge&r... GitHub = Git&Hub Hardware Transform = &Hardware Transform -Help = &Apua -Hybrid = &Hybridi -Hybrid + Bicubic = H&ybridi + Bicubic +Help = &Help +Hybrid = &Hybrid +Hybrid + Bicubic = H&ybrid + Bicubic Ignore Illegal Reads/Writes = &Ignore Illegal Reads/Writes Ignore Windows Key = Ignore Windows Key Keep PPSSPP On Top = &Keep PPSSPP on Top @@ -230,7 +166,6 @@ Log Console = &Log Console Memory View... = Memory &View... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Off Open Chat = Open Chat @@ -243,36 +178,37 @@ Pause = &Pause Pause When Not Focused = &Pause When Not Focused Portrait = Portrait Portrait reversed = Portrait reversed -PPSSPP Forums = PPSSPP:n &foorumit -Record = &Nauhoita -Record Audio = Nauhoita &ääntä -Record Display = Nauhoita &näyttöä -Rendering Mode = Ren&deröinti tapa -Rendering Resolution = &Renderöinti resoluutio -Reset = &Nollaa -Reset Symbol Table = Nollaa s&ymbolitaulukko -Run = &Suorita -Save .sym File... = Tallenna .&sym-tiedosto... -Save Map File... = Tallenna &kartoitustiedosto... -Save State = Tallenna &tila -Save State File... = Tilatallennuksen ti&edosto... -Savestate Slot = Tilatallennuksen &lohko -Screen Scaling Filter = N&äytön skaalaussuodatin -Show Debug Statistics = Näytä &vianetsinnän tiedot -Show FPS Counter = Näytä kuvalaskuri (FPS) -Skip Number of Frames = Ohita tämä määrä kuvia -Skip Percent of FPS = Ohita prosenttiosuus kuvista -Stop = &Pysäytä -Switch UMD = Vaihda UMD -Take Screenshot = Ota &kuvakaappaus -Texture Filtering = &Tekstuurien suodatus -Texture Scaling = &Tekstuurien skaalaus -Use Lossless Video Codec (FFV1) = Käytä häviötöntä &videokoodekkia (FFV1) -Use output buffer for video = Käytä ulostulopuskuria videolle +PPSSPP Forums = PPSSPP &Forums +Record = &Record +Record Audio = Record &audio +Record Display = Record &display +Rendering Mode = Rendering M&ode +Rendering Resolution = &Rendering Resolution +Reset = R&eset +Reset Symbol Table = Reset S&ymbol Table +Run = &Run +Save .sym File... = Sav&e .sym File... +Save Map File... = &Save Map File... +Save State = S&ave State +Save State File... = &Save State File... +Savestate Slot = Saves&tate Slot +Screen Scaling Filter = Scr&een Scaling Filter +Show Debug Statistics = Show Debu&g Statistics +Show FPS Counter = Show &FPS Counter +Skip Number of Frames = Skip number of frames +Skip Percent of FPS = Skip percent of FPS +Stop = &Stop +Switch UMD = Switch UMD +Take Screenshot = &Take Screenshot +Texture Filtering = Te&xture Filtering +Texture Scaling = &Texture Scaling +Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) +Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan -Window Size = &Ikkunan koko -www.ppsspp.org = Käy osoitteessa www.&ppsspp.org +Window Size = &Window Size +www.ppsspp.org = Visit www.&ppsspp.org xBRZ = &xBRZ [Developer] @@ -282,13 +218,10 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game -Current = Nykyinen -Debug overlay = Debug overlay -Debug stats = Debug stats -Dev Tools = Kehitystökalut -DevMenu = Kehitysvalikko +Current = Current +Dev Tools = Development tools +DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality Draw Frametimes Graph = Draw frametimes graph Dump Decrypted Eboot = Dump decrypted EBOOT.BIN on game boot @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Ota virheenkorjauksen kirjaaminen käyttöön Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = System information Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Takaisin -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Cancel Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Do you want to overwrite the data? @@ -363,7 +285,7 @@ ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Corrupted Data = Corrupted data Delete = Poista -Delete all = Poista kaikki +Delete all = Delete all Delete completed = Poisto onnistui. DeleteConfirm = Tämä tallennus poistetaan.\nHaluatko varmasti jatkaa? DeleteConfirmAll = Do you really want to delete all\nyour save data for this game? @@ -372,55 +294,41 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = Poistetaan\nOdota... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Valmis GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = Lataus onnistui. Loading = Ladataan\nOdota... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = NEW DATA No = Ei -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = Tallennus onnistui. Saving = Tallentaa\nOdota... -SavingFailed = Ei voitu tallentaa. +SavingFailed = Unable to save data. Search = Search -seconds, 0:off = sekunteissa, 0 = pois +seconds, 0:off = seconds, 0 = off Select = Valitse -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Tuettu There is no data = Dataa ei ole. Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Ei tuettu -Username = Käyttäjänimi When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Kyllä @@ -501,43 +405,36 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Aasia Calculate CRC = Laske CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Create shortcut Delete Game = Poista peli Delete Game Config = Poista pelin asetus Delete Save Data = Poista tallennustiedot Europe = Eurooppa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Peli -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Peliasetukset Homebrew = Kotitekoinenpeli Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japani Korea = Korea -MB = Mt +MB = MB One moment please... = Pieni hetki... Play = Pelaa Remove From Recent = Poista "äskettäin" listalta... SaveData = Tallennustieto Setting Background = Setting background Show In Folder = Näytä kansiossa -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background [Graphics] % of the void = % of the void % of viewport = % of viewport -%, 0:unlimited = %, 0 = rajoittamaton -(supersampling) = (ylinäytteistys) -(upscaling) = (ylösskaalaus) +%, 0:unlimited = %, 0 = unlimited +(supersampling) = (supersampling) +(upscaling) = (upscaling) 1x PSP = 1x PSP 2x = 2x 2x PSP = 2x PSP @@ -556,15 +453,15 @@ Use UI background = Use UI background 16x = 16x Aggressive = Aggressiivinen Alternative Speed = Vaihtoehtoinen nopeus -Alternative Speed 2 = Vaihtoehtoinen nopeus 2 +Alternative Speed 2 = Vaihtoehtoinen nopeus 2 (prosenteissa, 0 = rajoittamaton) Anisotropic Filtering = Anisotrooppisen suodatus -Antialiasing (MSAA) = Pehmentäminen (MSAA) +Antialiasing (MSAA) = Antialiasing (MSAA) Aspect Ratio = Kuvasuhde Auto = Automaattinen -Auto (1:1) = Automaattinen (1:1) -Auto (same as Rendering) = Automaattinen (sama kuin renderöintiresoluutio) -Auto FrameSkip = Automaattinen kuvanohitus -Auto Max Quality = Automaattinen maksimi laatu +Auto (1:1) = Auto (1:1) +Auto (same as Rendering) = Automaattinen (sama kuin renderöinti resoluutio) +Auto FrameSkip = Automaattinen ruudunohitus +Auto Max Quality = Auto Max Quality Auto Scaling = Automaattinen skaalaus Backend = Taustarajapinta Balanced = Tasapainotettu @@ -574,101 +471,101 @@ Buffer graphics commands (faster, input lag) = Buffer graphics commands (faster, BufferedRenderingRequired = Warning: This game is not compatible with "Skip buffer effects" Camera = Kamera Camera Device = Kameralaite -Cardboard Screen Size = Näyttökoko (näkymän koon prosentuaalinen osuus) -Cardboard Screen X Shift = X-siirtymä (tyhjän tilan prosentuaalinen osuus) -Cardboard Screen Y Shift = Y-siirtymä (tyhjän tilan prosentuaalinen osuus) -Cardboard VR Settings = Google Cardboard VR -asetukset +Cardboard Screen Size = Screen size (in % of the viewport) +Cardboard Screen X Shift = X shift (in % of the blank space) +Cardboard Screen Y Shift = Y shift (in % of the blank space) +Cardboard VR Settings = Google Cardboard VR settings Cheats = Huijaukset CPU Core = CPU core Debugging = Vian etsintä -DefaultCPUClockRequired = Varoitus: Tämä peli vaatii Prosessorin kellon olevan asetettu oletusarvoon. -Deposterize = Häiriöiden korjaus -Deposterize Tip = Korjaa visuaaliset viivamaiset häiriöt ylöskaalattujen tekstuurien yhteydessä. +DefaultCPUClockRequired = Warning: This game requires the CPU clock to be set to default. +Deposterize = Deposterize +Deposterize Tip = Fixes visual banding glitches in upscaled textures Device = Laite Direct3D 9 = Direct3D 9 Direct3D 11 = Direct3D 11 Disabled = Poistettu käytöstä -Display Layout && Effects = Näyttöasettelu ja -efektit -Display Resolution (HW scaler) = Näyttöresoluutio (Laitteiston skaalaaja) -Enable Cardboard VR = Ota käyttöön Cardboard VR +Display Layout && Effects = Display layout && effects +Display Resolution (HW scaler) = Display resolution (HW scaler) +Enable Cardboard VR = Enable Cardboard VR FPS = FPS -Frame Rate Control = Kuvataajuuden hallinta -Frame Skipping = Kuvan ohitus -Frame Skipping Type = Kuvan ohituksen tyyppi +Frame Rate Control = Framerate control +Frame Skipping = Ruudun ohitus +Frame Skipping Type = Frame skipping type FullScreen = Koko näyttö -Geometry shader culling = Geometria-varjostimen karsinta -GPUReadbackRequired = Varoitus: Tämä peli vaatii, että "Ohita näytönohjaimen lukemat" on pois päältä. -Hack Settings = Hakkerointiasetukset (saattaa aiheutaa virheitä) -Hardware Tessellation = Laitteistotessellaatio +Geometry shader culling = Geometry shader culling +GPUReadbackRequired = Warning: This game requires "Skip GPU Readbacks" to be set to Off. +Hack Settings = Hack settings (may cause glitches) +Hardware Tessellation = Hardware tessellation Hardware Transform = Laitteistomuunnos -hardware transform error - falling back to software = Laitteistomuunnosvirhe, palataan ohjelmistotilaan -HardwareTessellation Tip = Käyttää laitteistoa muodostaakseen käyriä -High = Korkea +hardware transform error - falling back to software = Hardware transform error, falling back to software +HardwareTessellation Tip = Uses hardware to make curves +High = High Hybrid = Hybridi -Hybrid + Bicubic = Hybridi + Bicubic -Ignore camera notch when centering = Ohita kameran lovi keskittäessä -Integer scale factor = Kokonaislukuskaalauksen kerroin -Internal Resolution = Sisäinen resoluutio -Lazy texture caching = Laiska tekstuurivarastointi (nopeutus) -Lazy texture caching Tip = Nopeampi, mutta voi aiheuttaa tekstiongelmia joissakin peleissä +Hybrid + Bicubic = Hybrid + Bicubic +Ignore camera notch when centering = Ignore camera notch when centering +Integer scale factor = Integer scale factor +Internal Resolution = Internal resolution +Lazy texture caching = Lazy texture caching (speedup) +Lazy texture caching Tip = Faster, but can cause text problems in a few games Linear = Lineaarinen -Low = Matala -LowCurves = Spline/Bezier-käyrien laatu -LowCurves Tip = Käytetään vain joissakin peleissä, ohjaa käyrien sileyttä -Lower resolution for effects (reduces artifacts) = Alempi resoluutio efekteille (vähentää häiriöitä) -Manual Scaling = Manuaalinen skaalaus -Medium = Keskitaso +Low = Low +LowCurves = Spline/Bezier curves quality +LowCurves Tip = Only used by some games, controls smoothness of curves +Lower resolution for effects (reduces artifacts) = Lower resolution for effects (reduces artifacts) +Manual Scaling = Manual scaling +Medium = Medium Mode = Mode -Must Restart = Sinun täytyy käynnistää PPSSPP uudelleen, jotta tämä muutos astuisi voimaan. -Native device resolution = Laiteen alkuperäinen resoluutio +Must Restart = You must restart PPSSPP for this change to take effect. +Native device resolution = Native device resolution Nearest = Lähin -No buffer = Ei puskuria -Render all frames = Render all frames +No buffer = No buffer Show Battery % = Näytä akku % Show Speed = Näytä nopeus -Skip Buffer Effects = Ohita puskuriefektit +Skip Buffer Effects = Skip buffer effects None = Ei mitään -Number of Frames = Kuvien määrä +Number of Frames = Number of frames Off = Pois OpenGL = OpenGL Overlay Information = Overlay information -Partial Stretch = Osittainen venytys -Percent of FPS = Kuvataajuden prosentti -Performance = Suorituskyky -Postprocessing shaders = Jälkikäsittelyvarjostimet +Partial Stretch = Partial stretch +Percent of FPS = Percent of FPS +Performance = Performance +Postprocessing shaders = Postprocessing shaders Recreate Activity = Recreate activity -Render duplicate frames to 60hz = Renderöi kuvat tuplana 60 Hz:siin -RenderDuplicateFrames Tip = Saattaa tehdä kuvataajuudesta tasaisemman peleissä, jotka toimivat matalammalla kuvataajuudella +Render duplicate frames to 60hz = Render duplicate frames to 60 Hz +RenderDuplicateFrames Tip = Can make framerate smoother in games that run at lower framerates Rendering Mode = Renderöinti tapa Rendering Resolution = Renderöinti resoluutio -RenderingMode NonBuffered Tip = Nopeampi, mutta kaikki ei välttämättä piirry joissakin peleissä +RenderingMode NonBuffered Tip = Nopeampi, mutta mitään ei välttämättä piirry joissakin peleissä Rotation = Kierto Safe = Turvallinen Screen Scaling Filter = Näytön skaalauksen suodatin Show Debug Statistics = Näytä virheenkorjaustilastot -Show FPS Counter = Näytä kuvalaskuri (FPS) -Skip GPU Readbacks = Ohita GPU-lukemat +Show FPS Counter = Näytä FPS-laskuri +Skip GPU Readbacks = Skip GPU Readbacks Software Rendering = Ohjelmistopohjainen renderointi (kokeellinen) -Software Skinning = Ohjelmistopohjainen muokkaus (skinning) -SoftwareSkinning Tip = Yhdistää skinnattujen mallien piirtämisen prosessorilla, nopeampi useimmissa peleissä +Software Skinning = Software skinning +SoftwareSkinning Tip = Combine skinned model draws on the CPU, faster in most games Speed = Nopeus -Speed Hacks = Nopeuskikat (saattaa aiheuttaa renderöinti virheitä!) +Speed Hacks = Nopeus kikkoja (saattaa aiheuttaa renderöinti virheitä!) Stereo display shader = Stereo display shader -Stereo rendering = Stereorenderöinti +Stereo rendering = Stereo renderöinti Stretch = Venytä Texture Filter = Tekstuurisuodatin Texture Filtering = Tekstuurin suodatus -Texture replacement pack activated = Tekstuurin korvauspaketti aktivoidu Texture Scaling = Tekstuurin skaalaus Texture Shader = Tekstuurin varjostin -Turn off Hardware Tessellation - unsupported = Ota pois käytöstä "laitteistotessellaatio": ei tuettu +Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported Unlimited = Rajoittamaton -Up to 1 = Enintään 1 -Up to 2 = Enintään 2 +Up to 1 = 1 asti +Up to 2 = 2 asti Upscale Level = Ylösskaalauksen taso Upscale Type = Ylösskaalauksen tapa UpscaleLevel Tip = Prosessorille raskas - joillekkin skaalauksille voidaan antaa viivettä nykimisen välttämiseksi Use all displays = Käytä kaikkia näyttöjä +Vertex Cache = Verteksivälimuisti +VertexCache Tip = Nopeampi, mutta voi välillä aiheuttaa vilkkumista VSync = VSync Vulkan = Vulkan Window Size = Ikkunan koko @@ -685,19 +582,17 @@ Zip archive corrupt = ZIP-arkisto on korruptoitunut Zip file does not contain PSP software = ZIP-tiedosto ei sisällä PSP-ohjelmistoa [KeyMapping] -Allow combo mappings = Salli yhdistelmäkartoitukset -Autoconfigure = Automaattinen määritys -Autoconfigure for device = Automaattinen määritys laitteelle -Bind All = Kartoita kaikki -Clear All = Tyhjennä kaikki -Combo mappings are not enabled = Yhdistelmäkuvaukset eivät ole käytössä -Default All = Palauta oletusasetukset -Map a new key for = Kartoita uusi näppäin kohteelle -Map Key = Kartoita näppäin -Map Mouse = Kartoita hiiri -Replace = Korvaa -Show PSP = Näytä PSP -You can press ESC to cancel. = Voit peruuttaa painamalla Esc. +Autoconfigure = Auto configure +Autoconfigure for device = Autoconfigure for device +Bind All = Bind All +Clear All = Clear all +Default All = Restore defaults +Map a new key for = Map a new key for +Map Key = Map key +Map Mouse = Map mouse +Replace = Replace +Show PSP = Show PSP +You can press ESC to cancel. = You can press Esc to cancel. [MainMenu] Browse = Selaa... @@ -716,12 +611,12 @@ Load = Lataa... Loading... = Ladataan... PinPath = PinPath PPSSPP can't load games or save right now = PPSSPP ei voi ladata pelejä tai tallentaa juuri nyt -Recent = Viimeisimmät +Recent = Äskettäin SavesAreTemporary = PPSSPP tallentaa tilapäiseen tallennustilaan SavesAreTemporaryGuidance = Pura PPSSPP jonnekkin tallentaaksesi pysyvästi SavesAreTemporaryIgnore = Jätä varoitus huomiotta -UnpinPath = Poista kiinnitetty polku -UseBrowseOrLoad = Käytä Selaa valitaksesi kansio tai Lataa valitaksesi tiedosto. +UnpinPath = Unpin +UseBrowseOrLoad = Use Browse to choose a folder, or Load to choose a file. www.ppsspp.org = www.ppsspp.org [MainSettings] @@ -734,118 +629,128 @@ System = Järjestelmä Tools = Työkalut [MappableControls] -Alt speed 1 = Vaihtoehtoinen nopeus 1 -Alt speed 2 = Vaihtoehtoinen nopeus 2 -An.Down = Analoginen alas -An.Left = Analoginen vasen -An.Right = Analoginen oikea -An.Up = Analoginen ylös -Analog limiter = Analoginen rajoitin -Analog speed = Analoginen nopeus -Analog Stick = Analoginen sauva -Audio/Video Recording = Ääni/video nauhoitus -AxisSwap = Akselinvaihto -Circle = Ympyrä -Cross = Risti -Custom %d = Mukautettu %d -D-pad down = Ristiohjain alas -D-pad left = Ristiohjain vasen -D-pad right = Ristiohjain oikea -D-pad up = Ristiohjain ylös -DevMenu = Kehittäjävalikko -Display Landscape = Näytä vaakakuva -Display Landscape Reversed = Näytä vaakakuva käänteisenä -Display Portrait = Näytä pystykuva -Display Portrait Reversed = Näytä pystykuva käänteisenä +Alt speed 1 = Alt speed 1 +Alt speed 2 = Alt speed 2 +An.Down = Analog Down +An.Left = Analog Left +An.Right = Analog Right +An.Up = Analog Up +Analog limiter = Analog limiter +Analog speed = Analog speed +Analog Stick = Analog stick +Audio/Video Recording = Audio/Video recording +AxisSwap = Axis swap +Circle = Circle +Cross = Cross +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 +D-pad down = D-pad down +D-pad left = D-pad left +D-pad right = D-pad right +D-pad up = D-pad up +DevMenu = DevMenu +Display Landscape = Display Landscape +Display Landscape Reversed = Display Landscape Reversed +Display Portrait = Display Portrait +Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button -Down = Alas -Dpad = Ristiohjain -Exit App = Exit App -Frame Advance = Kuva eteenpäin -Hold = Pidä +Down = Dpad Down +Dpad = Dpad +Frame Advance = Frame advance +Hold = Hold Home = Home L = L -Left = Vasemalle -Load State = Lataa tila +Left = Dpad Left +Load State = Load State Mute toggle = Mute toggle -Next Slot = Seuraava lohko -None = Ei mitään +Next Slot = Next Slot +None = None Note = Note -OpenChat = Avaa keskustelu +OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R -RapidFire = Nopea tulitus -Record = Nauhoita +RapidFire = Rapid-fire +Record = Record Remote hold = Remote hold -Rewind = Takaisinkelaus -Right = Oikealle -Right Analog Stick = Oikea analoginen sauva -RightAn.Down = OikeaAn.Alas -RightAn.Left = OikeaAn.Vasen -RightAn.Right = OikeaAn.Oikea -RightAn.Up = OikeaAn.Ylös -Rotate Analog (CCW) = Käännä analogista vastapäivään -Rotate Analog (CW) = Käännä analogista myötäpäivään -Save State = Tallena tila -Screen = Näyttö -Screenshot = Kuvakaappaus +Rewind = Rewind +Right = Dpad Right +Right Analog Stick = Right Analog Stick +RightAn.Down = RightAn.Down +RightAn.Left = RightAn.Left +RightAn.Right = RightAn.Right +RightAn.Up = RightAn.Up +Rotate Analog (CCW) = Rotate analog (CCW) +Rotate Analog (CW) = Rotate analog (CW) +Save State = Save State +Screen = Screen +Screenshot = Screenshot Select = Select -SpeedToggle = Nopeuden vaihto -Square = Neliö +SpeedToggle = Speed toggle +Square = Square Start = Start -Swipe Down = Pyyhkäise alas -Swipe Left = Pyyhkäise vasemmalle -Swipe Right = Pyyhkäise oikealle -Swipe Up = Pyyhkäise ylös -tap to customize = kosketa mukauttaaksesi -Texture Dumping = Tekstuurien tallentaminen -Texture Replacement = Tekstuurien korvaus -Toggle Fullscreen = Vaihda koko ruudun tilan välillä +Swipe Down = Swipe Down +Swipe Left = Swipe Left +Swipe Right = Swipe Right +Swipe Up = Swipe Up +tap to customize = tap to customize +Texture Dumping = Texture dumping +Texture Replacement = Texture replacement +Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN -Triangle = Kolmio -Fast-forward = Pikakelaus -Up = Ylös +Triangle = Triangle +Fast-forward = Fast-forward +Up = Dpad Up Vol + = Vol + Vol - = Vol - Wlan = WLAN [MemStick] -Already contains PSP data = Sisältää jo PSP-tiedot -Cancelled - try again = Cancelled - try again -Create or Choose a PSP folder = Luo tai valitse PSP-kansio -Current = Nykyinen -DataCanBeShared = Tiedot voidaan jakaa PPSSPP:n tavallisen / Gold-version välillä -DataCannotBeShared = Tietoja EI VOIDA jakaan PPSSPP:n tavallisen / Gold-version välillä! -DataWillBeLostOnUninstall = Varoitus! Tiedot häviävät, kun poistat PPSSPP:n! -DataWillStay = Tiedot säilyvät jopa jos poistat PPSSPP:n. -Done! = Valmis! -EasyUSBAccess = Helppo USB-pääsy -Failed to move some files! = Joitain tiedostoja ei voitu siirtää! -Failed to save config = Asetusten tallentaminen epäonnistui -Free space = Vapaa tila -Manually specify PSP folder = Määritä PSP-kansio manuaalisesti -MemoryStickDescription = Valitse minne haluat säilyttää PSP-tiedot (muistikortti) -Move Data = Siirrä tiedot +Already contains PSP data = Already contains PSP data +Create or Choose a PSP folder = Create or Choose a PSP folder +Current = Current +DataCanBeShared = Data can be shared between PPSSPP regular/Gold +DataCannotBeShared = Data CANNOT be shared between PPSSPP regular/Gold! +DataWillBeLostOnUninstall = Warning! Data will be lost when you uninstall PPSSPP! +DataWillStay = Data will stay even if you uninstall PPSSPP. +Done! = Done! +EasyUSBAccess = Easy USB access +Failed to move some files! = Failed to move some files! +Failed to save config = Failed to save config +Free space = Free space +Manually specify PSP folder = Manually specify PSP folder +MemoryStickDescription = Choose where to keep PSP data (Memory Stick) +Move Data = Move Data Selected PSP Data Folder = Selected PSP Data Folder -No data will be changed = Mitään tietoja ei muuteta -PPSSPP will restart after the change = PPSSPP käynnistyy uudelleen muutoksen jälkeen -Skip for now = Ohita nyt -Starting move... = Siirto alkaa... -That folder doesn't work as a memstick folder. = Kyseinen kansio ei toimi muistikorttikansiona. -USBAccessThrough = USB-pääsy Android/data/org.ppsspp.ppsspp/files -kautta -USBAccessThroughGold = USB-pääsy Android/data/org.ppsspp.ppssppgold/files -kautta -Use App Private Data = Käytä sovelluksen yksityistä dataa -Use PSP folder at root of storage = Käytä PSP-kansiota tallennustilan juuressa -Welcome to PPSSPP! = Tervetuloa PPSSPP:n! -WhatsThis = Mikä tämä on? +No data will be changed = No data will be changed +PPSSPP will restart after the change = PPSSPP will restart after the change +Skip for now = Skip for now +Starting move... = Starting move... +That folder doesn't work as a memstick folder. = That folder doesn't work as a memstick folder. +USBAccessThrough = USB access through Android/data/org.ppsspp.ppsspp/files +USBAccessThroughGold = USB access through Android/data/org.ppsspp.ppssppgold/files +Use App Private Data = Use App Private Data +Use PSP folder at root of storage = Use PSP folder at root of storage +Welcome to PPSSPP! = Welcome to PPSSPP! +WhatsThis = What's this? [Networking] AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,37 +809,20 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Automaattinen -Chinese (simplified) = Kiina (yksinkertaistettu) -Chinese (traditional) = Kiina (perinteinen) -Dutch = Hollanti -English = Englanti -French = Ranska -Game language = Pelin kieli -German = Saksa -Italian = Italia -Japanese = Japani -Korean = Korea -Games often don't support all languages = Pelit eivät usein tue kaikkia kieliä -Portuguese = Portugali -Russian = Venäjä -Spanish = Espanja - [Pause] Cheats = Huijaukset Continue = Jatka -Create Game Config = Luo pelin asetustiedosto -Delete Game Config = Poista pelin asetustiedosto -Exit to menu = Poistu valikkoon -Game Settings = Pelin asetukset -Load State = Lataa tila -Rewind = Takaisinkelaus -Save State = Tallenna tila +Create Game Config = Create game config +Delete Game Config = Delete game config +Exit to menu = Exit to menu +Game Settings = Game settings +Load State = Lataa tilanne +Rewind = Rewind +Save State = Tallenna tilanne Settings = Asetukset -Switch UMD = Vaihda UMD -Undo last load = Peru viimeisin tilan lataus -Undo last save = Peru viimeisin tilan tallennus +Switch UMD = Switch UMD +Undo last load = Undo last load +Undo last save = Undo last save [PostShaders] (duplicated setting, previous slider will be used) = (duplicated setting, previous slider will be used) @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,70 +862,69 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette [PSPCredits] -all the forum mods = kaikki foorumin moderaattorit -build server = koontipalvelin -Buy Gold = Osta Gold -check = Tutustu myös Dolphiniin, parhaaseen Wii/GC-emulaattoriin: -CheckOutPPSSPP = Tutustu PPSSPP:ään, mahtavaan PSP-emulaattoriin: https://www.ppsspp.org/ -contributors = Osallistujat: +all the forum mods = all the forum mods +build server = build server +Buy Gold = Buy Gold +check = Also check out Dolphin, the best Wii/GC emu around: +CheckOutPPSSPP = Check out PPSSPP, the awesome PSP emulator: https://www.ppsspp.org/ +contributors = Contributors: created = Luonut Discord = Discord -info1 = PPSSPP on tarkoitettu vain opetustarkoituksiin. -info2 = Varmista, että omistat oikeudet kaikkiin peleihin, -info3 = joita pelaat omistamalla UMD:n tai ostamalla digitaalisen -info4 = latauksen PSN-kaupasta oikealla PSP:lläsi. -info5 = PSP on Sony, Inc:n tavaramerkki. -iOS builds = iOS buildit -license = Ilmainen ohjelmisto, GPL 2.0+ -list = yhteensopivuuslistat, foorumit ja kehitystiedot -PPSSPP Forums = PPSSPP-foorumit -Privacy Policy = Tietosuojakäytäntö -Share PPSSPP = Jaa PPSSPP -specialthanks = Erityiskiitokset: -specialthanksKeithGalocy = NVIDIA:lle (laitteisto, neuvot) -specialthanksMaxim = hänen uskomattomasta Atrac3+ -dekooderityöstään -testing = testaus -this translation by = tämän käännöksen teki: -title = Nopea ja helposti siirrettävä PSP-emulaattori -tools = Vapaita käytettyjä työkaluja: +info1 = PPSSPP is intended for educational purposes only. +info2 = Please make sure that you own the rights to any games +info3 = you play by owning the UMD or by buying the digital +info4 = download from the PSN store on your real PSP. +info5 = PSP is a trademark by Sony, Inc. +iOS builds = iOS builds +license = Ilmainen ohjelmisto GPL 2.0+ +list = compatibility lists, forums, and development info +PPSSPP Forums = PPSSPP Forums +Privacy Policy = Privacy policy +Share PPSSPP = Share PPSSPP +specialthanks = Special thanks to: +specialthanksKeithGalocy = at NVIDIA (hardware, advice) +specialthanksMaxim = for his amazing Atrac3+ decoder work +testing = testing +this translation by = this translation by: +title = A fast and portable PSP emulator +tools = Free tools used: # Add translators or contributors who translated PPSSPP into your language here. # Add translators1-6 for up to 6 lines of translator credits. # Leave extra lines blank. 4 contributors per line seems to look best. -translators1 = Jaakko Saarikko +translators1 = translators2 = translators3 = translators4 = translators5 = translators6 = Twitter @PPSSPP_emu = Twitter @PPSSPP_emu -website = Tutustu verkkosivustoon: -written = Kirjoitettu C++:ssa nopeutta ja siirrettävyyttä varten +website = Check out the website: +written = Written in C++ for speed and portability [RemoteISO] -Browse Games = Selaa pelejä -Local Server Port = Paikallisen palvelimen portti -Manual Mode Client = Käsikäyttötilan asiakas -Remote disc streaming = Kauko-levyjen suoratoisto -Remote Port = Kaukoportti -Remote Server = Kaukopavelin -Remote Subdirectory = Kaukokansio -RemoteISODesc = Viimeksi käytettyjen pelien lista jaetaan -RemoteISOLoading = Yhdistetty, ladataan pelilistaa... -RemoteISOScanning = Etsitään... Valitse "jaa pelit" palvelinlaitteellasi -RemoteISOScanningTimeout = Etsitään... tarkista työpöydän palomuurin asetukset -RemoteISOWifi = Huomaa: Yhdistä molemmat laitteet samaan Wi-Fi-verkkoon -RemoteISOWinFirewall = VAROITUS: Windowsin palomuuri estää jakamisen -Settings = Asetukset -Share Games (Server) = Jaa pelejä (palvelin) -Share on PPSSPP startup = Jaa käynnistyksen yhteydessä -Stop Sharing = Lopeta jakaminen -Stopping.. = Lopetetaan... +Browse Games = Browse games +Local Server Port = Local server port +Manual Mode Client = Manual mode client +Remote disc streaming = Remote disc streaming +Remote Port = Remote port +Remote Server = Remote server +Remote Subdirectory = Remote subdirectory +RemoteISODesc = Games in your recent list will be shared +RemoteISOLoading = Connected, loading game list... +RemoteISOScanning = Scanning... Click "share games" on your server device +RemoteISOScanningTimeout = Scanning... check your desktop's firewall settings +RemoteISOWifi = Note: Connect both devices to the same Wi-Fi network +RemoteISOWinFirewall = WARNING: Windows Firewall is blocking sharing +Settings = Settings +Share Games (Server) = Share games (server) +Share on PPSSPP startup = Share on PPSSPP startup +Stop Sharing = Stop sharing +Stopping.. = Stopping... [Reporting] Bad = Bad @@ -1082,16 +970,16 @@ Unselected Overall Description = How well does this game emulate? View Feedback = View all feedbacks [Savedata] -Date = Päivämäärä -Filename = Tiedostonimi -No screenshot = Ei kuvakaappausta -None yet. Things will appear here after you save. = Ei vielä. Tähän ilmestyy asioita tallentamisen jälkeen. -Nothing matching '%1' was found. = Ei tuloksia haulla '%1'. -Save Data = Tallennustiedosto -Save States = Tilatallennukset -Savedata Manager = Tallennustiedoston hallinta -Showing matches for '%1'. = Näytetään tulokset haulle '%1'. -Size = Koko +Date = Date +Filename = Filename +No screenshot = No screenshot +None yet. Things will appear here after you save. = None yet. Things will appear here after you save. +Nothing matching '%1' was found. = Nothing matching '%1' was found. +Save Data = Save data +Save States = Save states +Savedata Manager = Savedata manager +Showing matches for '%1'. = Showing matches for '%1'. +Size = Size [Screen] Cardboard VR OFF = Cardboard VR off @@ -1123,22 +1011,22 @@ State load undone = State load undone Untitled PSP game = Untitled PSP game [Search] -Clear filter = Tyhjennä suodatin -Filter = Suodata -Filtering settings by '%1' = Suodatetaan asetuksia hakusanalla '%1' -Find settings = Etsi asetuksia -No settings matched '%1' = Ei löytynyt asetuksia hakusanalla '%1' -Search term = Hakusana +Clear filter = Clear filter +Filter = Filter +Filtering settings by '%1' = Filtering settings by '%1' +Find settings = Find settings +No settings matched '%1' = No settings matched '%1' +Search term = Search term [Store] -Already Installed = Jo asennettu -Connection Error = Yhteysvirhe -Install = Asenna -Launch Game = Käynnistä peli -Loading... = Ladataan... -MB = Mt -Size = Koko -Uninstall = Poista asennus +Already Installed = Already installed +Connection Error = Connection error +Install = Install +Launch Game = Launch game +Loading... = Loading... +MB = MB +Size = Size +Uninstall = Uninstall [SysInfo] %0.2f Hz = %0.2f Hz @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1212,29 +1097,29 @@ Vulkan Extensions = Vulkan extensions Vulkan Features = Vulkan features [System] -(broken) = (rikki) +(broken) = (broken) 12HR = 12HR 24HR = 24HR -Auto = Automaattinen -Auto Load Savestate = Lataa tilatallennus automaattisesti -AVI Dump started. = AVI-tallennus aloitettu. -AVI Dump stopped. = AVI-tallennus lopetettu. -Cache ISO in RAM = Lataa ISO-tiedosto RAM-muistiin -Change CPU Clock = Muuta emuloidun PSP:n näytönohjaimen kelloa (epävakaa) -Color Saturation = Värisaturaatio -Color Tint = Värin sävy +Auto = Auto +Auto Load Savestate = Auto load savestate +AVI Dump started. = AVI dump started +AVI Dump stopped. = AVI dump stopped +Cache ISO in RAM = Cache full ISO in RAM +Change CPU Clock = Change emulated PSP's CPU clock (unstable) +Color Saturation = Color Saturation +Color Tint = Color Tint Error: load undo state is from a different game = Error: load undo state is from a different game Failed to load state for load undo. Error in the file system. = Failed to load state for load undo. Error in the file system. Floating symbols = Floating symbols -Game crashed = Peli kaatui -Language = Kieli -Memory Stick folder = Muistikortin kansio -Memory Stick size = Muistikortin koko +Game crashed = Game crashed +Language = Language +Memory Stick folder = Memory Stick folder +Memory Stick size = Memory Stick size Change Nickname = Vaihda nimimerkkiä ChangingMemstickPath = Save games, save states, and other data will not be copied to this folder.\n\nChange the Memory Stick folder? ChangingMemstickPathInvalid = That path couldn't be used to save Memory Stick files. -Cheats = Huijaukset -Clear Recent = Tyhjennä "Viimeisimmät" +Cheats = Cheats +Clear Recent = Clear "Recent" Clear Recent Games List = Clear Recent games list Clear UI background = Clear UI background Confirmation Button = Confirmation button @@ -1248,94 +1133,92 @@ Display Games on a grid = Display "Games" on a grid Display Homebrew on a grid = Display "Homebrew && Demos" on a grid Display Recent on a grid = Display "Recent" on a grid Dynarec (JIT) = Dynarec (JIT) -Emulation = Emulaatio +Emulation = Emulation Enable Cheats = Ota huijaukset käyttöön Enable Compatibility Server Reports = Ota yhteensopivat palvelinilmoitukset käyttöön -Failed to load state. Error in the file system. = Tilatallennuksen lataus epäonnistui. Virhe tiedostojärjestelmässä. -Failed to save state. Error in the file system. = Tilatallennuksen luonti epäonnistui. Virhe tiedostojärjestelmässä. -Fast (lag on slow storage) = Nopea (viive hidas tallennustilassa) -Fast Memory = Nopea muisti -Force real clock sync (slower, less lag) = Pakota todellinen kellon synkronointi (hidastaa, vähemmän viivettä) -Games list settings = Peliluettelon asetukset -General = Yleiset -Grid icon size = Ruudukon kuvakkeen koko -Help the PPSSPP team = Auta PPSSPP-tiimiä -Host (bugs, less lag) = Isäntä (bugit, vähemmän viivettä) -Ignore bad memory accesses = Ohita huonot muistipääsyt -Increase size = Kasvata kokoa -Interpreter = Tulkki -IO timing method = I/O-aikamenetelmä -IR Interpreter = IR-tulkki -Memory Stick Folder = Muistikortin kansio -Memory Stick inserted = Muistikortin asetettu -MHz, 0:default = MHz, 0 = oletus -MMDDYYYY = KKPPVVVV -Moving background = Liikkuva tausta -Newest Save = Uusin tallennus -No animation = Ei animaatiota -Not a PSP game = Ei PSP-peli -Off = Pois -Oldest Save = Vanhin tallennus -Path does not exist! = Polkua ei ole olemassa! -PSP Memory Stick = PSP-muistikortti -PSP Model = PSP-malli -PSP Settings = PSP-asetukset +Failed to load state. Error in the file system. = Failed to load state. Error in the file system. +Failed to save state. Error in the file system. = Failed to save state. Error in the file system. +Fast (lag on slow storage) = Fast (lag on slow storage) +Fast Memory = Nopea muisti (epävakaa) +Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) +Games list settings = Games list settings +General = General +Grid icon size = Grid icon size +Help the PPSSPP team = Help the PPSSPP team +Host (bugs, less lag) = Host (bugs, less lag) +Ignore bad memory accesses = Ignore bad memory accesses +Increase size = Increase size +Interpreter = Interpreter +IO timing method = I/O timing method +IR Interpreter = IR interpreter +Memory Stick Folder = Memory Stick folder +Memory Stick inserted = Memory Stick inserted +MHz, 0:default = MHz, 0 = default +MMDDYYYY = MMDDYYYY +Moving background = Moving background +Newest Save = Newest save +No animation = No animation +Not a PSP game = Not a PSP game +Off = Off +Oldest Save = Oldest save +Path does not exist! = Path does not exist! +PSP Memory Stick = PSP Memory Stick +PSP Model = PSP model +PSP Settings = PSP settings PSP-1000 = PSP-1000 PSP-2000/3000 = PSP-2000/3000 -Recent games = Viimeisimmät pelit -Record Audio = Nauhoita ääntä -Record Display = Nauhoita näyttöä -Reset Recording on Save/Load State = Nollaa nauhoitus tallennettaessa/ladattaessa tila -Restore Default Settings = Palauta PPSSPP:n oletusasetukset -RetroAchievements = RetroAchievements -Rewind Snapshot Interval = Pikakelaa tilannevedosten välit (muistisyöppö) -Save path in installed.txt = Tallennuskansio installed.txt-tiedostossa -Save path in My Documents = Tallennuskansio Omat tiedostot -kansiossa -Savestate Slot = Tilatallennuksen lohko -Savestate slot backups = Tallennustilan paikan varmuuskopiot -Screenshots as PNG = Tallenna kuvankaappaukset PNG-muodossa -Set Memory Stick folder = Aseta muistikortin kansio -Set UI background... = Aseta käyttöliittymän tausta... -Show ID = Näytä tunniste -Show Memory Stick folder = Näytä muistikortin kansio -Show region flag = Näytä alueen lippu -Simulate UMD delays = Simuloi UMD-viiveet -Simulate UMD slow reading speed = Simulate UMD slow reading speed -Slot 1 = Lohko 1 -Slot 2 = Lohko 2 -Slot 3 = Lohko 3 -Slot 4 = Lohko 4 -Slot 5 = Lohko 5 -Storage full = Tallennustila täynnä -Sustained performance mode = Jatkuva suorituskykytila -Theme = Teema -Time Format = Ajan muoto -Transparent UI background = Läpinäkyvä käyttöliittymän tausta -UI = Käyttöliittymä -UI background animation = Käyttöliittymän taustan animaatio -UI Sound = Käyttöliittymän äänet -undo %c = peruuta %c +Recent games = Recent games +Record Audio = Record audio +Record Display = Record display +Reset Recording on Save/Load State = Reset recording on Save/Load state +Restore Default Settings = Restore PPSSPP's settings to default +Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) +Save path in installed.txt = Save path in installed.txt +Save path in My Documents = Save path in My Documents +Savestate Slot = Savestate slot +Savestate slot backups = Savestate slot backups +Screenshots as PNG = Save screenshots in PNG format +Set Memory Stick folder = Set Memory Stick folder +Set UI background... = Set UI background... +Show ID = Show ID +Show Memory Stick folder = Show Memory Stick folder +Show region flag = Show region flag +Simulate UMD delays = Simulate UMD delays +Slot 1 = Slot 1 +Slot 2 = Slot 2 +Slot 3 = Slot 3 +Slot 4 = Slot 4 +Slot 5 = Slot 5 +Storage full = Storage full +Sustained performance mode = Sustained performance mode +Theme = Theme +Time Format = Time format +Transparent UI background = Transparent UI background +UI = UI +UI background animation = UI background animation +UI Sound = UI sound +undo %c = backup %c USB = USB -Use Lossless Video Codec (FFV1) = Käytä häviöttömän videon koodekkia (FFV1) -Use O to confirm = Käytä O-näppäintä vahvistukseen +Use Lossless Video Codec (FFV1) = Use lossless video codec (FFV1) +Use O to confirm = Use O as confirmation button Use output buffer (with overlay) for recording = Use output buffer (with overlay) for recording -Use system native keyboard = Käytä järjestelmän omaa näppäimistöä -Use X to confirm = Käytä X-näppäintä vahvistukseen -VersionCheck = Tarkista uudet PPSSPP-versiot -WARNING: Android battery save mode is on = VAROITUS: Androidin akun säästötila on käytössä -WARNING: Battery save mode is on = VAROITUS: Akun säästötila on käytössä -Waves = Aallot -YYYYMMDD = VVVVKKPP +Use system native keyboard = Use system native keyboard +Use X to confirm = Use X as confirmation button +VersionCheck = Check for new versions of PPSSPP +WARNING: Android battery save mode is on = WARNING: Android battery save mode is On +WARNING: Battery save mode is on = WARNING: Battery save mode is on +Waves = Waves +YYYYMMDD = YYYYMMDD [TextureShaders] -Off = Pois +Off = Off TexMMPX = TexMMPX Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] -Dark = Tumma -Default = Oletus +Dark = Dark +Default = Default [UI Elements] %1 button = %1 button @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = New version of PPSSPP available [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 8dfc9262e..6fe551e98 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Volume en vitesse alternative Audio backend = Back-end du son (redémarrage requis) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Mémoire tampon adaptée au Bluetooth (+ lent) Auto = Automatique Device = Périphérique de sortie @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Étalonner Calibrated = Calibrated Calibration = Étalonnage -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classique Confine Mouse = Capturer la souris dans la fenêtre/zone d'affichage @@ -108,10 +48,8 @@ Deadzone radius = Rayon de la zone morte Disable D-Pad diagonals (4-way touch) = Désactiver les diagonales de la croix directionnelle Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Bordures lumineuses @@ -140,7 +78,6 @@ OnScreen = Commandes tactiles Portrait = Portrait Portrait Reversed = Portrait inversé PSP Action Buttons = Boutons d'action -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensibilité Shape = Shape Show Touch Pause Menu Button = Afficher le bouton Pause tactile -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Journal de débogage Memory View... = &Visionneur de mémoire More Settings... = &Plus de paramètres... Nearest = Le plus &proche -Recent = &Recent Skip Buffer Effects = &Pas d'effets en mémoire tampon (hack de vitesse) Off = &Désactivé Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = &Filtrage des textures Texture Scaling = Mise à l'échelle des &textures Use Lossless Video Codec (FFV1) = Utiliser un &codec vidéo sans perte (FFV1) Use output buffer for video = Utiliser une mémoire tampon pour la vidéo +Vertex Cache = &Cache vertex VSync = Synchronisation &verticale Vulkan = Vulkan Window Size = Ta&ille de la fenêtre @@ -282,11 +218,8 @@ Backspace = Retour arrière Block address = Adresse du bloc By Address = Par adresse Copy savestates to memstick root = Copier les états sauvegardés à la racine de la Memory Stick -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Créer/Ouvrir le fichier "textures.ini" pour le jeu en cours Current = Actuel -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Outils de développement DevMenu = MenuDev Disabled JIT functionality = Fonctionnalité JIT désactivée @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Activer le journal de débogage Enter address = Entrer une adresse FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Profileur d'image -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Test du pilote du GPU GPU log profiler = GPU log profiler GPU Profile = Profilage du GPU @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Enregistrer les statistiques sur les pertes d'ima Log Level = Niveau du journal Log View = Voir le journal Logging Channels = Filtres du journal de débogage -Multi-threaded rendering = Multi-threaded rendering Next = Suivant No block = Pas de bloc -Off = Off Prev = Précédent Random = Aléatoire Replace textures = Remplacer les textures @@ -332,12 +260,10 @@ Stats = Statistiques System Information = Informations système Texture ini file created = Texture ini file created Texture Replacement = Remplacement de textures -Audio Debug = Débogage audio -Control Debug = Control Debug +Toggle Audio Debug = Activer/Désactiver le débogage audio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Geler/Dégeler l'image Touchscreen Test = Test de l'écran tactile -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = × définition PSP Active = Actif Back = Retour -Bottom Center = En bas au centre -Bottom Left = En bas à gauche -Bottom Right = En bas à droite Cancel = Annuler Center = Centrer -Center Left = Au centre à gauche -Center Right = Au centre à droite -Changing this setting requires PPSSPP to restart. = La modification de ce paramètre nécessite le redémarrage de PPSSPP. Redémarrer maintenant ? +ChangingGPUBackends = Changer de rendu back-end nécessite de\nredémarrer PPSSPP.\nRedémarrer maintenant ? +ChangingInflightFrames = Modifier la mise en mémoire tampon des commandes graphiques nécessite le redémarrage de PPSSPP. Redémarrer maintenant ? Channel: = Canal : Choose PPSSPP save folder = Veuillez choisir le dossier de sauvegarde de PPSSPP. Confirm Overwrite = Voulez-vous écraser les données ? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Voulez-vous vraiment supprimer les paramètres pour ce DeleteFailed = Suppression impossible. Deleting = Suppression\nVeuillez patienter... Disable All = Tout désactiver -Disabled = Disabled Dumps = Dumps Edit = Éditer Enable All = Tout activer -Enabled = Enabled Enter = Entrer -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Terminer GE Frame Dumps = GE Frame Dumps Grid = Grille Inactive = Inactif -Installing... = Installing... InternalError = Une erreur interne est survenue. -Links = Links Load = Charger Load completed = Chargement terminé. Loading = Chargement\nVeuillez patienter... LoadingFailed = Chargement impossible. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Déplacer Move Down = Move Down Move Up = Move Up Network Connection = Connexion réseau NEW DATA = NOUVELLES DONNÉES No = Non -None = None ObtainingIP = Obtention de l'adresse IP\nVeuillez patienter... OK = OK Old savedata detected = Ancienne sauvegarde détectée Options = Options -Password = Password Remove = Remove Reset = Remise à 0 Resize = Zoomer -Restart = Restart Retry = Réessayer Save = Sauvegarder Save completed = Sauvegarde terminée. @@ -420,7 +329,6 @@ SavingFailed = Sauvegarde impossible. Search = Search seconds, 0:off = secondes, 0 = off Select = Sélectionner -Settings = Settings Shift = Majuscule Skip = Skip Snap = Aligner @@ -431,11 +339,7 @@ Supported = Supporté There is no data = Aucune donnée trouvée. Toggle All = Tout cocher Toggle List = Afficher liste -Top Center = En haut au centre -Top Left = En haut à gauche -Top Right = En haut à droite Unsupported = Non supporté -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Si vous sauvegardez, le chargement sera possible sur une PSP, mais pas sur une ancienne version de PPSSPP. When you save, it will not work on outdated PSP Firmware anymore = Si vous sauvegardez, le chargement ne sera plus possible sur une PSP avec un ancien firmware. Yes = Oui @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Le fichier est compressé (.zip).\nVeuillez [Game] Asia = Asie Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Confirmer -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Créer config. de jeu Create Shortcut = Créer un raccourci Delete Game = Supprimer jeu Delete Game Config = Supprimer config. de jeu Delete Save Data = Supprimer sauvegardes Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Jeu  -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Paramètres du jeu Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Installation des données  -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japon Korea = Corée MB = Mo @@ -527,8 +426,6 @@ Remove From Recent = Supprimer de "Récemment" SaveData = Sauvegarde  Setting Background = Paramétrage du fond d'écran Show In Folder = Montrer dans dossier -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Utiliser le fond d'écran @@ -623,7 +520,6 @@ Must Restart = Vous devez redémarrer PPSSPP pour que cette modification prenne Native device resolution = Définition native de l'appareil Nearest = Le plus proche No buffer = 0 -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Pas d'effets en mémoire tampon (hack vitesse) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Étirement Texture Filter = Filtre de textures Texture Filtering = Filtrage des textures -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Mise à l'échelle des textures Texture Shader = Shader de textures Turn off Hardware Tessellation - unsupported = Veuillez désactiver "Tessellation matérielle" : non supportée @@ -669,6 +564,8 @@ Upscale Level = Niveau de mise à l'échelle Upscale Type = Type de mise à l'échelle UpscaleLevel Tip = Lourd pour le CPU, certaines mises à l'échelle peuvent être différées pour éviter les saccades Use all displays = Utiliser tous les écrans +Vertex Cache = Cache vertex +VertexCache Tip = Plus rapide, mais peut causer des scintillements temporaires VSync = Synchronisation verticale Vulkan = Vulkan Window Size = Taille de la fenêtre @@ -685,12 +582,10 @@ Zip archive corrupt = Archive ZIP corrompue Zip file does not contain PSP software = Le fichier ZIP ne contient pas de logiciel PSP [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Configuration automatique Autoconfigure for device = Configuration automatique pour l'appareil Bind All = Bind All Clear All = Réinitialiser -Combo mappings are not enabled = Combo mappings are not enabled Default All = Par défaut Map a new key for = Choisir une nouvelle touche pour Map Key = Assigner une touche @@ -747,7 +642,16 @@ Audio/Video Recording = Enreg. audio/vidéo AxisSwap = Inverser axes Circle = Rond Cross = Croix -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = Bas croix directionnelle D-pad left = Gauche croix directionnelle D-pad right = Droite croix directionnelle @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Bas Dpad = Croix directionnelle -Exit App = Exit App Frame Advance = Avance d'image Hold = Verrouillage Home = Home @@ -773,7 +676,6 @@ None = Aucun Note = Note OpenChat = Ouvrir chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Tir rapide Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Extraire textures Texture Replacement = Remplacer textures Toggle Fullscreen = Plein écran Toggle mode = Mode basculement -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Vitesse max Up = Haut @@ -812,25 +713,24 @@ Vol - = Vol - Wlan = WLAN [MemStick] -Already contains PSP data = Contient déjà des données PSP -Cancelled - try again = Annulé - réessayer -Create or Choose a PSP folder = Créer ou choisir un dossier PSP +Already contains PSP data = Already contains PSP data +Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current -DataCanBeShared = Les données peuvent être partagées entre PPSSPP régulier/Gold -DataCannotBeShared = Les données NE PEUVENT PAS être partagées entre PPSSPP régulier/Gold! -DataWillBeLostOnUninstall = Avertissement! Les données seront perdues lorsque vous désinstallez PPSSPP! -DataWillStay = Les données resteront même si vous désinstallez PPSSPP. -Done! = Terminé! +DataCanBeShared = Data can be shared between PPSSPP regular/Gold +DataCannotBeShared = Data CANNOT be shared between PPSSPP regular/Gold! +DataWillBeLostOnUninstall = Warning! Data will be lost when you uninstall PPSSPP! +DataWillStay = Data will stay even if you uninstall PPSSPP. +Done! = Done! EasyUSBAccess = Easy USB access -Failed to move some files! = Impossible de déplacer certains fichiers! -Failed to save config = Échec de l’enregistrement de la configuration -Free space = Espace libre +Failed to move some files! = Failed to move some files! +Failed to save config = Failed to save config +Free space = Free space Manually specify PSP folder = Manually specify PSP folder MemoryStickDescription = Choose where to keep PSP data (Memory Stick) Move Data = Move Data Selected PSP Data Folder = Selected PSP Data Folder -No data will be changed = Aucune donnée ne sera modifiée -PPSSPP will restart after the change = PPSSPP redémarrera après le changement +No data will be changed = No data will be changed +PPSSPP will restart after the change = PPSSPP will restart after the change Skip for now = Skip for now Starting move... = Starting move... That folder doesn't work as a memstick folder. = That folder doesn't work as a memstick folder. @@ -838,7 +738,7 @@ USBAccessThrough = USB access through Android/data/org.ppsspp.ppsspp/files USBAccessThroughGold = USB access through Android/data/org.ppsspp.ppssppgold/files Use App Private Data = Use App Private Data Use PSP folder at root of storage = Use PSP folder at root of storage -Welcome to PPSSPP! = Bienvenue sur PPSSPP! +Welcome to PPSSPP! = Welcome to PPSSPP! WhatsThis = What's this? [Networking] @@ -846,6 +746,11 @@ AdHoc Server = Serveur ad hoc AdhocServer Failed to Bind Port = Échec de liaison du port par le serveur ad hoc AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Automatique +Bottom Center = En bas au centre +Bottom Left = En bas à gauche +Bottom Right = En bas à droite +Center Left = Au centre à gauche +Center Right = Au centre à droite Change Mac Address = Modifier l'adresse MAC Change proAdhocServer Address = Modifier l'adresse IP du serveur ad hoc (localhost = plusieurs instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = IP ou nom de domaine invalide Minimum Timeout = Temps d'expiration minimum (forçage en ms, 0 = par défaut) Misc = Divers (par défaut = compatibilité PSP) Network Initialized = Réseau initialisé ! +None = None Please change your Port Offset = Veuillez changer votre décalage de port Port offset = Décalage de port (0 = compatibilité PSP) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Chat rapide 3 Quick Chat 4 = Chat rapide 4 Quick Chat 5 = Chat rapide 5 QuickChat = Chat rapide -Randomize = Randomize Send = Envoyer Send Discord Presence information = Envoyer l'information "Rich Presence" de Discord +Top Center = En haut au centre +Top Left = En haut à gauche +Top Right = En haut à droite Unable to find UPnP device = Appareil UPnP introuvable UPnP (port-forwarding) = UPnP (redirection de port) UPnP need to be reinitialized = UPnP doit être réinitialisé @@ -901,23 +809,6 @@ Validating address... = Validation de l'adresse... WLAN Channel = Canal WLAN You're in Offline Mode, go to lobby or online hall = Vous êtes en mode hors ligne, allez dans le hall en ligne. -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Codes de triche Continue = Continuer @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Bordure noire Bloom = Flou lumineux -BloomNoBlur = Bloom (no blur) Brightness = Luminosité Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Correction des couleurs ColorPreservation = Color preservation Contrast = Contraste CRT = Lignes de balayage CRT -FakeReflections = FakeReflections FXAA = Anticrénelage FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Anticrénelage supersampling (Gauss) Strength = Strength Tex4xBRZ = 4×BRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Upscaling Spline36 VideoSmoothingAA = Anticrénelage des vidéos Vignette = Vignette @@ -1168,11 +1056,10 @@ GPU Flags = GPU Flags GPU Information = Informations GPU High precision float range = Amplitude de float haute précision High precision int range = Amplitude d'entier haute précision -Icon cache = Icon cache JIT available = JIT available Lang/Region = Langue/Région Memory Page Size = Taille de page mémoire -Native resolution = Définition native +Native Resolution = Définition native No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Extensions OpenGL OpenGL ES 2.0 Extensions = Extensions OpenGL ES 2.0 @@ -1181,9 +1068,7 @@ OpenGL Extensions = Extensions OpenGL Optimal frames per buffer = Nombre optimal d'images par mémoire tampon Optimal sample rate = Taux d'échantillonnage optimal OS Information = Informations sur l'OS -Pixel resolution = Pixel resolution PPSSPP build = Version de PPSSPP -Present modes = Present modes Refresh rate = Taux de rafraîchissement Release = Release RW/RX exclusive = Exclusif RW/RX @@ -1195,7 +1080,7 @@ System Information = Informations système System Name = Nom System Version = Version du système Threads = Fils d'exécution -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendeur Vendor (detected) = Vendeur (détecté) Version Information = Informations de version @@ -1278,7 +1163,6 @@ Record Audio = Enregistrer le son Record Display = Enregistrer l'affichage Reset Recording on Save/Load State = Redémarrer l'enregistrement lors de la sauvegarde/chargement d'état Restore Default Settings = Restaurer les paramètres par défaut -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Fréquence instantanés rembobinage (+ de mémoire) Save path in installed.txt = Chemin de sauvegarde dans "installed.txt" Save path in My Documents = Chemin de sauvegarde dans "Mes documents" @@ -1291,7 +1175,6 @@ Show ID = Afficher l'identifiant Show Memory Stick folder = Show Memory Stick folder Show region flag = Afficher le drapeau de région Simulate UMD delays = Simuler délais UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Emplacement 1 Slot 2 = Emplacement 2 Slot 3 = Emplacement 3 @@ -1346,11 +1229,12 @@ Download = Télécharger New version of PPSSPP available = Nouvelle version de PPSSPP disponible [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 3770d4279..6da4dbcb4 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Motor de audio (require reiniciar) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Automático Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrar Calibrated = Calibrated Calibration = Calibración -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Clásico Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Radio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonais do D-Pad Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Controis táctiles en pantalla Portrait = Vertical Portrait Reversed = Vertical invertido PSP Action Buttons = Botóns de acción -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensibilidade Shape = Shape Show Touch Pause Menu Button = Mostrar botón de menú -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Consola de re&xistros... Memory View... = Visor de &memoria... More Settings... = Máis &opcións... Nearest = &Cercano -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Non Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = &Filtrado de texturas Texture Scaling = &Escalado de texturas Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Caché de vértices VSync = Sincronización &vertical Vulkan = Vulkan Window Size = &Tamaño de ventá @@ -282,11 +218,8 @@ Backspace = Borrar Block address = Bloquear dirección By Address = Por dirección Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Actual -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Activar rexistro Enter address = Insertar dirección FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Nivel de rexistro Log View = Ver o rexistro Logging Channels = Canles de rexistro -Multi-threaded rendering = Multi-threaded rendering Next = Seguinte No block = Non bloquear -Off = Off Prev = Anterior Random = Aleatorio Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Información do sistema Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Depuración de audio -Control Debug = Control Debug +Toggle Audio Debug = Parar/Reanudar depuración de audio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Parar/Reanudar imaxe Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Atrás -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Cancelar Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Cambiar o motor gráfico require reiniciar PPSSPP.\nReiniciar agora? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Elixe a carpeta de gardado de PPSSPP. Confirm Overwrite = Desexas sobreescribir os datos? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Seguro que queres borrar a configuración deste xogo? DeleteFailed = Os datos non se puideron borrar. Deleting = Borrando\nEspera un momento... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Intro -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Terminar GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Cargar Load completed = Carga completada. Loading = Cargando\nAgarda un momento... LoadingFailed = Os datos nom se puideron cargar. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Posición Move Down = Move Down Move Up = Move Up Network Connection = Conexión de rede NEW DATA = NOVOS DATOS No = Non -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = Aceptar Old savedata detected = Detectados datos de gardado antigos. Options = Options -Password = Password Remove = Remove Reset = Reiniciar Resize = Tamaño -Restart = Restart Retry = Reintentar Save = Gardar Save completed = Gardado completado. @@ -420,7 +329,6 @@ SavingFailed = Os datos non se puideron gardar. Search = Search seconds, 0:off = seconds, 0 = off Select = Seleccionar -Settings = Settings Shift = Alternar Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = A tarxeta de memoria está baleira. Toggle All = Cambiar todo Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Cando gardes, a partida cargará nunha PSP, pero non en versións antigas de PPSSPP. When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Sí @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Arquivo comprimido (ZIP).\nNecesita ser des [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Confirmar -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Crear config. do xogo Create Shortcut = Crear acceso directo Delete Game = Borrar xogo Delete Game Config = Borrar config. do xogo Delete Save Data = Borrar datos Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Xogo -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Axustes de xogo Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instalación de datos -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Borrar de recentes SaveData = Datos Setting Background = Setting background Show In Folder = Mostrar en carpeta -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = Debes reiniciar PPSSPP para aplicar este cambio. Native device resolution = Resolución nativa do dispositivo Nearest = Pixelado No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Filtro de texturas Texture Filtering = Filtrado de texturas -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Escalado de texturas Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Nivel de escalado Upscale Type = Tipo de escalado UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Caché de vértices +VertexCache Tip = Faster, but may cause temporary flicker VSync = Sincronización vertical Vulkan = Vulkan Window Size = Tamaño de ventana @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autoconfigurar Autoconfigure for device = Autoconfigurar para dispositivo Bind All = Bind All Clear All = Borrar todo -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restaurar Map a new key for = Pulsa unha tecla para Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Invertir eixes Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = D-Pad Abaixo Dpad = D-Pad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pausa -Previous Slot = Previous Slot R = R RapidFire = Fogo rápido Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Modo turbo Up = D-Pad Arriba @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Cambiar dirección MAC Change proAdhocServer Address = Cambiar IP de proAdhocServer (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Rede inicializada +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Trucos Continue = Continuar @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Brillo -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Debuxos animados CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = Monitor con «scanlines» (CRT) -FakeReflections = FakeReflections FXAA = Antialiasing FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 «upscaler» VideoSmoothingAA = VideoSmoothingAA Vignette = Viñeta @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Reestablecer axustes -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Frecuencia de rebobinado de instantánea (mem hog) Save path in installed.txt = Carpeta de gardado en installed.txt Save path in My Documents = Carpeta de gardado en Meus documentos @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simular retardo UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Descargar New version of PPSSPP available = Nova versión de PPSSPP dispoñible [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index af17d0354..9f07143da 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Backend ήχου (Απ. Επανεκκίνηση) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Buffer φιλικό για Bluetooth (αργό) Auto = Αυτόματο Device = Συσκευή @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Βαθμονόμηση Calibrated = Calibrated Calibration = Βαθμονόμηση ψηφιακού πληκρολογίου -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Κλασικό Confine Mouse = Εγκλωβισμός ποντικιού μέσα στην περιοχή παραθύρου/οθόνης @@ -108,10 +48,8 @@ Deadzone radius = Ακτίνα ορίων Disable D-Pad diagonals (4-way touch) = Απενεργοποίηση διαγωνίων ψηφιακού πληκρολογίου Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Φωτιζόμενα σύνορα @@ -140,7 +78,6 @@ OnScreen = Χειριστήριο Οθόνης Αφής Portrait = Πορτραίτο Portrait Reversed = Πορτραίτο (αναστροφή) PSP Action Buttons = Πλήκτρα δράσης PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Ευαισθησία Shape = Shape Show Touch Pause Menu Button = Εμφάνιση απτικού κουμπιού μενού παύσης -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Κονσόλα Καταγραφέα Memory View... = Προβολή Μνήμης... More Settings... = Περισσότερες Ρυθμίσεις... Nearest = Κοντινότερο -Recent = &Recent Skip Buffer Effects = &Παράκαμψη εφέ buffer (γρηγορότερο) Off = &Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Φιλτράρισμα Υφών Texture Scaling = Κλιμάκωση Υφών Use Lossless Video Codec (FFV1) = Χρήση μη απολεστικού κωδικοποιητή (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = Π&ροσωρινή Μνήμη Κορυφών VSync = Κά&θετος Συγχρονισμός Vulkan = Vulkan Window Size = Μέγεθος Παραθύρου @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Διεύθυνση Block By Address = Κατά διεύθυνση Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Δημιουργία/Άνοιγμα αρχείου textures.ini για το τρέχον παιχνίδι Current = Τρέχον -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Εργαλεία ανάπτυξης DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Ενεργοποίηση καταγραφής αποσφαλμάτωσης Enter address = Διεύθυνση Enter FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Profiler πλαισίου -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Καταγραφή Στατιστικών για Log Level = Επίπεδο καταγραφής Log View = Εμφάνιση καταγραφέα Logging Channels = Καταγραφή καναλιών -Multi-threaded rendering = Multi-threaded rendering Next = Επόμενο No block = Κανένα block -Off = Off Prev = Προηγούμενο Random = Τυχαίο Replace textures = Αντικαταστήστε τις υφές @@ -332,12 +260,10 @@ Stats = Στατιστικά System Information = Πληροφορίες Συστήματος Texture ini file created = Texture ini file created Texture Replacement = Αντικατάσταση υφών -Audio Debug = Debug ήχου -Control Debug = Control Debug +Toggle Audio Debug = Εναλλαγή debug ήχου +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Πάγωμα Εναλαγής Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * ανάλυση PSP Active = ΕΝΕΡΓΟ Back = ΠΙΣΩ -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = ΑΚΥΡΟ Center = ΚΕΝΤΡΟ -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Η αλλαγή Συστημάτων Υποστήριξης GPU απαιτεί επανεκκίνηση του PPSSPP. Επανεκκίνηση τώρα? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Επιλογή φακέλου αποθήκευσης PPSSPP Confirm Overwrite = ΑΝΤΙΚΑΤΑΣΤΑΣΗ ΔΕΔΟΜΕΝΩΝ; @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Είστε σίγουροι ότι θέλετε να DeleteFailed = ΑΔΥΝΑΜΙΑ ΔΙΑΓΡΑΦΗΣ ΔΕΔΟΜΕΝΩΝ. Deleting = ΔΙΑΓΡΑΦΗ\nΠΑΡΑΚΑΛΩ ΠΕΡΙΜΕΝΕΤΕ... Disable All = ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ ΟΛΩΝ -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = ΕΝΕΡΓΟΠΟΙΗΣΗ ΟΛΩΝ -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = ΤΕΛΟΣ GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = ΑΝΕΝΕΡΓΟ -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = ΦΟΡΤΩΣΗ Load completed = ΦΟΡΤΩΣΗ ΟΛΟΚΛΗΡΩΘΗΚΕ Loading = ΦΟΡΤΩΣΗ\nΠΑΡΑΚΑΛΩ ΠΕΡΙΜΕΝΕΤΕ... LoadingFailed = ΑΔΥΝΑΜΙΑ ΦΟΡΤΩΣΗΣ ΔΕΔΟΜΕΝΩΝ. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = ΜΕΤΑΚΙΝΗΣΗ Move Down = Move Down Move Up = Move Up Network Connection = ΣΥΝΔΕΣΗ ΔΙΚΤΥΟΥ NEW DATA = ΝΕΑ ΔΕΔΟΜΕΝΑ No = ΟΧΙ -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Εντοπίστηκαν παλαιά αρχεία αποθήκευσης Options = ΕΠΙΛΟΓΕΣ -Password = Password Remove = Remove Reset = ΕΠΑΝΑΦΟΡΑ Resize = ΑΛΛΑΓΗ ΜΕΓΕΘΟΥΣ -Restart = Restart Retry = ΕΠΑΝΑΛΗΨΗ Save = ΑΠΟΘΗΚΕΥΣΗ Save completed = ΑΠΟΘΗΚΕΥΣΗ ΟΛΟΚΛΗΡΩΘΗΚΕ. @@ -420,7 +329,6 @@ SavingFailed = ΑΔΥΝΑΜΙΑ ΑΠΟΘΗΚΕΥΣΗΣ ΔΕΔΟΜΕΝΩΝ. Search = Search seconds, 0:off = δευτερόλεπτα, 0 = off Select = Select -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = ΔΕΝ ΥΠΑΡΧΟΥΝ ΔΕΔΟΜΕΝΑ Toggle All = ΕΝΑΛΛΑΓΗ ΟΛΩΝ Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Όταν αποθηκεύετε, θα φορτώσει στο PSP, αλλά όχι σε μια παλαιότερη έκδοση του PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = ΝΑΙ @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Το αρχείο είναι συμπισμ [Game] Asia = Ασία Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Διαγραφή -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Δημιουργία ρυθμίσεων παιχνιδιού Create Shortcut = Δημιουργία Συντόμευσης Delete Game = Διαγραφή Παιχνιδιού Delete Game Config = Διαγραφή ρυθμίσεων παιχνιδιού Delete Save Data = Διαγραφή savedata Europe = Ευρώπη -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Παιχνίδι -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Ρυθμίσεις Παιχνιδιού Homebrew = Homebrew Hong Kong = Χονγκ Κονγκ InstallData = Δεδομένα Εγκατάστασης -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Ιαπωνία Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Κατάργηση από τα πρόσφατα SaveData = Δεδομένα Αποθήκευσης Setting Background = Ρύθμιση φόντου Show In Folder = Εμφάνιση σε Φάκελο -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = ΗΠΑ Use UI background = Χρήση φόντου UI @@ -623,7 +520,6 @@ Must Restart = Πρέπει να επανεκκινήσετε το PPSSPP για Native device resolution = Χρήση ανάλυσης συσκευής Nearest = Κοντινότερο No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Παράκαμψη εφέ buffer (γρηγορότερο) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Επέκταση Texture Filter = Φίλτρο Υφών Texture Filtering = Φιλτράρισμα Υφών -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Κλιμάκωση Υφών Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Απενεργοποιήστε το "Hardware Tessellation": δεν υποστηρίζεται @@ -669,6 +564,8 @@ Upscale Level = Επίπεδο Κλιμάκωσης Upscale Type = Τύπος Κλιμάκωσης UpscaleLevel Tip = Βαρύ για τον επεξεργαστή - κάποια κλιμάκωση μπορεί να καθυστερήσει για να αποφευχθούν κολλήματα Use all displays = Χρησιμοποιήστε όλες τις οθόνες +Vertex Cache = Προσωρινή Μνήμη Κορυφών +VertexCache Tip = Πιο γρήγορα, αλλά μπορεί να προκαλέσει προσωρινό τρεμόπαιγμα VSync = Κάθετος Συγχρονισμός Vulkan = Vulkan Window Size = Μέγεθος Παραθύρου @@ -685,12 +582,10 @@ Zip archive corrupt = Το αρχείο ZIP είναι κατεστραμμέν Zip file does not contain PSP software = Το αρχείο ZIP δεν περιέχει λογισμικό PSP [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Αυτόματη ρύθμιση Autoconfigure for device = Αυτόματη ρύθμιση για τη συσκευή Bind All = Bind All Clear All = Καθαρισμός -Combo mappings are not enabled = Combo mappings are not enabled Default All = Επαναφορά Map a new key for = Πατήστε ένα πλήκτρο για το Map Key = ΡύΘμιση κουμπιού @@ -747,7 +642,16 @@ Audio/Video Recording = Εγγραφή Ήχου/Video AxisSwap = Ανταλλαγή αξόνων Circle = Ο Cross = X -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Κάτω Dpad = Ψηφιακό pad -Exit App = Exit App Frame Advance = Επόμενο καρέ Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Πάυση -Previous Slot = Previous Slot R = R RapidFire = Ταχεία βολή Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Εξαγωγή υφών Texture Replacement = Αντικατάσταση υφών Toggle Fullscreen = Λειτουργεία πλήρους οθόνης Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Τρίγωνο Fast-forward = Γρήγορη προώθηση Up = Πάνω @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Αλλαγή φυσικής διεύθυνσης (MAC) Change proAdhocServer Address = Αλλαγή διεύθυνσης IP proAdhocServer (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Μη έγκυρη IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Δίκτυο Εκκινήθηκε +None = None Please change your Port Offset = Please change your port offset Port offset = Offset πήλης(0 = για συμβατότητα PSP) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Αποστολή "Rich Presence" πληροφοριών σε Discord +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Επικύρωση διεύθυνσης... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Κωδικοί Continue = Συνέχεια @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Καρτούν CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = Γραμμές σάρωσης CRT -FakeReflections = FakeReflections FXAA = Εξομάλυνση κορυφών FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = Πληροφορίες GPU High precision float range = High precision float range High precision int range = Εύρος υψηλής ακρίβειας int -Icon cache = Icon cache JIT available = JIT available Lang/Region = Γλώσσα/Περιοχή Memory Page Size = Μέγεθος σελίδας μνήμης -Native resolution = Εγγενής ανάλυση +Native Resolution = Εγγενής ανάλυση No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Επεκτάσεις OGL OpenGL ES 2.0 Extensions = Επεκτάσεις OpenGL ES 2.0 @@ -1190,9 +1077,7 @@ OpenGL Extensions = Επεκτάσεις OpenGL Optimal frames per buffer = Βέλτιστα καρέ ανά buffer Optimal sample rate = Βέλτιστος ρυθμός δειγματοληψίας OS Information = Πληροφορίες OS -Pixel resolution = Pixel resolution PPSSPP build = Έκδοση PPSSPP -Present modes = Present modes Refresh rate = Ρυθμός ανανέωσης Release = Release RW/RX exclusive = RW/RX αποκλειστικό @@ -1204,7 +1089,7 @@ System Information = Πληροφορίες συστήματος System Name = Όνομα System Version = Έκδοση συστήματος Threads = Νήματα -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Προμηθευτής Vendor (detected) = Προμηθευτής (βρέθηκε) Version Information = Πληροφορίες έκδοσης @@ -1287,7 +1172,6 @@ Record Audio = Καταγραφή Ήχου Record Display = Καταγραφή Εικόνας Reset Recording on Save/Load State = Επαναφορά της εγγραφής κατή την Αποθήκευση/Φόρτωση σημείου αποθήκευσης Restore Default Settings = Επαναφορά προεπιλεγμένων ρυθμίσεων του PPSSPP -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Συχνότητα Αντιστροφής Στιγμιότυπου (mem hog) Save path in installed.txt = Αποθήκευση διαδρομής στο installed.txt Save path in My Documents = Αποθήκευση διαδρομής στα Έγγραφα μου @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Προσομόιωση καθυστερήσεων UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Κατέβασμα New version of PPSSPP available = Νέα διαθέσιμη έκδοση PPSSPP [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index d1e2e9d54..e8f158cf4 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classic Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = מקשי מגע על המסך Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &התחבר לקונסולה Memory View... = הצג &זיכרון... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xture Filtering Texture Scaling = &Texture Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window Size @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = אפשר דיווח באגים Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = מידע על המערכת Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = << -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = לטב Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = ?ולא םינותנ בתכשל הצור @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = ...ןתמה אנא ...קחומ Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = סנכה -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = םייס GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = .המלשוה הניעט Loading = ...ןתמה אנא ...ןעוט LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = םישדח םינותנ No = אל -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = רדסב Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = .המלשוה הרימש @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = רחב -Settings = Settings Shift = העבר Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = .םינותנ ןיא Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = ןכ @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = צור קיצור דרך Delete Game = Delete game Delete Game Config = Delete game config Delete Save Data = Delete savedata Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = משחק -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = הגדרות משחק Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = Savedata Setting Background = Setting background Show In Folder = Show in folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = הקרוב ביותר No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = קידוד טקסטורה Texture Filtering = קידוד טקסטורה -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = מידת טקסטורה Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = רמה יוקרתית Upscale Type = סוג יוקרתי UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex מטמון +VertexCache Tip = Faster, but may cause temporary flicker VSync = סנכרון אנכי Vulkan = Vulkan Window Size = Window size @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = נקה הכל -Combo mappings are not enabled = Combo mappings are not enabled Default All = החזר הכל Map a new key for = מיפוי מקש נוסף ל Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = v Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = עצור -Previous Slot = Previous Slot R = R RapidFire = RapidFire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = ^ @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = המשך @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = New version of PPSSPP available [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index fc198ee91..aa5d041e3 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classic Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = ךסמה לע עגמ ישקמ Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Log Console Memory View... = Memory &View... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xture Filtering Texture Scaling = &Texture Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window Size @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = םיגאב חוויד רשפא Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = תכרעמה לע עדימ Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = << -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = לטב Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = ?ולא םינותנ בתכשל הצור @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = ...ןתמה אנא ...קחומ Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = סנכה -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = םייס GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = .המלשוה הניעט Loading = ...ןתמה אנא ...ןעוט LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = םישדח םינותנ No = אל -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = רדסב Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = .המלשוה הרימש @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = רחב -Settings = Settings Shift = העבר Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = .םינותנ ןיא Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = ןכ @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Create shortcut Delete Game = Delete game Delete Game Config = Delete game config Delete Save Data = Delete savedata Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Game -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Game settings Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = Savedata Setting Background = Setting background Show In Folder = Show in folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = רתויב בורקה No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = הרוטסקט דודיק Texture Filtering = הרוטסקט דודיק -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = הרוטסקט תדימ Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = תיתרקוי המר Upscale Type = יתרקוי גוס UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex ןומטמ +VertexCache Tip = Faster, but may cause temporary flicker VSync = יכנא ןורכנס Vulkan = Vulkan Window Size = Window size @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = לכה הקנ -Combo mappings are not enabled = Combo mappings are not enabled Default All = לכה רזחה Map a new key for = ףסונ שקמ יופימ Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = v Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = עצור -Previous Slot = Previous Slot R = R RapidFire = RapidFire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = ^ @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = ךשמה @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = New version of PPSSPP available [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 29a6c3033..3ca684cf9 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Naizmjenična brzina zvuka Audio backend = Poslužitelj zvuka (ponovo pokrenuti) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-prijateljski poliranje (sporije) Auto = Automatski Device = Uređaj @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibriraj Calibrated = Calibrated Calibration = Kalibracija -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasično Confine Mouse = Zaključaj miš u window/display području @@ -108,10 +48,8 @@ Deadzone radius = Radijus mrtve zone Disable D-Pad diagonals (4-way touch) = Isključi D-Pad dijagonale (4-smjerni dodir) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Svijetleći rubovi @@ -140,7 +78,6 @@ OnScreen = Dodirne kontrole na ekranu Portrait = Portret Portrait Reversed = Obrnuti portret PSP Action Buttons = PSP akcijske kontrole -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Osjetljivost Shape = Shape Show Touch Pause Menu Button = Prikaži tipku za izbornik pauze -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Konzola log-a Memory View... = Pregled &memorije... More Settings... = &Više postavki... Nearest = &Najbliže -Recent = &Recent Skip Buffer Effects = &Preskoči bufferane efekte Off = &Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Fi<riranje teksturi Texture Scaling = &Skaliranje teksturi Use Lossless Video Codec (FFV1) = &Koristite lossless video protokol (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex cache VSync = VS&ync Vulkan = Vulkan Window Size = &Veličina prozora @@ -282,11 +218,8 @@ Backspace = Vrati Block address = Blokiraj addresu By Address = Od adrese Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Kreiraj/Otvori textures.ini datoteku za trenutnu igru Current = Trenutačno -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Razvojni alati DevMenu = DevMenu Disabled JIT functionality = Isključena JIT funkcionalnost @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Uključi debug logging Enter address = Upiši adresu FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Testiranje GPU drivera GPU log profiler = GPU log profiler GPU Profile = GPU profil @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log pregled Logging Channels = Logging kanali -Multi-threaded rendering = Multi-threaded rendering Next = Sljedeće No block = Nema bloka -Off = Off Prev = Prošlo Random = Nasumično Replace textures = Zamijeni teksture @@ -332,12 +260,10 @@ Stats = Stats System Information = System informacija Texture ini file created = Texture ini file created Texture Replacement = Zamjena teksturi -Audio Debug = Audio debuganje -Control Debug = Control Debug +Toggle Audio Debug = Uključi audio debuganje +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Uključi zamrzavanje Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Aktivno Back = Nazad -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Odustani Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Promjena ove postavke zahtijeva ponovno pokretanje PPSSPP-a. +ChangingGPUBackends = Mijenjanje GPU poslužitelja zahtijeva ponovno pokretanje PPSSPP. Ponovno pokrenuti? +ChangingInflightFrames = Mijenjanje grafičkih komandnih poliranja zahtijeva ponovno pokretanje PPSSPP. Ponovno pokrenuti? Channel: = Channel: Choose PPSSPP save folder = Izaberi PPSSPP save mapu Confirm Overwrite = Želite li pisati preko podataka? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Želiš li izbrisati postavke za ovu igru? DeleteFailed = Nije moguće izbrisati datu. Deleting = Brisanje\nPričekajte... Disable All = Isključi sve -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Uključi sve -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Dovrši GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Neaktivno -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Učitaj Load completed = Učitavanje dovršeno. Loading = Učitavanje\nPričekajte... LoadingFailed = Nije moguće učitati datu. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Pomakni Move Down = Move Down Move Up = Move Up Network Connection = Internetska veza NEW DATA = NOVA DATA No = Ne -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Uočena stara savedata Options = Opcije -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Ponovi Save = Spremi Save completed = Spremanje dovršeno. @@ -420,7 +329,6 @@ SavingFailed = Nije moguće spremiti datu. Search = Search seconds, 0:off = sekundi, 0 = isključeno Select = Select -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Podržano There is no data = Nema date. Toggle All = Uključi sve Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Nepodržano -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Kada spremiš,učitat će se na PSP, ali ne na starijem PPSSPP-u When you save, it will not work on outdated PSP Firmware anymore = Kada spremiš, neće uopće raditi na zastarjelom PSP firmwareu Yes = Da @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Datoteka je pakirana (ZIP).\nPrvo raspakira [Game] Asia = Azija Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Izbriši -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Kreiraj postavke igre Create Shortcut = Kreiraj prečac Delete Game = Izbriši igru Delete Game Config = Izbriši postavke igre Delete Save Data = Izbriši savedatu Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Igra -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Postavke igre Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instalirajte podatke -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Makni iz "Nedavno" SaveData = Savedata Setting Background = Postavljanje pozadine Show In Folder = Prikaži u mapi -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = SAD Use UI background = Koristi UI pozadinu @@ -623,7 +520,6 @@ Must Restart = Morate ponovno pokrenuti PPSSPP da bi se efekat primjenio. Native device resolution = Urođena rezolucija uređaja Nearest = Najbliže No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Preskoči efekte ublaživanja (nije ublaženo, faster) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Rastezanje Texture Filter = Filtar tekstura Texture Filtering = Filtriranje tekstura -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Mjerenje tekstura Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Isključi "hardver mozailk": nepodržano @@ -669,6 +564,8 @@ Upscale Level = Nadograđivanje razine Upscale Type = Vrsta nadograđivanja UpscaleLevel Tip = CPU težak - neke nadogradnje mogu biti usporene da izbjegnu mucanje Use all displays = Koristi sve prikaze +Vertex Cache = Predmemorija tjemena +VertexCache Tip = Brže, ali može izazvati privremeno treperenje VSync = VSync Vulkan = Vulkan Window Size = Veličina prozora @@ -685,12 +582,10 @@ Zip archive corrupt = Koruptana ZIP arhiva Zip file does not contain PSP software = ZIP datoteka ne sadrži PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Automatski konfiguriraj Autoconfigure for device = Automatski konfiguriraj za sve uređaje Bind All = Bind All Clear All = Obriši sve -Combo mappings are not enabled = Combo mappings are not enabled Default All = Vrati na zadano Map a new key for = Postavi novu tipku za Map Key = Postavi tipku @@ -747,7 +642,16 @@ Audio/Video Recording = Snimanje Zvuka/Videa AxisSwap = Izmijena Osi Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Dolje Dpad = Dpad -Exit App = Exit App Frame Advance = Ubrzavanje Frameova Hold = Hold Home = Početna @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Otvori chat Pause = Pauza -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Odlaganje tekstura Texture Replacement = Mijenjanje tesktura Toggle Fullscreen = Uključi puni zaslon Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Gore @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Promijeni MAC addresu Change proAdhocServer Address = Promijeni PRO ad hoc server IP addresu (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Nevažeći IP ili domaćin Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Veza Uspostavljena +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset (0 = PSP kompatibilnost) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Šalji Discord "Rich Presence" informaciju +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Provjeravanje adrese... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = Trenutno si u "Offline",idi u lobby ili online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Šifre Continue = Nastavi @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 nadograđivač VideoSmoothingAA = Video ublaživanja AA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = Informacije o GPU High precision float range = High precision float range High precision int range = Visoka preciznost int dohvata -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Regija Memory Page Size = Veličina memorijske stranice -Native resolution = Urođena rezolucija +Native Resolution = Urođena rezolucija No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL nastavci OpenGL ES 2.0 Extensions = OpenGL ES 2.0 nastavci @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL nastavci Optimal frames per buffer = Optimalni frame-ovi po ublaživanju Optimal sample rate = Optimalni omjer samplova OS Information = Informacije OS-a -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Brzina osvježavanja Release = Pusti RW/RX exclusive = RW/RX ekskluzivno @@ -1204,7 +1089,7 @@ System Information = Informacije sustava System Name = Ime sustava System Version = Verzija sustava Threads = Konci -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Prodavač Vendor (detected) = Prodavač (uočen) Version Information = Informacija verzije @@ -1287,7 +1172,6 @@ Record Audio = Snimi audio Record Display = Snimi prikaz Reset Recording on Save/Load State = Ponovo postavi snimak na Save/Load state Restore Default Settings = Vrati PPSSPP opcije na zadano -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Vrati snapshot frekvenciju (mem hog) Save path in installed.txt = Spremi put u installed.txt Save path in My Documents = Spremi put u My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simuliraj UMD kašnjenja -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Mjesto 1 Slot 2 = Mjesto 2 Slot 3 = Mjesto 3 @@ -1355,11 +1238,12 @@ Download = Instaliraj New version of PPSSPP available = Nova verzija PPSSPP-a je dostupna [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 2920ead21..0667d30c5 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard tracker = Leaderboard tracker -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternatív sebesség hangereje Audio backend = Audió backend (újraindítás szükséges) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-barát buffer (lassabb) Auto = Auto Device = Eszköz @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibrálása Calibrated = Calibrated Calibration = Kalibrálás -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasszikus Confine Mouse = Egérkurzor rögzítése az ablakhoz @@ -108,10 +48,8 @@ Deadzone radius = Holtzóna sugara Disable D-Pad diagonals (4-way touch) = D-Pad átlóinak letiltása (4-irányú érintés) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Világító szélek @@ -140,7 +78,6 @@ OnScreen = Érintőképernyős irányítás Portrait = Álló Portrait Reversed = Fordított álló PSP Action Buttons = PSP akció gombok -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Érzékenység Shape = Shape Show Touch Pause Menu Button = Szünet gomb megjelenítése -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Napló ablak Memory View... = Memória &nézet… More Settings... = &Egyéb beállítások… Nearest = Leg&közelebbi -Recent = &Recent Skip Buffer Effects = Bufferelt effektek kihagyá&sa (nem bufferelt, gyorsabb) Off = &Ki Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xtúra szűrés Texture Scaling = &Textúra nagyítás Use Lossless Video Codec (FFV1) = &Veszteségmentes videó codec használata (FFV1) Use output buffer for video = Kimeneti &buffer alkalmazása rögzítéskor +Vertex Cache = &Vertex gyorsítótár VSync = VS&ync Vulkan = &Vulkan Window Size = &Ablak méret @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Blokk cím By Address = Cím alapján Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = textures.ini fájl készítése/megnyitása a jelenlegi játékhoz Current = Jelenlegi -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Fejlesztői eszközök DevMenu = DevMenu Disabled JIT functionality = Kikapcsolt JIT funkcionalitások @@ -297,11 +230,8 @@ Enable Logging = Naplózás engedélyezése Enable driver bug workarounds = Enable driver bug workarounds Enter address = Cím megadása FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Képkocka profilozó -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver teszt GPU log profiler = GPU log profiler GPU Profile = GPU profil @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Eldobott képkockák statisztikáinak naplózása Log Level = Naplózási szint Log View = Nápló megtekintése Logging Channels = Naplózási csatornák -Multi-threaded rendering = Multi-threaded rendering Next = Következő No block = Nincs blokk -Off = Off Prev = Előző Random = Véletlenszerű Replace textures = Textúrák kicserélése @@ -332,12 +260,10 @@ Stats = Statisztikák System Information = Rendszer információ Texture ini file created = Texture ini file created Texture Replacement = Textúra csere -Audio Debug = Audio hibaelhárítás -Control Debug = Control Debug +Toggle Audio Debug = Audió hibakereső ki/bekapcsolása +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Fagyasztás ki/bekapcsolása Touchscreen Test = Érintőképernyő teszt -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP felbontás Active = Aktív Back = Vissza -Bottom Center = Alul középen -Bottom Left = Alul bal old. -Bottom Right = Alul jobb old. Cancel = Mégse Center = Középre -Center Left = Középen bal old. -Center Right = Középen jobb old. -Changing this setting requires PPSSPP to restart. = Grafikai parancs-bufferelés megváltoztatásához újra kell indítani az alkalmazást. Újraindítod most? +ChangingGPUBackends = GPU backend megváltoztatásához újra kell indítani az alkalmazást. Újraindítod most? +ChangingInflightFrames = Grafikai parancs-bufferelés megváltoztatásához újra kell indítani az alkalmazást. Újraindítod most? Channel: = Channel: Choose PPSSPP save folder = PPSSPP mentési mappa kiválasztása Confirm Overwrite = Biztosan felülírod? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Biztosan törölni akarod a játék beállításait? DeleteFailed = Törlés sikertelen. Deleting = Törlés\nKérlek várj... Disable All = Mind kikapcsolása -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Mind bekapcsolása -Enabled = Enabled Enter = Belép -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Kész GE Frame Dumps = GE Frame Dumps Grid = Rács Inactive = Inaktív -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Betöltés Load completed = Betöltve. Loading = Betöltés\nKérlek várj... LoadingFailed = Betöltés sikertelen. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Mozgat Move Down = Move Down Move Up = Move Up Network Connection = Hálózati kapcsolat NEW DATA = ÚJ MENTÉS No = Nem -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Régi mentés észlelve Options = Opciók -Password = Password Remove = Remove Reset = Visszaállít Resize = Átméretez -Restart = Restart Retry = Újra Save = Mentés Save completed = Mentve. @@ -420,7 +329,6 @@ SavingFailed = Mentés sikertelen. Search = Search seconds, 0:off = másodpercig, 0 = ki Select = Kiválaszt -Settings = Settings Shift = Shift Skip = Skip Snap = Igazít @@ -431,11 +339,7 @@ Supported = Támogatott There is no data = Nincs adat. Toggle All = Összes átkapcsolása Toggle List = Toggle list -Top Center = Felül középen -Top Left = Felül bal old. -Top Right = Felül jobb old. Unsupported = Nem támogatott -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Ha mentesz, PSP-n vissza tudod majd tölteni, de egy régebbi PPSSPP-n nem When you save, it will not work on outdated PSP Firmware anymore = Ha mentesz, már nem fog működni elavult PSP alapszoftveren Yes = Igen @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = A fájl tömörített (ZIP).\nElőbb csomag [Game] Asia = Ázsia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Törlés -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Új játékbeállítás Create Shortcut = Parancsikon létrehozása Delete Game = Játék törlése Delete Game Config = Játékbeállítások törlése Delete Save Data = Mentések törlése Europe = Európa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Játék -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Játékbeállítások Homebrew = Homebrew Hong Kong = Hongkong InstallData = Adatok telepítése -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japán Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Törlés a listából SaveData = Mentések Setting Background = Háttér beállítás Show In Folder = Mutatás mappában -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Alapértelmezett háttér használata @@ -623,7 +520,6 @@ Must Restart = A beállítások érvénybeléptetéséhez újra kell indítani a Native device resolution = Natív készülék felbontás Nearest = Legközelebbi No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Buffer effektek kihagyása (nem bufferelt, gyorsabb) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Nyújtás Texture Filter = Textúra szűrés Texture Filtering = Textúra szűrés -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Textúra nagyítás Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Kapcsold ki a "Hardveres tesszelációt": nem támogatott! @@ -669,6 +564,8 @@ Upscale Level = Nagyítási szint Upscale Type = Nagyítás típusa UpscaleLevel Tip = CPU intenzív - akadozások elkerülése végett olykor késleltetve nagyít. Use all displays = Minden megjelenítő használata +Vertex Cache = Vertex gyorsítótár +VertexCache Tip = Gyorsabb, de néha villódzást okoz VSync = VSync Vulkan = Vulkan Window Size = Ablak méret @@ -685,12 +582,10 @@ Zip archive corrupt = A ZIP archívum sérült Zip file does not contain PSP software = A ZIP fájl nem tartalmaz PSP szoftvert [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Automatikus beállítás Autoconfigure for device = Eszköz auto-beállítása Bind All = Bind All Clear All = Összes törlése -Combo mappings are not enabled = Combo mappings are not enabled Default All = Összeset alapért. Map a new key for = Új gomb beállítása ehhez: Map Key = Billentyű társítása @@ -747,7 +642,16 @@ Audio/Video Recording = Audió/Videó felvétel AxisSwap = Tengely csere Circle = Kör Cross = Kereszt -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad Le D-pad left = D-pad Balra D-pad right = D-pad Jobbra @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = D-Pad Le Dpad = D-Pad -Exit App = Exit App Frame Advance = Köv. képkocka Hold = Zár Home = Kezdőkép @@ -773,7 +676,6 @@ None = None Note = Megj. OpenChat = Open chat Pause = Szünet -Previous Slot = Previous Slot R = R RapidFire = Gyorstüzelés Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Textúra kiírás Texture Replacement = Textúra csere Toggle Fullscreen = Teljes képernyő Toggle mode = Üzemmód váltása -Toggle WLAN = Toggle WLAN Triangle = Háromszög Fast-forward = Gyorsítás Up = D-Pad Fel @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Alul középen +Bottom Left = Alul bal old. +Bottom Right = Alul jobb old. +Center Left = Középen bal old. +Center Right = Középen jobb old. Change Mac Address = MAC cím megváltoztatása Change proAdhocServer Address = ProAdhoc szerver címe (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Érvénytelen IP vagy kiszolgáló név Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Hálózat inicializálva +None = None Please change your Port Offset = Please change your port offset Port offset = Port eltolás/offset (0 = PSP kompatibilitás) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Gyors üzenet 3 Quick Chat 4 = Gyors üzenet 4 Quick Chat 5 = Gyors üzenet 5 QuickChat = Quick chat -Randomize = Randomize Send = Küldés Send Discord Presence information = Discord "Rich Presence" információ küldése +Top Center = Felül középen +Top Left = Felül bal old. +Top Right = Felül jobb old. Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Cím ellenőrzése... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = Offline üzemmódban vagy, menj a lobbiba vagy az online terembe -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Csalások Continue = Folytatás @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Fekete keret Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Rajzfilm CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Színkorrekció ColorPreservation = Color preservation Contrast = Kontraszt CRT = CRT -FakeReflections = FakeReflections FXAA = FXAA élsimítás Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 felskálázó VideoSmoothingAA = VideoSmoothingAA Vignette = Vignetta @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU információ High precision float range = High precision float range High precision int range = Nagy pontosságú int tartomány -Icon cache = Icon cache JIT available = JIT available Lang/Region = Nyelv/Régió Memory Page Size = Memória lapozóméret -Native resolution = Natív felbontás +Native Resolution = Natív felbontás No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL kiterjesztések OpenGL ES 2.0 Extensions = OpenGL ES 2.0 kiterjesztések @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL kiterjezstések Optimal frames per buffer = Bufferenkénti optimális képkockák Optimal sample rate = Optimális mintavételezés OS Information = Op.rendszer információ -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Frissítési gyakoriság Release = Release RW/RX exclusive = RW/RX exkluzív @@ -1204,7 +1089,7 @@ System Information = Rendszerinformáció System Name = Név System Version = Rendszer verzió Threads = Szálak -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Gyártó Vendor (detected) = Gyártó (észlelt) Version Information = Verzió információ @@ -1287,7 +1172,6 @@ Record Audio = Audió felvétele Record Display = Videó felvétele Reset Recording on Save/Load State = Felvétel leállítása állapotmentés készítésekor vagy betöltésekor Restore Default Settings = PPSSPP beállításainak alapértelmezettre állítása -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Visszatekerési állapotmentések gyakorisága (sok memória kell) Save path in installed.txt = Mentés helye installed.txt-ben Save path in My Documents = Mentés helye a Dokumentumok mappában @@ -1300,7 +1184,6 @@ Show ID = Azonosító megjelenítése Show Memory Stick folder = Show Memory Stick folder Show region flag = Régió ikon megjelenítése Simulate UMD delays = UMD késleltetések szimulálása -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Letöltés New version of PPSSPP available = Elérhető a PPSSPP egy újabb verziója [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index f187f91f3..c539b8fed 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Kecepatan volume alternatif Audio backend = Penyangga audio (perlu mulai ulang) Audio Error = Kesalahan audio -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Penyangga bluetooth (lambat) Auto = Otomatis Device = Perangkat @@ -95,7 +36,6 @@ Calibrate Analog Stick = Kalibrasi stik analog Calibrate = Kalibrasi Calibrated = Dikalibrasi Calibration = Kalibrasi -Circular low end radius = Circular low end radius Circular stick input = Masukan stik melingkar Classic = Klasik Confine Mouse = Kunci mouse di area layar @@ -108,10 +48,8 @@ Deadzone radius = Radius mati Disable D-Pad diagonals (4-way touch) = Matikan D-Pad diagonal (sentuhan 4 arah) Disable diagonal input = Nonaktifkan masukan diagonal Double tap = Ketuk dua kali -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Aktifkan kontrol gerakan Enable standard shortcut keys = Aktifkan tombol pintas standar -frames = frames Gesture = Gerak Gesture mapping = Pemetaan gerakan Glowing borders = Pinggiran bercahaya @@ -140,7 +78,6 @@ OnScreen = Kontrol sentuh di layar Portrait = Tegak Portrait Reversed = Tegak terbalik PSP Action Buttons = Tombol aksi PSP -Rapid fire interval = Rapid fire interval Raw input = Masukan mentah Repeat mode = Repeat mode Reset to defaults = Atur ulang ke pengaturan awal @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivitas (skala) Sensitivity = Sensitivitas Shape = Bentuk Show Touch Pause Menu Button = Tampilkan tombol menu jeda -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Geser Swipe sensitivity = Geser sensitivitas Swipe smoothing = Geser kehalusan @@ -230,7 +166,6 @@ Log Console = Konso&l pencatat Memory View... = Tampilan memori... More Settings... = Pengaturan lainnya... Nearest = Terdekat -Recent = &Recent Skip Buffer Effects = Lewati efek penyangga (tak-tersangga, lebih cepat) Off = Mati Open Chat = Buka opsi obrolan @@ -269,6 +204,7 @@ Texture Filtering = Pemfilteran tekstur Texture Scaling = Penskala &tekstur Use Lossless Video Codec (FFV1) = Gunakan kompresi video (FFV1) Use output buffer for video = Gunakan penyangga keluaran untuk video +Vertex Cache = Tembolok &vertex VSync = VS&ync Vulkan = Vulkan Window Size = Ukuran window @@ -282,11 +218,8 @@ Backspace = Menghapus Block address = Alamat blok By Address = Berdasarkan alamat Copy savestates to memstick root = Salin status simpan ke root Memory Stick -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Buat/Buka file textures.ini untuk permainan saat ini Current = Saat ini -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Alat pengembang DevMenu = Menu pengembang Disabled JIT functionality = Fungsi JIT dinonaktifkan @@ -297,11 +230,8 @@ Enable driver bug workarounds = Aktifkan solusi masalah driver Enable Logging = Hidupkan pencatat awakutu Enter address = Masukkan alamat FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Tes pembuangan laju bingkai Frame Profiler = Profil laju bingkai -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Tes driver GPU GPU log profiler = GPU log profiler GPU Profile = Profil GPU @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log statistik laju bingkai yang jatuh Log Level = Tingkatan pencatat Log View = Tampilan pencatat Logging Channels = Kanal pencatatan -Multi-threaded rendering = Multi-threaded rendering Next = Sesudah No block = Tidak ada blok -Off = Off Prev = Sebelum Random = Acak Replace textures = Ganti tekstur @@ -332,12 +260,10 @@ Stats = Statistik System Information = Informasi sistem Texture ini file created = Texture ini file created Texture Replacement = Penggantian tekstur -Audio Debug = Awakutu audio -Control Debug = Control Debug +Toggle Audio Debug = Alihkan awakutu audio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Alihkan pembekuan Touchscreen Test = Tes layar sentuh -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Aktif Back = Kembali -Bottom Center = Tengah bawah -Bottom Left = Kiri bawah -Bottom Right = Kanan bawah Cancel = Batal Center = Tengah -Center Left = Kiri tengah -Center Right = Kanan tengah -Changing this setting requires PPSSPP to restart. = Mengubah pengaturan ini memerlukan memulai ulang PPSSPP. +ChangingGPUBackends = Pergantian penyangga GPU memerlukan pemulaian ulang PPSSPP. Mulai ulang sekarang? +ChangingInflightFrames = Mengubah penyangga perintah grafis membutuhkan PPSSPP untuk memulai ulang. Mulai ulang sekarang? Channel: = Saluran: Choose PPSSPP save folder = Pilih berkas simpanan PPSSPP Confirm Overwrite = Apakah anda ingin menimpa data? @@ -372,47 +294,34 @@ DeleteConfirmGameConfig = Apakah Anda benar-benar ingin menghapus pengaturan unt DeleteFailed = Tidak dapat menghapus data. Deleting = Menghapus\nMohon tunggu... Disable All = Nonaktifkan semua -Disabled = Disabled Dumps = Buang Edit = Edit Enable All = Aktifkan semua -Enabled = Enabled Enter = Masuk -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Selesai GE Frame Dumps = Buang laju bingkai GE Grid = Kisi-kisi Inactive = Tidak aktif -Installing... = Installing... InternalError = Kesalahan internal telah terjadi. -Links = Links Load = Muat Load completed = Selesai memuat. Loading = Memuat\nMohon Tunggu... LoadingFailed = Tidak dapat memuat data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Pindah Move Down = Move Down Move Up = Move Up Network Connection = Koneksi Jaringan NEW DATA = DATA BARU No = Tidak -None = Tidak ada ObtainingIP = Mendapatkan alamat IP.\nHarap tunggu... OK = Oke Old savedata detected = Simpanan data lama terdeteksi Options = Pilihan -Password = Password Remove = Remove Reset = Atur ulang Resize = Atur ulang ukuran Retry = Coba lagi -Restart = Mengulang kembali Save = Simpan Save completed = Selesai menyimpan. Saving = Menyimpan\nMohon tunggu... @@ -420,7 +329,6 @@ SavingFailed = Tidak dapat menyimpan data. Search = Cari seconds, 0:off = detik, 0 = mati Select = Pilih -Settings = Settings Shift = Geser Skip = Lewati Snap = Garis pinggir @@ -431,11 +339,7 @@ Supported = Didukung There is no data = Tidak ada data. Toggle All = Alihkan semua Toggle List = Daftar pengalihan -Top Center = Tengah atas -Top Left = Kiri atas -Top Right = Kanan atas Unsupported = Tidak didukung -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Setelah anda menyimpan, ini akan dapat dimuat di PSP, namun tidak di PPSSPP lawas When you save, it will not work on outdated PSP Firmware anymore = Saat anda menyimpan, itu tidak akan berfungsi lagi pada firmware PSP yang sudah lawas Yes = Ya @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Berkas terkompresi (ZIP).\nSilakan ekstrak [Game] Asia = Asia Calculate CRC = Kalkulasi CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Hapus -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Buat konfigurasi permainan Create Shortcut = Buat jalan pintas Delete Game = Hapus permainan Delete Game Config = Hapus konfigurasi permainan Delete Save Data = Hapus simpanan data Europe = Eropa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Permainan -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Pengaturan permainan Homebrew = Paket Permainan Hong Kong = Hong Kong InstallData = Instalasi data -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Jepang Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Hapus dari "Terbaru" SaveData = Simpanan data Setting Background = Atur latar belakang Show In Folder = Tampilkan di berkas -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = Amerika Serikat Use UI background = Gunakan latar belakang UI @@ -623,7 +520,6 @@ Must Restart = Anda harus memulai ulang PPSSPP agar perubahan ini berfungsi. Native device resolution = Resolusi asli Nearest = Terdekat No buffer = Tidak ada penyangga -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Lewati efek penyangga (tak tersangga, lebih cepat) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Peregangan Texture Filter = Filter tekstur Texture Filtering = Pemfilteran tekstur -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Penskala tekstur Texture Shader = Tekstur shader Turn off Hardware Tessellation - unsupported = Matikan "Pengujian perangkat keras": Tidak didukung @@ -669,6 +564,8 @@ Upscale Level = Tingkat skala-atas Upscale Type = Jenis skala-atas UpscaleLevel Tip = Berat di CPU - beberapa penskala mungkin tertunda untuk menghindari kegagapan Use all displays = Gunakan semua tampilan +Vertex Cache = Tembolok vertex +VertexCache Tip = Lebih cepat, namun dapat menyebabkan kedipan sementara VSync = VSync Vulkan = Vulkan Window Size = Ukuran Window @@ -685,12 +582,10 @@ Zip archive corrupt = Arzip ZIP rusak Zip file does not contain PSP software = File ZIP tidak mengandung perangkat lunak PSP [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Konfigurasi otomatis Autoconfigure for device = Konfigurasi otomatis untuk perangkat Bind All = Ikat/simpan semua Clear All = Bersihkan semua -Combo mappings are not enabled = Combo mappings are not enabled Default All = Kembalikan ke pengaturan awal Map a new key for = Tombol kunci baru ditetapkan ke Map Key = Tetapkan kunci/tombol @@ -747,7 +642,16 @@ Audio/Video Recording = Perekam audio/video AxisSwap = Tukar sumbu Circle = Lingkaran Cross = Seberang -Custom %d = Kustom %d +Custom 1 = Kustom 1 +Custom 10 = Kustom 10 +Custom 2 = Kustom 2 +Custom 3 = Kustom 3 +Custom 4 = Kustom 4 +Custom 5 = Kustom 5 +Custom 6 = Kustom 6 +Custom 7 = Kustom 7 +Custom 8 = Kustom 8 +Custom 9 = Kustom 9 D-pad down = D-pad bawah D-pad left = D-pad kiri D-pad right = D-pad kanan @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Tekan tombol dua kali Down = Dpad Bawah Dpad = Dpad -Exit App = Exit App Frame Advance = Memajukan Bingkai Hold = Tahan Home = Beranda @@ -773,7 +676,6 @@ None = Tidak ada Note = Catatan OpenChat = Buka obrolan Pause = Jeda -Previous Slot = Previous Slot R = R RapidFire = Tembakan beruntun Record = Rekam @@ -803,7 +705,6 @@ Texture Dumping = Pembuangan tekstur Texture Replacement = Timpa tekstur Toggle Fullscreen = Pengalihan layar penuh Toggle mode = Mode pengalihan -Toggle WLAN = Toggle WLAN Triangle = Segitiga Fast-forward = Pemajuan cepat Up = Dpad Atas @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Sudah berisi data PSP -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Buat atau Pilih berkas PSP Current = Saat ini DataCanBeShared = Data bisa dibagikan antar PPSSPP reguler/emas @@ -846,6 +746,11 @@ AdHoc Server = Server Ad Hoc AdhocServer Failed to Bind Port = Server Ad Hoc gagal memuat port AM: Data from Unknown Port = AM: Data dari port tidak dikenal Auto = Otomatis +Bottom Center = Tengah bawah +Bottom Left = Kiri bawah +Bottom Right = Kanan bawah +Center Left = Kiri tengah +Center Right = Kanan tengah Change Mac Address = Ganti alamat MAC Change proAdhocServer Address = Ganti alamat IP pelayan PRO ad hoc (lokal) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = IP atau nama host tidak valid Minimum Timeout = Batas waktu minimum (batas dalam ms, 0 = bawaan) Misc = Lain-lain (bawaan= kompatibilitas PSP) Network Initialized = Jaringan terinisiasi +None = Tidak ada Please change your Port Offset = Harap ubah letak port Anda Port offset = Letak port (0 = kecocokan dengan PSP) Open PPSSPP Multiplayer Wiki Page = Halaman Wiki PPSSPP Ad-Hoc @@ -889,9 +795,11 @@ Quick Chat 3 = Obrolan cepat 3 Quick Chat 4 = Obrolan cepat 4 Quick Chat 5 = Obrolan cepat 5 QuickChat = Obrolan cepat -Randomize = Randomize Send = Kirim Send Discord Presence information = Kirim informasi "Kritik dan Saran" ke Discord +Top Center = Tengah atas +Top Left = Kiri atas +Top Right = Kanan atas Unable to find UPnP device = Tidak dapat menemukan perangkat UPnP UPnP (port-forwarding) = UPnP (penerusan port) UPnP need to be reinitialized = UPnP perlu diinisialisasi ulang @@ -901,23 +809,6 @@ Validating address... = Validasi alamat... WLAN Channel = Saluran WLAN You're in Offline Mode, go to lobby or online hall = Anda dalam mode offline, pergi ke lobi atau aula online -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Pengecoh Continue = Lanjutkan @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Perbatasan Hitam Bloom = Kembang -BloomNoBlur = Bloom (no blur) Brightness = Kecerahan Cartoon = Kartun CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Koreksi Warna ColorPreservation = Color preservation Contrast = Kontras CRT = CRT -FakeReflections = FakeReflections FXAA = Mengurangi Artifak Distorsi (FXAA) Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = SSAA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Kelas Atas VideoSmoothingAA = Penghalus Video AA Vignette = Penggelapan di sisi @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = Informasi GPU High precision float range = Kisaran pengambang presisi tinggi High precision int range = Rentang integer presisi tinggi -Icon cache = Icon cache JIT available = JIT available Lang/Region = Bahasa/regional Memory Page Size = Ukuran halaman memori -Native resolution = Resolusi asli +Native Resolution = Resolusi asli No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Ekstensi OGL OpenGL ES 2.0 Extensions = Ekstensi OpenGL ES 2.0 @@ -1190,9 +1077,7 @@ OpenGL Extensions = Ekstensi OpenGL Optimal frames per buffer = Optimalisasi bingkai penyangga Optimal sample rate = Optimalisasi tingkat analogi OS Information = Informasi OS -Pixel resolution = Pixel resolution PPSSPP build = Pembuatan PPSSPP -Present modes = Present modes Refresh rate = Penyegaran Release = Rilis RW/RX exclusive = RW/RX eksklusif @@ -1204,7 +1089,7 @@ System Information = Informasi sistem System Name = Nama sistem System Version = Versi sistem Threads = Inti -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Penyedia Vendor (detected) = Penyedia (terdeteksi) Version Information = Informasi versi @@ -1287,7 +1172,6 @@ Record Audio = Rekam suara Record Display = Rekam tampilan Reset Recording on Save/Load State = Atur ulang rekaman pada status simpan/muat Restore Default Settings = Atur ulang pengaturan PPSSPP ke awal -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Putar ulang frekuensi foto (memory hog) Save path in installed.txt = Simpan jalur dalam installed.txt Save path in My Documents = Simpan jalur dalam dokumen saya @@ -1300,7 +1184,6 @@ Show ID = Tampilkan ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Tampilkan bendera wilayah Simulate UMD delays = Simulasikan jeda UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Unduh New version of PPSSPP available = Versi baru PPSSPP tersedia [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 37d2aa8a5..667d8c4c1 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1,67 +1,8 @@ -[Achievements] -%1 achievements, %2 points = %1 obiettivi, %2 punti -%1: Attempt failed = %1: Tentativo fallito -%1: Attempt started = %1: Tentativo iniziato -Account = Account -Achievement unlocked = Obiettivo sbloccato -Achievement progress = Progresso dell'obiettivo -Achievements = Obiettivi -Achievements enabled = Obiettivi abilitati -Achievements are disabled = Gli obiettivi sono disabilitati -Achievements with active challenges = Obiettivi con sfide attive -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Obiettivi quasi completati -Can't log in to RetroAchievements right now = Impossibile accedere a RetroAchievements in questo momento -Challenge indicator = Indicatore sfida -Contacting RetroAchievements server... = Contatto con il server di RetroAchievements in corso... -Customize = Personalizza -Earned = Hai sbloccato %1 su %2 obiettivi, e guadagnato %3 su %4 punti -Encore Mode = Modalità Encore -Failed logging in to RetroAchievements = Accesso a RetroAchievements non riuscito -Failed to connect to RetroAchievements. Achievements will not unlock. = Connessione a RetroAchievements non riuscita. Gli obiettivi non verranno sbloccati. -Failed to identify game. Achievements will not unlock. = Identificazione del gioco non riuscita. Gli obiettivi non verranno sbloccati. -Hardcore Mode (no savestates) = Modalità Sfida (senza stati salvati) -Hardcore Mode = Modalità Sfida -How to use RetroAchievements = Come usare RetroAchievements -In Encore mode - listings may be wrong below = In modalità Encore - le voci qui sotto potrebbero essere errate -Leaderboard attempt started or failed = Tentativo di classifica iniziato o fallito -Leaderboard result submitted = Risultato di classifica inviato -Leaderboard score submission = Invio punteggio in classifica -Leaderboard submission is enabled = L'invio in classifica è abilitato -Leaderboards = Classifiche -Leaderboard tracker = Tracciatore classifica -Links = Link -Locked achievements = Obiettivi bloccati -Log bad memory accesses = Registra cattivi accessi alla memoria -Mastered %1 = Padroneggiato %1 -Around me = Intorno a me -Notifications = Notifiche -Recently unlocked achievements = Obiettivi recentemente sbloccati -Reconnected to RetroAchievements. = Riconnesso a RetroAchievements. -Register on www.retroachievements.org = Registrati su www.retroachievements.org -RetroAchievements are not available for this game = I RetroAchievements non sono disponibili per questo gioco -RetroAchievements website = Sito web di RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = Stato salvato caricato senza dati degli obiettivi -Save states not available in Hardcore Mode = Stati salvati non disponibili in Modalità Sfida -Sound Effects = Effetti Sonori -Statistics = Statistiche -Submitted %1 for %2 = Inviato %1 per %2 -Syncing achievements data... = Sincronizzazione dati obiettivi in corso... -Test Mode = Modalità Test -This feature is not available in Hardcore Mode = Questa funzione non è disponibile in Modalità Sfida -This game has no achievements = Questo gioco non ha obiettivi -Top players = Migliori giocatori -Unlocked achievements = Obiettivi sbloccati -Unsupported achievements = Obiettivi non supportati -Unofficial achievements = Obiettivi non ufficiali - -[Audio] -Alternate speed volume = Volume a velocità alternativa -Audio backend = Renderer Audio (riavvio necessario) +[Audio] +Alternate speed volume = Volume velocizzato alternativo +Audio backend = Renderer Audio (necessita il riavvio) Audio Error = Errore Audio -Audio file format not supported. Must be WAV. = Formato audio non supportato. Deve essere WAV. -AudioBufferingForBluetooth = Buffer compatibile con Bluetooth (più lento) +AudioBufferingForBluetooth = Buffer per Bluetooth (lento) Auto = Automatico Device = Dispositivo Disabled = Disabilitato @@ -72,7 +13,7 @@ Microphone = Microfono Microphone Device = Periferica Microfono Mute = Muto Reverb volume = Riverb. volume -Use new audio devices automatically = Usa nuovi dispositivi audio automaticamente. +Use new audio devices automatically = Usa il nuovo dispositivo audio automatic. Use global volume = Usa volume globale WASAPI (fast) = WASAPI (veloce) @@ -95,8 +36,7 @@ Calibrate Analog Stick = Calibra Stick Analogico Calibrate = Calibra Calibrated = Calibrato Calibration = Calibratura -Circular low end radius = Raggio circolare di base -Circular stick input = Input circolare levetta +Circular stick input = Input stick circolare Classic = Classico Confine Mouse = Confina il mouse all'interno dell'area della finestra Control Mapping = Mappatura dei Controlli @@ -108,17 +48,15 @@ Deadzone radius = Raggio della zona morta Disable D-Pad diagonals (4-way touch) = Disattiva Diagonali del D-Pad (Tocco a 4-Vie) Disable diagonal input = Disabilita input diagonale Double tap = Doppio tocco -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Abilita controllo gesti Enable standard shortcut keys = Abilita scorciatoie standard -frames = frame -Gesture = Gesto +Gesture = Gesti Gesture mapping = Mappatura gesti Glowing borders = Bordi luminosi HapticFeedback = Risposta Tattile (vibrazione) -Hide touch analog stick background circle = Nascondi cerchio di background della levetta analogica touch +Hide touch analog stick background circle = Nascondi cerchio dello stick analogico Icon = Icona -Ignore gamepads when not focused = Ignora i controller se non attiva +Ignore gamepads when not focused = Ignora i gamepad se non attivi Ignore Windows Key = Ignora il tasto "Windows" Invert Axes = Inverti gli Assi Invert Tilt along X axis = Inverti Inclinazione sull'asse X @@ -140,15 +78,13 @@ OnScreen = Controlli Touchscreen Portrait = Ritratto Portrait Reversed = Ritratto invertito PSP Action Buttons = Pulsanti Azione PSP (△◯✕☐) -Rapid fire interval = Intervallo fuoco rapido Raw input = Input grezzo -Reset to defaults = Reimposta su valori predefiniti +Reset to defaults = Reset ai predefiniti Screen Rotation = Rotazione Schermo Sensitivity (scale) = Sensibilità (scala) Sensitivity = Sensibilità Shape = Forma -Show Touch Pause Menu Button = Mostra Tasto Menu di Pausa -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) +Show Touch Pause Menu Button = Mostra Tasto di Pausa Swipe = Scorrimento Swipe sensitivity = Sensibilità Scorrimento Swipe smoothing = Fluidità Scorrimento @@ -160,7 +96,7 @@ Tilt Sensitivity along Y axis = Inverti Sensibilità sull'asse Y To Calibrate = Tieni il dispositivo all'angolazione che preferisci e premi "Calibra". Toggle mode = Scambia modalità Repeat mode = Modalità ripeti -Touch Control Visibility = Visibilità Controlli Touch +Touch Control Visibility = Visibilità controlli Touch Use custom right analog = Usa analogico destro personalizzato Use Mouse Control = Usa il controllo con il mouse Visibility = Visibilità @@ -230,7 +166,6 @@ Log Console = Log Console Memory View... = Visualizzazione Memoria... More Settings... = Altre Impostazioni... Nearest = Pixel perfect -Recent = &Recent Skip Buffer Effects = Salta effetti di buffer (niente buffer, più velocità) Off = Disattiva Open Chat = Apri Chat @@ -269,6 +204,7 @@ Texture Filtering = Filtro Texture Texture Scaling = Scalatura Texture Use Lossless Video Codec (FFV1) = Usa Codec Video senza perdite (FFV1) Use output buffer for video = Usa il buffer per il video +Vertex Cache = Cache dei Vertici VSync = Sincronizzazione Verticale Vulkan = Vulkan Window Size = Dimensioni Finestra @@ -282,45 +218,37 @@ Backspace = Backspace Block address = Blocca indirizzo By Address = Per indirizzo Copy savestates to memstick root = Copia gli stati salvati nella root della Memory Stick -Create frame dump = Crea dump frame Create/Open textures.ini file for current game = Crea/Apri il file textures.ini per il gioco corrente Current = Corrente -Debug overlay = Overlay debug -Debug stats = Statistiche debug Dev Tools = Strumenti di sviluppo -DevMenu = MenuSvil -Disabled JIT functionality = Funzionalità JIT Disattivata -Draw Frametimes Graph = Disegna Grafico dei Frametime +DevMenu = DevMenu +Disabled JIT functionality = Disattivata Funzionalità JIT +Draw Frametimes Graph = Disegna grafica dei frametimes Dump Decrypted Eboot = Crea EBOOT.BIN decriptato all'avvio del gioco Dump next frame to log = Crea Log del Frame Successivo Enable driver bug workarounds = Abilita espediente per superare i bug dei driver Enable Logging = Attiva Log del Debug Enter address = Inserire indirizzo FPU = FPU -Fragment = Frammento -Frame timing = Frame timing Framedump tests = Test del framedump -Frame Profiler = Profilatore di Frame -GPU Allocator Viewer = Visualizzatore dell'Allocatore GPU +Frame Profiler = Profilo Frame GPU Driver Test = Test dei driver GPU -GPU log profiler = Profilatore dei registri GPU +GPU log profiler = GPU log profiler GPU Profile = Profilo GPU Jit Compare = Confronto Jit JIT debug tools = Strumenti di debug JIT -Log Dropped Frame Statistics = Statistiche dei Frame Persi +Log Dropped Frame Statistics = Statistiche dei Frame persi Log Level = Livello del Log Log View = Visualizza Log Logging Channels = Registra Canali -Multi-threaded rendering = Multi-threaded rendering Next = Avanti No block = Nessun blocco -Off = Off Prev = Indietro Random = Casuale Replace textures = Sostituisci texture Reset = Reset Reset limited logging = Reset del logging limitato -RestoreDefaultSettings = Si desidera davvero ripristinare le impostazioni?\nQuest'azione non può essere annullata.\nRiavviare PPSSPP per caricare i cambiamenti. +RestoreDefaultSettings = Si desidera davvero ripristinare le impostazioni?\n\n\nQuest'azione non può essere annullata.\nRiavviare PPSSPP per caricare i cambiamenti. RestoreGameDefaultSettings = Si desidera davvero ripristinare le impostazioni specifiche per il gioco\nai valori predefiniti? Resume = Ripristina Run CPU Tests = Fai Test CPU @@ -332,12 +260,10 @@ Stats = Statistiche System Information = Informazioni Sistema Texture ini file created = Creato file ini delle texture Texture Replacement = Sostituzione Texture -Audio Debug = Debug Audio -Control Debug = Debug Controlli -Toggle Freeze = Attiva/Disattiva Congelamento -Touchscreen Test = Test del Touchscreen -Ubershaders = Ubershaders -Vertex = Vertex +Toggle Audio Debug = Attiva/Disattiva debug audio +Toggle Control Debug = Attiva/Disattiva controllo debug +Toggle Freeze = Attiva/Disattiva congelamento +Touchscreen Test = Test del touchscreen VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * definizione PSP Active = Attiva Back = Indietro -Bottom Center = In basso al centro -Bottom Left = In basso a sinistra -Bottom Right = In basso a destra Cancel = Annulla Center = Centra -Center Left = Al centro a sinistra -Center Right = Al centro a destra -Changing this setting requires PPSSPP to restart. = La modifica di questa impostazione richiede il riavvio di PPSSPP. +ChangingGPUBackends = Per cambiare il renderer GPU sarà necessario riavviare PPSSPP. Riavviare adesso? +ChangingInflightFrames = La modifica del buffering dei comandi grafici richiede il riavvio di PPSSPP. Riavviare adesso? Channel: = Canale: Choose PPSSPP save folder = Scegli la cartella di salvataggio PPSSPP Confirm Overwrite = Vuoi sovrascrivere i dati? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Vuoi veramente cancellare le impostazioni per questo g DeleteFailed = Impossibile cancellare i dati. Deleting = Cancellazione in corso.\nAttendere, prego... Disable All = Disattiva tutto -Disabled = Disabled Dumps = Dumps Edit = Modifica Enable All = Attiva tutto -Enabled = Enabled Enter = Invio -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filtro Finish = Fine GE Frame Dumps = GE Frame Dumps Grid = Griglia Inactive = Inattiva -Installing... = Installing... InternalError = È avvenuto un errore interno. -Links = Links Load = Carica Load completed = Caricamento completato. Loading = Caricamento in corso.\nAttendere, prego... LoadingFailed = Impossibile caricare i dati. -Log in = Accedi -Log out = Esci -Logged in! = Accesso eseguito! -Logging in... = Accesso in corso... Move = Sposta Move Down = Sposta giù Move Up = Sposta su Network Connection = Connessione di Rete NEW DATA = NUOVI DATI No = No -None = Nessuno ObtainingIP = Cerco di ottenere l'indirizzo IP.\nAttendere, prego... OK = OK Old savedata detected = Rilevati vecchi dati salvati Options = Opzioni -Password = Password Remove = Rimuovi Reset = Reset Resize = Ridimensiona -Restart = Riavvia Retry = Riprova Save = Salva Save completed = Salvataggio Completato. @@ -420,7 +329,6 @@ SavingFailed = Impossibile salvare i dati. Search = Cerca seconds, 0:off = secondi, 0 = spento Select = Seleziona -Settings = Settings Shift = Maiuscolo Skip = Salta Snap = Allinea @@ -431,11 +339,7 @@ Supported = Supportato There is no data = Non ci sono dati. Toggle All = Attiva Tutto Toggle List = Mostra lista -Top Center = In alto al centro -Top Left = In alto a sinistra -Top Right = In alto a destra Unsupported = Non supportato -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Salvando, sarà possibile effettuare il caricamento su una PSP, ma non su un vecchio PPSSPP. When you save, it will not work on outdated PSP Firmware anymore = Salvando, non sarà più possibile effettuare il caricamento su un vecchio firmware PSP. Yes = Sì @@ -473,14 +377,14 @@ MsgErrorSavedataDataBroken = Dati del salvataggio corrotti. MsgErrorSavedataMSFull = Memory Stick piena. Controllare lo spazio a disposizione. MsgErrorSavedataNoData = Attenzione: dati del salvataggio non trovati. MsgErrorSavedataNoMS = Memory Stick non inserita. -No EBOOT.PBP, misidentified game = Nessun EBOOT.PBP, gioco identificato erroneamente. +No EBOOT.PBP, misidentified game = No EBOOT.PBP, gioco identificato erroneamente. Not a valid disc image. = Immagine disco non valida. OpenGLDriverError = Errore Driver OpenGL PPSSPP doesn't support UMD Music. = PPSSPP non supporta Musica UMD. PPSSPP doesn't support UMD Video. = PPSSPP non supporta Video UMD. -PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPP esegue giochi PSP, non giochi PlayStation 1 o 2. +PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPP per giocare ai giochi PSP, non ai giochi PlayStation 1 o 2. PPSSPPDoesNotSupportInternet = PPSSPP attualmente non supporta connessioni Internet per DLC, PSN o aggiornamenti. -PS1 EBOOTs are not supported by PPSSPP. = Gli EBOOT PS1 non sono supportati da PPSSPP. +PS1 EBOOTs are not supported by PPSSPP. = PS1 EBOOT non supportati da PPSSPP. PSX game image detected. = Il file è un'immagine MODE2. PPSSPP non supporta giochi per PS1. RAR file detected (Require UnRAR) = Il file è compresso (RAR).\nPrima si deve decomprimere (prova UnRAR). RAR file detected (Require WINRAR) = Il file è compresso (RAR).\nPrima si deve decomprimere (prova WinRAR). @@ -488,11 +392,11 @@ Running slow: try frameskip, sound is choppy when slow = Emulazione lenta: prova Running slow: Try turning off Software Rendering = Emulazione lenta: prova a disattivare "rendering software" Save encryption failed. This save won't work on real PSP = Criptazione salvataggio fallita. Questo salvataggio non funzionerà su una PSP reale textures.ini filenames may not be cross-platform = I nomi dei file "textures.ini" potrebbero non essere multi-piattaforma. -This is a saved state, not a game. = Questo è uno stato salvato, non un gioco. -This is save data, not a game. = Questi sono dati salvati, non un gioco. +This is a saved state, not a game. = Questo è un salvataggio di stato, non un gioco. +This is save data, not a game. = Questi sono dei dati salvati, non un gioco. Unable to create cheat file, disk may be full = Impossibile creare il file cheat, il disco potrebbe essere pieno. -Unable to initialize rendering engine. = Impossibile inizializzare il motore di rendering. -Unable to write savedata, disk may be full = Impossibile scrivere i dati del salvataggio, il disco potrebbe essere pieno. +Unable to initialize rendering engine. = Impossibile inizializzare il renderer. +Unable to write savedata, disk may be full = Impossibile sovrascrivere i dati del salvataggio, il disco potrebbe essere pieno. Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = Attenzione: Memoria Video PIENA, ridurre l'upscaling e passare in modalità caching lenta. Warning: Video memory FULL, switching to slow caching mode = Attenzione: Memoria Video PIENA, passare in modalità caching lenta. ZIP file detected (Require UnRAR) = Il file è compresso (ZIP).\nPrima si deve decomprimere (prova UnRAR). @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Il file è compresso (ZIP).\nPrima si deve [Game] Asia = Asia Calculate CRC = Calcola CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Elimina -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO -Create Game Config = Crea Configurazione di Gioco +Create Game Config = Crea game config Create Shortcut = Crea Scorciatoia Delete Game = Elimina Gioco -Delete Game Config = Elimina Configurazione di Gioco -Delete Save Data = Elimina Dati Salvataggio +Delete Game Config = Elimina game config +Delete Save Data = Elimina dati salvataggio Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Gioco -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Impostazioni Gioco Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Installa i dati -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Giappone Korea = Corea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Rimuovi dai Recenti SaveData = Dati salvataggio Setting Background = Imposta sfondo Show In Folder = Mostra nella Cartella -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Usa sfondo interfaccia @@ -624,7 +521,6 @@ Must Restart = Sarà necessario riavviare PPSSPP per attivare le modifiche. Native device resolution = Risoluzione nativa della periferica Nearest = Pixel perfect No buffer = Niente buffer -Render all frames = Render all frames Show Battery % = Mostra batteria in % Show Speed = Mostra velocità Skip Buffer Effects = Salta effetti di buffer (niente buffer, più velocità) @@ -659,7 +555,6 @@ Stereo rendering = Rendering stereo Stretch = Adatta al Display Texture Filter = Filtro delle texture Texture Filtering = Filtraggio delle texture -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Scalatura delle texture Texture Shader = Shader delle texture Turn off Hardware Tessellation - unsupported = Disattivazione di "tessellazione hardware": non supportata @@ -670,6 +565,8 @@ Upscale Level = Livello Ottimizzazione Upscale Type = Tipo Ottimizzazione UpscaleLevel Tip = Pesante per le CPU - alcune scalature posso essere ritardate per evitare scatti Use all displays = Usa tutti i display +Vertex Cache = Cache dei Vertici +VertexCache Tip = Più veloce, ma potrebbe causare dei flicker temporanei VSync = Sincronizzazione Verticale Vulkan = Vulkan Window Size = Dimensioni Finestra @@ -686,23 +583,21 @@ Zip archive corrupt = Archivio ZIP corrotto Zip file does not contain PSP software = Il file ZIP non contiene software PSP [KeyMapping] -Allow combo mappings = Consenti mappature combinate Autoconfigure = Configurazione automatica Autoconfigure for device = Configurazione Automatica per il Dispositivo -Bind All = Associa Tutti -Clear All = Pulisci Tutti -Combo mappings are not enabled = Le mappature combinate non sono abilitate -Default All = Ripristina Tutti a Valori Predefiniti -Map a new key for = Mappa un nuovo tasto per: -Map Key = Mappa Tasto -Map Mouse = Mappa Mouse +Bind All = Mappa tutto +Clear All = Pulisci Tutto +Default All = Ripristina Tutto +Map a new key for = Seleziona Tasto di Controllo per: +Map Key = Mappatura tasto +Map Mouse = Mappatura mouse Replace = Sostituisci Show PSP = Mostra PSP You can press ESC to cancel. = Puoi premere Esc per annullare. [MainMenu] Browse = Sfoglia... -Buy PPSSPP Gold = Compra PPSSPP Gold +Buy PPSSPP Gold = Acquista PPSSPP Gold Choose folder = Scegli cartella Credits = Riconoscimenti Exit = Esci @@ -714,14 +609,14 @@ How to get games = Come ottenere giochi? How to get homebrew & demos = Come ottenere homebrew o demo? Load = Carica... Loading... = Caricamento in corso... -PPSSPP Homebrew Store = Store degli Homebrew di PPSSPP -PinPath = Fissa -PPSSPP can't load games or save right now = PPSSPP non può caricare i giochi o salvare in questo momento +PPSSPP Homebrew Store = PPSSPP Homebrew Store +PinPath = Pin +PPSSPP can't load games or save right now = PPSSPP non può caricare i giochi o salvarli, in questo momento Recent = Recenti SavesAreTemporary = PPSSPP sta salvando in una cartella temporanea -SavesAreTemporaryGuidance = Estrai PPSSPP da qualche parte per salvare permanentemente +SavesAreTemporaryGuidance = Estrae PPSSPP da qualche parte per salvarlo permanentemente SavesAreTemporaryIgnore = Ignora l'avviso -UnpinPath = Rimuovi dai fissati +UnpinPath = Stacca UseBrowseOrLoad = Usa Sfoglia per scegliere una cartella, oppure Carica per scegliere un file. www.ppsspp.org = www.ppsspp.org @@ -748,7 +643,16 @@ Audio/Video Recording = Registrazione Audio/Video AxisSwap = Scambia Assi Circle = Cerchio Cross = Croce -Custom %d = A scelta %d +Custom 1 = A scelta 1 +Custom 10 = A scelta 10 +Custom 2 = A scelta 2 +Custom 3 = A scelta 3 +Custom 4 = A scelta 4 +Custom 5 = A scelta 5 +Custom 6 = A scelta 6 +Custom 7 = A scelta 7 +Custom 8 = A scelta 8 +Custom 9 = A scelta 9 D-pad down = D-pad giù D-pad left = D-pad sinistra D-pad right = D-pad destra @@ -761,7 +665,6 @@ Display Portrait Reversed = Visuale ritratto invertita Double tap button = Pulsante doppio tocco Down = D-Pad Giù Dpad = Dpad -Exit App = Exit App Fast-forward = Avanti veloce Frame Advance = Avanzam. frame Hold = Hold @@ -775,7 +678,6 @@ None = Niente Note = Nota OpenChat = Apri la chat Pause = Pausa -Previous Slot = Previous Slot R = R RapidFire = Fuoco rapido Record = Record @@ -805,7 +707,6 @@ Texture Dumping = Dumping delle texture Texture Replacement = Sostituzione delle texture Toggle Fullscreen = Passa a Schermo Intero Toggle mode = Modalità Scambio -Toggle WLAN = Toggle WLAN Triangle = Triangolo Up = D-Pad Su Vol + = Volume + @@ -817,6 +718,11 @@ AdHoc Server = Server Ad hoc AdhocServer Failed to Bind Port = Il server Ad hoc non è riuscito a collegarsi alla porta AM: Data from Unknown Port = AM: Dati da porta sconosciuta Auto = Auto +Bottom Center = In basso al centro +Bottom Left = In basso a sinistra +Bottom Right = In basso a destra +Center Left = Al centro a sinistra +Center Right = Al centro a destra Change Mac Address = Cambia indirizzo MAC Change proAdhocServer Address = Cambia indirizzo server IP PRO ad hoc (localhost = istanze multiple) ChangeMacSaveConfirm = Generare un nuovo indirizzo MAC? @@ -850,6 +756,7 @@ Invalid IP or hostname = Indirizzo IP o nome del dominio non valido Minimum Timeout = Timeout minimo (forza in ms, 0 = predefinito) Misc = Varie (predefinito = compatibilità PSP) Network Initialized = Rete inizializzata +None = None Please change your Port Offset = Prego, cambiare l'offset della porta Port offset = Offset Porta (0 = compatibilità PSP) Open PPSSPP Multiplayer Wiki Page = Pagina Wiki Ad-Hoc PPSSPP @@ -860,9 +767,11 @@ Quick Chat 3 = Chat rapida 3 Quick Chat 4 = Chat rapida 4 Quick Chat 5 = Chat rapida 5 QuickChat = Chat rapida -Randomize = Randomize Send = Invia Send Discord Presence information = Invia informazioni Discord "Rich Presence" +Top Center = In alto al centro +Top Left = In alto a sinistra +Top Right = In alto a destra Unable to find UPnP device = Impossibile trovare il dispositivo UPnP UPnP (port-forwarding) = UPnP (reindirizzamento della porta) UPnP need to be reinitialized = UPnP dev'essere reinizializzato @@ -872,29 +781,12 @@ Validating address... = Convalida indirizzo... WLAN Channel = Canale WLAN You're in Offline Mode, go to lobby or online hall = Sei in modalità offline, vai alla lobby online. -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Lingua del gioco -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = I giochi spesso non supportano tutte le lingue -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] -Cheats = Trucchi +Cheats = Cheat Continue = Continua -Create Game Config = Crea Configurazione di Gioco -Delete Game Config = Elimina Configurazione di Gioco -Exit to menu = Vai al menu +Create Game Config = Crea game config +Delete Game Config = Elimina game config +Exit to menu = Vai al Menu Game Settings = Impostazioni Gioco Load State = Carica Stato Rewind = Riavvolgimento @@ -905,7 +797,7 @@ Undo last load = Annulla ultimo caricamento Undo last save = Annulla ultimo salvataggio [PostShaders] -(duplicated setting, previous slider will be used) = (parametro duplicato, verrà usata la precedente regolazione) +(duplicated setting, previous slider will be used) = (parametri duplicati, verrà usata la precedente regolazione) 4xHqGLSL = 4xHQ GLSL 5xBR = Upscaler 5xBR in pixel art 5xBR-lv2 = Upscaler 5xBR-lv2 in pixel art @@ -915,7 +807,6 @@ Animation speed (0 -> disable) = Velocità animazione (0 -> disabilita) Aspect = Aspetto Black border = Bordo nero Bloom = Sfocatura luminosa -BloomNoBlur = Bloom (senza sfocatura) Brightness = Luminosità Cartoon = Disegno CatmullRom = Upscaler bicubico (Catmull-Rom) @@ -923,7 +814,6 @@ ColorCorrection = Correzione dei colori ColorPreservation = Preservazione colore Contrast = Contrasto CRT = Linee di scansione CRT -FakeReflections = RiflessiFinti FXAA = Antialiasing FXAA Gamma = Gamma GreenLevel = Livello del verde @@ -944,7 +834,6 @@ SSAA(Gauss) = Supercampionamento AA (Gauss) Strength = Forza Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Upscaling Spline36 VideoSmoothingAA = AA nitido del video Vignette = Miniatura @@ -952,16 +841,16 @@ Vignette = Miniatura [PSPCredits] all the forum mods = tutte le mod del forum build server = crea server -Buy Gold = Compra Gold -check = Da' anche un'occhiata a Dolphin, il miglior emulatore per Wii/GC sulla piazza: -CheckOutPPSSPP = Da' un'occhiata a PPSSPP, il meraviglioso emulatore PSP: http://www.ppsspp.org/ +Buy Gold = Versione Gold +check = Prova anche il Dolphin, il miglior emulatore per Wii/GC: +CheckOutPPSSPP = Da' un'occhiata a PPSSPP, il magnifico emulatore PSP: http://www.ppsspp.org/ contributors = Collaboratori: created = Realizzato da Discord = Discord info1 = PPSSPP è realizzato esclusivamente a scopo didattico. info2 = Assicurarsi di avere i diritti di utilizzo dei propri giochi info3 = possedendo una copia UMD autentica o acquistando una copia -info4 = digitale dal PlayStation Store sulla propria PSP. +info4 = digitale dal negozio di PlayStation Network sulla propria PSP. info5 = PSP è un marchio di Sony, Inc. iOS builds = versione iOS license = Software Libero GPL 2.0+ @@ -986,12 +875,11 @@ translators4 = papel translators5 = translators6 = Twitter @PPSSPP_emu = Twitter -website = Da' un'occhiata al sito web: +website = Visita il sito web: written = Scritto in C++ per velocità e portabilità [MemStick] Already contains PSP data = Contiene già dati PSP -Cancelled - try again = Annullato - prova di nuovo Create or Choose a PSP folder = Scegli o crea una cartella PSP Current = Corrente DataCanBeShared = I dati possono essere condivisi tra PPSSPP normale/Gold @@ -1068,7 +956,7 @@ Perfect Description = Emulazione perfetta per tutto il gioco - magnifico! Plays = Giocabile Plays Description = Completamente giocabile ma sono presenti dei glitch ReportButton = Rapporto feedback -Show disc CRC = Mostra CRC disco +Show disc CRC = Show disc CRC Speed = Velocità Submit Feedback = Invia feedback SuggestionConfig = Guarda i rapporti sul sito web per le impostazioni migliori. @@ -1080,7 +968,7 @@ SuggestionsWaiting = Invia e consulta i feedback degli altri utenti... SuggestionUpgrade = Aggiorna alla nuova build del PPSSPP. SuggestionVerifyDisc = Verifica se l'ISO in tuo possesso è una copia funzionante del tuo disco. Unselected Overall Description = Quanto è stata precisa l'emulazione del gioco? -View Feedback = Visualizza tutti i Feedback +View Feedback = Mostra i Feedback [Savedata] Date = Data @@ -1178,11 +1066,10 @@ GPU Flags = Flag GPU GPU Information = Informazioni GPU High precision float range = Ampiezza di float ad alta precisione High precision int range = Ampiezza interi ad alta precisione -Icon cache = Icon cache JIT available = JIT disponibile Lang/Region = Lingua/Regione Memory Page Size = Ampiezza pagina di memoria -Native resolution = Risoluzione nativa +Native Resolution = Risoluzione nativa No GPU driver bugs detected = Nessun bug per i driver GPU rilevato OGL Extensions = Estensioni OGL OpenGL ES 2.0 Extensions = Estensioni OpenGL ES 2.0 @@ -1191,9 +1078,7 @@ OpenGL Extensions = Estensioni OpenGL Optimal frames per buffer = Frame per buffer ottimali Optimal sample rate = Frequenza di campionamento ottimale OS Information = Informazioni OS -Pixel resolution = Pixel resolution PPSSPP build = Versione PPSSPP -Present modes = Present modes Refresh rate = Frequenza d'aggiornamento Release = Rilascio RW/RX exclusive = Esclusiva RW/RX @@ -1205,7 +1090,7 @@ System Information = Informazioni Sistema System Name = Nome System Version = Versione del sistema Threads = Processi -UI resolution = Risoluzione interfaccia +UI Resolution = Risoluzione interfaccia Vendor = Venditore Vendor (detected) = Venditore (rilevato) Version Information = Informazioni Versione @@ -1262,7 +1147,6 @@ No animation = Nessuna animazione Path does not exist! = Il percorso non esiste! PSP Memory Stick = Memory Stick PSP Recent games = Giochi recenti -RetroAchievements = RetroAchievements Set Memory Stick folder = Imposta la cartella della Memory Stick Show Memory Stick folder = Mostra cartella Memory Stick Theme = Tema @@ -1304,7 +1188,6 @@ Set UI background... = Imposta sfondo interfaccia... Show ID = Mostra ID Show region flag = Mostra flag regione Simulate UMD delays = Simula ritardo UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1349,7 +1232,6 @@ Choices: = Scelte: List: = Lista: Progress: %1% = Avanzamento: %1% Screen representation = Rappresentazione su schermo - [Upgrade] Details = Dettagli Dismiss = Ignora @@ -1357,11 +1239,12 @@ Download = Scarica New version of PPSSPP available = È disponibile una nuova versione di PPSSPP [VR] +% of native FoV = % del FoV nativo 6DoF movement = Movimento 6DoF Camera type = Tipo di telecamera Distance to 2D menus and scenes = Distanza dai menu e dalle scene 2D -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Solo per esperti +Field of view scale = Scalatura "Field of view" Force 72Hz update = Forza aggiornamento a 72Hz Game camera rotation step per frame = Passo di rotazione della telecamera di gioco per fotogramma Game camera uses rotation smoothing = La telecamera di gioco utilizza la rotazione fluida diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index a7d279a51..a6d420de1 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1,70 +1,11 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1つの実績、 %2ポイント -Account = アカウント -Achievement progress = 実績進捗 -Achievement unlocked = 実績解除 -Achievements = 実績 -Achievements are disabled = 実績は無効化されています -Achievements enabled = 実績を有効化 -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = もう少しで達成する実績 -Around me = 自分の近く -Can't log in to RetroAchievements right now = 現在RetroAchievementsにログインできません。 -Challenge indicator = チャレンジ目標 -Contacting RetroAchievements server... = RetroAchievementsのサーバーに接続しています... -Customize = カスタマイズ -Earned = %2個中%1つの実績を解除し、%4ポイント中%3ポイントを得ています -Encore Mode = Encoreモード -Failed logging in to RetroAchievements = RetroAchievementsのログインに失敗しました -Failed to connect to RetroAchievements. Achievements will not unlock. = RetroAchievementsへの接続に失敗しました。実績はアンロックされません。 -Failed to identify game. Achievements will not unlock. = ゲームの識別に失敗しました。実績はアンロックされません。 -Hardcore Mode (no savestates) = チャレンジモード (セーブステートオフ) -Hardcore Mode = チャレンジモード -How to use RetroAchievements = RetroAchievementsの使い方 -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = リーダーボードの結果を投稿した -Leaderboard score submission = リーダーボードの結果投稿 -Leaderboard submission is enabled = リーダーボードへの投稿が有効 -Leaderboard tracker = リーダーボードトラッカー -Leaderboards = リーダーボード -Links = リンク -Locked achievements = 解除していない実績 -Log bad memory accesses = 不正なメモリ・アクセスを記録する -Mastered %1 = Mastered %1 -Notifications = 通知 -Recently unlocked achievements = 最近達成した実績 -Reconnected to RetroAchievements. = RetroAchievementsに再接続しました。 -Register on www.retroachievements.org = www.retroachievements.orgで登録 -RetroAchievements are not available for this game = RetroAchievementsはこのゲームでは使用できません -RetroAchievements website = RetroAchievementsウェブサイト -Rich Presence = リッチプリゼンス -Save state loaded without achievement data = 実績データなしでセーブステートが読み込まれました -Save states not available in Hardcore Mode = チャレンジ・モードではセーブ・ステートを使用できません -Sound Effects = サウンドエフェクト -Statistics = 統計 -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = 実績データの同期中... -Test Mode = テストモード -This feature is not available in Hardcore Mode = この機能はチャレンジモードでは使用できません -This game has no achievements = このゲームは実績機能がありません -Top players = トッププレイヤー -Unlocked achievements = 達成していない実績 -Unofficial achievements = 非公式な実績 -Unsupported achievements = サポートしていない実績 - [Audio] Alternate speed volume = カスタム速度時のボリューム Audio backend = オーディオのバックエンド (再起動が必要) Audio Error = オーディオエラー -Audio file format not supported. Must be WAV. = オーディオファイル形式に対応していません。WAVである必要があります。 AudioBufferingForBluetooth = Bluetoothに適したバッファ (低遅延) Auto = 自動 Device = デバイス -Disabled = 無効 +Disabled = Disabled DSound (compatible) = DSound (互換性重視) Enable Sound = オーディオを有効にする Global volume = グローバルボリューム @@ -95,7 +36,6 @@ Calibrate Analog Stick = アナログスティックをキャリブレートす Calibrate = キャリブレート Calibrated = キャリブレーション\n(調整)された動作 Calibration = キャリブレーション -Circular low end radius = Circular low end radius Circular stick input = 環状スティック入力 Classic = クラシック Confine Mouse = ウィンドウ/表示領域内でマウスをトラップする @@ -108,10 +48,8 @@ Deadzone radius = デッドゾーンの半径 Disable D-Pad diagonals (4-way touch) = 十字キーの斜め入力を無効にする (4方向タッチ) Disable diagonal input = 斜め入力を無効にする Double tap = ダブルタップ -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = ジェスチャー操作を有効にする Enable standard shortcut keys = 標準のショートカットキーを有効にする -frames = frames Gesture = ジェスチャー Gesture mapping = ジェスチャー操作の設定をする Glowing borders = 点灯する枠線 @@ -140,7 +78,6 @@ OnScreen = 画面にタッチ用のコントローラを表示する Portrait = 縦 Portrait Reversed = 縦 (反転) PSP Action Buttons = PSPアクションボタン -Rapid fire interval = 速射間隔 Raw input = 現実の入力 Repeat mode = Repeat mode Reset to defaults = デフォルトに戻す @@ -149,7 +86,6 @@ Sensitivity (scale) = 反応感度 (比率) Sensitivity = 感度 Shape = ボタンの形 Show Touch Pause Menu Button = 一時停止ボタンを表示する -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = スワイプ Swipe sensitivity = スワイプの感度 Swipe smoothing = スワイプの滑らかさ @@ -230,7 +166,6 @@ Log Console = ログコンソール(&L) Memory View... = メモリビュー(&V)... More Settings... = 詳細設定(&M)... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = ノンバッファレンダリング (高速化)(&S) Off = オフ(&O) Open Chat = Open Chat @@ -269,10 +204,11 @@ Texture Filtering = テクスチャフィルタリング(&X) Texture Scaling = テクスチャスケーリング(&T) Use Lossless Video Codec (FFV1) = ロスレスビデオコーデックを使う (FFV1)(&U) Use output buffer for video = ビデオに出力バッファを使う +Vertex Cache = 頂点キャッシュ(&V) VSync = VSync(&Y) Vulkan = Vulkan Window Size = ウィンドウサイズ(&W) -www.ppsspp.org = www.&ppsspp.org を開く +www.ppsspp.org = www.&ppsspp.org に行く xBRZ = &xBRZ [Developer] @@ -282,14 +218,11 @@ Backspace = Backspace Block address = アドレスをブロックする By Address = アドレスで Copy savestates to memstick root = SaveStateをメモリースティックの直下にコピーする -Create frame dump = フレームダンプを作成 Create/Open textures.ini file for current game = 現在のゲームの textures.ini ファイルを作成する/開く Current = 現在 -Debug overlay = デバッグオーバーレイ -Debug stats = Debug stats Dev Tools = 開発用ツール DevMenu = 開発者用メニュー -Disabled JIT functionality = 無効化するJIT機能 +Disabled JIT functionality = 無効されたJIT機能 Draw Frametimes Graph = フレームタイムグラフを描く Dump Decrypted Eboot = 復号したEBOOT.BINを起動時にダンプする Dump next frame to log = 次のフレームをログにダンプする @@ -297,11 +230,8 @@ Enable driver bug workarounds = ドライバーバグの回避の有効化 Enable Logging = デバッグログを有効にする Enter address = アドレスを入力する FPU = FPU -Fragment = フラグメント -Frame timing = フレームタイミング Framedump tests = フレームダンプのテスト Frame Profiler = フレームプロファイラ -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPUドライバをテスト GPU Profile = GPUプロファイル GPU log profiler = GPUログプロファイラ @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = ドロップしたフレームの統計を記録 Log Level = ログレベル Log View = ログビュー Logging Channels = ログチャネル -Multi-threaded rendering = マルチスレッドレンダリング Next = 次へ No block = ブロックなし -Off = Off Prev = 前へ Random = ランダム Replace textures = テクスチャを置き換える @@ -332,27 +260,21 @@ Stats = 状況 System Information = システム情報 Texture ini file created = Texture ini file created Texture Replacement = テクスチャの置き換え -Audio Debug = オーディオのデバッグを切り替える -Control Debug = Control Debug +Toggle Audio Debug = オーディオのデバッグを切り替える +Toggle Control Debug = Toggle Control Debug Toggle Freeze = フリーズを切り替える Touchscreen Test = タッチスクリーンのテスト -Ubershaders = Ubershaders -Vertex = 頂点 VFPU = VFPU [Dialog] -%d seconds = %d 秒 +%d seconds = %d seconds * PSP res = * PSP 解像度 Active = アクティブ Back = 戻る -Bottom Center = 下中央 -Bottom Left = 左下 -Bottom Right = 右下 Cancel = キャンセル Center = センタリング -Center Left = 左中央 -Center Right = 右中央 -Changing this setting requires PPSSPP to restart. = この設定を変更するには、PPSSPPを再起動する必要があります。 +ChangingGPUBackends = GPUバックエンドの変更にはPPSSPPの再起動が必要です。今すぐ再起動しますか? +ChangingInflightFrames = グラフィックスコマンドのバッファリングを変更するにはPPSSPPの再起動が必要です。 再起動しますか? Channel: = Channel: Choose PPSSPP save folder = PPSSPPのセーブ用フォルダを選択する Confirm Overwrite = データを上書きしますか? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = 本当にこのゲームの設定を削除しますか DeleteFailed = データを削除できませんでした。 Deleting = 削除中です。\nしばらくお待ちください... Disable All = 全て無効にする -Disabled = Disabled Dumps = Dumps Edit = 編集 Enable All = 全て有効にする -Enabled = Enabled Enter = 決定 -Failed to connect to server, check your internet connection. = サーバーへの接続に失敗しました。インターネット接続を確認してください。 -Failed to log in, check your username and password. = ログインに失敗しました。ユーザー名とパスワードを確認してください。 Filter = Filter Finish = 終了 GE Frame Dumps = GE Frame Dumps Grid = グリッドのサイズ Inactive = 非アクティブ -Installing... = Installing... InternalError = 内部エラーが発生しました。 -Links = リンク Load = ロード... Load completed = ロードが完了しました。 Loading = ロード中です。\nしばらくお待ちください... LoadingFailed = データをロードできませんでした。 -Log in = ログイン -Log out = ログアウト -Logged in! = ログインしました! -Logging in... = ログイン中... Move = 移動 Move Down = 下へ移動 Move Up = 上へ移動 Network Connection = ネットワーク接続 NEW DATA = 新しいデータ No = いいえ -None = 無し ObtainingIP = IPアドレスの取得中。 \nしばらくお待ちください... OK = OK Old savedata detected = 古いセーブデータを検出しました Options = オプション -Password = パスワード Remove = 削除 Reset = リセット Resize = リサイズ -Restart = PPSSPPを再起動します。 Retry = リトライ Save = セーブ Save completed = セーブが完了しました。 @@ -420,7 +329,6 @@ SavingFailed = データをセーブできませんでした。 Search = 検索 seconds, 0:off = 秒, 0 = オフ Select = セレクト -Settings = 設定 Shift = シフト Skip = スキップ Snap = グリッドに吸着 @@ -431,11 +339,7 @@ Supported = サポートしています There is no data = データがありません。 Toggle All = 全て反転する Toggle List = 切り替えリスト -Top Center = 上中央 -Top Left = 左上 -Top Right = 右上 Unsupported = サポートしていません -Username = ユーザー名 When you save, it will load on a PSP, but not an older PPSSPP = 保存すると、PSPではロードできますが古いPPSSPPではロードできません When you save, it will not work on outdated PSP Firmware anymore = 保存すると、古いPSPファームウェアでは動作しなくなります Yes = はい @@ -478,7 +382,7 @@ Not a valid disc image. = 有効なディスクイメージではありません OpenGLDriverError = OpenGLドライバエラー PPSSPP doesn't support UMD Music. = PPSSPPはUMD Musicをサポートしていません PPSSPP doesn't support UMD Video. = PPSSPPはUMD Videoをサポートしていません -PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPPはPlayStation 1・2 のゲームではなく、PSPのゲームを起動します。 +PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPP plays PSP games, not PlayStation 1 or 2 games. PPSSPPDoesNotSupportInternet = PPSSPPは現在、DLC、PSN、ゲーム更新のためのインターネット接続をサポートしていません。 PS1 EBOOTs are not supported by PPSSPP. = PPSSPPはPS1のEBOOTをサポートしていません。 PSX game image detected. = MODE2のイメージファイルです。PPSSPPはPS1のゲームをサポートしていません。 @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = ファイルが圧縮されています (ZI [Game] Asia = アジア Calculate CRC = CRCを算出する -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = 削除 -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = ゲームの設定を作成する Create Shortcut = ショートカットを作成する Delete Game = ゲームを削除する Delete Game Config = ゲームの設定を削除する Delete Save Data = セーブデータを削除する Europe = ヨーロッパ -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = ゲーム -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = ゲームの設定 Homebrew = 自作 Hong Kong = 香港 InstallData = データのインストール -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = 日本 Korea = 韓国 MB = MB @@ -527,8 +426,6 @@ Remove From Recent = 履歴から削除する SaveData = セーブデータ Setting Background = 背景を設定 Show In Folder = フォルダに表示する -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = UIの背景を使う @@ -544,13 +441,13 @@ Use UI background = UIの背景を使う 3x = 3× 3x PSP = 3× PSP 4x = 4× -4x PSP = 4× PSP (1080p) +4x PSP = 4x PSP (1080p) 5x = 5× 5x PSP = 5× PSP 6x PSP = 6× PSP 7x PSP = 7× PSP 8x = 8× -8x PSP = 8× PSP (4K) +8x PSP = 8x PSP (4K) 9x PSP = 9× PSP 10x PSP = 10× PSP 16x = 16× @@ -623,9 +520,8 @@ Must Restart = この変更を適用するにはPPSSPPを再起動してくだ Native device resolution = 機器のネイティブ解像度 Nearest = Nearest No buffer = バッファなし -Render all frames = Render all frames Show Battery % = Show Battery % -Show Speed = 速度を表示する +Show Speed = Show Speed Skip Buffer Effects = ノンバッファレンダリング (高速化) None = なし Number of Frames = フレーム数 @@ -652,13 +548,12 @@ Software Rendering = ソフトウェアレンダリング (実験的) Software Skinning = ソフトウェアスキニング SoftwareSkinning Tip = スキンモデルの描画をCPUでまとめて行う。ほとんどのゲームが高速化します Speed = 速度 -Speed Hacks = スピードハック (不具合あり) +Speed Hacks = Speed Hacks (不具合あり) Stereo display shader = ステレオディスプレイシェーダー Stereo rendering = ステレオレンダリング Stretch = 拡大 Texture Filter = テクスチャフィルタ Texture Filtering = テクスチャフィルタリング -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = テクスチャスケーリング Texture Shader = テクスチャシェーダ Turn off Hardware Tessellation - unsupported = 「ハードウェアテッセレーション」をオフにしてください。サポートされていません @@ -669,6 +564,8 @@ Upscale Level = アップスケールのレベル Upscale Type = アップスケールのタイプ UpscaleLevel Tip = CPUに重い負荷 - カクつきを避けるためタイプによっては遅延するスケーリングがあるかもしれません Use all displays = 全てのディスプレイを使う +Vertex Cache = 頂点キャッシュ +VertexCache Tip = 高速ですがフリッカーが生じるかもしれません VSync = VSync Vulkan = Vulkan Window Size = ウィンドウサイズ @@ -685,12 +582,10 @@ Zip archive corrupt = ZIPアーカイブが破損しています Zip file does not contain PSP software = ZIPファイルにPSPソフトウェアが含まれていません [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = 自動設定 Autoconfigure for device = デバイスの自動設定 -Bind All = 全ての割り当てを行う +Bind All = 全てを割り当てする Clear All = 全てクリアする -Combo mappings are not enabled = Combo mappings are not enabled Default All = デフォルトに戻す Map a new key for = 新しいキーを入力 Map Key = キーの割り当て指定 @@ -747,7 +642,16 @@ Audio/Video Recording = オーディオ/ビデオの記録 AxisSwap = 軸の入れ替え Circle = 〇 Cross = ✕ -Custom %d = カスタム %d +Custom 1 = カスタム 1 +Custom 10 = カスタム 10 +Custom 2 = カスタム 2 +Custom 3 = カスタム 3 +Custom 4 = カスタム 4 +Custom 5 = カスタム 5 +Custom 6 = カスタム 6 +Custom 7 = カスタム 7 +Custom 8 = カスタム 8 +Custom 9 = カスタム 9 D-pad down = 十字キー 下 D-pad left = 十字キー 左 D-pad right = 十字キー 右 @@ -760,7 +664,6 @@ Display Landscape Reversed = 横表示[逆位置]に切り替え Double tap button = ダブルタップ時の設定 Down = 十字キー 下 Dpad = 十字キー -Exit App = Exit App Frame Advance = コマ送り Hold = ホールド Home = Homeボタン @@ -773,7 +676,6 @@ None = 設定なし Note = ♪ボタン OpenChat = チャットを開く Pause = 一時停止 -Previous Slot = 前のスロット R = R RapidFire = 連射 Record = Record @@ -785,8 +687,8 @@ RightAn.Down = 右アナログパッド 下 RightAn.Left = 右アナログパッド 左 RightAn.Right = 右アナログパッド 右 RightAn.Up = 右アナログパッド 上 -Rotate Analog (CCW) = アナログ回転 (反時計) -Rotate Analog (CW) = アナログ回転 (時計) +Rotate Analog (CCW) = アナログ回転 (CCW) +Rotate Analog (CW) = アナログ回転 (CW) Save State = ステートをセーブ Screen = スクリーン Screenshot = スクリーンショット @@ -803,7 +705,6 @@ Texture Dumping = テクスチャのダンプ Texture Replacement = テクスチャの置換 Toggle Fullscreen = フルスクリーンの切り替え Toggle mode = モードの切り替え -Toggle WLAN = WLANの切り替え Triangle = △ Fast-forward = 速度制限を解除 Up = 十字キー 上 @@ -816,6 +717,11 @@ AdHoc Server = アドホックサーバ AdhocServer Failed to Bind Port = アドホックサーバーがポートのバインドに失敗しました AM: Data from Unknown Port = AM: 不明なポートからのデータ Auto = 自動 +Bottom Center = 下中央 +Bottom Left = 左下 +Bottom Right = 右下 +Center Left = 左中央 +Center Right = 右中央 Change Mac Address = MACアドレスを変更する Change proAdhocServer Address = PROアドホックサーバのIPアドレスを変更する (localhost = multiple instances) ChangeMacSaveConfirm = 新しいMACアドレスを生成しますか? @@ -849,6 +755,7 @@ Invalid IP or hostname = 無効なIPまたはホスト名 Minimum Timeout = 最小タイムアウト (低遅延をオーバーライド、単位ms) Misc = その他 (デフォルト = PSP互換) Network Initialized = ネットワークを初期化 +None = 無し Please change your Port Offset = ポートオフセットを変更してください Port offset = ポートオフセット (0 = PSP互換) Open PPSSPP Multiplayer Wiki Page = PPSSPPのアドホック接続Wikiページを開く (英語) @@ -859,35 +766,20 @@ Quick Chat 3 = クイックチャット3 Quick Chat 4 = クイックチャット4 Quick Chat 5 = クイックチャット5 QuickChat = クイックチャット -Randomize = Randomize Send = 送信する Send Discord Presence information = Discordのプレゼンス情報を送信する +Top Center = 上中央 +Top Left = 左上 +Top Right = 右上 Unable to find UPnP device = UPnPデバイスがみつかりません UPnP (port-forwarding) = UPnP(ポートフォワーディング) UPnP need to be reinitialized = UPnPの再初期化が必要です UPnP use original port = UPnPでオリジナルのポートを使用する (有効 = PSP互換) -UseOriginalPort Tip = デバイスやゲームによっては動作しない場合がありますので、wikiを参照してください。 +UseOriginalPort Tip = May not work for all devices or games, see wiki. Validating address... = アドレスを検証しています... WLAN Channel = WLANチャネル You're in Offline Mode, go to lobby or online hall = オフラインモードです。ロビーかホールに移動してください -[PSPSettings] -Auto = 自動 -Chinese (simplified) = 中国語(簡体字) -Chinese (traditional) = 中国語(繁体字) -Dutch = オランダ語 -English = 英語 -French = フランス語 -Game language = ゲームの言語 -German = ドイツ語 -Italian = イタリア語 -Japanese = 日本語 -Korean = 韓国語 -Games often don't support all languages = ゲームはすべての言語に対応していないことが多いです -Portuguese = ポルトガル語 -Russian = ロシア語 -Spanish = スペイン語 - [Pause] Cheats = チート Continue = 再開する @@ -900,7 +792,7 @@ Rewind = 巻き戻す Save State = ステートをセーブする Settings = 設定 Switch UMD = UMDを交換する -Undo last load = ロードを取り消す +Undo last load = Undo last load Undo last save = セーブ内容を戻す [PostShaders] @@ -914,7 +806,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -922,7 +813,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -943,7 +833,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = Video Smoothing AA Vignette = Vignette @@ -974,7 +863,7 @@ specialthanksMaxim = (素晴らしいAtrac3+デコーダ) testing = 動作テスト this translation by = 翻訳者: title = 高速で移植性のあるPSPエミュレータ -tools = 使用されているフリーツール: +tools = 使用したフリーツール: # PPSSPPの翻訳者や翻訳への貢献者をここに追加してください。 # 翻訳者のクレジットは6行までです。 # 余った行は空白のままにしてください。1行に4人記載するのがベストのようです。 @@ -990,13 +879,12 @@ written = 速度と移植性を保つためにC++で書かれています [MemStick] Already contains PSP data = 既にPSPデータが存在しています。 -Cancelled - try again = Cancelled - try again Current = 現在の -DataWillStay = データはPPSSPPをアンインストールしても残ります。 -DataCanBeShared = 通常版/ゴールド間でのデータの共有が可能です。 -DataCannotBeShared = 通常版/ゴールド間でのデータの共有は「できません」。 +DataWillStay = 保存データはPPSSPPをアンインストールしても残る。 +DataCanBeShared = 通常版/ゴールド間でのデータの共有が可能。 +DataCannotBeShared = 通常版/ゴールド間でのデータの共有が「できない」。 Done! = 完了! -EasyUSBAccess = PCとのUSB接続でフォルダにアクセスが簡単にできます。 +EasyUSBAccess = PCとのUSB接続でフォルダにアクセスが簡単にできる。 Failed to move some files! = いくつかのファイルの移動に失敗しました! Failed to save config = セーブコンフィグに失敗しました! Free space = 空き容量 @@ -1086,11 +974,11 @@ Date = 日付 Filename = ファイル名 No screenshot = スクリーンショットなし None yet. Things will appear here after you save. = まだありません。セーブ後に項目が表示されます。 -Nothing matching '%1' was found. = '%1'と一致するものは見つかりませんでした。 +Nothing matching '%1' was found. = Nothing matching '%1' was found. Save Data = セーブデータ Save States = セーブステート Savedata Manager = セーブデータを管理する -Showing matches for '%1'. = '%1'で見つかったものを表示します。 +Showing matches for '%1'. = Showing matches for '%1'. Size = サイズ [Screen] @@ -1142,8 +1030,8 @@ Uninstall = アンインストールする [SysInfo] %0.2f Hz = %0.2f Hz -%d (%d per core, %d cores) = %d (1コアあたり %dつ, コア数 %d) -%d bytes = %dバイト +%d (%d per core, %d cores) = %d (1コアあたり %d, コア数 %d) +%d bytes = %d bytes %d Hz = %d Hz (none detected) = (未検出) 3D API = 3D API @@ -1154,7 +1042,7 @@ Board = Board Build Config = ビルド設定 Build Configuration = ビルド設定 Built by = ビルド作成者 -Compressed texture formats = 圧縮テクスチャフォーマット +Compressed texture formats = Compressed texture formats Core Context = コアコンテキスト Cores = コア数 CPU Extensions = CPU拡張 @@ -1163,13 +1051,13 @@ CPU Name = CPU名 D3DCompiler Version = D3DCompilerバージョン Debug = デバッグ Debugger Present = デバッガーあり -Depth buffer format = デプスバッファ形式 +Depth buffer format = Depth buffer format Device Info = デバイス情報 Directories = ディレクトリ Display Color Formats = Display Color Formats Display Information = ディスプレイ情報 DPI = DPI -Driver bugs = ドライバーバグ +Driver bugs = Driver bugs Driver Version = ドライバのバージョン EGL Extensions = EGL拡張 Frames per buffer = バッファあたりのフレーム数 @@ -1177,12 +1065,11 @@ GPU Flags = GPU Flags GPU Information = GPU情報 High precision float range = 高精度浮動小数点の範囲 High precision int range = 高精度整数の範囲 -Icon cache = Icon cache JIT available = JIT available Lang/Region = 言語/地域 Memory Page Size = メモリページサイズ -Native resolution = ネイティブ解像度 -No GPU driver bugs detected = GPUドライバーのバグは検出されませんでした +Native Resolution = ネイティブ解像度 +No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL拡張 OpenGL ES 2.0 Extensions = OpenGL ES 2.0拡張 OpenGL ES 3.0 Extensions = OpenGL ES 3.0拡張 @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL拡張 Optimal frames per buffer = バッファあたりの最適フレーム Optimal sample rate = 最適サンプルレート OS Information = OS情報 -Pixel resolution = ピクセル解像度 PPSSPP build = PPSSPPビルド -Present modes = Presentモード Refresh rate = リフレッシュレート Release = リリース RW/RX exclusive = RW/RX専用 @@ -1204,7 +1089,7 @@ System Information = システム情報 System Name = システム名 System Version = システムバージョン Threads = スレッド数 -UI resolution = UI解像度 +UI Resolution = UI Resolution Vendor = ベンダ Vendor (detected) = ベンダ (検出されたもの) Version Information = バージョン情報 @@ -1276,18 +1161,17 @@ No animation = アニメーションなし Not a PSP game = PSPのゲームではありません Off = オフ Oldest Save = 最も古いセーブ -Path does not exist! = パスが存在しません +Path does not exist! = Path does not exist! PSP Memory Stick = メモリースティックの設定 PSP Model = PSPのモデル PSP Settings = PSPの設定 PSP-1000 = PSP-1000 PSP-2000/3000 = PSP-2000/3000 -Recent games = Recent games +Recent games = プレイ履歴のスライド Record Audio = オーディオを記録する Record Display = 画面を記録する Reset Recording on Save/Load State = ステートをセーブ/ロードしたら記録をリセットする Restore Default Settings = 設定をデフォルトに戻す -RetroAchievements = RetroAchievements Rewind Snapshot Interval = スナップショットの巻き戻し頻度 (メモリを消費) Save path in installed.txt = パスを installed.txt に保存する Save path in My Documents = パスを My Documents に保存する @@ -1300,7 +1184,6 @@ Show ID = IDを表示する Show region flag = 地域の旗を表示する Show Memory Stick folder = メモリスティックフォルダーの場所を開く Simulate UMD delays = UMDの遅延をシミュレートする -Simulate UMD slow reading speed = UMDの低速な読込速度をシミュレートする Slot 1 = スロット1 Slot 2 = スロット2 Slot 3 = スロット3 @@ -1334,7 +1217,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] -Dark = ダーク +Dark = Dark Default = デフォルト [UI Elements] @@ -1349,17 +1232,18 @@ List: = List: Progress: %1% = Progress: %1% Screen representation = Screen representation [Upgrade] -Details = 詳細 +Details = Details Dismiss = 無視 Download = ダウンロード New version of PPSSPP available = 新しいバージョンのPPSSPPを利用できます [VR] +% of native FoV = ネイティブ視野角(FoV)の % 6DoF movement = 6DoF動作 Camera type = Camera type Distance to 2D menus and scenes = 2Dメニューと空間までの距離 -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = 視野角のスケール Force 72Hz update = 72Hzに強制的に更新 Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 63c7ea4fd..ded6fee0c 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Suoro backend (Wiwiti maneh, req) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Otomatis Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibrasi Calibrated = Calibrated Calibration = Kalibrasi -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasik Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Radius deadzone Disable D-Pad diagonals (4-way touch) = Mateni D-Pad diagonals (4-cara tutul) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Tombol Layar-sentuh Portrait = Portret Portrait Reversed = Potret kebalik PSP Action Buttons = PSP Aksi tombol -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitiv Shape = Shape Show Touch Pause Menu Button = Deleng tombol menu ngaso -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Konsol Log Memory View... = Tampilan &Memory... More Settings... = Setelan sing luwih ... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = Skip efek buffer (ora yakuwi,luwih cepet) Off = &Mati Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Tektur Nyaring Texture Scaling = Tektur njongko Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Penyimpenan Vertex VSync = VS&ync Vulkan = Vulkan Window Size = &Ukuran Window @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Alamat pemblokiran By Address = Dening Alamat Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Saiki -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Ngatifke ngangkut barang Enter address = Ketik alamat FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Pigura Profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Tingkat Log Log View = Tampilan Log Logging Channels = Saluran ngangkut barang -Multi-threaded rendering = Multi-threaded rendering Next = Sabanjure No block = Ora pemblokiran -Off = Off Prev = Sadurunge Random = Acak Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Informasi Sistem Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Debug Suoro -Control Debug = Control Debug +Toggle Audio Debug = Pilian Debug Suoro +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Pilian Beku Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Bali -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Mbatalake Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Ganti backends GPU mbutuhake PPSSPP kanggo miwiti maneh. Wiwiti maneh saiki? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Peleh folder penyimpenan PPSSPP Confirm Overwrite = Njenengan arep Panganggoan data iki? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Yakin arep mbusek setelan kanggo dolanan iki? DeleteFailed = ora dapat mbusek data. Deleting = Mbusek\nMohon nteni... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Ketik -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Rampung GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Mbukak Load completed = Mbukak rampung. Loading = Mbukak\nMohon nteni... LoadingFailed = Ora biso mbukak data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Pindahno Move Down = Move Down Move Up = Move Up Network Connection = Koneksi Jaringan NEW DATA = DATA ANYAR No = Ora -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = He.eh Old savedata detected = Simpenan lawas terdeteksi Options = Opsi -Password = Password Remove = Remove Reset = Ngreset Resize = Ubah Ukuran -Restart = Restart Retry = Jajal Maning Save = Simpen Save completed = Nyimpen rampung. @@ -420,7 +329,6 @@ SavingFailed = Ora biso Nyimpen data. Search = Search seconds, 0:off = detik, 0 = off Select = Peleh -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Ora ana data. Toggle All = Peleh kabeh Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Nalika nyimpen, iku bakal mbukak ing PSP,nanging ora PPSSPP lawas When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = He.eh @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = berkas iki terkompres (ZIP).\nMohon bongkar [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Mbusek -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Nggawe Setelan Dolanan Create Shortcut = Nggawe Trobosan Delete Game = Mbusek Dolanan Delete Game Config = Mbusek Setelan Dolanan Delete Save Data = Mbusek Simpenan Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Dolanan -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Setelan Dolanan Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Nginstal data -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Mbusek soko "Terakher" SaveData = Simpen Data Setting Background = Setting background Show In Folder = Tampilno Nang Folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = Wiwiti maneh PPSSPP kanggo aplikasi setelan. Native device resolution = Resolusi piranti asal Nearest = Cedhak No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip efek buffer (non-yakuwi,luwih cepet) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Penyaring Tekstur Texture Filtering = Penyaring Tekstur -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Skala Tekstur Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Tingkatan Penaikan-skala Upscale Type = Jenis Penaikan-skala UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Penyimpenan Vertex +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Ukuran window @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Konfigurasi otomatis Autoconfigure for device = Konfigurasi otomatis kanggo piranti Bind All = Bind All Clear All = Ilangi kabeh -Combo mappings are not enabled = Combo mappings are not enabled Default All = Gawan kabeh Map a new key for = Petakan tombol anyar Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Ngisor Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Ngaso -Previous Slot = Previous Slot R = R RapidFire = RapidFire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Nduwur @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Ubah alamat MAC Change proAdhocServer Address = Ubah alamat pelayan IP PRO ad hoc (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Jaringan diinisiasi +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Mbeling Continue = Terusno @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Kartun CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Mulihake setelan PPSSPP kanggo gawan -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Frekuensi gambar asli seko mundur (mem hog) Save path in installed.txt = Nyimpen path ing installed.txt Save path in My Documents = Nyimpen path ing Dokumen kulo @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulasi UMD telat -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Unduh New version of PPSSPP available = Versi anyar PPSSPP mpun ono monggo di comot [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index b5aa3664c..25d6b9c75 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1,65 +1,6 @@ -[Achievements] -%1 achievements, %2 points = %1 성과, %2 포인트 -%1: Attempt started = %1: 순위표 시도 시작 -%1: Attempt failed = %1: 순위표 시도 실패 -Account = 계정 -Achievement unlocked = 성과 잠금 해제 -Achievement progress = 성과 진행률 -Achievements = 성과 -Achievements enabled = 성과 활성화 -Achievements are disabled = 성과 비활성화 -Achievements with active challenges = 도전 과제가 활성화된 성과 -Allow Save State in Hardcore Mode (but not Load State) = 하드코어 모드에서 상태 저장 허용 (로드 상태는 아님) -Almost completed achievements = 거의 완료된 성과 -Can't log in to RetroAchievements right now = 지금 RetroAchievements에 로그인할 수 없음 -Challenge indicator = 도전 표시기 -Contacting RetroAchievements server... = RetroAchievements 서버에 연결 중... -Customize = 맞춤 설정 -Earned = %1 의 %2 성과 및 %3 의 %4 포인트 획득 -Encore Mode = 앙코르 모드 -Failed logging in to RetroAchievements = RetroAchievements에 로그인 실패 -Failed to connect to RetroAchievements. Achievements will not unlock. = RetroAchievements에 연결하지 못했습니다. 성과가 잠금 해제되지 않습니다. -Failed to identify game. Achievements will not unlock. = 게임을 식별하지 못했습니다. 성과가 잠금 해제되지 않습니다. -Hardcore Mode (no savestates) = 도전 모드 (저장 상태 없음) -Hardcore Mode = 도전 모드 -How to use RetroAchievements = RetroAchievements 사용 방법 -In Encore mode - listings may be wrong below = 앙코르 모드 - 아래 목록이 잘못 표시될 수 있음 -Leaderboard attempt started or failed = 순위표 시도 시작 또는 실패 -Leaderboard result submitted = 순위표 결과 제출 -Leaderboard score submission = 순위표 점수 제출 -Leaderboard submission is enabled = 순위표 제출 활성화 -Leaderboards = 순위표 -Leaderboard tracker = 순위표 추적기 -Links = 링크 -Locked achievements = 잠겨진 성과 -Log bad memory accesses = 불량 메모리 접속 로그 -Mastered %1 = 마스터한 %1 -Around me = 내 주변 -Notifications = 알림 -Recently unlocked achievements = 최근 잠금 해제된 성과 -Reconnected to RetroAchievements. = RetroAchievements에 다시 연결되었습니다. -Register on www.retroachievements.org = www.retroachievements.org에 등록 -RetroAchievements are not available for this game = 이 게임에서는 RetroAchievements 사용할 수 없음 -RetroAchievements website = RetroAchievements 웹사이트 -Rich Presence = 활동 상태 -Save state loaded without achievement data = 성과 데이터 없이 로드된 상태 저장 -Save states not available in Hardcore Mode = 도전 모드에서 사용할 수 없는 저장 상태 -Sound Effects = 사운드 효과 -Statistics = 통계 -Submitted %1 for %2 = 2에 %1을(를) 제출함 -Syncing achievements data... = 성과 데이터 동기화 중... -Test Mode = 테스트 모드 -This feature is not available in Hardcore Mode = 도전 모드에서는 이 기능을 사용할 수 없음 -This game has no achievements = 이 게임에는 성과가 없음 -Top players = 상위 플레이어 -Unlocked achievements = 잠금 해제된 성과 -Unsupported achievements = 지원되지 않는 성과 -Unofficial achievements = 비공식 성과 - [Audio] Alternate speed volume = 대체 속도 볼륨 Audio backend = 오디오 백엔드 (재시작 요구) -Audio file format not supported. Must be WAV. = 오디오 파일 형식은 지원되지 않습니다. WAV여야 합니다. Audio Error = 오디오 오류 AudioBufferingForBluetooth = 블루투스 친화적 버퍼 (느림) Auto = 자동 @@ -95,7 +36,6 @@ Calibrate Analog Stick = 아날로그 스틱 보정 Calibrate = 보정 Calibrated = 보정됨 Calibration = 교정 -Circular low end radius = 원형 하단 반경 Circular stick input = 원형 스틱 입력 Classic = 클래식 Confine Mouse = 창/표시 영역 내에서 마우스 트랩 @@ -108,10 +48,8 @@ Deadzone radius = 데드존 반경 Disable D-Pad diagonals (4-way touch) = 십자 패드 대각선 비활성화 (4 방향 터치) Disable diagonal input = 대각선 입력 비활성화 Double tap = 두 번 탭 -Enable analog stick gesture = 아날로그 스틱 제스처 사용 Enable gesture control = 제스처 제어 활성화 Enable standard shortcut keys = 표준 단축키 활성화 -frames = 프레임 Gesture = 제스처 Gesture mapping = 제스처 맵핑 Glowing borders = 광선 테두리 @@ -140,7 +78,6 @@ OnScreen = 화면 터치 제어 Portrait = 세로 방향 Portrait Reversed = 세로 방향 반전 PSP Action Buttons = PSP 액션 버튼 -Rapid fire interval = 연사 간격 Raw input = 원시 입력 Reset to defaults = 기본값으로 재설정 Screen Rotation = 화면 회전 @@ -148,7 +85,6 @@ Sensitivity = 감도 Sensitivity (scale) = 감도 (스케일) Shape = 모양 Show Touch Pause Menu Button = 일시중지 메뉴 버튼 표시 -Sticky D-Pad (easier sweeping movements) = 스티커형 십자 패드(더 쉬운 밀기 동작) Swipe = 밀기 Swipe sensitivity = 밀기 감도 Swipe smoothing = 밀기 스무딩 @@ -157,7 +93,7 @@ Tilt control setup = 기울기 제어 설정... Tilt Input Type = 기울기 입력 유형 Tilt Sensitivity along X axis = X 축 기울기 감도 Tilt Sensitivity along Y axis = Y 축 기울기 감도 -To Calibrate = 원하는 각도로 장치를 잡고 "보정"을 누르세요. +To Calibrate = 원하는 각도로 장치를 잡고 "보정"을 누르십시오. Toggle mode = 토글 모드 Repeat mode = 반복 모드 Touch Control Visibility = 터치 제어 가시성 @@ -184,7 +120,7 @@ Auto = 자동(&A) Auto Max Quality = 자동 최대 품질(&Q) Backend = 렌더링 백엔드(&B) (PPSSPP 재시작) Bicubic = 고등차수(&B) -Break = 중단 +Break = 증딘 Break on Load = 불러오기 시 중단 Buy Gold = 골드 버전 구매(&G) Control Mapping... = 제어 맵핑(&O)... @@ -230,7 +166,7 @@ Log Console = 콘솔 로그(&L) Memory View... = 메모리 보기(&V)... More Settings... = 기타 설정(&M)... Nearest = 근접 필터링(&N) -Skip Buffer Effects = 버퍼 효과 건너뛰기(&S) +Skip Buffer Effects = 버퍼 효과 건너뛰기(버퍼되지 않음, 더 빠름)(&S) Off = 끔(&O) Open Chat = 채팅 열기 Open Directory... = 디렉터리 열기(&D)... @@ -243,7 +179,7 @@ Pause When Not Focused = 포커싱되지 않았을 때 일시 정지(&P) Portrait = 세로 방향 Portrait reversed = 세로 방향 반전 PPSSPP Forums = PPSSPP 포럼(&F) -Recent = 최근(&R) +Recent = 최근(&R) Record = 녹음(&R) Record Audio = 사운드 녹음(&A) Record Display = 영상 녹화(&D) @@ -269,6 +205,7 @@ Texture Filtering = 텍스처 필터링(&X) Texture Scaling = 텍스처 크기 조절(&T) Use Lossless Video Codec (FFV1) = 무손실 비디오 코덱 사용 (FFV1)(&U) Use output buffer for video = 비디오에 출력 버퍼 사용 +Vertex Cache = 정점 캐시(&V) VSync = 수직 동기화(&Y) Vulkan = Vulkan Window Size = 창 크기(&W) @@ -278,17 +215,12 @@ xBRZ = xBRZ 필터(&X) [Developer] Allocator Viewer = 할당기 뷰어 (Vulkan) Allow remote debugger = 원격 디버거 허용 -Audio Debug = 오디오 디버그 Backspace = 백스페이스 Block address = 주소 차단 By Address = 주소별 -Control Debug = 디버그 제어 Copy savestates to memstick root = 메모리 스틱 루트에 저장 상태 복사 -Create frame dump = 프레임 덤프 생성 Create/Open textures.ini file for current game = 현재 게임에 대한 textures.ini 파일 생성/열기 Current = 현재 -Debug overlay = 디버그 오버레이 -Debug stats = 디버그 통계 Dev Tools = 개발 도구 DevMenu = 개발메뉴 Disabled JIT functionality = 비활성화된 JIT 기능 @@ -298,12 +230,9 @@ Dump next frame to log = 다음 프레임을 로그로 덤프 Enable driver bug workarounds = 드라이버 버그 해결 방법 활성화 Enable Logging = 디버그 로깅 활성화 Enter address = 주소 입력 -Fragment = 단편 FPU = FPU Framedump tests = 프레임 덤프 테스트 Frame Profiler = 프레임 프로파일러 -Frame timing = 프레임 타이밍 -GPU Allocator Viewer = GPU 할당기 뷰어 GPU Driver Test = GPU 드라이버 테스트 GPU Profile = GPU 프로파일 GPU log profiler = GPU 로그 프로파일러 @@ -313,10 +242,8 @@ Log Dropped Frame Statistics = 삭제된 프레임 통계 기록 Log Level = 로그 레벨 Log View = 로그 보기 Logging Channels = 로깅 채널 -Multi-threaded rendering = 다중 스레드 렌더링 Next = 다음 No block = 차단 없음 -Off = 끔 Prev = 이전 Random = 랜덤 Replace textures = 텍스처 교체 @@ -334,10 +261,10 @@ Stats = 상태 System Information = 시스템 정보 Texture ini file created = 텍스처 ini 파일 생성 Texture Replacement = 텍스쳐 교체 +Toggle Audio Debug = 오디오 디버그 토글 +Toggle Control Debug = 제어 디버그 토글 Toggle Freeze = 프리징 토글 Touchscreen Test = 터치화면 테스트 -Ubershaders = 우버셰이더 -Vertex = 꼭짓점 VFPU = VFPU [Dialog] @@ -345,22 +272,18 @@ VFPU = VFPU * PSP res = * PSP 리소스 Active = 활성화 Back = 뒤로가기 -Bottom Center = 하단 중앙 -Bottom Left = 하단 왼쪽 -Bottom Right = 하단 오른쪽 Cancel = 취소 Center = 중앙 -Center Left = 중앙 왼쪽 -Center Right = 중앙 오른쪽 +ChangingGPUBackends = GPU 백엔드를 변경하려면 PPSSPP를 다시 시작해야 합니다. 지금 다시 시작하겠습니까? +ChangingInflightFrames = 그래픽 명령 버퍼링을 변경하려면 PPSSPP를 다시 시작해야 합니다. 지금 다시 시작하겠습니까? Channel: = 채널: -Changing this setting requires PPSSPP to restart. = 이 설정을 변경하려면 PPSSPP를 다시 시작해야 합니다. Choose PPSSPP save folder = PPSSPP 저장 폴더 선택 Confirm Overwrite = 데이터를 덮어쓰겠습니까? Confirm Save = 이 데이터를 저장할까요? ConfirmLoad = 이 데이터를 불러오겠습니까? ConnectingAP = 접속 포인트에 연결하는 중입니다.\n잠시만 기다려 주세요... ConnectingPleaseWait = 연결 중입니다.\n잠시만 기다려 주세요... -ConnectionName = 연결 이름 +ConnectionName = 결 이름 Corrupted Data = 손상된 데이터 Delete = 삭제 Delete all = 모두 삭제 @@ -372,46 +295,33 @@ DeleteConfirmGameConfig = 이 게임의 설정을 삭제할까요? DeleteFailed = 데이터를 삭제할 수 없습니다. Deleting = 삭제 중\n잠시만 기다려 주세요... Disable All = 모두 비활성화 -Disabled = 비활성화 Dumps = 덤프 Edit = 편집 Enable All = 모두 활성화 -Enabled = 활성화 Enter = 입력 -Failed to log in, check your username and password. = 로그인에 실패했습니다. 사용자 이름과 비밀번호를 확인하세요. -Failed to connect to server, check your internet connection. = 서버에 연결하지 못했습니다. 인터넷 연결을 확인하세요. Filter = 필터 Finish = 마침 GE Frame Dumps = GE 프레임 덤프 Grid = 그리드 Inactive = 비활성 -Installing... = 설치 중... InternalError = 내부 오류가 발생했습니다. -Links = 링크 Load = 불러오기 Load completed = 불러오기가 완료되었습니다. Loading = 불러오기 중\n잠시만 기다려 주세요... LoadingFailed = 데이터를 불러올 수 없습니다. -Log in = 로그인 -Log out = 로그아웃 -Logging in... = 로그인 중... -Logged in! = 로그인했습니다! Move = 이동 Move Up = 위로 이동 Move Down = 아래로 이동 Network Connection = 네트워크 연결 NEW DATA = 새로운 데이터 No = 아니오 -None = 없음 ObtainingIP = IP 주소를 가져오는 중입니다.\n잠시만 기다려 주세요... OK = 확인 Old savedata detected = 오래된 저장 데이터 감지됨 Options = 옵션 -Password = 비밀번호 Remove = 제거 Reset = 재설정 Resize = 크기 조정 -Restart = PPSSPP를 다시 시작합니다. Retry = 재시도 Save = 저장 Save completed = 저장이 완료되었습니다. @@ -420,7 +330,6 @@ SavingFailed = 데이터를 저장할 수 없습니다. Search = 검색 seconds, 0:off = 초, 0 = 끔 Select = 선택 -Settings = 설정 Shift = 전환 Skip = 건너뜀 Snap = 스냅 @@ -431,11 +340,7 @@ Supported = 지원 There is no data = 데이터가 없습니다. Toggle All = 모두 토글 Toggle List = 토글 목록 -Top Center = 상단 중앙 -Top Left = 상단 왼쪽 -Top Right = 상단 오른쪽 Unsupported = 미지원 -Username = 사용자이름 When you save, it will load on a PSP, but not an older PPSSPP = 저장하면 PSP에 불러오지만 이전 PPSSPP에는 부러오지 않습니다. When you save, it will not work on outdated PSP Firmware anymore = 저장하면 오래된 PSP 펌웨어에서는 더 이상 작동하지 않습니다. Yes = 예 @@ -497,27 +402,21 @@ Warning: Video memory FULL, reducing upscaling and switching to slow caching mod Warning: Video memory FULL, switching to slow caching mode = 비디오 메모리가 가득 찼서, 저속 캐싱 모드로 전환합니다. ZIP file detected (Require UnRAR) = 파일은 (ZIP으로) 압축되어 있습니다.\n먼저 압축을 해제하세요 (UnRAR 시도). ZIP file detected (Require WINRAR) = 파일은 (ZIP으로) 압축되어 있습니다.\n먼저 압축을 해제하세요 (WinRAR 시도). - [Game] Asia = 아시아 Calculate CRC = CRC 계산 -Click "Calculate CRC" to verify ISO = ISO를 확인하려면 "CRC 계산"을 클릭 ConfirmDelete = 삭제 -CRC checksum does not match, bad or modified ISO = CRC 체크섬이 일치하지 않거나, ISO가 잘못되었거나 수정 Create Game Config = 게임 구성 생성 Create Shortcut = 단축 키 생성 Delete Game = 게임 삭제 Delete Game Config = 게임 구성 삭제 Delete Save Data = 저장데이터 삭제 Europe = 유럽 -File size incorrect, bad or modified ISO = 파일 크기가 잘못되었거나 잘못되었거나, 수정된 ISO Game = 게임 -Game ID unknown - not in the ReDump database = 게임 ID를 알 수 없음 - ReDump 데이터베이스에 없음 Game Settings = 게임 설정 Homebrew = 홈브류 Hong Kong = 홍콩 InstallData = 데이터 설치 -ISO OK according to the ReDump project = ReDump 프로젝트에 따라 ISO 확인 Japan = 일본 Korea = 한국 MB = 메가바이트 @@ -527,11 +426,8 @@ Remove From Recent = "최근"에서 제거 SaveData = 저장데이터 Setting Background = 배경 설정 Show In Folder = 폴더에 표기 -Time Played: %1h %2m %3s = 플레이 시간: %1h %2m %3s -Uncompressed = 비압축 USA = 미국 Use UI background = UI 배경 사용 - [Graphics] % of the void = 공백의 % % of viewport = 뷰포트의 % @@ -636,7 +532,6 @@ Percent of FPS = FPS 비율 Performance = 성능 Postprocessing shaders = 후처리 쉐이더 Recreate Activity = 활동 재생성 -Render all frames = 모든 프레임 렌더링 Render duplicate frames to 60hz = 중복 프레임을 60Hz로 렌더링 RenderDuplicateFrames Tip = 낮은 프레임 속도에서 실행되는 게임에서 프레임 속도를 더 부드럽게 만들 수 있습니다. Rendering Mode = 렌더링 모드 @@ -658,7 +553,6 @@ Stereo rendering = 스트레오 렌더링 Stretch = 늘이기 Texture Filter = 텍스처 필터링 Texture Filtering = 텍스처 필터링 -Texture replacement pack activated = 텍스처 교체 팩 활성화 Texture Scaling = 텍스처 스케일링 Texture Shader = 텍스처 쉐이더 Turn off Hardware Tessellation - unsupported = "하드웨어 조각화" 끄기: 지원되지 않음 @@ -669,11 +563,12 @@ Upscale Level = 업스케일 레벨 Upscale Type = 업스케일 유형 UpscaleLevel Tip = CPU 사용률 높음 - 버벅거림을 방지하기 위해 일부 확장이 지연될 수 있음 Use all displays = 모든 화면 사용 +Vertex Cache = 정점 캐시 +VertexCache Tip = 더 빠르지만 일시적인 깜박임이 발생할 수 있습니다. VSync = 수직 동기화 Vulkan = Vulkan Window Size = 창 크기 -xBRZ = xBRZ - +xBRZ = xBRZ 필터 [InstallZip] Delete ZIP file = ZIP 파일 삭제 Install = 설치 @@ -685,12 +580,10 @@ Zip archive corrupt = ZIP 아카이브가 손상되었습니다. Zip file does not contain PSP software = ZIP 파일에 PSP 소프트웨어가 포함되어 있지 않음 [KeyMapping] -Allow combo mappings = 콤보 매핑 허용 Autoconfigure = 자동 구성 Autoconfigure for device = 장치 자동 구성 Bind All = 모두 바인딩 Clear All = 모두 지움 -Combo mappings are not enabled = 콤보 매핑이 활성화되지 않음 Default All = 기본값 복원 Map a new key for = 새로운 키 입력 Map Key = 키 매핑 @@ -723,7 +616,6 @@ SavesAreTemporaryIgnore = 경고 무시 UnpinPath = 고정 해제 UseBrowseOrLoad = 찾아보기를 사용하여 폴더를 선택하거나 불러오기를 사용하여 파일을 선택합니다. www.ppsspp.org = www.ppsspp.org - [MainSettings] Audio = 오디오 Controls = 조작 @@ -732,7 +624,6 @@ Networking = 네트워킹 System = 시스템 Tools = 도구 Search = 검색 - [MappableControls] Alt speed 1 = 대체 속도 1 Alt speed 2 = 대체 속도 2 @@ -747,7 +638,16 @@ Audio/Video Recording = 오디오/비디오 녹화 AxisSwap = 축 교체 Circle = 동그라미 Cross = 십자 -Custom %d = 커스텀 %d +Custom 1 = 커스텀 1 +Custom 2 = 커스텀 2 +Custom 3 = 커스텀 3 +Custom 4 = 커스텀 4 +Custom 5 = 커스텀 5 +Custom 6 = 커스텀 6 +Custom 7 = 커스텀 7 +Custom 8 = 커스텀 8 +Custom 9 = 커스텀 9 +Custom 10 = 커스텀 10 D-pad down = 십자 패드 아래쪽 D-pad left = 십자 패드 왼쪽 D-pad right = 십자 패드 오른쪽 @@ -756,7 +656,6 @@ DevMenu = 개발메뉴 Double tap button = 두 번 탭 버튼 Down = 십자 패드 아래쪽 Dpad = 십자 패드 -Exit App = App 종료 Frame Advance = 프레임 어드밴스 Hold = 잠금 Home = 홈 @@ -769,7 +668,6 @@ None = 없음 Note = 참고 OpenChat = 채팅 열기 Pause = 일시 정지 -Previous Slot = 이전 슬롯 R = R RapidFire = 연사 Record = 녹화 @@ -781,8 +679,8 @@ RightAn.Down = 우측 아날로그 아래쪽 RightAn.Left = 우측 아날로그 왼쪽 RightAn.Right = 우측 아날로그 오른쪽 RightAn.Up = 우측 아날로그 위쪽 -Rotate Analog (CCW) = 아날로그 회전 (반시계방향) -Rotate Analog (CW) = 아날로그 회전 (시계방향) +Rotate Analog (CCW) = 아날로그 회전 (CCW) +Rotate Analog (CW) = 아날로그 회전 (CW) Save State = 상태 저장하기 Screen = 화면 Screenshot = 스크린샷 @@ -798,11 +696,10 @@ tap to customize = 탭하여 맞춤 설정 Texture Dumping = 텍스처 덤핑 Texture Replacement = 텍스처 교체 Toggle Fullscreen = 전체 화면 토글 -Toggle mode = 모드 토글 -Toggle WLAN = 무선랜 토글 +Toggle mode = 토글 모드 Triangle = 세모 Fast-forward = 빨리 감기 -Up = 십자 패드 위쪽 +Up = 집자 패드 위쪽 Vol + = 볼륨 + Vol - = 볼륨 - Wlan = 무선랜 @@ -810,14 +707,18 @@ Display Landscape = 가로방향 표시 Display Landscape Reversed = 가로방향 반전 표시 Display Portrait = 세로방향 표시 Display Portrait Reversed = 세로방향 반전 표시 - [Networking] AdHoc Server = Ad hoc 서버 AdhocServer Failed to Bind Port = Ad Hoc 서버가 포트를 바인딩하지 못했습니다. AM: Data from Unknown Port = AM: 알 수 없는 포트의 데이터 Auto = 자동 +Bottom Center = 하단 중앙 +Bottom Left = 하단 왼쪽 +Bottom Right = 하단 오른쪽 +Center Left = 중앙 왼쪽 +Center Right = 중앙 오른쪽 Change Mac Address = MAC 주소 변경 -ChangeMacSaveConfirm = 새로운 MAC 주소를 생성하겠습니까? +ChangeMacSaveConfirm = 새로운 MAC 주소를 생성하시겠습니까? ChangeMacSaveWarning = 일부 게임은 저장 데이터를 불러올 때 MAC 주소를 확인하므로 이전 저장이 손상될 수 있습니다. Change proAdhocServer Address = PRO ad hoc 서버 IP 주소 변경 (로컬호스트 = 다중 인스턴스) Chat = 채팅 @@ -849,6 +750,7 @@ Invalid IP or hostname = 잘못된 IP 또는 호스트 이름 Minimum Timeout = 최소 시간 초과 (ms 단위로 재정의, 0 = 기본값) Misc = 기타 (기본값 = PSP 호환성) Network Initialized = 네트워크 초기화 +None = 없음 Please change your Port Offset = 포트 오프셋을 변경하세요. Port offset = 포트 오프셋 (0 = PSP 호환성) Open PPSSPP Multiplayer Wiki Page = PPSSPP 멀티플레이어 위키 페이지 열기 @@ -859,9 +761,11 @@ Quick Chat 3 = 빠른 채팅 3 Quick Chat 4 = 빠른 채팅 4 Quick Chat 5 = 빠른 채팅 5 QuickChat = 빠른 채팅 -Randomize = 무작위화 Send = 보내기 Send Discord Presence information = 디스코드 "리치 프레즌스" 정보 보내기 +Top Center = 상단 중앙 +Top Left = 상단 왼쪽 +Top Right = 상단 오른쪽 Unable to find UPnP device = UPnP 장치를 찾을 수 없습니다. UPnP (port-forwarding) = UPnP (포트 포워딩) UPnP need to be reinitialized = UPnP를 다시 초기화해야 합니다. @@ -896,7 +800,6 @@ Amount = 양 Aspect = 화면 Black border = 검정 테두리 Bloom = 블룸 -BloomNoBlur = 블룸 (흐림 없음) Brightness = 밝기 Cartoon = 카툰 ColorCorrection = 색상 교정 @@ -906,7 +809,6 @@ CRT = CRT 스캔라인 FXAA = FXAA 안티 에일리어싱 Gamma = 감마 GreenLevel = 녹색 수준 -FakeReflections = 가짜반사 Intensity = 강도 LCDPersistence = LCD 지속성 Natural = 자연스러운 색상 @@ -923,7 +825,6 @@ SSAA(Gauss) = 슈퍼샘플 AA (가우스) Strength = 늘이기 Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = 업스케일바이큐빅 UpscaleSpline36 = 스플라인36 업스케일러 VideoSmoothingAA = 비디오 스무딩 AA Vignette = 비네트 효과 @@ -955,7 +856,7 @@ specialthanks = 특별히 감사한 분: specialthanksKeithGalocy = NVIDIA (하드웨어, 조언) specialthanksMaxim = 놀라운 Atrac3+ 디코더 작업 testing = 테스트 -this translation by = 번역가: +this translation by = 번역자: title = 빠르고 휴대 가능한 PSP 에뮬레이터 tools = 사용된 무료 도구: # Add translators or contributors who translated PPSSPP into your language here. @@ -973,7 +874,6 @@ written = 속도와 이식성을 위해 C++로 작성되었습니다. [MemStick] Already contains PSP data = 이미 PSP 데이터가 포함되어 있습니다. -Cancelled - try again = 취소됨 - 다시 시도 Create or Choose a PSP folder = PSP 폴더 생성 또는 선택 Current = 현재 DataCanBeShared = PPSSPP 레귤러/골드 간에 데이터 공유 가능 @@ -1001,23 +901,6 @@ Use PSP folder at root of storage = 저장공간 루트에서 PSP 폴더 사용 Welcome to PPSSPP! = PPSSPP에 오신 것을 환영합니다! WhatsThis = 이것은 무엇인가요? -[PSPSettings] -Auto = 자동 -Chinese (simplified) = 중국어 (간체) -Chinese (traditional) = 중국어 (번체) -Dutch = 네덜란드어 -English = 영어 -French = 프랑스어 -Game language = 게임 언어 -German = 독일어 -Italian = 이탈리아어 -Japanese = 일본어 -Korean = 한국어 -Games often don't support all languages = 게임이 모든 언어를 지원하지 않는 경우가 많음 -Portuguese = 포르투갈어 -Russian = 러시아어 -Spanish = 스페인어 - [RemoteISO] Browse Games = 게임 찾아보기 Local Server Port = 로컬 서버 포트 @@ -1037,7 +920,6 @@ Share Games (Server) = 게임 공유하기 (서버) Share on PPSSPP startup = PPSSPP 시작시 자동으로 공유하기 Stop Sharing = 공유 끝내기 Stopping.. = 중지하는 중... - [Reporting] Bad = 나쁨 FeedbackCRCCalculating = 디스크 CRC: 계산 중... @@ -1094,7 +976,7 @@ Showing matches for '%1'. = '%1'에 대한 일치 항목을 표시합니다. Size = 크기 [Screen] -Cardboard VR OFF = 카드보드 VR 끔 +Cardboard VR OFF = 카드보드 VR off Chainfire3DWarning = 경고: Chainfire3D가 감지되어 문제를 일으킬 수 있습니다. Failed to load state = 상태를 불러오지 못함 Failed to save state = 상태를 저장하지 못함 @@ -1117,11 +999,10 @@ Save State Failed = 상태 저장 실패! Saved State = 저장된 상태 saveNewTextures_false = 텍스처 저장이 비활성화되었습니다. saveNewTextures_true = 이제 텍스처가 저장 공간에 저장됩니다. -SpeedCustom2 = 속도: 대체 2 +SpeedCustom2 = Speed: 대체 2 standard = 속도: 표준 State load undone = 상태 불러오기 취소 Untitled PSP game = 제목 없는 PSP 게임 - [Store] Already Installed = 이미 설치됨 Connection Error = 연결 오류 @@ -1131,7 +1012,6 @@ Loading... = 불러오기 중... MB = 메가바이트 Size = 크기 Uninstall = 제거 - [SysInfo] %d (%d per core, %d cores) = %d (코어 당 %d, 코어 %d 개) %d bytes = %d 바이트 @@ -1168,11 +1048,10 @@ GPU Flags = GPU 플래그 GPU Information = GPU 정보 High precision float range = 고정밀 부동소수점 범위 High precision int range = 고정밀 정수 범위 -Icon cache = 아이콘 캐시 JIT available = JIT 사용 가능 Lang/Region = 언어/지역 Memory Page Size = 메모리 페이지 크기 -Native resolution = 기본 해상도 +Native Resolution = 기본 해상도 No GPU driver bugs detected = GPU 드라이버 버그가 감지되지 않았음 OGL Extensions = OGL 확장 OpenGL ES 2.0 Extensions = OpenGL ES 2.0 확장 @@ -1181,9 +1060,7 @@ OpenGL Extensions = OpenGL 확장 Optimal frames per buffer = 버퍼당 최적 프레임 Optimal sample rate = 최적의 샘플 속도 OS Information = OS 정보 -Pixel resolution = 픽셀 해상도 PPSSPP build = PPSSPP 빌드 -Present modes = 현재 모드 Refresh rate = 주사율 Release = 개정 RW/RX exclusive = RW/RX 전용 @@ -1195,14 +1072,13 @@ System Information = 시스템 정보 System Name = 이름 System Version = 시스템 버전 Threads = 스레드 -UI resolution = UI 해상도 +UI Resolution = UI 해상도 Vendor = 공급업체 Vendor (detected) = 공급업체 (탐지됨) Version Information = 버전 정보 Vulkan Extensions = Vulkan 확장 Vulkan Features = Vulkan 기능 Display Color Formats = 디스플레이 색상 형식 - [System] (broken) = (고장) 12HR = 12시간 @@ -1277,7 +1153,6 @@ Record Audio = 오디오 녹음 Record Display = 녹화 표시 Reset Recording on Save/Load State = 저장/불러오기 상태에서 녹화 재설정 Restore Default Settings = PPSSPP의 설정을 기본값으로 복원 -RetroAchievements = RetroAchievements Rewind Snapshot Interval = 되감기 스냅샷 빈도 (메모리 호그) Save path in installed.txt = install.txt에 경로 저장 Save path in My Documents = 내 문서에 경로 저장 @@ -1289,7 +1164,6 @@ Set UI background... = UI 배경 설정... Show ID = ID 표시 Show region flag = 지역 플래그 표시 Simulate UMD delays = UMD 지연 시뮬레이션 -Simulate UMD slow reading speed = UMD 느린 읽기 속도 시뮬레이션 Slot 1 = 슬롯 1 Slot 2 = 슬롯 2 Slot 3 = 슬롯 3 @@ -1356,19 +1230,20 @@ Progress: %1% = 진행율: %1% Screen representation = 화면 표현 [VR] +% of native FoV = 실제 시야의 % 6DoF movement = 6DoF 이동 Distance to 2D menus and scenes = 2D 메뉴 및 장면까지의 거리 -Distance to 3D scenes when VR disabled = VR 비활성화 시 3D 장면까지의 거리 Experts only = 전문가 전용 Game camera rotation step per frame = 프레임당 게임 카메라 회전 단계 Game camera uses rotation smoothing = 회전 스무딩을 사용하는 게임 카메라 -Force 72Hz update = 강제 72Hz 업데이트 -Heads-up display scale = 헤드업 디스플레이 스케일 +Field of view scale = 시야 스케일 +Force 72Hz update = 강제 72Hz 업데이트 Heads-up display detection = 헤드업 디스플레이 감지 +Heads-up display scale = 상방시현기 스케일 Map controller movements to keys = 컨트롤러 이동을 키에 매핑 Map HMD rotations on keys instead of VR camera = VR 카메라 대신 키에 HMD 회전 매핑하기 Manual switching between flat screen and VR using SCREEN key = 화면 키를 사용하여 평면 화면과 VR 간 수동 전환 -Camera type = 카메라 유형 +Camera type = 카메라 유형 Motion needed to generate action = 동작 생성에 필요한 동작 Stereoscopic vision (Experimental) = 입체시 (실험적) Virtual reality = 가상 현실 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 8008a5b5a..87c0e38ba 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = ຮູບແບບສຽງທີ່ຮອງຮັບ (ຕ້ອງຣີສຕາຣ໌ດ) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = ອັດຕະໂນມັດ Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = ປັບຄ່າຄວາມຄາດເຄື່ອນຂອງ Calibrated = Calibrated Calibration = ປັບຄ່າຄວາມຄາດເຄື່ອນ -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = ແບບດັ້ງເດີມ Confine Mouse = ຈຳກັດເມົ້າໃນໜ້າຕ່າງ/ພື້ນທີ່ສະແດງຜົນ @@ -108,10 +48,8 @@ Deadzone radius = ຂອບເຂດ Deadzone Disable D-Pad diagonals (4-way touch) = ປິດການໃຊ້ງານປຸ່ມ D-Pad (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = ໃຊ້ໜ້າຈໍຄວບຄຸມແບບສຳຜັດ Portrait = ແນວຕັ້ງ Portrait Reversed = ກັບດ້ານແນວຕັ້ງ PSP Action Buttons = ປຸ່ມກົດຂອງ PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = ຄວາມໄວຕໍ່ການຕອບສະໜອງ Shape = Shape Show Touch Pause Menu Button = ສະແດງປຸ່ມຢຸດສຳລັບເຂົ້າເມນູ -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &ເກັບຄ່າຄອນໂຊລ Memory View... = &ມຸມມອງຄ່າຄວາມຈຳ... More Settings... = &ການຕັ້ງຄ່າອື່ນໆ... Nearest = &ພາບເປັນຮອຍຍັກໄດ້ -Recent = &Recent Skip Buffer Effects = &ຂ້າມການໃຊ້ເອັບເຟັກບັບເຟີ້ (ບໍ່ມີບັບເຟີ້, ໄວຂຶ້ນ) Off = &ປິດ Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = &ຕອງພື້ນຜິວ Texture Scaling = &ປັບພື້ນຜິວ Use Lossless Video Codec (FFV1) = Use Lossless Video Codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex ແຄດ VSync = VS&ync Vulkan = Vulkan Window Size = &ຂະໜາດໜ້າຈໍ @@ -282,11 +218,8 @@ Backspace = ຖອຍຫຼັງ Block address = ບລັອກຄ່າທີ່ຢູ່ By Address = ໂດຍຄ່າທີ່ຢູ່ Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = ສ້າງ/ເປີດໄຟລ໌ textures.ini ຂອງເກມນີ້ Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = ເປີດໃຊ້ງານ logging Enter address = ໃສ່ຄ່າທີ່ຢູ່ FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = ລາຍລະອຽດຂອງເຟຣມ -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = ເກັບຄ່າສະຖິຕິເຟຣ Log Level = ເກັບຄ່າລະດັບ Log View = ເກັບຄ່າມຸມມອງ Logging Channels = ຊ່ອງທາງເກັບຄ່າຂໍ້ມູນ -Multi-threaded rendering = Multi-threaded rendering Next = ຕໍ່ໄປ No block = ບໍ່ຕ້ອງບລັອກ -Off = Off Prev = ກ່ອນໜ້າ Random = ສຸມ Replace textures = ແທນທີ່ພື້ນຜິວ @@ -332,12 +260,10 @@ Stats = ສະຖິຕິ System Information = ຂໍ້ມູນຂອງລະບົບ Texture ini file created = Texture ini file created Texture Replacement = ການແທນທີ່ພື້ນຜິວ -Audio Debug = ແກ້ໄຂຈຸດບົກພ່ອງຂອງສຽງ -Control Debug = Control Debug +Toggle Audio Debug = ແກ້ໄຂຈຸດບົກພ່ອງຂອງສຽງ +Toggle Control Debug = Toggle Control Debug Toggle Freeze = ປຸ່ມແຊ່ແຂງ Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * ຂະໜາດຈໍ PSP Active = Active Back = ຍ້ອນກັບ -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = ຍົກເລີກ Center = ທາງກາງ -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = ເມື່ອປ່ຽນແປງຮູບແບບການສະໜັບສະໜູນ GPU \n ຈະຕ້ອງເລີ່ມ PPSSPP ໃໝ່ອີກຄັ້ງ. ເລີ່ມໃໝ່ເລີຍບໍ່? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = ເລືອກໂຟນເດີ້ເຊບ PPSSPP Confirm Overwrite = ຕ້ອງການໃຫ້ຂຽນທັບຂໍ້ມູນເກົ່າຫຼືບໍ່? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = ເຈົ້າຕ້ອງການທີ່ຈະລ DeleteFailed = ບໍ່ສາມາດລຶບຂໍ້ມູນ. Deleting = ກຳລັງລຶບຂໍ້ມູນ\nກະລຸນາຖ້າ.. Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = ຢືນຢັນ -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = ສິ້ນສຸດ GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = ໂຫຼດ Load completed = ໂຫຼດຂໍ້ມູນສຳເລັດ Loading = ກຳລັງໂຫຼດ\nກະລຸນາລໍຖ້າ... LoadingFailed = ບໍ່ສາມາດໂຫຼດຂໍ້ມູນ. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = ເຄື່ອນຍ້າຍ Move Down = Move Down Move Up = Move Up Network Connection = ການເຊື່ອມຕໍ່ເຄື່ອຂ່າຍ NEW DATA = ຂໍ້ມູນໃໝ່ No = ບໍ່ແມ່ນ -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = ຕົກລົງ Old savedata detected = ກວດພົບຂໍ້ມູນເຊບເກົ່າ Options = ໂຕເລືອກ -Password = Password Remove = Remove Reset = ຕັ້ງຄ່າໃໝ່ Resize = ປັບຂະໜາດ -Restart = Restart Retry = ລອງໃໝ່ອີກຄັ້ງ Save = ບັນທຶກ Save completed = ບັນທຶກຂໍ້ມູນສຳເລັດ @@ -420,7 +329,6 @@ SavingFailed = ບໍ່ສາມາດບັນທຶກຂໍ້ມູນ. Search = Search seconds, 0:off = ວິນາທີ, 0 = ປິດ Select = ເລືອກ -Settings = Settings Shift = ປ່ຽນ Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = ບໍ່ມີຂໍ້ມູນ. Toggle All = ເລືອກທັງໝົດ Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = ເມື່ອເຈົ້າເຊບເກມ, ຈະສາມາດນຳໄປໂຫຼດເທິງເຄື່ອງ PSP ໄດ້\nແຕ່ບໍ່ແມ່ນສຳລັບ PPSSPP ທີ່ເກົ່າກວ່າ When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = ແມ່ນ @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = ໄຟລ໌ຖືກບີບອັດ (ZI [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = ຢືນຢັນການລຶບ -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = ສ້າງການຕັ້ງຄ່າເກມ Create Shortcut = ຈາກຫຼ້າສຸດ Delete Game = ລຶບເກມ Delete Game Config = ລຶບການຕັ້ງຄ່າເກມ Delete Save Data = ລຶບຂໍ້ມູນທີ່ບັນທຶກ Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = ເກມ -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = ການຕັ້ງຄ່າເກມ Homebrew = Homebrew Hong Kong = Hong Kong InstallData = ຕິດຕັ້ງຂໍ້ມູນ -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = ເອົາອອກຈາກໜ້າ "ຫຼ້າສຸ SaveData = ບັນທຶກຂໍ້ມູນ Setting Background = Setting background Show In Folder = ສະແດງໃນໂຟນເດີ້ -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = ໃຊ້ເປັນພາບພື້ນຫຼັງ @@ -623,7 +520,6 @@ Must Restart = ເຈົ້າຄວນເລີ່ມ PPSSPP ໃໝ່ເພື Native device resolution = ຄ່າຄວາມລະອຽດດັ້ງເດີມຂອງອຸປະກອນ Nearest = Nearest No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = ຂ້າມການໃຊ້ບັບເຟີເອັບເຟກ (ບໍ່ໃຊ້ບັບເຟີ, ໄວຂຶ້ນ) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = ດຶງເຕັມຈໍ Texture Filter = ໂຕຕອງພື້ນຜິວ Texture Filtering = ຕອງພື້ນຜິວ -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = ປັບພື້ນຜິວ Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = ການເພີ່ມລະດັບສເກລພາບ Upscale Type = ຮູບແບບການເພີ່ມສເກລພາບ UpscaleLevel Tip = ຊີພີຢູເຮັດວຽກໜັກຂຶ້ນ - ບາງສເກລພາບອາດເກີດອາການໜ່ວງຈົນເຖິງຂັ້ນບໍ່ສະແດງ Use all displays = Use all displays +Vertex Cache = Vertex Cache +VertexCache Tip = ໄວຂຶ້ນ, ແຕ່ອາດເກີດມີອາການພາບກະພິບໃນບາງເທື່ອ VSync = ຄວບຄຸມລະດັບເຟຣມເຣດໃຫ້ຄົງທີ່ Vulkan = Vulkan Window Size = ຂະໜາດໜ້າຈໍ @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = ກຳນົດຄ່າອັດຕະໂນມັດ Autoconfigure for device = ກຳນົດຄ່າໃຫ້ອັດຕະໂນມັດສຳລັບອຸປະກອນນີ້ Bind All = Bind All Clear All = ລຶບທັງໝົດ -Combo mappings are not enabled = Combo mappings are not enabled Default All = ຄືນຄ່າເລີ່ມຕົ້ນໃໝ່ໝົດ Map a new key for = ປັບປຸ່ມໃໝ່ເພື່ອ Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = ສະຫຼັບດ້ານແກນ Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad ລົງ Dpad = Dpad -Exit App = Exit App Frame Advance = Frame Advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = ຢຸດຊົ່ວຄາວ -Previous Slot = Previous Slot R = R RapidFire = ປຸ່ມລົວຕໍ່ເນື່ອງ Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = ເລັ່ງເທີໂບ Up = Dpad ຂຶ້ນ @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = ປ່ຽນຄ່າທີ່ຢູ່ MAC Change proAdhocServer Address = ປ່ຽນໄອພີທີ່ຢູ່ຂອງເຊີບເວີ Pro Adhoc (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = ເລີ່ມການເຮັດວຽກລະບົບເຄື່ອຂ່າຍແລ້ວ +None = None Please change your Port Offset = Please change your port offset Port offset = ພອຣ໌ດຊົດເຊີຍ (0 = ຄ່າເລີ່ມຕົ້ນຂອງ PSP) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = ສູດໂກງ Continue = ຫຼິ້ນຕໍ່ @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT -FakeReflections = FakeReflections FXAA = FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = ບັນທຶກສຽງ Audio Record Display = ບັນທຶກພາບ Display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = "ຄືນຄ່າການຕັ້ງຄ່າຂອງ PPSSPP ເປັນຄ່າເລີ່ມຕົ້ນ" -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = ບັນທຶກຂໍ້ມູນໃນ installed.txt Save path in My Documents = ບັນທຶກຂໍ້ມູນໄວ້ທີ່ My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = ດາວໂຫຼດ New version of PPSSPP available = ເວີຊັ່ນໃໝ່ຂອງ PPSSPP ພ້ອມໃຫ້ໂຫຼດແລ້ວ! [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 48ee31d00..db994959d 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibruoti Calibrated = Calibrated Calibration = Kalibravimas -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasikinis Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = "Mirties zonos" spindulys Disable D-Pad diagonals (4-way touch) = Išjungti krypčių mygtukų įstrižainę (4 paspaudimais vienu metu liečiamam ekranui) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Ekrano liečiami kontrolės mygtukai Portrait = Status Portrait Reversed = Status (apsuktas) PSP Action Buttons = PSP konsolės veiksmų mygtukai -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivacija Shape = Shape Show Touch Pause Menu Button = Rodyti liečiamą pauzės meniu mygtuką -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = "&Statuso" konsolė Memory View... = Atminties &rodymas... More Settings... = &Daugiau parametrų... Nearest = &Arčiausias -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Išjungti Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&kstūrų filtravimas Texture Scaling = &Tekstūrų Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = "VS&ync" Vulkan = Vulkan Window Size = &Lango dydis @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Įjungti testinio režimo statuso rašymą į failus Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Rašymo į statusą kanalai -Multi-threaded rendering = Multi-threaded rendering Next = Kitas No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Sistemos informacija Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Atgal -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Atšaukti Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Pasirinkite PPSSPP išsaugojimo aplanką Confirm Overwrite = Ar norite perrašyti šitus duomenis? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Ar tikrai norite ištrinti šiuos nustatymus iš šito DeleteFailed = Neįmanoma ištrinti duomenų. Deleting = Ištrina\nPrašome palaukti... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Įeitis -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Baigti GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Krauti Load completed = Krovimas baigtas. Loading = Kraunama\nPrašome palaukti... LoadingFailed = Neįmanoma krauti duomenų. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Perkelti Move Down = Move Down Move Up = Move Up Network Connection = Interneto tinklas NEW DATA = NAUJI DUOMENYS No = Ne -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = Gerai Old savedata detected = Aptikti seniau išsaugoti duomenys Options = Options -Password = Password Remove = Remove Reset = Perkrauti Resize = Perkeisti dydį -Restart = Restart Retry = Pabandyti dar kartą Save = Išsaugoti Save completed = Išsaugojimas baigtas. @@ -420,7 +329,6 @@ SavingFailed = Neįmanoma išsaugoti duomenų. Search = Search seconds, 0:off = sekundžių, 0 = off Select = Pasirinkti -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Čia nėra jokių duomenų. Toggle All = Perjungti visus Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Taip @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Failas yra suspaustas (ZIP formato).\nReiki [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Ištrinti -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Kurti nuorodą Delete Game = Ištrinti žaidimą Delete Game Config = Delete game config Delete Save Data = Ištrinti išsaugojimą Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Žaidimas -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Žaidimo parametrai Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instaliuoti duomenis -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = Megabaitai @@ -527,8 +426,6 @@ Remove From Recent = Ištrinti iš "Paskutiniai" sąrašo SaveData = Išsaugojimai Setting Background = Setting background Show In Folder = Rodyti aplanke -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = Jūs turite perkrauti "PPSSPP" programą, kad pakeisti parametrai Native device resolution = Įrenginio rezoliucija Nearest = Arčiausias No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Tekstūrų filtravimas Texture Filtering = Tekstūrų filtravimas -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Tekstūrų skalė Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = "Pakėlimo" lygis Upscale Type = "Pakėlimo" tipas UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = "Tikra" spartinamoji atmintis +VertexCache Tip = Faster, but may cause temporary flicker VSync = Kadrų per sekundę sinchrovizavimas su monitoriumi Vulkan = Vulkan Window Size = Lango dydis @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Automatiškai sukonfiguruoti įrenginiui Bind All = Bind All Clear All = Ištrinti viską -Combo mappings are not enabled = Combo mappings are not enabled Default All = Akturti numatytus parametrus Map a new key for = Nustatyti naują klavišą Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Krypčių mygtukas žemyn Dpad = Krypčių mygtukai -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pauzė -Previous Slot = Previous Slot R = R RapidFire = Greita-"ugnis" Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Krypčių mygtukas aukštyn @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Kodai Continue = Tęsti @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Animacinis filmas CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT skenavimo linjos -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Išaukštinimas VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Nustatyti "PPSSPP" parametrus į numatytuosius -RetroAchievements = RetroAchievements Rewind Snapshot Interval = "Vėjinti" momentinės nuotraukos dažnį (atminties "rijikas") Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Parsisiūsti New version of PPSSPP available = Galima nauja "PPSSPP" versija [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index f7e83b17d..a99ec20b0 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Enjin suara (PPSSPP perlu dibuka semula) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasik Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Lumpuhkan PadD diagonal (4-jalan sentuh) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Kawalan sentuh di skrin Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Log Konsol Memory View... = Lihat &Memori... More Settings... = &Tetapan lanjutan... Nearest = &Terdekat -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Tutup Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Penapisan Te&kstur Texture Scaling = &Penskalaan Tekstur Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Kuki Vertek VSync = VS&ync Vulkan = Vulkan Window Size = &Saiz tetingkap @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Alat pembangunan DevMenu = DevMenu Disabled JIT functionality = Fungsi JIT yang dilumpuhkan @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Upayakan log pepijat Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Ujian driver GPU GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Log Channel -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Rawak Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Maklumat sistem Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Balik -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Batal Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Penukaran enjin GPU memerlukan PPSSPP untuk dimulakan semula. Mula Semula? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Anda hendak menulis ganti data ini? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Pemadaman data gagal. Deleting = Memadam\nSila tunggu... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Masuk -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Tamat GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Muatkan Load completed = Memuat selesai. Loading = Memuat\nSila tunggu... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = DATA BAHARU No = Tidak -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Mula semula Resize = Resize -Restart = Restart Retry = Cuba semula Save = Simpan Save completed = Menyimpan selesai. @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = Pilih -Settings = Settings Shift = Shif Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Tiada data disini. Toggle All = Periksa semua Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Tidak disokong -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Ya @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Fail dimampatkan (ZIP).\nSila nyah-mampatka [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Padam -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Buat pintasan Delete Game = Padam permainan Delete Game Config = Delete game config Delete Save Data = Padam data disimpan Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Permainan -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Tetapan permainan Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Hapuskan dari "Semasa" SaveData = Data disimpan Setting Background = Setting background Show In Folder = Papar dalam folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = Terdekat No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Penapis Tekstur Texture Filtering = Penapisan Tekstur -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Penskalaan Tekstur Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Tahap penskalaan Upscale Type = Jenis penskalaan UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Kuki Vertek +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Saiz tetingkap @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Bersihkan semua -Combo mappings are not enabled = Combo mappings are not enabled Default All = Lalaikan semua Map a new key for = Petakan kekunci baru untuk Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Bawah Dpad = PadD -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Jeda -Previous Slot = Previous Slot R = R RapidFire = Tembak-Berterusan Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Atas @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheat Continue = Teruskan @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Mekar -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Kartun CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Anti aliasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Penskalaan spline36 VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Kembalikan tetapan PPSSPP ke lalai -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Kekerapan pusingan gambar skrin (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Muat turun New version of PPSSPP available = Versi terbaru PPSSPP tersedia [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index e8b10427d..66788fd63 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audiobackend (vereist herstart) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-vriendelijke buffer (trager) Auto = Automatisch Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibreren Calibrated = Calibrated Calibration = Kalibreren -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klassiek Confine Mouse = Muis binnen venster/weergavegebied vastzetten @@ -108,10 +48,8 @@ Deadzone radius = Straal dode zone Disable D-Pad diagonals (4-way touch) = Diagonale pijltoetsen uitzetten (4 richtingen) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Aanraakbesturing op het scherm Portrait = Portret Portrait Reversed = Omgekeerd portret PSP Action Buttons = PSP-actietoetsen -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Gevoeligheid Shape = Shape Show Touch Pause Menu Button = Pauzemenutoets weergeven -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Logboek&console Memory View... = &Geheugenweergave... More Settings... = &Meer instellingen... Nearest = &Naaste buur -Recent = &Recent Skip Buffer Effects = &Buffereffecten nalaten (niet-gebufferd, sneller) Off = &Uit Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = &Texturefilter Texture Scaling = Te&xtures schalen Use Lossless Video Codec (FFV1) = Lossless videocodec gebruiken (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = Vertex &Cache VSync = Ve&rticale Synchronisatie Vulkan = Vulkan Window Size = Venster&grootte @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Blokadres By Address = Op adres Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = textures.ini-bestand voor huidige game aanmaken/openen Current = Huidige -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Ontwikkelingstools DevMenu = Ontwikkelaarsmenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Foutlogboek inschakelen Enter address = Adres invoeren FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frameanalyse -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Overgeslagen framestatistieken vastleggen Log Level = Logniveau Log View = Logboekoverzicht Logging Channels = Logboekkanalen -Multi-threaded rendering = Multi-threaded rendering Next = Volgende No block = Geen blok -Off = Off Prev = Vorige Random = Willekeurig Replace textures = Textures vervangen @@ -332,12 +260,10 @@ Stats = Statistieken System Information = Systeeminformatie Texture ini file created = Texture ini file created Texture Replacement = Texturevervanging -Audio Debug = Foutopsporing voor audio -Control Debug = Control Debug +Toggle Audio Debug = Foutopsporing voor audio in-/uitschakelen +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Bevriezen in-/uitschakelen Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP-resolutie Active = Active Back = Terug -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Annuleren Center = Centreren -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Als u de GPU-backend wijzigt moet u PPSSPP opnieuw\nopstarten. Nu opnieuw opstarten? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = PPSSPP-opslagmap selecteren Confirm Overwrite = Wilt u de opgeslagen data overschrijven? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Weet u zeker dat u de instellingen voor deze game\nwil DeleteFailed = Kan de data niet verwijderen. Deleting = Bezig met verwijderen...\nEen ogenblik geduld. Disable All = Alles uitschakelen -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Alles inschakelen -Enabled = Enabled Enter = Bevestigen -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Voltooien GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactief -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Laden Load completed = Het laden is voltooid. Loading = Bezig met laden...\nEen ogenblik geduld. LoadingFailed = Kan de data niet laden. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Slepen Move Down = Move Down Move Up = Move Up Network Connection = Netwerkverbinding NEW DATA = NIEUWE DATA No = Nee -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Oude savedata gedetecteerd Options = Opties -Password = Password Remove = Remove Reset = Herstellen Resize = Schalen -Restart = Restart Retry = Opnieuw Save = Opslaan Save completed = Het opslaan is voltooid. @@ -420,7 +329,6 @@ SavingFailed = Kan de data niet opslaan. Search = Search seconds, 0:off = seconds, 0 = uit Select = Selecteren -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Ondersteund There is no data = Er zijn geen data. Toggle All = Alles schakelen Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Niet ondersteund -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Als u opslaat kunt u de opgeslagen data laden op\nPSP-systemen, maar niet op oudere PPSSPP-versies. When you save, it will not work on outdated PSP Firmware anymore = Als u opslaat, werkt deze niet meer op verouderde PSP-firmware. Yes = Ja @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = het bestand is verkleind (ZIP).\nPak het be [Game] Asia = Azië Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Verwijderen -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Gameopties aanmaken Create Shortcut = Snelkoppeling maken Delete Game = Game wissen Delete Game Config = Gameopties wissen Delete Save Data = Savedata wissen Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Game -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Game-instellingen Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data installeren -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Wissen uit "Recent" SaveData = Opgeslagen data Setting Background = Achtergrondinstelling Show In Folder = Weergeven in map -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = VS Use UI background = UI-achtergrond gebruiken @@ -623,7 +520,6 @@ Must Restart = U moet PPSSPP herstarten om de wijzigingen door te voeren. Native device resolution = Apparaatresolutie Nearest = Naaste buur No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Buffereffecten nalaten (niet-gebufferd, sneller) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Uitrekken Texture Filter = Texturefilter Texture Filtering = Texturefilter -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Textures schalen Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Schakel "hardwarebetegeling" uit: niet ondersteund @@ -669,6 +564,8 @@ Upscale Level = Upscaleniveau Upscale Type = Upscaletype UpscaleLevel Tip = CPU-belastend - schalen kan vertraagd worden om haperingen te voorkomen Use all displays = Alle beeldschermen gebruiken +Vertex Cache = Vertexcache +VertexCache Tip = Sneller, maar kan tijdelijk flikkeringen veroorzaken VSync = Verticale synchronisatie Vulkan = Vulkan Window Size = Venstergrootte @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autoconfiguratie Autoconfigure for device = Automatisch voor apparaat configureren Bind All = Bind All Clear All = Alles legen -Combo mappings are not enabled = Combo mappings are not enabled Default All = Herstellen Map a new key for = Stel een nieuwe toets in voor Map Key = Toets indelen @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/video opnemen AxisSwap = Assen wisselen Circle = Cirkel Cross = Kruis -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Beneden Dpad = Richtingstoetsen -Exit App = Exit App Frame Advance = Frame doorspoelen Hold = Ingedrukt Home = Home @@ -773,7 +676,6 @@ None = None Note = Muzieknoot OpenChat = Open chat Pause = Pauzeren -Previous Slot = Previous Slot R = R RapidFire = Snelvuur Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Volledig scherm schakelen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Driehoek Fast-forward = Versnellen Up = Boven @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = MAC-adres wijzigen Change proAdhocServer Address = IP-adres van PRO Ad hoc-server wijzigen (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Netwerk geïnitialiseerd +None = None Please change your Port Offset = Please change your port offset Port offset = Poortoffset (0 = PSP-compatibiliteit) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = Doorgaan @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloeieffect -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT-scanlijnen -FakeReflections = FakeReflections FXAA = FXAA-antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36-upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignet @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU-informatie High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Taal/regio Memory Page Size = Grootte geheugenpagina -Native resolution = Oorspronkelijke resolutie +Native Resolution = Oorspronkelijke resolutie No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL-extensies OpenGL ES 2.0 Extensions = OpenGL ES 2.0-extensies @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL-extensies Optimal frames per buffer = Optimale frames per buffer Optimal sample rate = Optimale samplerate OS Information = OS-informatie -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Vernieuwingsfrequentie Release = Release RW/RX exclusive = RW/RX-excusief @@ -1204,7 +1089,7 @@ System Information = Systeeminformatie System Name = Naam System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Verkoper Vendor (detected) = Verkoper (gedetecteerd) Version Information = Versie-informatie @@ -1287,7 +1172,6 @@ Record Audio = Audio opnemen Record Display = Scherm opnemen Reset Recording on Save/Load State = Opname opnieuw opstarten bij opslaan/laden van states Restore Default Settings = PPSSPP's standaardinstellingen herstellen -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Terugspoelfrequentie (kost geheugen) Save path in installed.txt = Opslagpad in installed.txt Save path in My Documents = Opslagpad in Mijn documenten @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = UMD-vertraging simuleren -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Downloaden New version of PPSSPP available = Er is een nieuwe versie van PPSSPP beschikbaar [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 98f09f72a..9569fe4f8 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Audio backend (restart req.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Kalibrer Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Classic Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Touch-kontroller på skjermen Portrait = Portrait Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Shape Show Touch Pause Menu Button = Show pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = &Log Console Memory View... = Memory &View... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Te&xture Filtering Texture Scaling = &Texture Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window Size @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Debugloggning Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Systeminformasjon Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Tilbake -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Cancel Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Changing GPU backends requires PPSSPP to restart. Restart now? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Do you want to overwrite the data? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Do you really want to delete the settings for this gam DeleteFailed = Unable to delete data. Deleting = Sletter\nVent litt... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Ferdig GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = Ferdig lastet. Loading = Laster\nVent litt... LoadingFailed = Unable to load data. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Move Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = NEW DATA No = Nei -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Old savedata detected Options = Options -Password = Password Remove = Remove Reset = Reset Resize = Resize -Restart = Restart Retry = Retry Save = Save Save completed = Ferdig lagret. @@ -420,7 +329,6 @@ SavingFailed = Unable to save data. Search = Search seconds, 0:off = seconds, 0 = off Select = Velg -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Det finnes ingen data. Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Ja @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Delete -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Create game config Create Shortcut = Create shortcut Delete Game = Delete game Delete Game Config = Delete game config Delete Save Data = Delete savedata Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Game -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Game settings Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Data install -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Remove from "Recent" SaveData = Savedata Setting Background = Setting background Show In Folder = Show in folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = Nermest No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Tekstur filtrering Texture Filtering = Tekstur filtrering -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Teksturskalning Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -669,6 +564,8 @@ Upscale Level = Oppskaler nivå Upscale Type = Oppskaler type UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex buffer +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Window size @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Clear all -Combo mappings are not enabled = Combo mappings are not enabled Default All = Restore defaults Map a new key for = Map a new key for Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Down Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pause -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Dpad Up @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Change MAC address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Cheats Continue = Fortsettelse @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1287,7 +1172,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Restore PPSSPP's settings to default -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = New version of PPSSPP available [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 6c41c7bd8..781686829 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Próba nieudana -%1: Attempt started = %1: Próba wystartowała -%1 achievements, %2 points = %1 Osiągnięć, %2 punktów -Account = Konto -Achievement progress = Postęp osiągnięcia -Achievement unlocked = Osiągnięcie odblokowane -Achievements = Osiągnięcia -Achievements are disabled = Osiągnięcia są wyłączone -Achievements enabled = Osiągnięcia włączone -Achievements with active challenges = Osiągnięcia z aktywnymi wyzwaniami -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Prawie ukończone osiągnięcia -Around me = Wokół mnie -Can't log in to RetroAchievements right now = W tym momencie nie można zalogować do RetroAchievements -Challenge indicator = Wskazówki Wyzwania -Contacting RetroAchievements server... = Łączenie z serwerem RetroAchievements... -Customize = Dostosuj -Earned = Zdobyłeś %1 z %2 osiągnięć i %3 z %4 punktów -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Logowanie do RetroAchievements nieudane -Failed to connect to RetroAchievements. Achievements will not unlock. = Łączenie z serwerem RetroAchievements nieudane. Osiągnięcia nie będą odblokowywane. -Failed to identify game. Achievements will not unlock. = Identyfikacja gry nieudana. Osiągnięcia nie będą odblokowywane. -Hardcore Mode (no savestates) = Tryb Wyzwania (bez zapisów stanu) -Hardcore Mode = Tryb Wyzwania -How to use RetroAchievements = Jak używać RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Start Tabeli wyników udany lub nieudany -Leaderboard result submitted = Rezultat tabeli wyników przesłany -Leaderboard score submission = Przesyłanie rezultatów tabeli wyników -Leaderboard submission is enabled = Przesyłanie rezultatów tabeli wyników włączone -Leaderboard tracker = Śledzenie tabeli wyników -Leaderboards = Tabele wyników -Links = Linki -Locked achievements = Zablokowane osiągnięcia -Log bad memory accesses = Rejestruj złe dostępy do pamięci -Mastered %1 = Wymaksowane %1 -Notifications = Powiadomiemia -Recently unlocked achievements = Ostatnio odblokowane osiągnięcia -Reconnected to RetroAchievements. = Połączono ponownie z RetroAchievements. -Register on www.retroachievements.org = Zarejestruj się na www.retroachievements.org -RetroAchievements are not available for this game = Usługa RetroAchievements nie jest dostępna dla tej gry -RetroAchievements website = Strona internetowa RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = Zapis stanu załadowany bez danych osiągnięć -Save states not available in Hardcore Mode = Zapisy stanu nie są dostępne w Trybie Wyzwania -Sound Effects = Efekty dźwiękowe -Statistics = Statystyki -Submitted %1 for %2 = Przesłano %1 dla %2 -Syncing achievements data... = Synchronizacja osiągnięć... -Test Mode = Tryb Testowy -This feature is not available in Hardcore Mode = Ta funkcja nie jest dostępna w Trybie Wyzwania -This game has no achievements = Ta gra nie posiada osiągnięć -Top players = Najlepsi gracze -Unlocked achievements = Odblokowane osiągnięcia -Unofficial achievements = Nieoficjalnie osiągnięcia -Unsupported achievements = Niewspierane osiągnięcia - [Audio] Alternate speed volume = Alternatywna prędkość emulacji Audio backend = Sterownik dźwięku (wymagany restart) Audio Error = Błąd Audio -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bufory dźwięku dost. do Bluetooth (wolniejsze) Auto = Automatyczny Device = Urządzenie @@ -82,7 +23,7 @@ Analog Limiter = Ogranicznik Analoga Analog Settings = Ustawienia Analoga Analog Stick = Gałka Analogowa Analog Style = Styl Analoga -AnalogLimiter Tip = Jeśli "Ogranicznik Analoga" jest aktywny +AnalogLimiter Tip = Jeśli "ogranicznik Analoga" jest aktywny Auto = Automatyczny Auto-centering analog stick = Autocentrowanie analoga Auto-hide buttons after delay = Automatyczne ukrywanie przycisków po: @@ -95,8 +36,7 @@ Calibrate Analog Stick = Kalibracja Analoga Calibrate = Kalibracja Calibrated = Skalibrowany Calibration = Kalibracja -Circular low end radius = Okrągły promień dolny -Circular stick input = Okrągły odczyt analoga +Circular stick input = Circular stick input Classic = Klasyczny Confine Mouse = Zablokuj myszkę w oknie Control Mapping = Mapowanie przycisków @@ -108,10 +48,8 @@ Deadzone radius = Promień martwej strefy Disable D-Pad diagonals (4-way touch) = Wył. przekątne krzyżaka (pozostaw 4 kierunki) Disable diagonal input = Wyłącz wejście cyfrowe Double tap = Dwukrotne dotknięcie -Enable analog stick gesture = Włącz gesty gałki analogowej -Enable gesture control = Włącz kontrolę gestami +Enable gesture control = Włącz kontrolę kestami Enable standard shortcut keys = Włącz standardowe klawisze skrótów -frames = klatki Gesture = Gesty Gesture mapping = Konfiguracja gestów Glowing borders = Świecące krawędzie @@ -123,13 +61,13 @@ Ignore Windows Key = Ignoruj klawisz Windows Invert Axes = Odwrócone osie Invert Tilt along X axis = Odwróć przechył wzdłuż osi X Invert Tilt along Y axis = Odwróć przechył wzdłuż osi Y -Keep this button pressed when right analog is pressed = Kontynuuj naciskanie tego klawisza, gdy prawa Gałka Analogowa jest wciśnięta +Keep this button pressed when right analog is pressed = Kontynuuj naciskanie tego klawisza gdy prawa Gałka Analogowa wciśnięta Keyboard = Ustawienia klawiatury L/R Trigger Buttons = Przyciski L/R Landscape = Poziomo Landscape Auto = Poziomo automatycznie Landscape Reversed = Odwrócone poziomo -Low end radius = Promień dolny +Low end radius = Low end radius Mouse = Ustawienia myszy Mouse sensitivity = Czułość myszy Mouse smoothing = Wygładzanie myszy @@ -140,19 +78,17 @@ OnScreen = Przyciski ekranowe Portrait = Pionowo Portrait Reversed = Odwrócone pionowo PSP Action Buttons = Klawisze akcji PSP -Rapid fire interval = Raw input = Zwykłe wejście Repeat mode = Tryb powtarzania Reset to defaults = Domyślne Screen Rotation = Obrót ekranu Sensitivity (scale) = Czułość (dostosuj) Sensitivity = Czułość -Shape = Kształt -Show Touch Pause Menu Button = Pokaż dotykowy przycisk Menu Pauzy -Sticky D-Pad (easier sweeping movements) = Lepki D-Pad (łatwiejsze ruchy rozległe) -Swipe = Przesunięcie palcem -Swipe sensitivity = Czułość przesunięcia -Swipe smoothing = Wygładzanie przesunięcia +Shape = Shape +Show Touch Pause Menu Button = Pokaż przycisk Menu Pauzy +Swipe = Swipe +Swipe sensitivity = Swipe sensitivity +Swipe smoothing = Swipe smoothing Thin borders = Cienkie krawędzie Tilt control setup = Zmodyfikuj przechył... Tilt Input Type = Typ przechyłu @@ -161,10 +97,10 @@ Tilt Sensitivity along Y axis = Czułość przechyłu wzdłuż osi Y To Calibrate = Trzymaj urządzenie pod preferowanym kątem i naciśnij „Kalibracja”. Toggle mode = Zmień tryb Touch Control Visibility = Kontroler dotykowy (widoczny) -Use custom right analog = Użyj niestandardowego prawego analoga +Use custom right analog = Use custom right analog Use Mouse Control = Włącz kontrolę myszką Visibility = Widoczność -Visible = Widoczny +Visible = WIdoczny X = X Y = Y @@ -183,12 +119,12 @@ About PPSSPP... = O PPSSPP... Auto = Automatycznie Auto Max Quality = Automatyczna maksymalna &Jakość Backend = &Sterownik obrazu (Restartuje PPSSPP) -Bicubic = Dwusześcienne +Bicubic = Bicubic (Dwusześcienne) Break = Zatrzymaj Break on Load = Zatrzymaj po załadowaniu Buy Gold = Kup wersję Gold Control Mapping... = Ustawienia przycisków... -Copy PSP memory base address = Copy Skopiuj bazę i adresy pamięci PSP +Copy PSP memory base address = Copy PSP memory base &address Debugging = &Debugowanie Deposterize = Deposteryzacja Direct3D9 = &Direct3D9 @@ -213,7 +149,7 @@ GitHub = Git&Hub Hardware Transform = &Transformacja sprzętowa Help = Pomoc Hybrid = Hybrydowe -Hybrid + Bicubic = Hybrydowe + Dwusześcienne +Hybrid + Bicubic = Hybrydowe + Bicubic Ignore Illegal Reads/Writes = Ignoruj nieprawidłowe odczyty/zapisy Ignore Windows Key = Ignoruj klawisz Windows Keep PPSSPP On Top = Trzymaj PPSSPP na wierzchu @@ -230,7 +166,6 @@ Log Console = Konsola dziennika zdarzeń Memory View... = Podgląd pamięci... More Settings... = Więcej ustawień... Nearest = Najbliższe -Recent = &Ostatnie Skip Buffer Effects = &Nie renderuj efektów z bufora (niebuforowane, szybsze) Off = Wyłącz Open Chat = Otwórz Chat @@ -268,7 +203,8 @@ Take Screenshot = Wykonaj zrzut ekranu Texture Filtering = Filtrowanie tekstur Texture Scaling = Skalowanie tekstur Use Lossless Video Codec (FFV1) = &Używaj stratnego kodeka wideo (FFV1) -Use output buffer for video = Używaj buforu wyjścia dla wideo +Use output buffer for video = Use output buffer for video +Vertex Cache = Pamięć podręczna wierzchołków VSync = Limit klatek Vulkan = Vulkan Window Size = Rozmiar okna @@ -282,26 +218,20 @@ Backspace = Backspace Block address = Adres bloku By Address = Po adresie Copy savestates to memstick root = Skopiuj zapisane stany do folderu głównego Karty Pamięci -Create frame dump = Stwórz zrzut klatki Create/Open textures.ini file for current game = Stwórz/otwórz plik textures.ini z bieżącej gry Current = Obecny -Debug overlay = Nakładka debugowania -Debug stats = Statystyki debugowania Dev Tools = Narzędzia Developerskie -DevMenu = Menu deweloperskie +DevMenu = DevMenu Disabled JIT functionality = Wyłącz funkcje JIT -Draw Frametimes Graph = Narysuj wykres czasu klatki +Draw Frametimes Graph = Draw frametimes graph Dump Decrypted Eboot = Zachowuj odszyfrowany EBOOT.BIN przy starcie Dump next frame to log = Zrzuć następną klatkę do dziennika zdarzeń Enable driver bug workarounds = Uruchom obejścia błędów sterownika Enable Logging = Włącz dziennik zdarzeń debugera Enter address = Wprowadź adres FPU = FPU -Fragment = Fragment -Frame timing = Frame timing -Framedump tests = Test zrzutu klatki +Framedump tests = Framedump tests Frame Profiler = Profiler klatki -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Test sterownika GPU GPU log profiler = Profilowanie logów GPU GPU Profile = Profil GPU @@ -311,15 +241,13 @@ Log Dropped Frame Statistics = Loguj statystyki pominiętych klatek Log Level = Poziom dziennika zdarzeń Log View = Pokaż dziennik zdarzeń Logging Channels = Kanały dziennika zdarzeń debugera -Multi-threaded rendering = Renderowanie wielowątkowe Next = Następny No block = Brak bloku -Off = Wyłączone Prev = Poprzedni Random = Przypadkowy Replace textures = Podmiana tekstur Reset = Reset -Reset limited logging = Zresetuj ograniczone logi +Reset limited logging = Reset limited logging RestoreDefaultSettings = Czy na pewno chcesz przywrócić domyślne ustawienia?\n\nNie można tego cofnąć.\nZrestartuj PPSSPP, aby zastosować zmiany. RestoreGameDefaultSettings = Czy na pewno chcesz przywrócić ustawienia specyficzne dla danych gier\npowrót do ustawień domyślnych PPSSPP? Resume = Wznów @@ -327,32 +255,26 @@ Run CPU Tests = Uruchom testy CPU Save new textures = Zapisz nową teksturę Shader Viewer = Podgląd Shaderów Show Developer Menu = Pokaż przycisk menu dewelopera -Show on-screen messages = Pokaż komunikaty na ekranie +Show on-screen messages = Show on-screen messages Stats = Statystyki System Information = Informacje o systemie Texture ini file created = Stworzono plik ini Tekstury Texture Replacement = Podmiana tekstur -Audio Debug = Debugowanie audio -Control Debug = Debugowanie sterowania +Toggle Audio Debug = Wł./Wył. debugowanie audio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Wł./Wył. zamrożenie Touchscreen Test = Test ekranu dotykowego -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] -%d seconds = %d sekund +%d seconds = %d seconds * PSP res = * rozdz. PSP Active = Aktywny Back = Powrót -Bottom Center = Dolny środek -Bottom Left = Dolne lewo -Bottom Right = Dolne prawo Cancel = Anuluj Center = Wyśrodkuj -Center Left = Środkowe lewo -Center Right = Środkowe prawo -Changing this setting requires PPSSPP to restart. = Zmiana tego ustawienia wymaga ponownego uruchomienia PPSSPP. +ChangingGPUBackends = Zmiana sterownika grafiki wymaga restartu PPSSPP. Zrestartować teraz? +ChangingInflightFrames = Zmiana komend buffera grafiki wymaka restartu PPSSPP. Zrestartować teraz? Channel: = Kanał: Choose PPSSPP save folder = Wybierz folder do zapisu stanów PPSSPP Confirm Overwrite = Czy chcesz nadpisać te dane? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Czy na pewno chcesz usunąć ustawienia dla tej gry? DeleteFailed = Nie można usunąć danych. Deleting = Usuwanie\nProszę czekać... Disable All = Wyłącz wszystko -Disabled = Wyłączono -Dumps = Zrzuty +Dumps = Dumps Edit = Edytuj Enable All = Włącz wszystko -Enabled = Włączono Enter = Dalej -Failed to connect to server, check your internet connection. = Połączenie z serwerem nieudane, sprawdź swoje połączenie z internetem. -Failed to log in, check your username and password. = Logowanie nieudane, sprawdź swoje hasło i nazwę użytkownika. Filter = Filtruj Finish = Zakończ -GE Frame Dumps = Zrzuty klatek GE -Grid = Rozmiar siatki +GE Frame Dumps = GE Frame Dumps +Grid = Siatka Inactive = Nieaktywny -Installing... = Instalowanie... InternalError = Występił wewnętrzny błąd aplikacji -Links = Linki Load = Wczytaj Load completed = Ładowanie zakończone. Loading = Ładowanie\nProszę czekać... LoadingFailed = Nie można wczytać danych. -Log in = Zaloguj -Log out = Wyloguj -Logged in! = Zalogowano! -Logging in... = Logowanie... Move = Przenieś -Move Down = Przenieś w dół -Move Up = Przenieś w górę +Move Down = Move Down +Move Up = Move Up Network Connection = Połączenie sieciowe NEW DATA = NOWE DANE No = Nie -None = Nic ObtainingIP = Uzyskiwanie adresu IP.\nProszę czekać... OK = OK Old savedata detected = Wykryto stary zapis gry Options = Opcje -Password = Hasło -Remove = Usuń +Remove = Remove Reset = Resetuj Resize = Przeskaluj -Restart = Uruchom ponownie Retry = Spróbuj ponownie Save = Zapisz Save completed = Zapisywanie zakończone. @@ -420,23 +329,18 @@ SavingFailed = Nie można zapisać danych. Search = Szukaj seconds, 0:off = sekundy, 0 = wył. Select = Wybierz -Settings = Ustawienia Shift = Shift Skip = Pomiń -Snap = Tryb siatki +Snap = Snap Space = Spacja SSID = SSID Submit = Wyślij Supported = Wspierane There is no data = Brak danych. Toggle All = Wybierz wszystko -Toggle List = Wybierz listę -Top Center = Górny środek -Top Left = Górne lewo -Top Right = Górne prawo +Toggle List = Toggle list Unsupported = Niewspierane -Username = Nazwa użytkownika -When you save, it will load on a PSP, but not an older PPSSPP = Jeśli zapiszesz, PSP wczyta ten zapis gry, ale starsze PPSSPP już nie. +When you save, it will load on a PSP, but not an older PPSSPP = Jeśli zapiszesz, PSP wczyta ten zapis gry, ale starszy PPSSPP już nie. When you save, it will not work on outdated PSP Firmware anymore = Jeśli zapiszesz, ten zapis nie zadziała już na starych wersjach firmware PSP. Yes = Tak Zoom = Powiększ @@ -444,7 +348,7 @@ Zoom = Powiększ [Error] 7z file detected (Require 7-Zip) = plik skompresowany (7z).\nProszę najpierw wypakować (spróbuj 7-Zip lub WinRAR). A PSP game couldn't be found on the disc. = Na dysku nie znaleziono gry na PSP. -Cannot boot ELF located outside mountRoot. = Nie można uruchomić ELF znajdującego się poza mountRoot. +Cannot boot ELF located outside mountRoot. = Cannot boot ELF located outside mountRoot. Could not save screenshot file = Nie można zapisać zrzutu ekranu. D3D9or11 = Direct3D 9? (Wybierz "nie" by wybrać Direct3D 11) D3D11CompilerMissing = Plik D3DCompiler_47.dll nie został znaleziony. Proszę go zainstalować, lub nacisnąć Tak, by przełączyć się na Direct3D 9. @@ -452,7 +356,7 @@ D3D11InitializationError = Błąd inicjalizacji sterownika Direct3D 11 D3D11Missing = Twój system operacyjny nie posiada D3D11. Proszę uruchomić Windows Update.\n\nNaciśnij Tak, by przełączyć się na Direct3D 9. D3D11NotSupported = Twoja karta graficzna nie wspiera Direct3D 11.\n\nCzy chcesz przełączyć się na Direct3D 9? Disk full while writing data = Dysk zapełniony. -ELF file truncated - can't load = Okrojony plik ELF - nie można załadować +ELF file truncated - can't load = ELF file truncated - can't load Error loading file = Wystąpił błąd: Error reading file = Błąd podczas odczytywania pliku. Failed initializing CPU/Memory = Nie można zainicjować CPU lub pamięci @@ -484,11 +388,8 @@ PS1 EBOOTs are not supported by PPSSPP. = Pliki EBOOT PS1 nie są obsługiwane p PSX game image detected. = Plik jest obrazem MODE2. PPSSPP nie obsługuje gier z PS1. RAR file detected (Require UnRAR) = Wykryto plik RAR.\nRozpakuj go przed użyciem (spróbuj UnRAR). RAR file detected (Require WINRAR) = Wykryto plik RAR.\nRozpakuj go przed użyciem (spróbuj WinRAR). -Running slow: try frameskip, sound is choppy when slow = Running slow: try frameskip, sound is choppy when slow -Running slow: Wypróbuj pomijania klatek, dźwięk przerywa gdy emulacja spowalnia = Running slow: try frameskip, sound is choppy when slow -Running slow: Try turning off Software Rendering = Running slow: try turning off "software rendering" -Running slow: Wolne działanie: spróbuj pomijania klatek, dźwięk zacina przy wolnym działaniu -Running slow: Wolne działanie: spróbuj wyłączyć "Renderowanie programowe" +Running slow: try frameskip, sound is choppy when slow = Wolne działanie: spróbuj pomijania klatek, dźwięk zacina przy wolnym działaniu +Running slow: Try turning off Software Rendering = Wolne działanie: spróbuj wyłączyć "Renderowanie programowe" Save encryption failed. This save won't work on real PSP = Nie można zaszyfrować pliku zapisu gry. Ten zapis gry nie zadziała na prawdziwym PSP. textures.ini filenames may not be cross-platform = Nazwy plików w "textures.ini" mogą nie być kompatybilne między platformami. This is a saved state, not a game. = To jest zapis stanu, a nie gra. @@ -496,33 +397,26 @@ This is save data, not a game. = To jest zapis gry, a nie gra. Unable to create cheat file, disk may be full = Nie można utworzyć pliku kodów, dysk może być już zapełniony. Unable to initialize rendering engine. = Nie można zainicjować silnika renderowania. Unable to write savedata, disk may be full = Nie można zapisać danych zapisu gry, dysk może być już zapełniony. -Warning: Ostrzeżenie: Pamięć wideo jest PEŁNA, nastąpi zmniejszenie rozdzielczości i zmiana na powolne buforowanie. -Warning: Ostrzeżenie: Pamięć wideo jest PEŁNA, nastąpi zmiana na powolne buforowanie. -Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = Warning: Video memory FULL, reducing upscaling and switching to slow caching mode. -Warning: Video memory FULL, switching to slow caching mode = Warning: Video memory FULL, switching to slow caching mode. +Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = Ostrzeżenie: Pamięć wideo jest PEŁNA, nastąpi zmniejszenie rozdzielczości i zmiana na powolne buforowanie. +Warning: Video memory FULL, switching to slow caching mode = Ostrzeżenie: Pamięć wideo jest PEŁNA, nastąpi zmiana na powolne buforowanie. ZIP file detected (Require UnRAR) = Wykryto plik ZIP.\nRozpakuj go przed użyciem (spróbuj UnRAR). ZIP file detected (Require WINRAR) = Wykryto plik ZIP.\nRozpakuj go przed użyciem (spróbuj WinRAR). [Game] Asia = Azja -Calculate CRC = Oblicz CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO +Calculate CRC = Calculate CRC ConfirmDelete = Usuń -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Utwórz konfigurację gry Create Shortcut = Utwórz skrót Delete Game = Usuń grę Delete Game Config = Usuń konfigurację gry Delete Save Data = Usuń zapisy gry Europe = Europa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Gra -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Ustawienia gry Homebrew = Homebrew Hong Kong = Hongkong InstallData = Zainstalowane dane -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japonia Korea = Korea MB = MB @@ -532,14 +426,12 @@ Remove From Recent = Usuń z "Ostatnio uruchamianych tytułów" SaveData = Zapisy gier Setting Background = Ustawianie tła Show In Folder = Pokaż w folderze -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Użyj tego tła [Graphics] -% of the void = % pustej przestrzeni -% of viewport = % widocznego obszaru +% of the void = % of the void +% of viewport = % of viewport %, 0:unlimited = %, 0 = bez limitu (supersampling) = (supersampling) (upscaling) = (skalowanie) @@ -563,28 +455,28 @@ Aggressive = Agresywne Alternative Speed = Alternatywna prędkość (w %, 0 = bez limitu) Alternative Speed 2 = Alternatywna prędkość 2 (w %, 0 = bez limitu) Anisotropic Filtering = Filtrowanie anizotropowe -Antialiasing (MSAA) = Wygładzanie krawędzi (MSAA) -Aspect Ratio = Proporcje ekranu +Antialiasing (MSAA) = Antialiasing (MSAA) +Aspect Ratio = Aspect Ratio Auto = Automatyczne Auto (1:1) = Automatyczna (1:1) -Auto (same as Rendering) = Automatyczne (jak roz. renderowania) +Auto (same as Rendering) = Auto (jak roz. renderowania) Auto FrameSkip = Automatyczne pomijanie klatek -Auto Max Quality = Automatyczne (Maksymalna jakość) +Auto Max Quality = Auto Max Quality Auto Scaling = Automatyczne skalowanie Backend = Sterownik graficzny Balanced = Zbalansowane Bicubic = Bicubic (Dwusześcienne) Both = Oba -Buffer graphics commands (faster, input lag) = Bufor komend grafiki (szybsze, może powodować lagi sterowania) +Buffer graphics commands (faster, input lag) = Bufor komand grafiki (szybsze, może powodować lagi sterowania) BufferedRenderingRequired = Uwaga: Ta gra wymaga włączonej opcji "Renderowanie buforowe". Camera = Kamera -Camera Device = Kamera (urządzenie) +Camera Device = Kamera Cardboard Screen Size = Rozmiar ekranu (% widocznego obszaru) Cardboard Screen X Shift = Przesunięcie X (% pustej przestrzeni) Cardboard Screen Y Shift = Przesunięcie Y (% pustej przestrzeni) Cardboard VR Settings = Ustawienia Google Cardboard VR -Cheats = Kody -CPU Core = Rdzeń procesora +Cheats = Cheats +CPU Core = Core CPU Debugging = Debugowanie DefaultCPUClockRequired = Uwaga: Ta gra wymaga, by częstotliwość taktowania CPU była domyślna. Deposterize = Deposteryzacja @@ -601,8 +493,8 @@ Frame Rate Control = Kontrola klatek na sekundę Frame Skipping = Pomijanie klatek Frame Skipping Type = Tryb pomijania klatek FullScreen = Pełny ekran -Geometry shader culling = Przycinanie shaderów geometrii -GPUReadbackRequired = Uwaga: Ta gra wymaga wyłączenia opcji "Pomiń odczyty zwrotne GPU". +Geometry shader culling = Geometry shader culling +GPUReadbackRequired = Warning: This game requires "Skip GPU Readbacks" to be set to Off. Hack Settings = Ustawienia specjalne (powodują problemy) Hardware Tessellation = Sprzętowa teselacja Hardware Transform = Transformacja sprzętowa @@ -610,12 +502,12 @@ hardware transform error - falling back to software = Błąd transformacji sprz HardwareTessellation Tip = Tworzy krzywe sprzętowo High = Wysokie Hybrid = Hybrydowe -Hybrid + Bicubic = Hybrydowe + Dwusześcienne -Ignore camera notch when centering = Ignoruj przesunięcie kamery podczas centrowania -Integer scale factor = Całkowity współczynnik skali +Hybrid + Bicubic = Hybrydowe + Bicubic +Ignore camera notch when centering = Ignore camera notch when centering +Integer scale factor = Integer scale factor Internal Resolution = Rozdzielczość wewnętrzna Lazy texture caching = Leniwa pamięć tekstur (przyśpieszenie) -Lazy texture caching Tip = Szybsze, ale może powodować problemy z tekstem/napisami w niektórych grach +Lazy texture caching Tip = Faster, but can cause text problems in a few games Linear = Liniowe Low = Niskie LowCurves = Detale krzywych sklejanych/Beziera (przyśpieszenie) @@ -624,13 +516,12 @@ Lower resolution for effects (reduces artifacts) = Zmniejszenie rozdzielczość Manual Scaling = Ręczne skalowanie Medium = Średnie Mode = Tryb -Must Restart = Musisz zrestartować PPSSPP, aby zastosować zmiany. +Must Restart = Musisz zrestartować PPSSPP, aby zobaczyć zmiany. Native device resolution = Natywna rozdzielczość urządzenia Nearest = Najbliższe -No buffer = Bez bufora -Render all frames = Render all frames -Show Battery % = Pokaż % baterii -Show Speed = Pokaż prędkość +No buffer = No buffer +Show Battery % = Show Battery % +Show Speed = Show Speed Skip Buffer Effects = Nie renderuj efektów z bufora (niebuforowane, szybsze) None = Wył. Number of Frames = Ilość klatek @@ -641,9 +532,9 @@ Partial Stretch = Częściowe rozciągnięcie Percent of FPS = Procent FPS Performance = Wydajność Postprocessing shaders = Efekty wizualne shaderów -Recreate Activity = Odtwórz czynność +Recreate Activity = Recreate activity Render duplicate frames to 60hz = Renderuj duplikowane klatki w 60 Hz -RenderDuplicateFrames Tip = Może zwiększyć płynność w grach o niskiej ilości klatek na sekundę +RenderDuplicateFrames Tip = Can make framerate smoother in games that run at lower framerates Rendering Mode = Tryb renderowania Rendering Resolution = Rozdzielczość renderowania RenderingMode NonBuffered Tip = Szybsze, ale niektóre gry mogą się nie wyświetlać @@ -652,28 +543,29 @@ Safe = Bezpieczne Screen Scaling Filter = Filtrowanie skalowania ekranu Show Debug Statistics = Pokaż statystyki debugowania Show FPS Counter = Pokaż licznik FPS -Skip GPU Readbacks = Pomiń odczyty zwrotne GPU +Skip GPU Readbacks = Skip GPU Readbacks Software Rendering = Renderowanie programowe (wolne) Software Skinning = Programowy skinning SoftwareSkinning Tip = Łączy na CPU wywołania rysujące modele z animacjami, przyspieszenie w większości gier Speed = Prędkość (procentowo) -Speed Hacks = Haki Prędkościowe (powodują problemy) -Stereo display shader = Stereoskopowe wyświetlanie shaderów -Stereo rendering = Renderowanie stereoskopowe +Speed Hacks = Speed Hacks (powodują problemy) +Stereo display shader = Stereo display shader +Stereo rendering = Stereo rendering Stretch = Rozciąganie Texture Filter = Filtrowanie tekstur Texture Filtering = Filtrowanie tekstur -Texture replacement pack activated = Paczka podmienionych tekstur aktywowana Texture Scaling = Skalowanie tekstur -Texture Shader = Shadery tekstur +Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Wyłącz sprzętową teselację: opcja nie jest wspierana Unlimited = Bez limitu -Up to 1 = Maks. jeden -Up to 2 = Maks. dwa +Up to 1 = Up to 1 +Up to 2 = Up to 2 Upscale Level = Poziom skalowania Upscale Type = Rodzaj skalowania UpscaleLevel Tip = Obciąża CPU - skalowanie może zostać opóźnione by zapobiec spadkom płynności Use all displays = Używaj wszystkich monitorów +Vertex Cache = Pamięć podręczna wierzchołków +VertexCache Tip = Szybsze, jednak może powodować krótkotrwałe migotanie VSync = Synchronizacja pionowa Vulkan = Vulkan Window Size = Rozmiar okna @@ -685,23 +577,21 @@ Install = Zainstaluj Install game from ZIP file? = Zainstalować grę z pliku ZIP? Install textures from ZIP file? = Czy zainstalować teksturę z archiwum ZIP? Installed! = Zainstalowano! -Texture pack doesn't support install = Paczka tekstur nie obsługuje instalacji -Zip archive corrupt = Niepoprawne archiwum ZIP +Texture pack doesn't support install = Texture pack doesn't support install +Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = Archiwum ZIP nie zawiera aplikacji dla PSP [KeyMapping] -Allow combo mappings = Zezwalaj na mapowanie kombinacji Autoconfigure = Autokonfiguracja Autoconfigure for device = Skonfiguruj automatycznie -Bind All = Przypisz (wszystkie) -Clear All = Wyczyść (wszystkie) -Combo mappings are not enabled = Mapowanie kombinacji jest wyłączone -Default All = Domyślne (wszystkie) +Bind All = Bind All +Clear All = Wyczyść +Default All = Domyślne Map a new key for = Przypisz nowy klawisz dla Map Key = Mapuj przycisk Map Mouse = Mapuj mysz -Replace = Zamień -Show PSP = Pokaż PSP +Replace = Replace +Show PSP = Show PSP You can press ESC to cancel. = Możesz zamknąć to okienko naciskając Esc. [MainMenu] @@ -714,11 +604,11 @@ Exit = Zamknij Game Settings = Ustawienia Games = Gry Give PPSSPP permission to access storage = Zezwól PPSSPP na dostęp do pamięci -Homebrew & Demos = Homebrew i Dema +Homebrew & Demos = Homebrew i dema How to get games = Jak zdobyć gry? How to get homebrew & demos = Jak zdobyć gry homebrew i dema? Load = Otwórz... -Loading... = Ładowanie... +Loading... = Loading... PinPath = Przypnij PPSSPP can't load games or save right now = PPSSPP nie może teraz załadować gier ani zapisywać stanów Recent = Ostatnio uruchamiane @@ -726,7 +616,7 @@ SavesAreTemporary = PPSSPP zapisuje do pamięci tymczasowej SavesAreTemporaryGuidance = Wypakuj PPSSPP, by móc trwale zapisywać SavesAreTemporaryIgnore = Ignoruj UnpinPath = Odepnij -UseBrowseOrLoad = Użyj opcji "Przeglądaj", aby wybrać folder lub "Otwórz", aby wybrać plik. +UseBrowseOrLoad = Use Browse to choose a folder, or Load to choose a file. www.ppsspp.org = www.ppsspp.org [MainSettings] @@ -734,7 +624,7 @@ Audio = Dźwięk Controls = Sterowanie Graphics = Grafika Networking = Sieć -Search = Wyszukiwanie +Search = Search System = System Tools = Narzędzia @@ -746,85 +636,90 @@ An.Left = Gałka w lewo An.Right = Gałka w prawo An.Up = Gałka w górę Analog limiter = Ogranicznik analoga -Analog speed = Prędkość analoga +Analog speed = Analog speed Analog Stick = Gałka analogowa Audio/Video Recording = Nagrywanie audio/video AxisSwap = Zamiana osi -Circle = Kółko -Cross = Krzyżyk -Custom %d = Niestandardowe %d -D-pad down = Krzyżak w dół -D-pad left = Krzyżak w lewo -D-pad right = Krzyżak w prawo -D-pad up = Krzyżak w górę -DevMenu = Menu deweloperskie -Display Landscape = Tryb panoramiczny -Display Landscape Reversed = Tryb panoramiczny (odwrócony) -Display Portrait = Tryb portretowy -Display Portrait Reversed = Tryb portretowy (odwrócony) -Double tap button = Przycisk podwójnego stuknięcia +Circle = Circle +Cross = Cross +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 +D-pad down = D-pad down +D-pad left = D-pad left +D-pad right = D-pad right +D-pad up = D-pad up +DevMenu = Menu developerskie +Display Landscape = Display Landscape +Display Landscape Reversed = Display Landscape Reversed +Display Portrait = Display Portrait +Display Portrait Reversed = Display Portrait Reversed +Double tap button = Double tap button Down = Strzałka w dół Dpad = Krzyżak -Exit App = Exit App Frame Advance = Nast. klatka -Hold = Wstrzymaj +Hold = Hold Home = Home L = L Left = Strzałka w lewo Load State = Wczytaj stan -Mute toggle = Przełącznik wyciszenia -Next Slot = Następny Slot -None = Nic -Note = Notka -OpenChat = Otwórz czat +Mute toggle = Mute toggle +Next Slot = Następny slot +None = None +Note = Note +OpenChat = Open chat Pause = Pauza -Previous Slot = Poprzedni Slot R = R RapidFire = Auto. strzelanie -Record = Nagraj -Remote hold = Zdalne przytrzymanie +Record = Record +Remote hold = Remote hold Rewind = Przewiń do tyłu Right = Strzałka w prawo -Right Analog Stick = Prawa gałka analogowa +Right Analog Stick = Prawa Gałka Analogowa RightAn.Down = Pr. gałk. w dół RightAn.Left = Pr. gałk. w lewo RightAn.Right = Pr. gałk. w prawo RightAn.Up = Pr. gałk. w górę -Rotate Analog (CCW) = Obróć analog (CCW) -Rotate Analog (CW) = Obróć analog (CW) +Rotate Analog (CCW) = Rotate analog (CCW) +Rotate Analog (CW) = Rotate analog (CW) Save State = Zapisz stan -Screen = Ekran +Screen = Screen Screenshot = Zrzut ekranu Select = Select SpeedToggle = Zmień prędkość -Square = Kwadrat +Square = Square Start = Start -Swipe Down = Przesunięcie palcem w dół -Swipe Left = Przesunięcie palcem w lewo -Swipe Right = Przesunięcie palcem w prawo -Swipe Up = Przesunięcie palcem w górę -tap to customize = Dotknij, aby dostosować +Swipe Down = Swipe Down +Swipe Left = Swipe Left +Swipe Right = Swipe Right +Swipe Up = Swipe Up +tap to customize = tap to customize Texture Dumping = Zrzut tekstur Texture Replacement = Podmiana tekstur Toggle Fullscreen = Wł./wył. pełny ekran -Toggle mode = Tryb przełączania -Toggle WLAN = Przełącz WLAN -Triangle = Trójkąt +Toggle mode = Toggle mode +Triangle = Triangle Fast-forward = Pełna prędkość Up = Strzałka w górę -Vol + = Głośność + -Vol - = Głośność - +Vol + = Vol + +Vol - = Vol - Wlan = WLAN [MemStick] -Already contains PSP data = Już zawiera dane PSP -Cancelled - try again = Anulowano - spróbuj ponownie -Create or Choose a PSP folder = Utwórz lub Wybierz folder PSP -Current = Obecny -DataCanBeShared = Dane mogą być udostępniane pomiędzy zwykłą wersją PPSSPP, a wersją Gold -DataCannotBeShared = Dane NIE mogą być udostępniane pomiędzy zwykłą wersją PPSSPP, a wersją Gold! -DataWillBeLostOnUninstall = Uwaga! Utracisz wszystkie dane po odinstalowaniu PPSSPP! -DataWillStay = Dane zostaną na urządzeniu, nawet po odinstalowaniu PPSSPP. +Already contains PSP data = Already contains PSP data +Create or Choose a PSP folder = Create or Choose a PSP folder +Current = Current +DataCanBeShared = Data can be shared between PPSSPP regular/Gold +DataCannotBeShared = Data CANNOT be shared between PPSSPP regular/Gold! +DataWillBeLostOnUninstall = Warning! Data will be lost when you uninstall PPSSPP! +DataWillStay = Data will stay even if you uninstall PPSSPP. Done! = Ukończono! EasyUSBAccess = Łatwy dostęþ do USB Failed to move some files! = Nie udało się przenieść niektórych plików! @@ -832,97 +727,87 @@ Failed to save config = Nie udało się zapisać ustawień Free space = Wolne miejsce Manually specify PSP folder = Ustaw folder PSP ręcznie MemoryStickDescription = Wybierz, gdzie chcesz umieścić dane PSP (Karta Pamięci) -Move Data = Przenieś dane -Selected PSP Data Folder = Wybrany folder danych PSP -No data will be changed = Żadne dane nie zostaną zmienione -PPSSPP will restart after the change = Po zmianie nastąpi reset PPSSPP -Skip for now = Na razie pomiń -Starting move... = Rozpoczynam przenoszenie... -That folder doesn't work as a memstick folder. = Ten folder nie działa jako folder kary pamięci. +Move Data = Move Data +Selected PSP Data Folder = Selected PSP Data Folder +No data will be changed = No data will be changed +PPSSPP will restart after the change = PPSSPP will restart after the change +Skip for now = Skip for now +Starting move... = Starting move... +That folder doesn't work as a memstick folder. = That folder doesn't work as a memstick folder. USBAccessThrough = Dostęp do USB poprzez Android/data/org.ppsspp.ppsspp/files USBAccessThroughGold = Dostęþ do USB poprzez Android/data/org.ppsspp.ppssppgold/files -Use App Private Data = Użyj prywatnych danych aplikacji -Use PSP folder at root of storage = Użyj folderu PSP jako głównego magazynu danych -Welcome to PPSSPP! = Witaj w PPSSPP! -WhatsThis = A co to? +Use App Private Data = Use App Private Data +Use PSP folder at root of storage = Use PSP folder at root of storage +Welcome to PPSSPP! = Welcome to PPSSPP! +WhatsThis = What's this? [Networking] -AdHoc Server = Serwer Ad-Hoc -AdhocServer Failed to Bind Port = Błąd przy przypisywaniu portu na serwerze Ad-Hoc -AM: Data from Unknown Port = AM: Dane z nieznanego portu -Auto = Automatycznie +AdHoc Server = Ad hoc server +AdhocServer Failed to Bind Port = Ad hoc server failed to bind port +AM: Data from Unknown Port = AM: Data from Unknown Port +Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Zmień adres MAC Change proAdhocServer Address = Zmień adres IP serwera PRO dla trybu ad hoc (localhost = multiple instances) -ChangeMacSaveConfirm = Wygenerować nowy adres MAC? -ChangeMacSaveWarning = Niektóre gry weryfikują adres MAC przy odczytywaniu zapisu, co może popsuć stare zapisy. -Chat = Czat +ChangeMacSaveConfirm = Generate a new MAC address? +ChangeMacSaveWarning = Some games verify the MAC address when loading savedata, so this may break old saves. +Chat = Chat Chat Button Position = Pozycja przycisku chatu Chat Here = Napisz wiadomość Chat message = Wiadomość Chat Screen Position = Pozycja ekranu chatu -Disconnected from AdhocServer = Rozłączono z serwerem Ad-Hoc -DNS Error Resolving = Rozwiązywanie błędów DNS -Enable built-in PRO Adhoc Server = Włącz wbudowany serwer PRO dla trybu Ad-Hoc -Enable network chat = Uruchom czat +Disconnected from AdhocServer = Rozłączono z ad hoc serwerem +DNS Error Resolving = DNS error resolving +Enable built-in PRO Adhoc Server = Włącz wbudowany serwer PRO dla trybu ad hoc +Enable network chat = Uruchom chat Enable networking = Włącz sieć/WLAN (beta, może powodować błędy) Enable UPnP = Uruchom UPnP (potrzebuje kilka sekund na wykrycie) EnableQuickChat = Uruchom szybki chat -Enter a new PSP nickname = Wpisz nową nazwę użytkownika PSP +Enter a new PSP nickname = Enter a new PSP nickname Enter Quick Chat 1 = Wejdź na szybki chat 1 Enter Quick Chat 2 = Wejdź na szybki chat 2 Enter Quick Chat 3 = Wejdź na szybki chat 3 Enter Quick Chat 4 = Wejdź na szybki chat 4 Enter Quick Chat 5 = Wejdź na szybki chat 5 Error = Błąd -Failed to Bind Localhost IP = Błąd przy przypisywaniu adresu IP lokalnego hosta -Failed to Bind Port = Błąd przy przypisywaniu portu -Failed to connect to Adhoc Server = Błąd przy łączeniu z serwerem Ad-Hoc +Failed to Bind Localhost IP = Failed to bind localhost IP +Failed to Bind Port = Failed to bind port +Failed to connect to Adhoc Server = Failed to connect to ad hoc server Forced First Connect = Wymuszenie pierwszego połączenie (szybsze łączenie) -#GM = Dane z nieznanego portu -GM: Data from Unknown Port = GM: Dane z nieznanego portu -Hostname = Nazwa hosta -Invalid IP or hostname = Niepoprawny adres IP lub nazwa hosta +GM: Data from Unknown Port = GM: Data from Unknown Port +Hostname = Hostname +Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimalny czas oczekiwania (podaj w ms, domyślnie 0) Misc = Inne (domyślnie = Kompatybilność z PSP) Network Initialized = Sieć została zainicjowana -Please change your Port Offset = Proszę zmienić port +None = None +Please change your Port Offset = Please change your port offset Port offset = Zmień port (0 = zgodne z PSP) Open PPSSPP Multiplayer Wiki Page = Przejdź do strony PPSSPP pomocy dla wielu graczy. -proAdhocServer Address: = Adres serwera Ad-Hoc: -Quick Chat 1 = Szybki czat 1 -Quick Chat 2 = Szybki czat 2 -Quick Chat 3 = Szybki czat 3 -Quick Chat 4 = Szybki czat 4 -Quick Chat 5 = Szybki czat 5 -QuickChat = Szybki czat -Randomize = Losuj -Send = Wyślij -Send Discord Presence information = Przesyłaj informacje Discord Rich Presence +proAdhocServer Address: = Ad hoc server address: +Quick Chat 1 = Quick chat 1 +Quick Chat 2 = Quick chat 2 +Quick Chat 3 = Quick chat 3 +Quick Chat 4 = Quick chat 4 +Quick Chat 5 = Quick chat 5 +QuickChat = Quick chat +Send = Send +Send Discord Presence information = Transmituj informacje Discord Rich Presence +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Nie udało się zlokalizować urządzenia UPnP -UPnP (port-forwarding) = UPnP (przekierowanie portów) -UPnP need to be reinitialized = Należy ponownie zainicjować UPnP +UPnP (port-forwarding) = UPnP (port forwarding) +UPnP need to be reinitialized = UPnP need to be reinitialized UPnP use original port = UPnP używa oryginalnego portu (włączone = kompatybilność z PSP) -UseOriginalPort Tip = Może nie działać ze wszystkimi grami i/lub urządzeniami. Po więcej informacji udaj się na wiki. +UseOriginalPort Tip = May not work for all devices or games, see wiki. Validating address... = Uwierzytelnianie addresu... WLAN Channel = Kanał WLAN -You're in Offline Mode, go to lobby or online hall = Jesteś w trybie offline; wejdź do lobby lub pokoju online - -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Język gry -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Gry często nie wspierają wszystkich języków -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish +You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall [Pause] Cheats = Kody @@ -940,53 +825,50 @@ Undo last load = Cofnij ostatnio wczytane Undo last save = Cofnij ostatni zapis [PostShaders] -(duplicated setting, previous slider will be used) = (zduplikowane ustawienia; użyte zostanie poprzednie ustawienie) +(duplicated setting, previous slider will be used) = (duplicated setting, previous slider will be used) 4xHqGLSL = Skalowanie 4×HQ 5xBR = 5xBR pixel art upscaler 5xBR-lv2 = 5xBR-lv2 pixel art upscaler AAColor = Kolor AA -Amount = Ilość -Animation speed (0 -> disable) = Prędkość animacji (0 -> wył.) -Aspect = Proporcje +Amount = Amount +Animation speed (0 -> disable) = Animation speed (0 -> disable) +Aspect = Aspect Black border = Black border Bloom = Efekt rozmycia -BloomNoBlur = Bloom (no blur) -Brightness = Jasność +Brightness = Brightness Cartoon = Komiks -CatmullRom = Dwusześcienny (Catmull-Rom) Upscaler -ColorCorrection = Korekcja kolorów -ColorPreservation = Zachowanie kolorów -Contrast = Kontrast +CatmullRom = Bicubic (Catmull-Rom) Upscaler +ColorCorrection = Color correction +ColorPreservation = Color preservation +Contrast = Contrast CRT = Imitacja monitora CRT -FakeReflections = FakeReflections FXAA = Wygładzanie FXAA Gamma = Gamma -GreenLevel = Poziom zieleni -Intensity = Intensywność -LCDPersistence = Trwałość wyświetlacza LCD -MitchellNetravali = Dwusześcienny (Mitchell-Netravali) Upscaler +GreenLevel = Green level +Intensity = Intensity +LCDPersistence = LCD Persistence +MitchellNetravali = Bicubic (Mitchell-Netravali) Upscaler Natural = Naturalne kolory NaturalA = Naturalne kolory (bez rozmycia) Off = Wyłącz -Power = Moc -PSPColor = Kolor PSP -RedBlue = Czerwono-niebieskie okulary -Saturation = Saturacja +Power = Power +PSPColor = PSP color +RedBlue = Red/Blue glasses +Saturation = Saturation Scanlines = Linie skanowania Sharpen = Wyostrzenie -SideBySide = Wyświetlanie obok siebie -SSAA(Gauss) = Wygładzanie metodą supersampling (algorytm Gaussa) -Strength = Siła +SideBySide = Side by side (SBS) +SSAA(Gauss) = Supersampling AA (Gauss) +Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Skalowanie Spline36 -VideoSmoothingAA = Wygładzanie wideo +VideoSmoothingAA = Video Smoothing AA Vignette = Winieta [PSPCredits] all the forum mods = wszystkich moderatorów forum -build server = Serwer kompilacji +build server = Ciągła Integracja Buy Gold = Kup PPSSPP Gold check = Wypróbuj również Dolphin, najlepszy emulator Wii/GC: CheckOutPPSSPP = Wypróbuj PPSSPP, świetny emulator PSP: https://www.ppsspp.org/ @@ -1015,12 +897,12 @@ tools = Wykorzystane narzędzia: # Add translators1-6 for up to 6 lines of translator credits. # Leave extra lines blank. 4 contributors per line seems to look best. translators1 = Daniel Kluz, Michał Kasprzak, Mateusz Godlewski, Łukasz Bereza -translators2 = oop23, Silent, Patrxgt, Dominik +translators2 = oop23, Silent translators3 = Poprzednią edycję tłumaczenia stworzyli: translators4 = hrydgard, The Dax, mikusp, adrian17 translators5 = translators6 = -Twitter @PPSSPP_emu = X (Twitter): @PPSSPP_emu +Twitter @PPSSPP_emu = Twitter @PPSSPP_emu website = Zajrzyj na stronę: written = Napisano w C++ dla wydajności i mobilności @@ -1035,9 +917,9 @@ Remote Subdirectory = Podkatalog zdalny RemoteISODesc = Lista aktualnie udostępnianych gier RemoteISOLoading = Połączono. Ładowanie listy gier... RemoteISOScanning = Skanowanie... Wciśnij "Udostępniaj gry" na urządzeniu serwerowym -RemoteISOScanningTimeout = Skanowanie... sprawdź ustawienia zapory ogniowej swojego komputera +RemoteISOScanningTimeout = Scanning... check your desktop's firewall settings RemoteISOWifi = Informacja: Połącz oba urządzenia z tą samą siecią Wi-Fi -RemoteISOWinFirewall = UWAGA: Zapora ogniowa Windows blokuje udostępnianie +RemoteISOWinFirewall = WARNING: Windows Firewall is blocking sharing Settings = Ustawienia Share Games (Server) = Udostępniaj gry (serwer) Share on PPSSPP startup = Udostępniaj przy starcie PPSSPP @@ -1046,8 +928,8 @@ Stopping.. = Zatrzymywanie... [Reporting] Bad = Zła -FeedbackCRCCalculating = CRC dysku: Obliczanie... -FeedbackCRCValue = CRC dysku: %1 +FeedbackCRCCalculating = Disc CRC: Calculating... +FeedbackCRCValue = Disc CRC: %1 FeedbackDelayInfo = Twoje odpowiedzi wysyłane są w tle. FeedbackDesc = Jak działa emulacja? Pozwól nam i społeczności się dowiedzieć! FeedbackDisabled = Raporty kompatybilności muszą być włączone. @@ -1061,7 +943,7 @@ Graphics = Grafika Great = Świetna In-game = W grze In-game Description = Przechodzi do gry, jednak zbyt dużo bugów by ją ukończyć -Menu/Intro = Menu/Wstęp +Menu/Intro = Menu/Intro Menu/Intro Description = Nie przechodzi do gry Nothing = Nic Nothing Description = Całkowicie zepsuta emulacja @@ -1092,30 +974,30 @@ Date = Data Filename = Nazwa pliku No screenshot = Brak obrazka None yet. Things will appear here after you save. = Na razie nic tu nie ma. Wpisy pojawią się, gdy zapiszesz grę. -Nothing matching '%1' was found. = Nie znaleziono niczego, co pasowałoby do '%1'. +Nothing matching '%1' was found. = Nothing matching '%1' was found. Save Data = Zapisy gier Save States = Pliki zapisów stanów Savedata Manager = Zarządzanie zapisami gier -Showing matches for '%1'. = Wyświetlanie dopasowań dla '%1'. +Showing matches for '%1'. = Showing matches for '%1'. Size = Rozmiar [Screen] -Cardboard VR OFF = Wył. Cardboard VR +Cardboard VR OFF = Cardboard VR off Chainfire3DWarning = UWAGA: Wykryto Chainfire3D, może powodować problemy. Failed to load state = Nie można wczytać zapisu stanu Failed to save state = Nie można zapisać stanu fixed = Prędkość: alternatywna GLToolsWarning = UWAGA: Wykryto GLTools, może powodować problemy. -In menu = W menu +In menu = In menu Load savestate failed = Nie można wczytać zapisu stanu Loaded State = Wczytano stan gry -Loaded. Game may refuse to save over different savedata. = Wczytano. Gra może odmówić zapisywania w przypadku różnych zapisów. -Loaded. Game may refuse to save over newer savedata. = Wczytano. Gra może odmówić nadpisywania nowszych zapisów. +Loaded. Game may refuse to save over different savedata. = Loaded. Game may refuse to save over different savedata. +Loaded. Game may refuse to save over newer savedata. = Loaded. Game may refuse to save over newer savedata. Loaded. Save in game, restart, and load for less bugs. = Wczytano. By zmniejszyć ryzyko potencjalnych problemów, zapisz stan w grze, zrestartuj ją i wczytaj. LoadStateDoesntExist = Nie można wczytać stanu: Zapis stanu nie istnieje! LoadStateWrongVersion = Nie można wczytać stanu: Zapis stanu przeznaczony jest dla starszej wersji PPSSPP! norewind = Brak zapisów stanów potrzebnych do przewinięcia. -Playing = W grze +Playing = Playing PressESC = Naciśnij klawisz ESC, aby otworzyć menu pauzy. replaceTextures_false = Tekstury nie są już podmieniane. replaceTextures_true = Podmiana tekstur włączona. @@ -1125,8 +1007,8 @@ saveNewTextures_false = Zapisywanie tekstur wyłączone. saveNewTextures_true = Tekstury będą zapisywane na nośnik. SpeedCustom2 = Prędkość: alternatywna 2 standard = Prędkość: standardowa -State load undone = Cofnięto załadowanie stanu -Untitled PSP game = Niezatytułowana gra na PSP +State load undone = State load undone +Untitled PSP game = Untitled PSP game [Search] Clear filter = Wyczyść frazę @@ -1134,7 +1016,7 @@ Filter = Szukaj Filtering settings by '%1' = Wyszukiwanie ustawień '%1' Find settings = Szukaj ustawień No settings matched '%1' = Brak wyników dla '%1' -Search term = Wyszukaj frazę +Search term = Search term [Store] Already Installed = Zainstalowane @@ -1160,35 +1042,34 @@ Board = Płyta główna Build Config = Konfiguracja wersji Build Configuration = Konfiguracja Wersji Built by = Zbudowane przez -Compressed texture formats = Obsługiwane formaty kompresji tekstur +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Rdzenie CPU Extensions = Rozszerzenia CPU CPU Information = Informacje o CPU -CPU Name = Nazwa procesora +CPU Name = Nazwa D3DCompiler Version = Wersja D3DCompiler -Debug = Debugowanie +Debug = Debug Debugger Present = Debugger obecny -Depth buffer format = Format bufora głębi +Depth buffer format = Depth buffer format Device Info = Inf. o urządzeniu -Directories = Katalogi -Display Color Formats = Wyświetl formaty kolorów +Directories = Directories +Display Color Formats = Display Color Formats Display Information = Informacje o Wyświetlaczu DPI = DPI -Driver bugs = Błędy sterownika +Driver bugs = Driver bugs Driver Version = Wersja sterownika EGL Extensions = Rozszerzenia EGL Frames per buffer = Klatek na bufor -GPU Flags = Flagi GPU +GPU Flags = GPU Flags GPU Information = Informacje o GPU -High precision float range = Zakres l. zmiennoprzecinkowych wys. precyzji +High precision float range = High precision float range High precision int range = Zakres l. całkowitych wys. precyzji -Icon cache = Icon cache -JIT available = JIT dostępne +JIT available = JIT available Lang/Region = Język/Region -Memory Page Size = Rozmiar pamięci stronnicowania -Native resolution = Natywna rozdzielczość -No GPU driver bugs detected = Nie znaleziono żadnych błędów sterownika GPU +Memory Page Size = Rozmiar strony pamięci +Native Resolution = Natywna rozdzielczość +No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Rozszerzenia OGL OpenGL ES 2.0 Extensions = Rozszerzenia OpenGL ES 2.0 OpenGL ES 3.0 Extensions = Rozszerzenia OpenGL ES 3.0 @@ -1196,21 +1077,19 @@ OpenGL Extensions = Rozszerzenia OpenGL Optimal frames per buffer = Optymalna ilość klatek na bufor Optimal sample rate = Optymalna częstotliwość próbkowania OS Information = Informacje o OS -Pixel resolution = Rozdzielczość pixeli PPSSPP build = Kompilacja PPSSPP -Present modes = Present modes Refresh rate = Częstotliwość odświeżania -Release = Wydanie +Release = Release RW/RX exclusive = Wyłączne RW/RX Sample rate = Częstotliwość próbkowania Shading Language = Język shadingu -Storage = Pamięć +Storage = Storage Sustained perf mode = Tryb wysokiej wydajności System Information = Informacje o systemie System Name = Nazwa -System Version = Wersja systemu +System Version = System version Threads = Liczba wątków -UI resolution = Rozdzielczość interfejsu +UI Resolution = UI Resolution Vendor = Producent Vendor (detected) = Producent (wykryty) Version Information = Informacje o wersji @@ -1221,16 +1100,16 @@ Vulkan Features = Opcje Vulkana (broken) = (nie działa) 12HR = 12 godzinny 24HR = 24 godzinny -Auto = Automatyczny +Auto = Auto Auto Load Savestate = Automatyczne wczytywanie stanów zapisu AVI Dump started. = Rozpoczęto zrzut do AVI AVI Dump stopped. = Zatrzymano zrzut do AVI Cache ISO in RAM = Wczytuj całe ISO do RAM'u Change CPU Clock = Zmień częstotliwość zegara CPU (niestabilnie) -Color Saturation = Saturacja -Color Tint = Odcień -Error: load undo state is from a different game = Błąd: ładowany stan pochodzi z innej gry -Failed to load state for load undo. Error in the file system. = Błąd podczas ładowania stanu dla cofnięcia. Błąd systemu plików. +Color Saturation = Color Saturation +Color Tint = Color Tint +Error: load undo state is from a different game = Error: load undo state is from a different game +Failed to load state for load undo. Error in the file system. = Failed to load state for load undo. Error in the file system. Floating symbols = Przepływ symboli Game crashed = Gra uległa awarii Language = Język @@ -1240,18 +1119,18 @@ Change Nickname = Zmień pseudonim ChangingMemstickPath = Zapisy gier, zapisy stanu i inne dane nie zostaną skopiowane do tego folderu.\n\nZmienić ścieżkę do folderu Karty Pamięci? ChangingMemstickPathInvalid = Ta ścieżka nie może zostać użyta do zapisu plików Karty Pamięci. Cheats = Kody -Clear Recent = Wyczyść "Ostatnio uruchamiane" +Clear Recent = Wyczyść "Ostatni uruchamiane" Clear Recent Games List = Wyczyść listę ostatnio uruchamianych Clear UI background = Przywróć tło interfejsu Confirmation Button = Przycisk potwierdzenia Date Format = Format daty Day Light Saving = Czas letni DDMMYYYY = DD/MM/RRRR -Decrease size = Zmniejsz +Decrease size = Decrease size Developer Tools = Narzędzia programistyczne -Display Extra Info = Wyświetl dodatkowe informacje -Display Games on a grid = Wyświetl "Gry" jako siatkę -Display Homebrew on a grid = Wyświetl "Homebrew i Dema" jako siatkę +Display Extra Info = Display extra info +Display Games on a grid = Display "Games" on a grid +Display Homebrew on a grid = Display "Homebrew && Demos" on a grid Display Recent on a grid = Wyświetlaj "Ostatnio Uruchamiane" w projekcji siatki Dynarec (JIT) = Dynarec (JIT) Emulation = Emulacja @@ -1262,13 +1141,13 @@ Failed to save state. Error in the file system. = Nie można zapisać stanu. Bł Fast (lag on slow storage) = Szybka (zacina na wolnych dyskach) Fast Memory = Szybka pamięć (niestabilne) Force real clock sync (slower, less lag) = Wymuś rzeczywistą synchr. zegara (wolniej, mniej zacina) -Games list settings = Ustawienia listy gier +Games list settings = Games list settings General = Ogólne -Grid icon size = Rozmiar siatki ikon +Grid icon size = Grid icon size Help the PPSSPP team = Pomóż zespołowi PPSSPP Host (bugs, less lag) = Host (błędy, mniejsze zacinanie) -Ignore bad memory accesses = Ignoruj złe dostępy do pamięci -Increase size = Powiększ +Ignore bad memory accesses = Ignore bad memory accesses +Increase size = Increase size Interpreter = Interpreter IO timing method = Metoda synchronizacji I/O IR Interpreter = Interpreter IR @@ -1276,13 +1155,13 @@ Memory Stick Folder = Folder Karty Pamięci Memory Stick inserted = Karta Pamięci włożona MHz, 0:default = MHz, 0 = domyślne MMDDYYYY = MM/DD/RRRR -Moving background = Ruchome tło +Moving background = Moving background Newest Save = Najnowszy zapis -No animation = Bez animacji +No animation = No animation Not a PSP game = To nie jest gra PSP Off = Wył. Oldest Save = Najstarszy zapis -Path does not exist! = Ta ścieżka nie istnieje! +Path does not exist! = Path does not exist! PSP Memory Stick = Karta Pamięci PSP PSP Model = Model PSP PSP Settings = Ustawienia PSP @@ -1293,20 +1172,18 @@ Record Audio = Nagrywaj dźwięk Record Display = Nagrywaj obraz Reset Recording on Save/Load State = Resetuj nagrywanie przy zapisie/wczytaniu stanu Restore Default Settings = Przywróć domyślne ustawienia -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Częstotl. zapisu stanów przewijania (wymaga pamięci) Save path in installed.txt = Ścieżka zapisu w installed.txt Save path in My Documents = Ścieżka zapisu w Dokumentach Savestate Slot = Slot zapisu stanu Savestate slot backups = Kopie zapasowe slota zapisu stanu Screenshots as PNG = Zapisuj zrzuty ekranu jako PNG -Set Memory Stick folder = Ustaw folder Karty Pamięci +Set Memory Stick folder = Set Memory Stick folder Set UI background... = Zmień tło interfejsu... -Show ID = Pokazuj ID +Show ID = Show ID Show Memory Stick folder = Pokaż folder Karty Pamięci -Show region flag = Pokazuj flagi regionu +Show region flag = Show region flag Simulate UMD delays = Symuluj opóźnienia UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1316,31 +1193,31 @@ Storage full = Dysk zapełniony Sustained performance mode = Tryb wysokiej wydajności Theme = Motyw Time Format = Format czasu -Transparent UI background = Przezroczyste tło interfejsu użytkownika +Transparent UI background = Transparent UI background UI = Interfejs użytkownika UI background animation = Animacja tła -UI Sound = Dźwięki interfejsu użytkownika -undo %c = kopia zapasowa %c +UI Sound = Dźwięki interfejsu urzydkownika +undo %c = backup %c USB = USB Use Lossless Video Codec (FFV1) = Używaj stratnego kodeka wideo (FFV1) Use O to confirm = Używaj O jako potwierdzenia -Use output buffer (with overlay) for recording = Używaj bufora wyjściowego (z nakładką) do nagrywania -Use system native keyboard = Używaj natywnej klawiatury systemowej +Use output buffer (with overlay) for recording = Use output buffer (with overlay) for recording +Use system native keyboard = Use system native keyboard Use X to confirm = Używaj X jako potwierdzenia VersionCheck = Sprawdzaj dostępne aktualizacje WARNING: Android battery save mode is on = UWAGA: Oszczędzanie energii zostało włączone WARNING: Battery save mode is on = UWAGA: Oszczędzanie energii jest włączone -Waves = Fale (jak w XMB) +Waves = Waves YYYYMMDD = RRRR/MM/DD [TextureShaders] -Off = Wył. +Off = Off TexMMPX = TexMMPX Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] -Dark = Ciemny +Dark = Dark Default = Domyślny [UI Elements] @@ -1355,27 +1232,28 @@ List: = List: Progress: %1% = Progress: %1% Screen representation = Screen representation [Upgrade] -Details = Zmiany +Details = Details Dismiss = Odrzuć Download = Pobierz New version of PPSSPP available = Dostępna jest nowa wersja PPSSPP! [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement -Camera type = Typ kamery -Distance to 2D menus and scenes = Dystans do elemtentów 2D -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled -Experts only = Tylko dla ekspertów -Force 72Hz update = Wymuś odświeżanie w 72Hz -Game camera rotation step per frame = Krok obrotu kamery gry na klatkę -Game camera uses rotation smoothing = Kamera gry wykorzystuje wygładzanie rotacji -Heads-up display detection = Wykrywanie interfejsu w grze -Heads-up display scale = Skala interfejsu w grze -Manual switching between flat screen and VR using SCREEN key = Ręczne przełączanie między płaskim ekranem a VR za pomocą klawisza SCREEN -Map controller movements to keys = Przypisz ruch kontrolera do przycisków -Map HMD rotations on keys instead of VR camera = Przypisz rotację HMD na przyciskach, zamiast na kamerze VR -Motion needed to generate action = Aby wygenerować akcję, potrzebny jest ruch -Stereoscopic vision (Experimental) = Widzenie stereoskopowe (Eksperymentalne) -Virtual reality = Wirtualna rzeczywistość -VR camera = Kamera VR -VR controllers = Kontrolery VR +Camera type = Camera type +Distance to 2D menus and scenes = Distance to 2D menus and scenes +Experts only = Experts only +Field of view scale = Field of view scale +Force 72Hz update = Force 72Hz update +Game camera rotation step per frame = Game camera rotation step per frame +Game camera uses rotation smoothing = Game camera uses rotation smoothing +Heads-up display detection = Heads-up display detection +Heads-up display scale = Heads-up display scale +Manual switching between flat screen and VR using SCREEN key = Manual switching between flat screen and VR using SCREEN key +Map controller movements to keys = Map controller movements to keys +Map HMD rotations on keys instead of VR camera = Map HMD rotations on keys instead of VR camera +Motion needed to generate action = Motion needed to generate action +Stereoscopic vision (Experimental) = Stereoscopic vision (Experimental) +Virtual reality = Virtual reality +VR camera = VR camera +VR controllers = VR controllers diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index f5e298310..b51ed8b27 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -22,68 +22,9 @@ # # Happy translating. -[Achievements] -%1 achievements, %2 points = %1 conquistas, %2 pontos -%1: Attempt started = %1: A tentativa começou -%1: Attempt failed = %1: A tentativa falhou -Account = Conta -Achievement unlocked = Conquistas Destrancadas -Achievement progress = Progresso das Conquistas -Achievements = Conquistas -Achievements enabled = Conquistas ativadas -Achievements are disabled = As conquistas estão desativadas -Achievements with active challenges = Conquistas com desafios ativos -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Conquistas quase completadas -Can't log in to RetroAchievements right now = Não consegue logar no RetroAchievements agora -Challenge indicator = Indicador do desafio -Contacting RetroAchievements server... = Contactando o servidor do RetroAchievements... -Customize = Personalizar -Earned = Você ganhou %1 de %2 conquistas e %3 de %4 pontos -Encore Mode = Modo de Repetição -Failed logging in to RetroAchievements = Falhou em logar no RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Falhou em conectar com o RetroAchievements. As conquistas não destrancarão. -Failed to identify game. Achievements will not unlock. = Falhou em identificar o jogo. As conquistas não destrancarão. -Hardcore Mode (no savestates) = Modo Desafio (sem save states) -Hardcore Mode = Modo Desafio -How to use RetroAchievements = Como usar os RetroAchievements -In Encore mode - listings may be wrong below = No modo de repetição - As listagens abaixo podem estar erradas -Leaderboard attempt started or failed = A tentativa da tabela de classificação começou ou falhou -Leaderboard result submitted = Resultado submetido a tabela de classificação -Leaderboard score submission = Submissão de pontuações a tabela de classificação -Leaderboard submission is enabled = A submissão a tabela de classificação está ativada -Leaderboards = Tabelas de classificação -Leaderboard tracker = Rastreador do Leaderboard -Links = Links -Locked achievements = Conquistas trancadas -Log bad memory accesses = Registrar acessos ruins da memória -Mastered %1 = Conquistou o %1 -Around me = Ao redor de mim -Notifications = Notificações -Recently unlocked achievements = Recentemente destrancou as conquistas -Reconnected to RetroAchievements. = Reconectou com os RetroAchievements. -Register on www.retroachievements.org = Registrar no www.retroachievements.org -RetroAchievements are not available for this game = Os RetroAchievements não estão disponíveis pra este jogo -RetroAchievements website = Site dos RetroAchievements -Rich Presence = Presença Rica -Save state loaded without achievement data = O save state foi carregado sem os dados das conquistas -Save states not available in Hardcore Mode = Os save states não estão disponíveis no Modo Desafio -Sound Effects = Efeitos de Som -Statistics = Estatísticas -Submitted %1 for %2 = Submeteu o %1 pro %2 -Syncing achievements data... = Sincronizando os dados das conquistas... -Test Mode = Modo Teste -This feature is not available in Hardcore Mode = Esta função não está disponível no Modo Desafio -This game has no achievements = Este jogo não tem conquistas -Top players = Os melhores jogadores -Unlocked achievements = Conquistas destrancadas -Unsupported achievements = Conquistas não suportadas -Unofficial achievements = Conquistas não oficiais - [Audio] Alternate speed volume = Velocidade alternativa do volume -Audio backend = Backend do áudio (requer reiniciar) -Audio file format not supported. Must be WAV. = Formato do arquivo de áudio não suportado. Deve ser WAV. +Audio backend = Backed do áudio (requer reiniciar) Audio Error = Erro do Áudio AudioBufferingForBluetooth = Buffer amigável do Bluetooth (mais lento) Auto = Automático @@ -101,7 +42,7 @@ Use global volume = Usar volume global WASAPI (fast) = WASAPI (rápido) [Controls] -Analog Binding = Associação com o Analógico +Analog Binding = Ligação com o Analógico Analog Limiter = Limitador do analógico Analog Settings = Configurações do Analógico Analog Stick = Direcional analógico @@ -111,15 +52,14 @@ Auto = Automático Auto-centering analog stick = Auto-centralizar o direcional analógico Auto-hide buttons after delay = Auto-esconder os botões após um atraso de Auto-rotation speed = Velocidade da auto-rotação -Binds = Associações -Button Binding = Associação com os botões +Binds = Vinculados +Button Binding = Vinculação dos botões Button Opacity = Opacidade dos botões Button style = Estilo do botão Calibrate Analog Stick = Calibrar Direcional Analógico Calibrate = Calibrar Calibrated = Calibrado Calibration = Calibração -Circular low end radius = Raio low end circular Circular stick input = Entrada circular do direcional Classic = Clássico Confine Mouse = Travar o mouse dentro da janela/área de exibição @@ -132,10 +72,8 @@ Deadzone radius = Raio da zona morta Disable D-Pad diagonals (4-way touch) = Desativar diagonais do D-Pad (toque de 4 direções) Disable diagonal input = Desativar entrada diagonal Double tap = Toque duplo -Enable analog stick gesture = Ativar gesto do direcional analógico Enable gesture control = Ativar controle dos gestos Enable standard shortcut keys = Ativar teclas padrão dos atalhos -frames = frames Gesture = Gesto Gesture mapping = Mapeamento dos gestos Glowing borders = Bordas brilhantes @@ -164,7 +102,6 @@ OnScreen = Controles do toque na tela Portrait = Retrato Portrait Reversed = Retrato invertido PSP Action Buttons = Botões de ação do PSP -Rapid fire interval = Intervalo do fogo rápido Raw input = Entrada natural dos dados Reset to defaults = Resetar para os padrões Screen Rotation = Rotação da tela @@ -172,7 +109,6 @@ Sensitivity = Sensibilidade Sensitivity (scale) = Sensibilidade (escala) Shape = Forma Show Touch Pause Menu Button = Mostrar o botão do menu da pausa -Sticky D-Pad (easier sweeping movements) = Direcional pegajoso (movimentos abrangentes mais fáceis) Swipe = Deslizar Swipe sensitivity = Sensibilidade do deslizar Swipe smoothing = Suavidade do deslizar @@ -267,7 +203,6 @@ Pause When Not Focused = &Pausar quando não focado Portrait = Retrato Portrait reversed = Retrato invertido PPSSPP Forums = Fórums do &PPSSPP -Recent = &Recentes Record = &Gravar Record Audio = Gravar &áudio Record Display = Gravar &exibição @@ -293,6 +228,7 @@ Texture Filtering = Fi<ragem das texturas Texture Scaling = &Dimensionamento das texturas Use Lossless Video Codec (FFV1) = &Usar codec de vídeo sem perdas (FFV1) Use output buffer for video = Usar buffer de saída pro vídeo +Vertex Cache = &Cache do vértice VSync = VS&ync Vulkan = Vulkan Window Size = &Tamanho da janela @@ -302,17 +238,12 @@ xBRZ = &xBRZ [Developer] Allocator Viewer = Visualizador do alocador (Vulkan) Allow remote debugger = Permitir debug remoto -Audio Debug = Debug do Áudio Backspace = Backspace Block address = Bloquear endereço By Address = Pelo endereço -Control Debug = Debug dos Controles Copy savestates to memstick root = Copiar os save states pra raiz do cartão de memória -Create frame dump = Criar dump do frame Create/Open textures.ini file for current game = Criar/Abrir o arquivo textures.ini pro jogo atual Current = Atual -Debug overlay = Sobreposição do debug -Debug stats = Estatísticas do debug Dev Tools = Ferramentas de desenvolvimento DevMenu = Menu do DEV Disabled JIT functionality = Funcionalidade do JIT desativada @@ -322,25 +253,20 @@ Dump next frame to log = Dumpar o frame seguinte no registro Enable driver bug workarounds = Ativar soluções alternativas pros bugs dos drivers Enable Logging = Ativar o registro do debug Enter address = Inserir endereço -Fragment = Fragmento FPU = FPU Framedump tests = Testes dos dumps dos frames Frame Profiler = Analista dos frames -Frame timing = Tempo do frame -GPU Allocator Viewer = Visualizador do Distribuidor da GPU GPU Driver Test = Teste do driver da GPU GPU Profile = Perfil da GPU GPU log profiler = Criador do perfil do registro da GPU Jit Compare = Comparar JIT JIT debug tools = Ferramentas de debug do JIT -Log Dropped Frame Statistics = Registrar as estatísticas da queda dos frames +Log Dropped Frame Statistics = Registrar as estátisticas da queda dos frames Log Level = Nível do registro Log View = Visualização do registro Logging Channels = Canais do registro -Multi-threaded rendering = Renderização multi-threads Next = Próximo No block = Nenhum bloco -Off = Desligado Prev = Anterior Random = Aleatório Replace textures = Substituir texturas @@ -358,10 +284,10 @@ Stats = Estatísticas System Information = Informação do sistema Texture ini file created = Arquivo ini da textura criado Texture Replacement = Substituição das texturas +Toggle Audio Debug = Alternar debug do áudio +Toggle Control Debug = Alternar Debug do Controle Toggle Freeze = Alternar congelamento Touchscreen Test = Teste do Touchscreen -Ubershaders = Ubershaders -Vertex = Vértice VFPU = VFPU [Dialog] @@ -369,16 +295,12 @@ VFPU = VFPU * PSP res = * Resolução do PSP Active = Ativo Back = Voltar -Bottom Center = No centro do rodapé -Bottom Left = A esquerda do rodapé -Bottom Right = A direita do rodapé Cancel = Cancelar Center = Centro -Center Left = A esquerda do centro -Center Right = A direita do centro -Channel: = Canaal: -Changing this setting requires PPSSPP to restart. = Mudar esta configuração requer que o PPSSPP reinicie. -Choose PPSSPP save folder = Escolha a pasta de salvamento do PPSSPP +ChangingGPUBackends = Mudar os backends da GPU requer que o PPSSPP reinicie. Reiniciar agora? +ChangingInflightFrames = Mudar o buffer do comando dos gráficos requer que o PPSSPP reinicie. Reiniciar agora? +Channel: = Canal: +Choose PPSSPP save folder = Escolha a pasta dos saves do PPSSPP Confirm Overwrite = Você quer sobrescrever os dados? Confirm Save = Você quer salvar estes dados? ConfirmLoad = Carregar estes dados? @@ -396,46 +318,33 @@ DeleteConfirmGameConfig = Você realmente quer apagar as configurações deste j DeleteFailed = Incapaz de apagar os dados. Deleting = Apagando\nPor favor espere... Disable All = Desativar tudo -Disabled = Desativado Dumps = Dumps Edit = Editar Enable All = Ativar tudo -Enabled = Ativado Enter = Inserir -Failed to log in, check your username and password. = Falhou em logar, verifique seu nome de usuário e senha. -Failed to connect to server, check your internet connection. = Falhou em conectar ao servidor, verifique sua conexão com a internet. Filter = Filtro Finish = Concluir GE Frame Dumps = Dumps do Frame do GE Grid = Grade Inactive = Inativo -Installing... = Instalando... InternalError = Ocorreu um erro interno. -Links = Links Load = Carregar Load completed = Carregamento completado. Loading = Carregando\nPor favor espere... LoadingFailed = Incapaz de carregar os dados. -Log in = Logar -Log out = Sair -Logging in... = Logando... -Logged in! = Logado! Move = Mover Move Up = Mover pra Cima Move Down = Mover pra Baixo Network Connection = Conexão de rede NEW DATA = NOVOS DADOS No = Não -None = Nenhum ObtainingIP = Obtendo endereço de IP.\nPor favor espere... OK = Ok Old savedata detected = Dados antigos do save detectados Options = Opções -Password = Senha Remove = Remover Reset = Resetar Resize = Redimensionar -Restart = Reiniciar Retry = Tentar de novo Save = Salvar Save completed = Salvamento completado. @@ -444,7 +353,6 @@ SavingFailed = Incapaz de salvar os dados. Search = Busca seconds, 0:off = segundos, 0 = desligado Select = Selecionar -Settings = Configurações Shift = Shift Skip = Ignorar Snap = Grade @@ -455,11 +363,7 @@ Supported = Suportado There is no data = Não há dados. Toggle All = Alternar todos Toggle List = Alternar lista -Top Center = No centro do topo -Top Left = A esquerda do topo -Top Right = A direita do topo Unsupported = Não suportado -Username = Nome de usuário When you save, it will load on a PSP, but not an older PPSSPP = Quando você salvar ele carregará num PSP mas não num PPSSPP mais antigo When you save, it will not work on outdated PSP Firmware anymore = Quando você salvar ele não funcionará mais num firmware de PSP desatualizado Yes = Sim @@ -525,23 +429,18 @@ ZIP file detected (Require WINRAR) = O arquivo está comprimido (ZIP).\nPor favo [Game] Asia = Ásia Calculate CRC = Calcular CRC -Click "Calculate CRC" to verify ISO = Clique em "Calcular CRC" pra verificar a ISO ConfirmDelete = Apagar -CRC checksum does not match, bad or modified ISO = O checksum do CRC não combina, ISO ruim ou modificada Create Game Config = Criar configuração do jogo Create Shortcut = Criar atalho Delete Game = Apagar jogo Delete Game Config = Apagar configuração do jogo Delete Save Data = Apagar dados do save Europe = Europa -File size incorrect, bad or modified ISO = Tamanho do arquivo incorreto, ISO ruim ou modificada Game = Jogo -Game ID unknown - not in the ReDump database = ID do jogo desconhecida - não está no banco de dados do ReDump Game Settings = Configurações do jogo Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Dados da instalação -ISO OK according to the ReDump project = ISO OK de acordo com o projeto ReDump Japan = Japão Korea = Coréia MB = MBs @@ -551,8 +450,6 @@ Remove From Recent = Remover dos "Recentes" SaveData = Dados do save Setting Background = Configurando o cenário de fundo Show In Folder = Mostrar na pasta -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = EUA Use UI background = Usar cenário de fundo da interface do usuário @@ -615,21 +512,21 @@ Direct3D 11 = Direct3D 11 Disabled = Desativado Display Layout && Effects = Exibir esquema && efeitos Display Resolution (HW scaler) = Resolução da tela (Dimensionador do hardware) -Enable Cardboard VR = Ativa o cartaz da realidade virtual +Enable Cardboard VR = Ativa o VR Cardboard FPS = FPS Frame Rate Control = Controle da taxa dos frames Frame Skipping = Pulo dos frames Frame Skipping Type = Tipo de pulo dos frames FullScreen = Tela cheia Geometry shader culling = Abate do shader da geometria -Hack Settings = Configurações dos hacks (pode causar erros gráficos) +Hack Settings = Configurações dos hacks (pode causar erros gráficos) Hardware Tessellation = Tesselação por hardware Hardware Transform = Transformação por hardware hardware transform error - falling back to software = Erro de transformação pelo hardware, retrocedendo pro software. HardwareTessellation Tip = Usa o hardware pra fazer as curvas High = Alta Hybrid = Híbrido -Hybrid + Bicubic = Híbrido + bi-cúbico +Hybrid + Bicubic = Híbrido + Bi-cúbico Ignore camera notch when centering = Ignora o nível da câmera quando centralizar Integer scale factor = Fator de escala do inteiro Internal Resolution = Resolução interna @@ -660,7 +557,6 @@ Percent of FPS = Porcentagem dos FPS Performance = Performance Postprocessing shaders = Shaders de pós-processamento Recreate Activity = Recriar atividade -Render all frames = Renderizar todos os frames Render duplicate frames to 60hz = Renderizar frames duplicados a 60 Hz RenderDuplicateFrames Tip = Pode tornar a taxa dos frames mais suave em jogos que executam em taxas de frames menores Rendering Mode = Modo de renderização @@ -682,7 +578,6 @@ Stereo rendering = Renderização do estéreo Stretch = Esticar Texture Filter = Filtragem das texturas Texture Filtering = Filtragem das texturas -Texture replacement pack activated = Pacote de substituição das texturas ativado Texture Scaling = Dimensionamento das texturas Texture Shader = Shader das texturas Turn off Hardware Tessellation - unsupported = Desliga a "Tesselação por hardware": não suportado. @@ -693,6 +588,8 @@ Upscale Level = Nível da ampliação Upscale Type = Tipo de ampliação UpscaleLevel Tip = Pesado pra CPU - alguns dimensionamentos podem ser atrasados pra evitar travamentos Use all displays = Usar todas as telas +Vertex Cache = Cache do vértice +VertexCache Tip = Mais rápido mas pode causar tremulação temporária VSync = VSync Vulkan = Vulkan Window Size = Tamanho da janela @@ -709,12 +606,10 @@ Zip archive corrupt = Arquivo ZIP corrompido Zip file does not contain PSP software = O arquivo ZIP não contém software do PSP [KeyMapping] -Allow combo mappings = Permitir os mapeamentos dos combos Autoconfigure = Auto-configurar Autoconfigure for device = Auto-configurar pro dispositivo -Bind All = Associar tudo +Bind All = Vincular tudo Clear All = Limpar tudo -Combo mappings are not enabled = Os mapeamentos dos combos não estão ativados Default All = Restaurar os padrões Map a new key for = Mapear uma nova tecla pra Map Key = Mapear tecla @@ -771,7 +666,16 @@ Audio/Video Recording = Gravação de Áudio/Vídeo AxisSwap = Trocar eixos Circle = Círculo Cross = Cruz -Custom %d = Personalizar % +Custom 1 = Personalizar 1 +Custom 2 = Personalizar 2 +Custom 3 = Personalizar 3 +Custom 4 = Personalizar 4 +Custom 5 = Personalizar 5 +Custom 6 = Personalizar 6 +Custom 7 = Personalizar 7 +Custom 8 = Personalizar 8 +Custom 9 = Personalizar 9 +Custom 10 = Personalizar 10 D-pad down = Direcional pra baixo D-pad left = Direcional esquerdo D-pad right = Direcional direito @@ -780,7 +684,6 @@ DevMenu = Menu dos desenvolvedores Double tap button = Botão do toque duplo Down = Direcional pra Baixo Dpad = Direcional -Exit App = Sair do Aplicativo Frame Advance = Avanço dos frames Hold = Segurar Home = Home @@ -793,7 +696,6 @@ None = Nenhum Note = Nota OpenChat = Abrir o bate-papo Pause = Pausar -Previous Slot = Slot anterior R = R RapidFire = Fogo rápido Record = Gravar @@ -823,7 +725,6 @@ Texture Dumping = Dumpagem das texturas Texture Replacement = Substituição das texturas Toggle Fullscreen = Alternar pra tela cheia Toggle mode = Alternar modo -Toggle WLAN = Alternar WLAN Triangle = Triângulo Fast-forward = Avanço rápido Up = Direcional pra Cima @@ -837,9 +738,14 @@ Display Portrait Reversed = Exibir Retrato Revertido [Networking] AdHoc Server = Servidor Ad-hoc -AdhocServer Failed to Bind Port = O servidor Ad-hoc falhou em se associar com a porta +AdhocServer Failed to Bind Port = O servidor Ad-hoc falhou em se conectar a porta AM: Data from Unknown Port = AM: Dados de uma Porta Desconhecida Auto = Auto +Bottom Center = Centro do rodapé +Bottom Left = A esquerda do rodapé +Bottom Right = A direita do rodapé +Center Left = Centralizar a esquerda +Center Right = Centralizar a direita Change Mac Address = Mudar o endereço do MAC ChangeMacSaveConfirm = Gerar um novo endereço pro MAC? ChangeMacSaveWarning = Alguns jogos verificam o endereço do MAC quando carregam os dados do save então isto pode quebrar os saves antigos. @@ -863,8 +769,8 @@ Enter Quick Chat 3 = Entrar no bate-papo rápido 3 Enter Quick Chat 4 = Entrar no bate-papo rápido 4 Enter Quick Chat 5 = Entrar no bate-papo rápido 5 Error = Erro -Failed to Bind Localhost IP = Falhou em associar com o IP do hospedeiro local -Failed to Bind Port = Falhou em associar com a porta +Failed to Bind Localhost IP = Falhou em conectar ao IP do hospedeiro local +Failed to Bind Port = Falhou em conectar a porta Failed to connect to Adhoc Server = Falhou em conectar ao servidor ad hoc Forced First Connect = Primeira conexão forçada (conexão mais rápida) GM: Data from Unknown Port = GM: Dados da Porta Desconhecida @@ -873,6 +779,7 @@ Invalid IP or hostname = IP ou nome do hospedeiro inválido Minimum Timeout = Tempo mínimo pra encerrar (substituição em ms, 0 = padrão) Misc = Miscelânea (padrão = compatibilidade com o PSP) Network Initialized = Rede inicializada +None = Nenhum Please change your Port Offset = Por favor mude seu deslocamento da porta Port offset = Deslocamento da porta (0 = Compatibilidade com o PSP) Open PPSSPP Multiplayer Wiki Page = Abrir a Página do Multiplayer do Wiki do PPSSPP @@ -883,9 +790,11 @@ Quick Chat 3 = Bate-papo rápido 3 Quick Chat 4 = Bate-papo rápido 4 Quick Chat 5 = Bate-papo rápido 5 QuickChat = Bate-papo rápido -Randomize = Tornar aleatório Send = Enviar Send Discord Presence information = Enviar informação da "Presença Rica" no Discord +Top Center = Centro superior +Top Left = Superior esquerdo +Top Right = Superior direito Unable to find UPnP device = Incapaz de achar o dispositivo UPnP UPnP (port-forwarding) = UPnP (abertura das portas) UPnP need to be reinitialized = O UPnP precisa ser reinicializado @@ -915,12 +824,11 @@ Undo last save = Desfazer o último salvamento 4xHqGLSL = Ampliador da arte dos pixels 4×HQ 5xBR = Ampliador da arte dos pixels 5xBR 5xBR-lv2 = Ampliador da arte dos pixels 5xBR-lv2 -AAColor = Cores do AA +AAColor = Cores-do-AA Amount = Quantidade Aspect = Aspecto Black border = Borda preta Bloom = Bloom -BloomNoBlur = Bloom (sem desfoque) Brightness = Brilho Cartoon = Cartoon ColorCorrection = Correção das cores @@ -930,7 +838,6 @@ CRT = Scanlines do CRT FXAA = Anti-aliasing do FXAA Gamma = Gama GreenLevel = Nível verde -FakeReflections = Reflexos falsos Intensity = Intensidade LCDPersistence = Persistência do LCD Natural = Cores naturais @@ -947,13 +854,12 @@ SSAA(Gauss) = Super-amostragem do AA (Gauss) Strength = Força Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = Ampliador bi-cúbico -UpscaleSpline36 = Ampliador spline36 +UpscaleSpline36 = Ampliador Spline36 VideoSmoothingAA = Suavização de vídeo do AA Vignette = Vinheta Animation speed (0 -> disable) = Velocidade da animação (0 -> desativar) -CatmullRom = Ampliador bi-cúbico (Catmull-Rom) -MitchellNetravali = Ampliador bi-cúbico (Mitchell-Netravali) +CatmullRom = Ampliador Bi-cúbico (Catmull-Rom) +MitchellNetravali = Ampliador Bi-cúbico (Mitchell-Netravali) [PSPCredits] all the forum mods = Todos os moderadores do fórum @@ -979,7 +885,7 @@ specialthanks = Agradecimentos especiais: specialthanksKeithGalocy = da NVIDIA (hardware, conselho) specialthanksMaxim = pelo trabalho incrível dele com o decodificador Atrac3+ testing = Testagem -this translation by = Traduzido pelo: +this translation by = Traduzido por: title = Um emulador de PSP rápido e portátil tools = Ferramentas grátis usadas: # Add translators or contributors who translated PPSSPP into your language here. @@ -997,7 +903,6 @@ written = Escrito em C++ pela velocidade e portabilidade [MemStick] Already contains PSP data = Já contém dados do PSP -Cancelled - try again = Cancelado - tente de novo Create or Choose a PSP folder = Criar ou escolher uma pasta do PSP Current = Atual DataCanBeShared = Os dados podem ser compartilhados entre o PPSSPP regular/Gold @@ -1025,23 +930,6 @@ Use PSP folder at root of storage = Use a pasta do PSP na raiz da armazenagem Welcome to PPSSPP! = Bem-vindo ao PPSSPP! WhatsThis = O que é isto? -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinês (simplificado) -Chinese (traditional) = Chinês (tradicional) -Dutch = Holandês -English = Inglês -French = Francês -Game language = Idioma do jogo -German = Alemão -Italian = Italiano -Japanese = Japonês -Korean = Coreano -Games often don't support all languages = Os jogos frequentemente não suportam todos os idiomas -Portuguese = Português -Russian = Russo -Spanish = Espanhol - [RemoteISO] Browse Games = Procurar jogos Local Server Port = Porta do servidor local @@ -1109,7 +997,7 @@ View Feedback = Visualizar todos os feedbacks Date = Data Filename = Nome do arquivo No screenshot = Sem screenshot -None yet. Things will appear here after you save. = Nada ainda. As coisas aparecerão aqui após você salvar. +None yet. Things will appear here after you save. = Nada ainda. As coisas aparecerão aqui após você salvar. Nothing matching '%1' was found. = Nada combinando com o '%1' foi achado. Save Data = Dados salvos Save States = States salvos @@ -1192,11 +1080,10 @@ GPU Flags = Bandeira da GPU GPU Information = Informações da GPU High precision float range = Alcance do flutuante de alta precisão High precision int range = Alcance do inteiro de alta precisão -Icon cache = Cache do ícone JIT available = JIT disponível Lang/Region = Idioma/Região Memory Page Size = Tamanho da página de memória -Native resolution = Resolução nativa +Native Resolution = Resolução nativa No GPU driver bugs detected = Não foram detectado bugs no driver da GPU OGL Extensions = Extensões do OGL OpenGL ES 2.0 Extensions = Extensões do OpenGL 2.0 ES @@ -1205,12 +1092,10 @@ OpenGL Extensions = Extensões do OpenGL Optimal frames per buffer = Melhores frames por buffer Optimal sample rate = Melhor taxa de amostragem OS Information = Informação do sistema operacional -Pixel resolution = Resolução dos pixels PPSSPP build = Build do PPSSPP -Present modes = Modos presentes Refresh rate = Taxa de atualização Release = Lançamento -RW/RX exclusive = Exclusivo do RW/RX +RW/RX exclusive = RW/RX exclusivo Sample rate = Taxa de amostragem Shading Language = Idioma do shader Storage = Armazenagem @@ -1219,7 +1104,7 @@ System Information = Informação do sistema System Name = Nome System Version = Versão do sistema Threads = Threads -UI resolution = Resolução da Interface do Usuário +UI Resolution = Resolução da Interface do Usuário Vendor = Vendedor Vendor (detected) = Vendedor (detectado) Version Information = Informação da versão @@ -1301,7 +1186,6 @@ Record Audio = Gravar áudio Record Display = Gravar tela Reset Recording on Save/Load State = Resetar a gravação ao salvar/carregar o state Restore Default Settings = Restaurar as configurações do PPSSPP para os padrões -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Retroceder a frequência dos snapshots (consome muita memória) Save path in installed.txt = Caminho do save em installed.txt Save path in My Documents = Caminho do save em Meus Documentos @@ -1313,7 +1197,6 @@ Set UI background... = Definir o cenário de fundo da interface do usuário... Show ID = Mostrar ID Show region flag = Mostrar a bandeira da região Simulate UMD delays = Simular atrasos do UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1380,12 +1263,13 @@ Progress: %1% = Progresso: %1% Screen representation = Representação da tela [VR] +% of native FoV = % do campo de visão nativo 6DoF movement = Movimentação do 6DoF Distance to 2D menus and scenes = Distância até os menus e cenas 2D -Distance to 3D scenes when VR disabled = Distância nas cenas em 3D quando a realidade virtual está desativada Experts only = Só pra experts Game camera rotation step per frame = Passo da rotação da câmera do jogo por frame Game camera uses rotation smoothing = A câmera do jogo usa suavização da rotação +Field of view scale = Escala do campo de visualização Force 72Hz update = Forçar atualização em 72 Hz Heads-up display scale = Escala do aviso antecipado da exibição Heads-up display detection = Detecção do aviso antecipado da exibição diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 9adcb768f..d6855c3fa 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -22,70 +22,11 @@ # # Happy translating. -[Achievements] -%1: Attempt failed = %1: A tentativa falhou -%1: Attempt started = %1: A tentativa começou -%1 achievements, %2 points = %1 conquistas, %2 pontos -Account = Conta -Achievement progress = Progresso das Conquistas -Achievement unlocked = Conquistas Desbloqueadas -Achievements = Conquistas -Achievements are disabled = As conquistas estão desativadas -Achievements enabled = Conquistas ativadas -Achievements with active challenges = Conquistas com desafios ativos -Allow Save State in Hardcore Mode (but not Load State) = Permitir salvar estados no Modo Desafio (mas não carregar estados) -Almost completed achievements = Conquistas quase desbloqueadas -Around me = À minha volta -Can't log in to RetroAchievements right now = Não é possível cadastrar em RetroAchievements por agora, tenta novamente mais tarde -Challenge indicator = Indicador do Desafio -Contacting RetroAchievements server... = Contactando os servidores de RetroAchievements... -Customize = Personalizar -Earned = Desbloqueaste %1 de %2 conquistas e ganhaste %3 de %4 pontos -Encore Mode = Modo de Repetição -Failed logging in to RetroAchievements = Não foi possível cadastrar em RetroAchievements, tente novamente mais tarde -Failed to connect to RetroAchievements. Achievements will not unlock. = Não foi possível conectar a RetroAchievements. As conquistas não serão desbloqueadas. -Failed to identify game. Achievements will not unlock. = Não foi possível identificar o jogo. As conquistas não serão desbloqueadas. -Hardcore Mode (no savestates) = Modo Desafio (sem estados salvos) -Hardcore Mode = Modo Desafio -How to use RetroAchievements = Como usar a RetroAchievements -In Encore mode - listings may be wrong below = No Modo de Repetição - as listagem abaixo poderão estar incorretas -Leaderboard attempt started or failed = Tabela classificativa começou ou falhou -Leaderboard result submitted = O resultado foi enviado à tabela classificativa -Leaderboard score submission = Envio de resultados à tabela classificativa -Leaderboard submission is enabled = Envio à tabela classificativa está ativado -Leaderboard tracker = Rastreador da tabela classificativa -Leaderboards = Tabelas classificativas -Links = Links -Locked achievements = Conquistas bloqueadas -Log bad memory accesses = Fazer Log de acessos inválidos na memória -Mastered %1 = Conquistou %1 -Notifications = Notificações -Recently unlocked achievements = Conquistas recentemente desbloqueadas -Reconnected to RetroAchievements. = Reconectado a RetroAchievements. -Register on www.retroachievements.org = Cadastra-te em www.retroachievements.org -RetroAchievements are not available for this game = Os RetroAchievements não estão disponíveis para este jogo -RetroAchievements website = Website da RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = Estado Salvo carregado sem os dados das conquistas -Save states not available in Hardcore Mode = Os Estados Salvos não estão disponíveis no Modo Desafio -Sound Effects = Efeitos Sonoros (SFX) -Statistics = Estatísticas -Submitted %1 for %2 = Enviado %1 para %2 -Syncing achievements data... = A sincronizar os dados das conquistas... -Test Mode = Modo de Teste -This feature is not available in Hardcore Mode = Esta função não está disponível no Modo Desafio -This game has no achievements = Este jogo não tem conquistas disponíveis -Top players = Jogadores no topo -Unlocked achievements = Conquistas desbloqueadas -Unofficial achievements = Conquistas não oficiais -Unsupported achievements = Conquistas incompatíveis - [Audio] Alternate speed volume = Velocidade alternativa do volume Audio backend = API de áudio (requer reiniciar) -Audio Error = Erro no áudio -Audio file format not supported. Must be WAV. = Formato de ficheiro áudio não compatível. Use WAV. -AudioBufferingForBluetooth = Buffer amigável de Bluetooth (mais lento) +Audio Error = Erro do Áudio +AudioBufferingForBluetooth = Buffer amigável do Bluetooth (mais lento) Auto = Automático Device = Dispositivo Disabled = Desativado @@ -96,33 +37,32 @@ Microphone = Microfone Microphone Device = Dispositivo de Microfone Mute = Mudo Reverb volume = Reverberar volume -Use new audio devices automatically = Usar novos dispositivos de áudio automaticamente +Use new audio devices automatically = Usar novos dispositivos de áudio automáticamente Use global volume = Usar volume global WASAPI (fast) = WASAPI (rápido) [Controls] Analog Binding = Ligação com o Analógico Analog Limiter = Limitador do Analógico -Analog Settings = Definições do Analógico +Analog Settings = Configurações do Analógico Analog Stick = Analógico Analog Style = Estilo do Analógico AnalogLimiter Tip = Quando o botão limitador do analógico é pressionado Auto = Automático -Auto-centering analog stick =Centralização automática do analógico -Auto-hide buttons after delay = Esconder automaticamente os botões após segundos -Auto-rotation speed = Velocidade da Rotação Automática -Binds = Associações -Button Binding = Associação dos botões +Auto-centering analog stick = Auto-centralização do analógico +Auto-hide buttons after delay = Auto-esconder os botões após segundos +Auto-rotation speed = Velocidade da auto-rotação +Binds = Vinculados +Button Binding = Vinculação dos botões Button Opacity = Opacidade dos botões Button style = Estilo do botão Calibrate Analog Stick = Calibrar Analógico Calibrate = Calibrar Calibrated = Calibrado Calibration = Calibração -Circular low end radius = Raio circular inferior Circular stick input = Entrada circular do direcional Classic = Clássico -Confine Mouse = Isolar o rato dentro da janela/área de exibição +Confine Mouse = Travar o mouse dentro da janela/área de exibição Control Mapping = Mapeamento dos Controlos Custom Key Setting = Configuração Personalizada das Teclas Customize = Personalizar @@ -132,10 +72,8 @@ Deadzone radius = Raio da zona morta Disable D-Pad diagonals (4-way touch) = Desativar diagonais do D-Pad (toque de 4 direções) Disable diagonal input = Desativar entrada diagonal Double tap = Toque duplo -Enable analog stick gesture = Ativar gestos do Analógico Enable gesture control = Ativar controlo dos gestos Enable standard shortcut keys = Ativar teclas padrão dos atalhos -frames = frames Gesture = Gesto Gesture mapping = Mapeamento dos Gestos Glowing borders = Bordas brilhantes @@ -153,18 +91,17 @@ L/R Trigger Buttons = Botões do gatilho L/R Landscape = Panorâmico Landscape Auto = Panorâmico automático Landscape Reversed = Panorâmico invertido -Low end radius = Raio inferior +Low end radius = Raio Low End Mouse = Definições do Rato Mouse sensitivity = Sensibilidade do Rato Mouse smoothing = Suavização do Rato MouseControl Tip = Agora podes mapear o rato na tela de mapeamento dos controlos pressionando o ícone 'M'. None (Disabled) = Nenhum (desativado) -Off = Desativado +Off = Desligado OnScreen = Controlos no ecrã Portrait = Retrato Portrait Reversed = Retrato invertido -PSP Action Buttons = Botões de ação da PSP -Rapid fire interval = Intervalo de disparo rápido +PSP Action Buttons = Botões de ação do PSP Raw input = Entrada natural dos dados Reset to defaults = Restaurar para os padrões Screen Rotation = Rotação do ecrã @@ -172,10 +109,9 @@ Sensitivity = Sensibilidade Sensitivity (scale) = Sensibilidade (escala) Shape = Forma Show Touch Pause Menu Button = Mostrar o botão do menu de pausa -Sticky D-Pad (easier sweeping movements) = D-Pad pegajoso (para deslizar de forma mais fácil) Swipe = Deslizar -Swipe sensitivity = Sensibilidade do deslizamento -Swipe smoothing = Suavidade do deslizamento +Swipe sensitivity = Sensibilidade do deslizar +Swipe smoothing = Suavidade do deslizar Thin borders = Bordas Finas Tilt control setup = Personalizar inclinação... Tilt Input Type = Controlo da entrada de inclinação @@ -197,7 +133,7 @@ Cheats = Cheats Edit Cheat File = Editar ficheiro de Cheats Import Cheats = Importar de cheat.db Import from %s = Importar de %s -Refresh Rate = Taxa de atualização +Refresh Rate = Taxa de refrescamento [DesktopUI] # If your language does not show well with the default font, you can use Font to specify a different one. @@ -205,15 +141,15 @@ Refresh Rate = Taxa de atualização #Font = Trebuchet MS About PPSSPP... = &Sobre o PPSSPP... Auto = &Automático -Auto Max Quality = Maximizar automaticamente a &qualidade +Auto Max Quality = Auto-maximizar a &qualidade Backend = API de &renderização (Reinicia o PPSSPP) -Bicubic = &Bicúbico +Bicubic = &Bi-cúbico Break = Parar Break on Load = Parar ao carregar Buy Gold = Comprar &Gold Control Mapping... = M&apeamento dos controlos... -Copy PSP memory base address = Copiar &endereço base da memória da PSP -Debugging = &Debugging +Copy PSP memory base address = Copy PSP memory base &address +Debugging = &Depurar Deposterize = &Deposterizar Direct3D9 = Direct3D &9 Direct3D11 = Direct3D &11 @@ -228,8 +164,8 @@ Enable Sound = Ativar S&om Exit = S&air Extract File... = E&xtrair ficheiro... File = &Ficheiro -Frame Skipping = &Salto de Frames -Frame Skipping Type = Tipo de salto de Frames +Frame Skipping = &Salto de Quadros +Frame Skipping Type = Tipo de salto de Quadros Fullscreen = Te&la cheia Game Settings = &Definições do Jogo GE Debugger... = Depurador do G&E... @@ -237,8 +173,8 @@ GitHub = Git&Hub Hardware Transform = &Transformação por Hardware Help = &Ajuda Hybrid = &Híbrido -Hybrid + Bicubic = Híbrido + Bicúbico -Ignore Illegal Reads/Writes = &Ignorar acessos/escritas inválidos na memória +Hybrid + Bicubic = Híbrido + Bi-cúbico +Ignore Illegal Reads/Writes = &Ignorar leituras/gravações ilegais Ignore Windows Key = Ignorar a tecla Windows Keep PPSSPP On Top = &Manter PPSSPP no Topo Landscape = Panorâmico @@ -254,23 +190,22 @@ Log Console = &Console dos Logs Memory View... = Visualização da &memória... More Settings... = &Mais Definições... Nearest = &Mais próximo -Recent = &Recente -Skip Buffer Effects = &Ignorar efeitos de buffer (sem buffer, mais rápido) -Off = &Desativado +Skip Buffer Effects = &Ignorar efeitos do buffer (sem buffer, mais rápido) +Off = &Desligado Open Chat = Abrir Bate-Papo Open Directory... = Abrir &Diretório... Open from MS:/PSP/GAME... = A&brir do MS:/PSP/GAME... -Open Memory Stick = Abrir &cartão de memória +Open Memory Stick = Abrir &Cartão de Memória Open New Instance = Abrir Nova Instância OpenGL = &OpenGL Pause = &Pausar -Pause When Not Focused = &Pausar quando a janela não estiver em foco +Pause When Not Focused = &Pausar quando não focado Portrait = Retrato Portrait reversed = Retrato invertido -PPSSPP Forums = Fóruns do &PPSSPP +PPSSPP Forums = Fórums do &PPSSPP Record = &Gravar Record Audio = Gravar &Áudio -Record Display = Gravar &Ecrã +Record Display = Gravar &Exibição Rendering Mode = Modo de r&enderização Rendering Resolution = &Resolução da renderização Reset = R&einiciar @@ -283,9 +218,9 @@ Save State File... = &Guardar ficheiro do estado... Savestate Slot = Espaç&o do Estado Salvo Screen Scaling Filter = Fi<ro do Dimensionamento da Tela Show Debug Statistics = Mostrar as estatíst&icas de depuração -Show FPS Counter = Mostrar o contador de &FPS (Frames Por Segundo) -Skip Number of Frames = Saltar o número de frames -Skip Percent of FPS = Ignorar percentagem de FPS (Frames Por Segundo) +Show FPS Counter = Mostrar o contador dos &FPS (Quadros Por Segundo) +Skip Number of Frames = Saltar o número dos quadros +Skip Percent of FPS = Ignorar percentagem do FPS (Quadros Por Segundo) Stop = &Parar Switch UMD = Trocar UMD Take Screenshot = &Criar Captura de Tela @@ -293,6 +228,7 @@ Texture Filtering = Fi<ragem das texturas Texture Scaling = &Dimensionamento das texturas Use Lossless Video Codec (FFV1) = &Usar Codec de Vídeo sem perdas (FFV1) Use output buffer for video = Usar buffer de saída para o vídeo +Vertex Cache = &Cache do vértice VSync = VS&ync Vulkan = Vulkan Window Size = &Tamanho da Janela @@ -301,258 +237,219 @@ xBRZ = &xBRZ [Developer] Allocator Viewer = Visualizador do Alocador (Vulkan) -Allow remote debugger = Permitir debugger remoto +Allow remote debugger = Permitir depuração remota Backspace = Backspace Block address = Bloquear endereço By Address = Pelo endereço -Copy savestates to memstick root = Copiar os estados salvos para a raiz do cartão de memória -Create frame dump = Criar um dump do frame +Copy savestates to memstick root = Copiar os Estados Salvos para a raiz do Cartão de Memória Create/Open textures.ini file for current game = Criar/Abrir o ficheiro textures.ini para o jogo atual Current = Atual -Debug overlay = Sobreposição Debug -Debug stats = Estatísticas Debug -Dev Tools = Ferramentas de desenvolvedor +Dev Tools = Ferramentas de desenvolvimento DevMenu = Menu de Desenvolvedor Disabled JIT functionality = Funcionalidade do JIT desabilitada -Draw Frametimes Graph = Desenhar gráfico dos tempos dos frames -Dump Decrypted Eboot = Guardar EBOOT.BIN desencriptado no arranque do jogo -Dump next frame to log = Guardar o próximo frame no Log -Enable driver bug workarounds = Ativar soluções alternativas para erros de Drivers -Enable Logging = Ativar Log do Debug +Draw Frametimes Graph = Desenhar gráfico dos tempos dos quadros +Dump Decrypted Eboot = Guardar EBOOT.BIN decriptado no boot do jogo +Dump next frame to log = Guardar o próximo frame no log +Enable driver bug workarounds = Ativar soluções alternativas para erros dos Drivers +Enable Logging = Ativar log do depurador Enter address = Inserir endereço FPU = FPU -Fragment = Fragmento -Frame timing = Tempo do frame -Framedump tests = Testes dos dumps dos frames -Frame Profiler = Analista dos frames -GPU Allocator Viewer = Visualizador do Distribuidor da GPU +Framedump tests = Testes dos dumps dos quadros +Frame Profiler = Analista dos quadros GPU Driver Test = Teste do driver da GPU GPU Profile = Perfil da GPU GPU log profiler = Criador do Perfil do Registro da GPU Jit Compare = Comparar JIT JIT debug tools = Ferramentas de depuração do JIT -Log Dropped Frame Statistics = Guardar no Log as estátisticas da queda de frames -Log Level = Nível de Log -Log View = Visualização do Log -Logging Channels = Canais de Logging -Multi-threaded rendering = Renderização Multi-threaded +Log Dropped Frame Statistics = Guardar no log as estátisticas da queda dos quadros +Log Level = Nível do log +Log View = Visualização do log +Logging Channels = Canais do log Next = Próximo No block = Nenhum bloco -Off = Off Prev = Anterior Random = Aleatório Replace textures = Substituir texturas Reset = Reiniciar -Reset limited logging = Reiniciar o Log limitado -RestoreDefaultSettings = Tens a certeza que queres restaurar todas as definições de volta ao padrão?\n\nNão poderás desfazer isto.\nPor favor reinicia o PPSSPP para as mudanças terem efeito. -RestoreGameDefaultSettings = Tens a certeza que queres restaurar as definições específicas do jogo\nde volta para os padrões do PPSSPP? +Reset limited logging = Reiniciar o log limitado +RestoreDefaultSettings = Tens a certeza que queres restaurar todas as Definições de volta ao padrão?\n\nTu não podes desfazer isto.\nPor favor reinicie o PPSSPP para as mudanças terem efeito. +RestoreGameDefaultSettings = Tens a certeza que queres restaurar as Definições específicas do jogo\nde volta para os padrões do PPSSPP? Resume = Resumir -Run CPU Tests = Executar testes na CPU +Run CPU Tests = Executar testes da CPU Save new textures = Guardar novas texturas Shader Viewer = Visualizador dos Shaders Show Developer Menu = Mostrar Menu de Desenvolvedor -Show on-screen messages = Mostrar mensagens no ecrã +Show on-screen messages = Mostrar mensagens na tela Stats = Estatísticas System Information = Informação do sistema Texture ini file created = Ficheiro .ini da textura criado com sucesso Texture Replacement = Substituição das texturas -Audio Debug = Debugging do áudio -Control Debug = Debugging dos controlos +Toggle Audio Debug = Alternar depuração do áudio +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Alternar congelamento -Touchscreen Test = Teste do ecrã -Ubershaders = Ubershaders -Vertex = Vértice +Touchscreen Test = Teste do Touchscreen VFPU = VFPU [Dialog] %d seconds = %d segundos -* PSP res = * Resolução da PSP +* PSP res = * Resolução do PSP Active = Ativo Back = Voltar -Bottom Center = Centro do rodapé -Bottom Left = A esquerda do rodapé -Bottom Right = A direita do rodapé Cancel = Cancelar Center = Centro -Center Left = Centralizar a esquerda -Center Right = Centralizar a direita -Changing this setting requires PPSSPP to restart. = A alteração desta definição requer que reinicies o PPSSPP. +ChangingGPUBackends = Mudar os backends da GPU requer que o PPSSPP reinicie. Reiniciar agora? +ChangingInflightFrames = Mudar o buffer do comando dos gráficos requer que o PPSSPP reinicie. Reiniciar agora? Channel: = Canal: -Choose PPSSPP save folder = Escolha a pasta de salvamento do PPSSPP +Choose PPSSPP save folder = Escolha a pasta de save do PPSSPP Confirm Overwrite = Queres sobrescrever os dados? Confirm Save = Queres guardar estes dados? ConfirmLoad = Carregar estes dados? -ConnectingAP = A conectar ao ponto de acesso.\nPor favor espere... -ConnectingPleaseWait = A conectar.\nPor favor espere... +ConnectingAP = Conectando ao ponto de acesso.\nPor favor espere... +ConnectingPleaseWait = Conectando.\nPor favor espere... ConnectionName = Nome da conexão Corrupted Data = Dados Corrompidos Delete = Eliminar Delete all = Eliminar tudo -Delete completed = Eliminação completa. -DeleteConfirm = Estes dados do salvamento serão eliminados.\nTens a certeza que queres continuar? -DeleteConfirmAll = Queres realmente eliminar todos\nos teus dados salvos deste jogo? -DeleteConfirmGame = Queres realmente eliminar este jogo\ndo teu dispositivo? Não poderás desfazer isto. -DeleteConfirmGameConfig = Queres realmente eliminar as definições deste jogo? -DeleteFailed = Não foi possível eliminar os dados. -Deleting = A eliminar\nPor favor espere... -Disable All = Desativar tudo -Disabled = Desativado +Delete completed = Exclusão completa. +DeleteConfirm = Este dado do save será apagado.\nTens a certeza que queres continuar? +DeleteConfirmAll = Queres realmente Eliminar todos\nos seus dados salvos deste jogo? +DeleteConfirmGame = Queres realmente Eliminar este jogo\ndo seu dispositivo? Não podes desfazer isto. +DeleteConfirmGameConfig = Queres realmente Eliminar as Definições deste jogo? +DeleteFailed = Não foi possível Eliminar os dados. +Deleting = Apagando\nPor favor espere... +Disable All = Desabilitar tudo Dumps = Dumps Edit = Editar Enable All = Ativar tudo -Enabled = Ativado Enter = Inserir -Failed to connect to server, check your internet connection. = Não foi possível conectar ao servidor, verifica a tua conexão com a internet. -Failed to log in, check your username and password. = Não foi possível cadastrar, verifica o teu apelido e palavra-passe. Filter = Filtro Finish = Concluir GE Frame Dumps = Dumps do Frame do GE Grid = Grade Inactive = Inativo -Installing... = A instalar... InternalError = Ocorreu um erro interno. -Links = Links Load = Carregar -Load completed = Carregamento completo. -Loading = A carregar\nPor favor espere... -LoadingFailed = Não foi possível carregar os dados. -Log in = Cadastrar -Log out = Sair -Logged in! = Cadastrado! -Logging in... = A cadastrar... +Load completed = Carregamento completado. +Loading = Carregando\nPor favor espere... +LoadingFailed = Incapaz de carregar os dados. Move = Mover -Move Down = Mover para baixo -Move Up = Mover para cima +Move Down = Move Down +Move Up = Move Up Network Connection = Conexão de rede NEW DATA = NOVOS DADOS No = Não -None = Nenhum -ObtainingIP = A obter o Endereço de IP.\nPor favor espere... +ObtainingIP = Obtendo o Endereço de IP.\nPor favor espere... OK = Ok -Old savedata detected = Dados antigos do salvamento detetados -Options = Definições -Password = Palavra-passe -Remove = Remover +Old savedata detected = Dados antigos do save detectados +Options = Opções +Remove = Remove Reset = Reiniciar Resize = Redimensionar -Restart = Reiniciar Retry = Tentar de novo Save = Salvar -Save completed = Salvamento completo. -Saving = A salvar\nPor favor espere... -SavingFailed = Não foi possível salvar os dados. +Save completed = Salvamento completado. +Saving = Salvando\nPor favor espere... +SavingFailed = Incapaz de salvar os dados. Search = Pesquisar -seconds, 0:off = segundos, 0 = Desativado +seconds, 0:off = segundos, 0 = Desligado Select = Selecionar -Settings = Definições Shift = Shift Skip = Ignorar Snap = Grade Space = Espaço SSID = SSID -Submit = Enviar -Supported = Compatível +Submit = Submeter +Supported = Suportado There is no data = Não existem dados. Toggle All = Alternar todos Toggle List = Alternar lista -Top Center = Centro superior -Top Left = Canto superior esquerdo -Top Right = Canto superior direito -Unsupported = Não compatível -Username = Apelido -When you save, it will load on a PSP, but not an older PPSSPP = Quando gravares, os dados irão carregar com sucesso numa PSP, mas não num PPSSPP antigo. -When you save, it will not work on outdated PSP Firmware anymore = Quando gravares, os dados não funcionarão mais num firmware de PSP desatualizado. +Unsupported = Não suportado +When you save, it will load on a PSP, but not an older PPSSPP = Quando gravar, os dados vão carregar numa PSP, mas não num PPSSPP antigo. +When you save, it will not work on outdated PSP Firmware anymore = Quando gravar, os dados não funcionarão mais num firmware de PSP desatualizado. Yes = Sim Zoom = Zoom [Error] -7z file detected (Require 7-Zip) = O ficheiro está comprimido (.7z).\nPor favor descomprima-o primeiro (tente usar o 7-zip ou WinRAR). -A PSP game couldn't be found on the disc. = Nenhum jogo de PSP foi ser encontrado no disco. +7z file detected (Require 7-Zip) = O ficheiro está comprimido (.7z).\nPor favor descomprima-o primeiro (tente o 7-zip ou WinRAR). +A PSP game couldn't be found on the disc. = Nenhum jogo de PSP não pôde ser encontrado no disco. Cannot boot ELF located outside mountRoot. = Não é possível bootar no ELF localizado fora do mountRoot. -Could not save screenshot file = Não foi possível salvar o ficheiro da captura de tela. -D3D9or11 = Direct3D 9? ("não" para usar Direct3D 11) -D3D11CompilerMissing = "D3DCompiler_47.dll" não foi encontrado. Por favor instale-o. Ou pressione "Sim" para tentar de novo usando o Direct3D 9. +Could not save screenshot file = Não é possível salvar o ficheiro da Captura de Tela. +D3D9or11 = Direct3D 9? (ou "não" para o Direct3D 11) +D3D11CompilerMissing = O D3DCompiler_47.dll não foi encontrado. Por favor instale-o. Ou pressione Sim para tentar de novo usando o Direct3D 9 ao invés disto. D3D11InitializationError = Erro de inicialização do Direct3D 11 -D3D11Missing = A tua versão do sistema operacional não inclui o D3D11. Por favor executa o Windows Update.\n\nPressiona "Sim" para tentar de novo usando o Direct3D 9. -D3D11NotSupported = A tua GPU não suporta o Direct3D 11.\n\nGostarias de tentar de novo usando o Direct3D 9? +D3D11Missing = A sua versão do sistema operacional não inclui o D3D11. Por favor execute o Windows Update.\n\nPressione Sim para tentar de novo usando o Direct3D 9 ao invés disto. +D3D11NotSupported = A sua GPU não suporta o Direct3D 11.\n\nGostarias de tentar de novo usando o Direct3D 9 ao invés disto? Disk full while writing data = O disco ficou cheio enquanto gravava os dados. ELF file truncated - can't load = Ficheiro .ELF truncado - não é possível carregar Error loading file = Não é possível carregar o ficheiro. Error reading file = Erro ao ler o ficheiro. -Failed initializing CPU/Memory = Erro ao inicializar a CPU/memória. +Failed initializing CPU/Memory = Erro ao inicializar a CPU ou a memória. Failed to load executable: = Erro ao carregar o executável: File corrupt = Ficheiro Corrompido Game disc read error - ISO corrupt = Erro de leitura do disco do jogo: ISO corrompida. -GenericAllStartupError = O PPSSPP falhou em iniciar com todos backends gráficos disponíveis. Tenta atualizar os seus gráficos e outros drivers. -GenericBackendSwitchCrash = O PPSSPP crashou enquanto iniciava.\n\nIsto geralmente significa que há um problema no driver dos gráficos. Tenta atualizar os drivers.\n\nO backend dos gráficos foi trocado: -GenericDirect3D9Error = Erro ao inicializar os gráficos. Tenta atualizar os teus drivers de gráficos e o runtime do DirectX 9.\n\nGostarias de tentar trocar para o OpenGL?\n\nMensagem de erro: -GenericGraphicsError = Erro de Gráficos -GenericOpenGLError = Erro ao inicializar os gráficos. Tenta atualizar os teus drivers de gráficos.\n\nGostarias de tentar trocar para o DirectX 9?\n\nMensagem de erro: -GenericVulkanError = Erro ao inicializar os gráficos. Tenta atualizar os teus drivers de gráficos.\n\nGostarias de tentar trocar para o OpenGL?\n\nMensagem de erro: -InsufficientOpenGLDriver = Incompatibilidade do driver de OpenGL detectado!\n\nA tua GPU não suporta OpenGL 2.0. Gostarias de tentar usar o DirectX?\n\nO DirectX atualmente é compatível com menos jogos mas na tua GPU pode ser a única escolha.\n\nVisita os fóruns em https://forums.ppsspp.org para mais informações.\n\n +GenericAllStartupError = O PPSSPP falhou em iniciar com qualquer backend gráfico. Tente atualizar os seus gráficos e outros drivers. +GenericBackendSwitchCrash = O PPSSPP crashou enquanto iniciava.\n\nIsto geralmente significa que há um problema no driver dos gráficos. Tente atualizar os drivers.\n\nO backend dos gráficos foi trocado: +GenericDirect3D9Error = Erro ao inicializar os gráficos. Tente atualizar os seus drivers dos gráficos e o runtime do DirectX 9.\n\nGostarias de tentar trocar para o OpenGL?\n\nMensagem de erro: +GenericGraphicsError = Erro dos Gráficos +GenericOpenGLError = Erro ao inicializar os gráficos. Tente atualizar os seus drivers dos gráficos.\n\nGostarias de tentar trocar para o DirectX 9?\n\nMensagem de erro: +GenericVulkanError = Erro ao inicializar os gráficos. Tente atualizar os seus drivers dos gráficos.\n\nGostarias de tentar trocar para o OpenGL?\n\nMensagem de erro: +InsufficientOpenGLDriver = Suporte insuficiente do driver do OpenGL detectado!\n\nA sua GPU não suporta OpenGL 2.0. Gostarias de tentar usar o DirectX ao invés disto?\n\nO DirectX atualmente é compatível com menos jogos mas na sua GPU pode ser a única escolha.\n\nVisite os fóruns em https://forums.ppsspp.org para mais informações.\n\n Just a directory. = Apenas um diretório. Missing key = Chave ausente MsgErrorCode = Código de erro: -MsgErrorSavedataDataBroken = Os dados do salvamento estavam corrompidos. -MsgErrorSavedataMSFull = Cartão de memória cheio. Verifica o teu espaço de armazenamento. -MsgErrorSavedataNoData = Aviso: Não foram encontrados os dados do salvamento. -MsgErrorSavedataNoMS = Cartão de memória não inserido. +MsgErrorSavedataDataBroken = Os dados do save estavam corrompidos. +MsgErrorSavedataMSFull = Cartão de Memória cheio. Verifique seu espaço de armazenamento. +MsgErrorSavedataNoData = Aviso: Não foram encontrados os dados do save. +MsgErrorSavedataNoMS = Cartão de Memória não inserido. No EBOOT.PBP, misidentified game = Não existe EBOOT.PBP, jogo mal identificado. Not a valid disc image. = Imagem de disco inválida. -OpenGLDriverError = Erro do driver de OpenGL -PPSSPP doesn't support UMD Music. = O PPSSPP não é compatível com UMDs de música. -PPSSPP doesn't support UMD Video. = O PPSSPP não é compatível com UMDs de vídeo. -PPSSPP plays PSP games, not PlayStation 1 or 2 games. = O PPSSPP apenas é compatível com jogos de PSP, não jogos de PlayStation 1 ou 2. -PPSSPPDoesNotSupportInternet = O PPSSPP atualmente não é compatível com conexão à Internet para DLC, PSN ou atualizações de jogos. -PS1 EBOOTs are not supported by PPSSPP. = EBOOTS de PS1 não são compatíveis com o PPSSPP. -PSX game image detected. = O ficheiro é uma imagem do MODE2. O PPSSPP não é compatível com jogos de PS1. -RAR file detected (Require UnRAR) = O ficheiro está comprimido (.rar).\nPor favor descomprima-o primeiro (tente usar o UnRAR). -RAR file detected (Require WINRAR) = O ficheiro está comprimido (.rar).\nPor favor descomprima-o primeiro (tente usar o WinRAR). -Running slow: try frameskip, sound is choppy when slow = Rodando lento: Tenta "frameskip", o som fica demasiado travado quando está lento. -Running slow: Try turning off Software Rendering = Rodando lento: Tenta desativar a "Renderização por Software" -Save encryption failed. This save won't work on real PSP = Erro ao encriptar o salvamento. Este salvamento não funcionará num PSP. +OpenGLDriverError = Erro do driver do OpenGL +PPSSPP doesn't support UMD Music. = O PPSSPP não suporta música do UMD. +PPSSPP doesn't support UMD Video. = O PPSSPP não suporta vídeo do UMD. +PPSSPP plays PSP games, not PlayStation 1 or 2 games. = O PPSSPP roda jogos de PSP, não jogos de PlayStation 1 ou 2. +PPSSPPDoesNotSupportInternet = O PPSSPP atualmente não suporta conexão com a Internet para DLC, PSN ou atualizações de jogos. +PS1 EBOOTs are not supported by PPSSPP. = EBOOTS de PS1 não são suportados pelo PPSSPP. +PSX game image detected. = O ficheiro é uma imagem do MODE2. O PPSSPP não suporta jogos de PS1. +RAR file detected (Require UnRAR) = O ficheiro está comprimido (.rar).\nPor favor descomprima-o primeiro (tente o UnRAR). +RAR file detected (Require WINRAR) = O ficheiro está comprimido (.rar).\nPor favor descomprima-o primeiro (tente o WinRAR). +Running slow: try frameskip, sound is choppy when slow = Rodando lento: Tente "frameskip", o som fica demasiado instável quando está lento. +Running slow: Try turning off Software Rendering = Rodando lento: Tente desabilitar a "Renderização por Software" +Save encryption failed. This save won't work on real PSP = Erro ao encriptar o save. Este save não funcionará num PSP. textures.ini filenames may not be cross-platform = Os nomes dos ficheiros em "textures.ini" podem não ser multi-plataforma. -This is a saved state, not a game. = Este é um estado salvo, não um jogo. +This is a saved state, not a game. = Este é um Estado Salvo, não um jogo. This is save data, not a game. = Isto são dados salvos, não um jogo. -Unable to create cheat file, disk may be full = Não foi possível criar um ficheiro de Cheat. O disco poderá estar cheio. -Unable to initialize rendering engine. = Não foi possível inicializar a engine de renderização. -Unable to write savedata, disk may be full = Não foi possível gravar os dados do salvamento. O disco poderá estar cheio. -Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = AVISO: Memória de vídeo CHEIA, a reduzir a ampliação e a trocar para o modo de cache lento. -Warning: Video memory FULL, switching to slow caching mode = AVISO: Memória de vídeo CHEIA, a trocar para o modo de cache lento. -ZIP file detected (Require UnRAR) = O ficheiro está comprimido (.zip).\nPor favor descomprima-o primeiro (tente usar o UnRAR). -ZIP file detected (Require WINRAR) = O ficheiro está comprimido (.zip).\nPor favor descomprima-o primeiro (tente usar o WinRAR). +Unable to create cheat file, disk may be full = Não foi possíevl criar ficheiro de Cheat. O disco poderá estar cheio. +Unable to initialize rendering engine. = Não foi possível inicializar a engine da renderização. +Unable to write savedata, disk may be full = Não foi possível gravar os dados do save. O disco poderá estar cheio. +Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = AVISO: Memória de vídeo Cheia, reduzindo a ampliação e trocando para o modo de cache lento. +Warning: Video memory FULL, switching to slow caching mode = AVISO: Memória de vídeo CHEIA, trocando para o modo de cache lento. +ZIP file detected (Require UnRAR) = O ficheiro está comprimido (.zip).\nPor favor descomprima-o primeiro (tente o UnRAR). +ZIP file detected (Require WINRAR) = O ficheiro está comprimido (.zip).\nPor favor descomprima-o primeiro (tente o WinRAR). [Game] Asia = Ásia Calculate CRC = Calcular CRC -Click "Calculate CRC" to verify ISO = Clica em "Calcular CRC" para verificar a ISO ConfirmDelete = Eliminar -CRC checksum does not match, bad or modified ISO = A checksum da CRC não corresponde, esta ISO provavelmente é uma copia de má qualidade ou está modificada Create Game Config = Criar definições do jogo Create Shortcut = Criar atalho Delete Game = Eliminar jogo Delete Game Config = Eliminar definições do jogo Delete Save Data = Eliminar dados salvos Europe = Europa -File size incorrect, bad or modified ISO = Tamanho de ficheiro incorreto, esta ISO provavelmente é uma copia de má qualidade ou está modificada Game = Jogo -Game ID unknown - not in the ReDump database = ID do Jogo desconhecida, não está na base de dados do ReDump Game Settings = Definições do jogo Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Dados da Instalação -ISO OK according to the ReDump project = Esta ISO está OK de acordo com o projeto de ReDump Japan = Japão Korea = Coreia -MB = MBs +MB = MB One moment please... = Um momento por favor... Play = Jogar -Remove From Recent = Remover de "Recente" +Remove From Recent = Remover de "Recentes" SaveData = Dados Salvos -Setting Background = Definindo o cenário de fundo +Setting Background = Configurando o cenário de fundo Show In Folder = Mostrar na pasta -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = EUA Use UI background = Usar cenário de fundo da interface do usuário. @@ -583,19 +480,19 @@ Alternative Speed = Velocidade alternativa (em %, 0 = ilimitada) Alternative Speed 2 = Segunda Velocidade alternativa (em %, 0 = ilimitada) Anisotropic Filtering = Filtragem anisotrópica Antialiasing (MSAA) = Antialiasing (MSAA) -Aspect Ratio = Proporção do ecrã +Aspect Ratio = Aspect Ratio Auto = Automático Auto (1:1) = Automático (1:1) -Auto (same as Rendering) = Auto (a mesma da resolução de renderização) -Auto FrameSkip = Salto automático de frames -Auto Max Quality = Maximizar automaticamente a qualidade -Auto Scaling = Redimensionamento automático +Auto (same as Rendering) = Auto (a mesma de que a da resolução de renderização) +Auto FrameSkip = Auto-pulo dos quadros +Auto Max Quality = Auto-maximizar a qualidade +Auto Scaling = Auto-redimensionamento Backend = Backend Balanced = Balanceado -Bicubic = Bicúbico +Bicubic = Bi-cúbico Both = Ambos -Buffer graphics commands (faster, input lag) = Buffer dos Comandos Gráficos (mais rápido, mais atraso na entrada dos dados) -BufferedRenderingRequired = Aviso: Este jogo requer com que o "modo de renderização" esteja definido "com buffer". +Buffer graphics commands (faster, input lag) = Buffer dos Comandos Gráficos (mais rápido, atraso na entrada dos dados) +BufferedRenderingRequired = Aviso: Este jogo requer que o "modo de renderização" esteja definido "com buffer". Camera = Câmera Camera Device = Dispositivo de câmera Cardboard Screen Size = Tamanho da tela (em % do visor) @@ -604,7 +501,7 @@ Cardboard Screen Y Shift = Deslocamento do Y (em % do espaço vazio) Cardboard VR Settings = Definições do Google VR Cardboard Cheats = Cheats CPU Core = Núcleo da CPU -Debugging = Debugging +Debugging = Depuração DefaultCPUClockRequired = Aviso: Este jogo requer que o clock da CPU esteja definido como padrão. Deposterize = Deposterizar Deposterize Tip = Conserta erros gráficos visuais das faixas nas texturas ampliadas. @@ -615,26 +512,26 @@ Disabled = Desativado Display Layout && Effects = Mostrar o editor dos esquemas Display Resolution (HW scaler) = Resolução da tela (Dimensionador do hardware) Enable Cardboard VR = Ativar o VR Cardboard -FPS = FPS (Frames Por Segundo) -Frame Rate Control = Controlo da taxa dos frames -Frame Skipping = Salto de frames -Frame Skipping Type = Tipo de salto de frames -FullScreen = Ecrã Cheio -Geometry shader culling = Abate do Shader Geométric -GPUReadbackRequired = AVISO: Este jogo requer que "Saltar Readbacks da GPU" esteja desativado. +FPS = FPS (Quadros Por Segundo) +Frame Rate Control = Controle da taxa dos quadros +Frame Skipping = Pulo dos quadros +Frame Skipping Type = Tipo de pulo dos quadros +FullScreen = Tela Cheia +Geometry shader culling = Geometry shader culling +GPUReadbackRequired = Warning: This game requires "Skip GPU Readbacks" to be set to Off. Hack Settings = Definições dos Hacks (pode causar erros gráficos) Hardware Tessellation = Tesselação por Hardware Hardware Transform = Transformação por Hardware -hardware transform error - falling back to software = Erro de transformação pelo hardware, a retroceder para software. +hardware transform error - falling back to software = Erro de transformação pelo hardware, retrocedendo para o software. HardwareTessellation Tip = Usa o Hardware para fazer as curvas High = Alta Hybrid = Híbrido -Hybrid + Bicubic = Híbrido + Bicúbico +Hybrid + Bicubic = Híbrido + Bi-cúbico Ignore camera notch when centering = Ignora o nível da câmera quando centralizar -Integer scale factor = Fator de escala inteiro +Integer scale factor = Integer scale factor Internal Resolution = Resolução interna -Lazy texture caching = Caching preguiçoso da textura (mais rápido) -Lazy texture caching Tip = Mais rápido, mas pode causar problemas no texto em alguns jogos +Lazy texture caching = Cache preguiçoso da textura (mais rápido) +Lazy texture caching Tip = Mais rápido mas pode causar problemas no texto em alguns jogos Linear = Linear Low = Baixa LowCurves = Qualidade das curvas spline/bezier @@ -647,52 +544,52 @@ Must Restart = Deverás reiniciar o PPSSPP para esta mudança ter efeito. Native device resolution = Resolução Nativa do Dispositivo Nearest = Mais próximo No buffer = Sem buffer -Render all frames = Renderizar todos os frames -Show Battery % = Mostrar a percentagem da Bateria -Show Speed = Mostrar velocidade +Show Battery % = Show Battery % +Show Speed = Show Speed Skip Buffer Effects = Ignorar efeitos do buffer (sem buffer, mais rápido) None = Nenhum -Number of Frames = Número de frames -Off = Desativado +Number of Frames = Número de quadros +Off = Desligado OpenGL = OpenGL Overlay Information = Informações da sobreposição Partial Stretch = Esticamento Parcial -Percent of FPS = Percentagem de FPS +Percent of FPS = Percentagem dos FPS Performance = Performance Postprocessing shaders = Shaders de Pós-Processamento Recreate Activity = Recriar atividade -Render duplicate frames to 60hz = Renderizar frames duplicados a 60 Hz -RenderDuplicateFrames Tip = Pode tornar a taxa de frames mais suave em jogos que executam em taxas de frames menores +Render duplicate frames to 60hz = Renderizar quadros duplicados a 60 Hz +RenderDuplicateFrames Tip = Pode tornar a taxa dos quadros mais suave em jogos que executam em taxas de quadros menores Rendering Mode = Modo de renderização Rendering Resolution = Resolução da renderização RenderingMode NonBuffered Tip = Mais rápido, mas poderá não ser desenhado nada em alguns jogos Rotation = Rotação Safe = Seguro Screen Scaling Filter = Filtro do dimensionamento da tela -Show Debug Statistics = Mostrar estatísticas de Debug +Show Debug Statistics = Mostrar estatísticas de depuração Show FPS Counter = Mostrar contador de FPS -Skip GPU Readbacks = Saltar Readbacks da GPU +Skip GPU Readbacks = Skip GPU Readbacks Software Rendering = Renderização por software (lento) -Software Skinning = Skinning por software +Software Skinning = Skinning via software SoftwareSkinning Tip = Combina os desenhos dos modelos de skinning na CPU, mais rápido na maioria dos jogos Speed = Velocidade -Speed Hacks = Hacks de velocidade (podem causar erros gráficos) -Stereo display shader = Shader de exibição do estéreo -Stereo rendering = Renderização do estéreo +Speed Hacks = Speed Hacks (pode causar erros gráficos) +Stereo display shader = Stereo display shader +Stereo rendering = Stereo rendering Stretch = Esticamento -Texture Filter = Filtro das texturas +Texture Filter = Filtração das texturas Texture Filtering = Filtração das texturas -Texture replacement pack activated = Pacote de substituição de texturas ativado Texture Scaling = Dimensionamento das texturas Texture Shader = Shader das texturas -Turn off Hardware Tessellation - unsupported = Desliga a "Tesselação por hardware": não compatível. +Turn off Hardware Tessellation - unsupported = Desliga a "Tesselação por hardware": não suportado. Unlimited = Ilimitado Up to 1 = Até 1 Up to 2 = Até 2 Upscale Level = Nível de ampliação Upscale Type = Tipo de ampliação -UpscaleLevel Tip = Pesado para a CPU - alguns dimensionamentos poderão ser atrasados para evitar travamentos +UpscaleLevel Tip = Pesado para a CPU - alguns dimensionamentos poderão atrasados para evitar travamentos Use all displays = Usar todas as telas +Vertex Cache = Cache do vértice +VertexCache Tip = Mais rápido, mas pode causar tremulação temporária VSync = VSync Vulkan = Vulkan Window Size = Tamanho da janela @@ -704,24 +601,22 @@ Install = Instalar Install game from ZIP file? = Instalar o jogo do ficheiro .zip? Install textures from ZIP file? = Instalar as texturas do ficheiro .zip? Installed! = Instalado! -Texture pack doesn't support install = O pacote de texturas não é compatível com a instalação. +Texture pack doesn't support install = O pacote de texturas não suporta a instalação. Zip archive corrupt = Ficheiro .zip compactado corrompido. Zip file does not contain PSP software = O ficheiro .zip não contém software de PSP. [KeyMapping] -Allow combo mappings = Permitir mapeamentos combo -Autoconfigure = Configurar automaticamente -Autoconfigure for device = Configurar automaticamente para o dispositivo -Bind All = Associar tudo +Autoconfigure = Auto-configurar +Autoconfigure for device = Auto-configurar para o dispositivo +Bind All = Vincular tudo Clear All = Limpar tudo -Combo mappings are not enabled = Mapeamentos combo não estão ativados -Default All = Restaurar para os padrões +Default All = Restaurar os padrões Map a new key for = Mapear uma nova tecla para Map Key = Mapear tecla Map Mouse = Mapear o Rato Replace = Substituir -Show PSP = Mostrar a PSP -You can press ESC to cancel. = Podes pressionar a tecla Esc para cancelar. +Show PSP = Mostrar o PSP +You can press ESC to cancel. = Podes pressionar o Esc para cancelar. [MainMenu] Browse = Procurar... @@ -734,14 +629,14 @@ Game Settings = Definições Games = Jogos Give PPSSPP permission to access storage = Dê ao PPSSPP permissão para acessar o armazenamento Homebrew & Demos = Homebrew e Demos -How to get games = Como posso eu obter jogos? -How to get homebrew & demos = Como posso eu obter Homebrews e Demos? +How to get games = Como eu posso obter jogos? +How to get homebrew & demos = Como eu posso obter Homebrews e Demos? Load = Carregar... Loading... = Carregando... PinPath = Fixar -PPSSPP can't load games or save right now = O PPSSPP não consegue carregar ou salvar jogos neste momento. -Recent = Recente -SavesAreTemporary = O PPSSPP está a salvar no armazenamento temporário +PPSSPP can't load games or save right now = O PPSSPP não consegue carregar jogos ou salvar agora. +Recent = Recentes +SavesAreTemporary = O PPSSPP está salvando no armazenamento temporária SavesAreTemporaryGuidance = Extraia o PPSSPP em algum lugar para salvar permanentemente. SavesAreTemporaryIgnore = Ignorar aviso UnpinPath = Desafixar @@ -761,69 +656,75 @@ Search = Pesquisa Alt speed 1 = Velocidade alternativa 1 Alt speed 2 = Velocidade alternativa 2 An.Down = Analógico para Baixo -An.Left = Analógico para a Esquerda -An.Right = Analógico para a Direita +An.Left = Analógico Esquerdo +An.Right = Analógico Direito An.Up = Analógico para Cima Analog limiter = Limitador do analógico -Analog speed = Velocidade do analógico +Analog speed = Analog speed Analog Stick = Analógico Audio/Video Recording = Gravação de Áudio/Vídeo AxisSwap = Trocar Eixos Circle = Círculo Cross = Cruz -Custom %d = Personalizar %d +Custom 1 = Personalizar 1 +Custom 2 = Personalizar 2 +Custom 3 = Personalizar 3 +Custom 4 = Personalizar 4 +Custom 5 = Personalizar 5 +Custom 6 = Personalizar 6 +Custom 7 = Personalizar 7 +Custom 8 = Personalizar 8 +Custom 9 = Personalizar 9 +Custom 10 = Personalizar 10 D-pad down = Direcional para baixo -D-pad left = Direcional para a esquerda -D-pad right = Direcional para a direita +D-pad left = Direcional esquerdo +D-pad right = Direcional direito D-pad up = Direcional para cima -DevMenu = Menu de Desenvolvedor +DevMenu = Menu dos Desenvolvedores Double tap button = Botão de Toque Duplo Down = Direcional para Baixo Dpad = Direcional -Exit App = Sair da App Frame Advance = Avanço de quadros Hold = Segurar -Home = Botão Home +Home = Home L = L Left = Direcional Esquerdo Load State = Carregar Estado -Mute toggle = Alternar para Mudo +Mute toggle = Alternar para o mudo Next Slot = Próximo Espaço None = Nenhum Note = Nota -OpenChat = Abrir o Bate-Papo +OpenChat = Abrir o bate-papo Pause = Pausar -Previous Slot = Slot anterior R = R -RapidFire = Disparo rápido +RapidFire = Fogo rápido Record = Gravar Remote hold = Segurar remoto -Rewind = Retroceder +Rewind = Rebobinar Right = Direcional Direito Right Analog Stick = Direcional Análogico Direito RightAn.Down = Analógico Direito para Baixo -RightAn.Left = Analógico Direito para a Esquerda -RightAn.Right = Analógico Direito para a Direita +RightAn.Left = Analógico Direito a Esquerda +RightAn.Right = Analógico Direito a Direita RightAn.Up = Analógico Direito para Cima Rotate Analog (CCW) = Rotação do analógico (Sentido Anti-horário) Rotate Analog (CW) = Rotação do analógico (Sentido horário) Save State = Salvar Estado -Screen = Ecrã +Screen = Tela Screenshot = Captura de Tela -Select = Botão Select +Select = Select SpeedToggle = Alternar velocidade Square = Quadrado -Start = Botão Start +Start = Start Swipe Down = Deslizar para Baixo -Swipe Left = Deslizar para a Esquerda -Swipe Right = Deslizar para a Direita +Swipe Left = Deslizar para Esquerda +Swipe Right = Deslizar para Direita Swipe Up = Deslizar para Cima tap to customize = Toque para personalizar Texture Dumping = Dumpagem das texturas Texture Replacement = Substituição das texturas Toggle Fullscreen = Alternar para Tela Cheia Toggle mode = Alternar modo -Toggle WLAN = Alternar WLAN Triangle = Triângulo Fast-forward = Avanço rápido Up = Direcional para Cima @@ -840,14 +741,18 @@ AdHoc Server = Servidor Ad-hoc AdhocServer Failed to Bind Port = O servidor Ad-hoc falhou a conectar-se à porta. AM: Data from Unknown Port = AM: Dados de uma Porta Desconhecida. Auto = Automático -Change Mac Address = Mudar Endereço MAC +Bottom Center = Centro do rodapé +Bottom Left = A esquerda do rodapé +Bottom Right = A direita do rodapé +Center Left = Centralizar a esquerda +Center Right = Centralizar a direita +Change Mac Address = Mudar Endereço de MAC Change proAdhocServer Address = Mudar o Endereço de IP do servidor Ad Hoc PRO (localhost = múltiplas instâncias) -ChangeMacSaveConfirm = Gerar um novo endereço MAC? +ChangeMacSaveConfirm = Generate a new MAC address? ChangeMacSaveWarning = Some games verify the MAC address when loading savedata, so this may break old saves. -ChangeMacSaveWarning = Alguns jogos verificam o endereço MAC quando carregam o salvamento, então isto poderá fazer salvamentos antigos destes jogos pararem de funcionar. -Chat = Bate-Papo +Chat = Bate-papo Chat Button Position = Posição do botão de bate-papo -Chat Here = Bata-papo aqui +Chat Here = Bata-papo aqui! Chat message = Mensagem do bate-papo Chat Screen Position = Posição da tela de bate-papo Disconnected from AdhocServer = Desconectado do servidor ad-hoc @@ -855,9 +760,9 @@ DNS Error Resolving = Resolução de erros do DNS Enable built-in PRO Adhoc Server = Ativar o servidor ad-hoc PRO embutido Enable network chat = Ativar bate-papo na rede Enable networking = Ativar rede/WLAN (beta, pode quebrar os jogos) -Enable UPnP = Ativar UPnP (precisa de alguns segundos para detetar) +Enable UPnP = Ativar UPnP (precisa de alguns segundos para detectar) EnableQuickChat = Ativar bate-papo rápido -Enter a new PSP nickname = Insira um novo nome para a PSP +Enter a new PSP nickname = Insira um novo nome para o PSP Enter Quick Chat 1 = Entrar no bate-papo rápido 1 Enter Quick Chat 2 = Entrar no bate-papo rápido 2 Enter Quick Chat 3 = Entrar no bate-papo rápido 3 @@ -872,10 +777,11 @@ GM: Data from Unknown Port = GM: Dados da Porta Desconhecida Hostname = Nome do Hospedeiro Invalid IP or hostname = IP ou nome do Hospedeiro inválido Minimum Timeout = Tempo mínimo para encerrar (substituição em ms, 0 = padrão) -Misc = Miscelânea (padrão = compatibilidade com a PSP) +Misc = Miscelânea (padrão = compatibilidade com o PSP) Network Initialized = Rede inicializada -Please change your Port Offset = Por favor muda o teu offset da porta -Port offset = Offset da porta (0 = Compatibilidade com a PSP) +None = Nenhum +Please change your Port Offset = Por favor mude o seu deslocamento da porta +Port offset = Deslocamento da porta (0 = Compatibilidade com o PSP) Open PPSSPP Multiplayer Wiki Page = Abrir a Página do Multiplayer da Wiki do PPSSPP proAdhocServer Address: = Endereço do servidor ad-hoc: Quick Chat 1 = Bate-papo rápido 1 @@ -884,35 +790,19 @@ Quick Chat 3 = Bate-papo rápido 3 Quick Chat 4 = Bate-papo rápido 4 Quick Chat 5 = Bate-papo rápido 5 QuickChat = Bate-papo rápido -Randomize = Aleatorizar Send = Enviar -Send Discord Presence information = Enviar informação de "Rich Presence" no Discord +Send Discord Presence information = Enviar informação de "Presença Rica" no Discord +Top Center = Centro superior +Top Left = Superior esquerdo +Top Right = Superior direito Unable to find UPnP device = Não é possível encontrar o dispositivo UPnP UPnP (port-forwarding) = UPnP (abertura das portas) UPnP need to be reinitialized = O UPnP precisa ser reiniciado -UPnP use original port = O UPnP usa a porta original (ativado = compatibilidade com a PSP) +UPnP use original port = O UPnP usa a porta original (ativado = compatibilidade com o PSP) UseOriginalPort Tip = May not work for all devices or games, see wiki. -UseOriginalPort Tip = Poderá não funcionar com todos os dispositivos/jogos, para mais informações, vê a wiki. Validating address... = A validar Endereço... WLAN Channel = Canal do WLAN -You're in Offline Mode, go to lobby or online hall = Estás no modo Offline, vai para o lobby/salão Online - -[PSPSettings] -Auto = Automático -Chinese (simplified) = Chinês (simplificado) -Chinese (traditional) = Chinês (tradicional) -Dutch = Holandês -English = Inglês -French = Francês -Game language = Idioma do Jogo -German = Alemão -Italian = Italiano -Japanese = Japonês -Korean = Coreano -Games often don't support all languages = Normalmente, jogos não costumam ser compatíveis com todos os idiomas -Portuguese = Português -Russian = Russo -Spanish = Espanhol +You're in Offline Mode, go to lobby or online hall = Estás no modo Offline, vá para o lobby ou pro salão Online [Pause] Cheats = Cheats @@ -922,7 +812,7 @@ Delete Game Config = Eliminar definições do jogo Exit to menu = Sair para o menu Game Settings = Definições do jogo Load State = Carregar Estado -Rewind = Retroceder +Rewind = Rebobinar Save State = Salvar Estado Settings = Definições Switch UMD = Trocar UMD @@ -931,63 +821,60 @@ Undo last save = Desfazer o último salvamento [PostShaders] (duplicated setting, previous slider will be used) = (Definição duplicada, o slider anterior será usado) -4xHqGLSL = Ampliador da arte de pixels 4×HQ -5xBR = Ampliador da arte de pixeis 5xBR -5xBR-lv2 = Ampliador da arte de pixeis 5xBR-lv2 -AAColor = Cores do AA +4xHqGLSL = 4xHQ pixel art upscaler +5xBR = 5xBR pixel art upscaler +5xBR-lv2 = 5xBR-lv2 pixel art upscaler +AAColor = Cores-do-AA Amount = Quantidade -Aspect = Aspeto +Aspect = Aspect Black border = Borda preta Bloom = Bloom -BloomNoBlur = Bloom (sem desfocar) Brightness = Brilho Cartoon = Estilo Cartoon ColorCorrection = Correção das cores -ColorPreservation = Preservação da cor +ColorPreservation = Color preservation Contrast = Contraste -CRT = Scanlines de CRT -FakeReflections = Reflexos falsos +CRT = Scanlines do CRT FXAA = Anti-aliasing do FXAA Gamma = Gama -GreenLevel = Nível verde +GreenLevel = Green level Intensity = Intensidade -LCDPersistence = Persistência do LCD +LCDPersistence = LCD Persistence Natural = Cores naturais -NaturalA = Cores naturais (sem desfocar) -Off = Desativado +NaturalA = Cores naturais (sem borrão) +Off = Desligado Power = Energia -PSPColor = Cor da PSP -RedBlue = Óculos Vermelhos/Azuis +PSPColor = Cor do PSP +RedBlue = Red/Blue glasses Saturation = Saturação Scanlines = Scanlines (CRT) Sharpen = Aprimorado -SideBySide = Lado a lado (SBS) +SideBySide = Side by side (SBS) SSAA(Gauss) = Super-amostragem do AA (Gauss) -Strength = Força +Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = Ampliador Bicúbico UpscaleSpline36 = Ampliador Spline36 VideoSmoothingAA = Suavização de vídeo do AA Vignette = Vinheta Animation speed (0 -> disable) = Velocidade da animação (0 -> desativar) -CatmullRom = Ampliador Bicúbico (Catmull-Rom) -MitchellNetravali = Ampliador Bicúbico (Mitchell-Netravali) +CatmullRom = Ampliador Bi-cúbico (Catmull-Rom) +MitchellNetravali = Ampliador Bi-cúbico (Mitchell-Netravali) [PSPCredits] all the forum mods = Todos os moderadores do fórum -build server = Servidor das builds +build server = Servidor dos builds Buy Gold = Comprar Versão Gold -check = Experimenta também o Dolphin, o melhor emulador de Wii/GameCube: -CheckOutPPSSPP = Experimenta o PPSSPP, o incrível emulador de PSP: https://www.ppsspp.org/ +check = Experimente também o Dolphin, o melhor emulador de Wii/GC: +CheckOutPPSSPP = Experimente PPSSPP, o incrível emulador de PSP: https://www.ppsspp.org/ contributors = Contribuidores: created = Criado por Discord = Discord -info1 = O PPSSPP é destinado apenas para propósitos educacionais. -info2 = Por favor tem a certeza que possuis os direitos para quaisquer +info1 = O PPSSPP é destinado só para propósitos educacionais. +info2 = Por favor tenha certeza que possui os direitos para quaisquer info3 = jogos que jogas possuindo o UMD ou comprando o download -info4 = digital da loja PSN na tua PSP. -info5 = A PSP é uma marca registrada da Sony, Inc. +info4 = digital da loja PSN no seu PSP. +info5 = O PSP é uma marca registrada da Sony, Inc. iOS builds = Builds do iOS license = Software livre sob a GPL 2.0+ list = Listas de compatibilidade, fóruns e informações do desenvolvimento @@ -1004,23 +891,22 @@ tools = Ferramentas gratuitas usadas: # Add translators or contributors who translated PPSSPP into your language here. # Add translators1-6 for up to 6 lines of translator credits. # Leave extra lines blank. 4 contributors per line seems to look best. -translators1 = danssmnt (antigo MicSuit) +translators1 = MicSuit translators2 = translators3 = translators4 = translators5 = translators6 = -Twitter @PPSSPP_emu = Twitter/X @PPSSPP_emu -website = Verifica o website: +Twitter @PPSSPP_emu = Twitter @PPSSPP_emu +website = Verifique o website: written = PPSSPP foi escrito em C++ pela sua velocidade e portabilidade [MemStick] -Already contains PSP data = Já contém dados da PSP -Cancelled - try again = Cancelado - tenta de novo -Create or Choose a PSP folder = Criar ou escolher uma pasta da PSP +Already contains PSP data = Já contém dados do PSP +Create or Choose a PSP folder = Criar ou escolher uma pasta do PSP Current = Atual DataCanBeShared = Os dados podem ser partilhados entre o PPSSPP Regular/Gold -DataCannotBeShared = Os dados não podem ser partilhados entre o PPSSPP Regular/Gold +DataCannotBeShared = Os dados NÃO PODEM ser partilhados entre o PPSSPP Regular/Gold! DataWillBeLostOnUninstall = Aviso! Os dados serão perdidos quando desinstalares o PPSSPP! DataWillStay = Os dados permanecerão intactos mesmo se desinstalares o PPSSPP. Done! = Concluído! @@ -1028,19 +914,19 @@ EasyUSBAccess = Acesso fácil ao USB Failed to move some files! = Erro ao mover alguns ficheiros! Failed to save config = Erro ao salvar a definição Free space = Espaço livre -Manually specify PSP folder = Especificar manualmente a pasta da PSP -MemoryStickDescription = Escolher aonde manter os dados da PSP (cartão de memória) +Manually specify PSP folder = Especificar manualmente a pasta do PSP +MemoryStickDescription = Escolher aonde manter os dados do PSP (Cartão de Memória) Move Data = Mover Dados -Selected PSP Data Folder = Pasta Selecionada dos dados da PSP +Selected PSP Data Folder = Pasta Selecionada dos Dados do PSP Skip for now = Ignorar por enquanto No data will be changed = Nenhum dado será mudado PPSSPP will restart after the change = O PPSSPP reiniciará após a mudança -Starting move... = A iniciar a movimentação... -That folder doesn't work as a memstick folder. = Não é possível usar esta pasta como um cartão de memória. +Starting move... = Iniciando a movimentação... +That folder doesn't work as a memstick folder. = Não é possível usar esta pasta como um Cartão de Memória. USBAccessThrough = Acesso ao USB através de Android/data/org.ppsspp.ppsspp/files USBAccessThroughGold = Acesso ao USB através de Android/data/org.ppsspp.ppssppgold/files -Use App Private Data = Use os dados privados da aplicação -Use PSP folder at root of storage = Use a pasta da PSP na raiz do armazenamento +Use App Private Data = Use os Dados Privados da Aplicação +Use PSP folder at root of storage = Use a pasta do PSP na raiz do armazenamento Welcome to PPSSPP! = Bem-vindo ao PPSSPP! WhatsThis = O que é isto? @@ -1052,30 +938,30 @@ Remote disc streaming = Streaming remoto do disco Remote Port = Porta remota Remote Server = Servidor remoto Remote Subdirectory = Sub-diretório remoto -RemoteISODesc = Os jogos na sua lista de "Recente" serão partilhados -RemoteISOLoading = Conectado, a carregar a lista de jogos... -RemoteISOScanning = A procurar... Clique em "Partilhar Jogos" no dispositivo do seu servidor -RemoteISOScanningTimeout = A procurar... Verifique suas Definições do firewall na área de trabalho +RemoteISODesc = Os jogos na sua lista de "Recentes" serão partilhados +RemoteISOLoading = Conectado, carregando a lista de jogos... +RemoteISOScanning = Escaneando... Clique em "Partilhar Jogos" no dispositivo do seu servidor +RemoteISOScanningTimeout = Escaneando... Verifique suas Definições do firewall na área de trabalho RemoteISOWifi = Nota: Conecte os dois dispositivos na mesma rede Wi-Fi RemoteISOWinFirewall = AVISO: O Firewall do Windows está a bloquear o partilhamento Settings = Definições Share Games (Server) = Partilhar Jogos (servidor) Share on PPSSPP startup = Partilhar na inicialização do PPSSPP -Stop Sharing = Parar o partilhamento +Stop Sharing = Parar com o Partilhamento Stopping.. = A parar... [Reporting] Bad = Mau FeedbackCRCCalculating = CRC do Disco: A calcular... FeedbackCRCValue = CRC do Disco: %1 -FeedbackDelayInfo = Os teus dados estão a ser enviados em segundo plano. -FeedbackDesc = Como está a emulação? Deixa a comunidade e nós sabermos! +FeedbackDelayInfo = Seus dados estão a ser submetidos em segundo plano. +FeedbackDesc = Como está a emulação? Deixe a comunidade e nós sabermos! FeedbackDisabled = Os relatórios da compatibilidade com o servidor devem estar ativados. FeedbackIncludeCRC = Nota: A bateria será usada para enviar um CRC do disco. FeedbackIncludeScreen = Incluir uma Captura de Tela. -FeedbackSubmitDone = Seus dados foram enviados. -FeedbackSubmitFail = Não foi possível enviar os dados para o servidor. Tenta atualizar o PPSSPP. -FeedbackThanks = Obrigado pelo teu feedback! +FeedbackSubmitDone = Seus dados foram submetidos. +FeedbackSubmitFail = Não foi possível submeter os dados para o servidor. Tente atualizar o PPSSPP. +FeedbackThanks = Obrigado pelo seu feedback! Gameplay = Jogabilidade Graphics = Gráficos Great = Ótimo @@ -1095,15 +981,15 @@ Plays Description = Totalmente jogável mas pode ter problemas gráficos. ReportButton = Reportar feedback Show disc CRC = Mostrar CRC do disco Speed = Velocidade -Submit Feedback = Enviar feedback +Submit Feedback = Submeter feedback SuggestionConfig = Veja os relatórios no website para obter boas definições. SuggestionCPUSpeed0 = Desativa a definição da velocidade do clock travado da CPU. SuggestionDowngrade = Volte para uma versão mais antiga do PPSSPP (por favor reporte este erro). SuggestionsFound = Outros usuários relataram resultados melhores. Pressione "Visualizar Feedback" para mais detalhes. SuggestionsNone = Este jogo também não está a funcionar com outros usuários. -SuggestionsWaiting = A enviar e a verificar o feedback dos outros usuários... +SuggestionsWaiting = A submeter e a verificar o feedback dos outros usuários... SuggestionUpgrade = Atualize para uma versão mais recente do PPSSPP. -SuggestionVerifyDisc = Verifica se a tua ISO é uma cópia boa do teu disco. +SuggestionVerifyDisc = Verifique se sua ISO é uma cópia boa do seu disco. Unselected Overall Description = Quão bem este jogo emula? View Feedback = Visualizar todos os feedbacks @@ -1112,11 +998,11 @@ Date = Data Filename = Nome do ficheiro No screenshot = Sem Captura de tela None yet. Things will appear here after you save. = Nada ainda. As coisas vão aparecer aqui após salvares. -Nothing matching '%1' was found. = Nada que combinasse com %1' foi encontrado. +Nothing matching '%1' was found. = Nada combinando com %1' foi encontrado. Save Data = Dados salvos Save States = Estados salvos Savedata Manager = Gerenciador dos Dados Salvos -Showing matches for '%1'. = A mostrar combinações com '%1'. +Showing matches for '%1'. = Mostrando combinações com '%1'. Size = Tamanho [Screen] @@ -1129,23 +1015,23 @@ GLToolsWarning = AVISO: GLTools detectado, poderá causar problemas. In menu = No menu Load savestate failed = Erro ao carregar o Estado Loaded State = Estado carregado -Loaded. Save in game, restart, and load for less bugs. = Carregado. Salva no jogo, reinicia e carrega para menos erros. -Loaded. Game may refuse to save over different savedata. = Carregado. O jogo poderá recusar-se a salvar dados diferentes dos salvamentos. -Loaded. Game may refuse to save over newer savedata. = Carregado. O jogo poderá recusar-se a salvar dados mais novos dos salvamentos. +Loaded. Save in game, restart, and load for less bugs. = Carregado. Salve no jogo, reinicie e carregue para menos erros. +Loaded. Game may refuse to save over different savedata. = Carregado. O jogo pode recusar-se a salvar dados diferentes dos salvamentos. +Loaded. Game may refuse to save over newer savedata. = Carregado. O jogo pode recusar-se a salvar dados mais novos dos salvamentos. LoadStateDoesntExist = Erro ao carregar o Estado: O Estado salvo não existe! LoadStateWrongVersion = Erro ao carregar o Estado: O Estado salvo é de uma versão mais antiga do PPSSPP! -norewind = Não há Estados salvos disponíveis para retroceder. +norewind = Não há Estados salvos disponíveis para rebobinar. Playing = Jogando -PressESC = Pressione a tecla Esc para abrir o menu de pausa. +PressESC = Pressione ESC para abrir o menu de pausa. replaceTextures_false = As texturas não estão mais a ser substituídas. replaceTextures_true = A substituição das texturas está ativada. Save State Failed = Erro ao salvar o Estado! Saved State = Estado salvo -saveNewTextures_false = O salvamento das texturas foi desativado. -saveNewTextures_true = As texturas agora serão salvas no teu armazenamento. +saveNewTextures_false = O salvamento das texturas foi desabilitado. +saveNewTextures_true = As texturas agora serão salvas no seu armazenamento. SpeedCustom2 = Velocidade: alternativa 2 standard = Velocidade: padrão -State load undone = Carregamento do estado desfeito +State load undone = Carregamento do state desfeito Untitled PSP game = Jogo de PSP sem título [Store] @@ -1154,7 +1040,7 @@ Connection Error = Erro de conexão Install = Instalar Launch Game = Iniciar jogo Loading... = Carregando... -MB = MBs +MB = MB Size = Tamanho Uninstall = Desinstalar @@ -1177,39 +1063,37 @@ Core Context = Contexto do núcleo Cores = Núcleos CPU Extensions = Extensões da CPU CPU Information = Informações da CPU -CPU Name = Nome da CPU +CPU Name = Nome D3DCompiler Version = Versão do compilador D3D Debug = Debug -Debugger Present = Debugger presente -Depth buffer format = Formato do buffer de profundidade +Debugger Present = Depurador presente +Depth buffer format = Depth buffer format Device Info = Informação do dispositivo Directories = Diretórios -Display Information = Mostrar informação +Display Information = Informação da tela DPI = DPI -Driver bugs = Bugs do Driver +Driver bugs = Driver bugs +Driver Version = Versão do driver Driver Version = Versão do driver EGL Extensions = Extensões do EGL -Frames per buffer = Frames por buffer -GPU Flags = Flags da GPU +Frames per buffer = Quadros por buffer +GPU Flags = GPU Flags GPU Information = Informações da GPU High precision float range = Alcance do flutuante de alta precisão High precision int range = Alcance do inteiro de alta precisão -Icon cache = Cache do Ícone -JIT available = JIT disponível +JIT available = JIT available Lang/Region = Idioma/Região Memory Page Size = Tamanho da página de memória -Native resolution = Resolução Nativa +Native Resolution = Resolução Nativa No GPU driver bugs detected = Não foram detectados erros no driver da GPU OGL Extensions = Extensões do OGL OpenGL ES 2.0 Extensions = Extensões do OpenGL 2.0 ES OpenGL ES 3.0 Extensions = Extensões do OpenGL 3.0 ES OpenGL Extensions = Extensões do OpenGL -Optimal frames per buffer = Melhores frames por buffer +Optimal frames per buffer = Melhores quadros por buffer Optimal sample rate = Melhor taxa de amostragem OS Information = Informação do Sistema Operacional -Pixel resolution = Resolução do pixel PPSSPP build = Build do PPSSPP -Present modes = Modos presentes Refresh rate = Taxa de atualização Release = Lançamento RW/RX exclusive = RW/RX exclusivo @@ -1221,9 +1105,9 @@ System Information = Informação do sistema System Name = Nome do Sistema System Version = Versão do sistema Threads = Threads -UI resolution = Resolução do UI -Vendor = Fornecedor -Vendor (detected) = Fornecedor (detectado) +UI Resolution = UI Resolution +Vendor = Vendedor +Vendor (detected) = Vendedor (detectado) Version Information = Informação da versão Vulkan Extensions = Extensões do Vulkan Vulkan Features = Características do Vulkan @@ -1234,21 +1118,21 @@ Display Color Formats = Mostrar Formatos das Cores 12HR = 12 HRs 24HR = 24 HRs Auto = Automático -Auto Load Savestate = Carregar automaticamente o Estado salvo +Auto Load Savestate = Auto-carregar o Estado salvo AVI Dump started. = Dump do AVI iniciado AVI Dump stopped. = Dump do AVI parado -Cache ISO in RAM = Colocar a ISO inteira na memória RAM -Change CPU Clock = Mudar o clock da CPU da PSP emulado (instável) -Game crashed = O jogo crashou +Cache ISO in RAM = Colocar a ISO inteira na RAM +Change CPU Clock = Mudar o clock da CPU do PSP emulado (instável) +Game crashed = Game crashed Language = Idioma -Memory Stick folder = Pasta do cartão de memória -Memory Stick size = Tamanho do cartão de memória -Change Nickname = Mudar Apelido -ChangingMemstickPath = Jogos salvos, Estados salvos e outros dados não serão copiados para esta pasta.\n\nMudar a pasta do cartão de memória? -ChangingMemstickPathInvalid = Não é possível utilizar este caminho para salvar os ficheiros do cartão de memória. +Memory Stick folder = Pasta do Cartão de Memória +Memory Stick size = Tamanho do Cartão de Memória +Change Nickname = Mudar Nome +ChangingMemstickPath = Jogos salvos, Estados salvos e outros dados não serão copiados para esta pasta.\n\nMudar a pasta do Cartão de Memória? +ChangingMemstickPathInvalid = Não é possível utilizar esse caminho para salvar os ficheiros do cartão de memória. Cheats = Cheats -Clear Recent = Limpar "Recente" -Clear Recent Games List = Limpar a lista de "Recente" +Clear Recent = Limpar "Recentes" +Clear Recent Games List = Limpar a lista dos "Recentes" Clear UI background = Limpar o cenário de fundo da interface do usuário Confirmation Button = Botão de confirmação Date Format = Formato da data @@ -1259,16 +1143,16 @@ Developer Tools = Ferramentas de desenvolvedor Display Extra Info = Exibir informações extras Display Games on a grid = Exibir "Jogos" em uma grade Display Homebrew on a grid = Exibir "Homebrew e Demos" em uma grade -Display Recent on a grid = Exibir "Recente" em uma grade +Display Recent on a grid = Exibir "Recentes" em uma grade Dynarec (JIT) = Dynarec (JIT) Emulation = Emulação Enable Cheats = Ativar Cheats Enable Compatibility Server Reports = Ativar relatórios de compatibilidade com o servidor Error: load undo state is from a different game = Erro: o estado do carregamento desfeito é de um jogo diferente -Failed to load state. Error in the file system. = Não foi possível carregar o estado devido a um erro no sistema de ficheiros. -Failed to save state. Error in the file system. = Não foi possível salvar o estado devido a um erro no sistema de ficheiros. -Failed to load state for load undo. Error in the file system. = Não foi possível carregar o estado do carregamento desfeito devido a um erro no sistema de ficheiros. -Fast (lag on slow storage) = Rápido (lento em armazenamento lento) +Failed to load state. Error in the file system. = Erro ao carregar o estado. Erro no sistema de ficheiros. +Failed to save state. Error in the file system. = Erro ao salvar o estado. Erro no sistema de ficheiros. +Failed to load state for load undo. Error in the file system. = Erro ao carregar o state do carregamento desfeito. Erro no ficheiro do sistema. +Fast (lag on slow storage) = Rápido (mais lento no armazenamento lento) Fast Memory = Memória Rápida (instável) Floating symbols = Símbolos flutuantes Force real clock sync (slower, less lag) = Forçar sincronização com o relógio real (mais lento, menos atrasos) @@ -1277,91 +1161,89 @@ General = Geral Grid icon size = Tamanho do ícone da grade Help the PPSSPP team = Ajude a equipa do PPSSPP Host (bugs, less lag) = Hospedeiro (mais erros, menos atrasos) -Ignore bad memory accesses = Ignorar acessos inválidos da memória +Ignore bad memory accesses = Ignorar acessos maus da memória Increase size = Aumentar tamanho Interpreter = Interpretador IO timing method = Método de cronometragem da E/S IR Interpreter = Interpretador do IR -Memory Stick Folder = Pasta do cartão de memória -Memory Stick inserted = Cartão de memória inserido +Memory Stick Folder = Pasta do Cartão de Memória +Memory Stick inserted = Cartão de Memória inserido MHz, 0:default = MHz, 0 = padrão MMDDYYYY = MMDDAAAA Moving background = Movendo o cenário de fundo -Newest Save = Salvamento mais novo +Newest Save = Save mais novo No animation = Sem animação Not a PSP game = Não é um jogo de PSP -Off = Desativado -Oldest Save = Salvamento mais antigo +Off = Desligado +Oldest Save = Save mais antigo Path does not exist! = O caminho não existe! -PSP Memory Stick = Cartão de memória da PSP -PSP Model = Modelo da PSP -PSP Settings = Definições da PSP +PSP Memory Stick = Cartão de Memória do PSP +PSP Model = Modelo do PSP +PSP Settings = Definições do PSP PSP-1000 = PSP-1000 PSP-2000/3000 = PSP-2000/3000 Recent games = Jogos recentes Record Audio = Gravar áudio -Record Display = Gravar ecrã +Record Display = Gravar tela Reset Recording on Save/Load State = Reiniciar a gravação ao salvar/carregar o estado -Restore Default Settings = Restaurar as definições do PPSSPP para os padrões -RetroAchievements = RetroAchievements -Rewind Snapshot Interval = Rebobinar a frequência dos snapshots (consome memória) -Save path in installed.txt = Caminho do salvamento em installed.txt -Save path in My Documents = Caminho do salvamento em "Meus Documentos" +Restore Default Settings = Restaurar as Definições do PPSSPP para os padrões +Rewind Snapshot Interval = Rebobinar frequência dos snapshots (consome memória) +Save path in installed.txt = Caminho do save em installed.txt +Save path in My Documents = Caminho do save em Meus Documentos Savestate Slot = Espaço do estado salvo Savestate slot backups = Backups dos espaços dos estados salvos Screenshots as PNG = Salvar as Capturas de Tela em formato .png -Set Memory Stick folder = Definir a pasta do cartão de memória +Set Memory Stick folder = Set Memory Stick folder Set UI background... = Definir o cenário de fundo da interface do usuário... Show ID = Mostrar ID Show region flag = Mostrar a bandeira da região Simulate UMD delays = Simular atrasos do UMD -Simulate UMD slow reading speed = Simular leitura lenta do UMD -Slot 1 = Slot 1 -Slot 2 = Slot 2 -Slot 3 = Slot 3 -Slot 4 = Slot 4 -Slot 5 = Slot 5 +Slot 1 = Espaço 1 +Slot 2 = Espaço 2 +Slot 3 = Espaço 3 +Slot 4 = Espaço 4 +Slot 5 = Espaço 5 Storage full = Armazenamento cheio Sustained performance mode = Modo de performance sustentado Time Format = Formato da hora -Transparent UI background = Cenário de fundo da interface do usuário transparente +Transparent UI background = Transparent UI background UI = Interface do usuário UI Sound = Som da interface do usuário UI background animation = Animação do cenário de fundo da interface do usuário undo %c = Backup %c USB = USB Use Lossless Video Codec (FFV1) = Usar codec de vídeo sem perdas (FFV1) -Use O to confirm = Usar O como botão de confirmação (círculo) +Use O to confirm = Usar O como botão de confirmação (Círculo) Use output buffer (with overlay) for recording = Usar buffer de saída (com sobreposição) para gravação Use system native keyboard = Usar teclado nativo do sistema -Use X to confirm = Usar X como botão de confirmação (cruz) +Use X to confirm = Usar X como botão de confirmação (Cruz) VersionCheck = Procurar novas versões do PPSSPP -WARNING: Android battery save mode is on = AVISO: O Modo de Economia da Bateria do Android está ativado -WARNING: Battery save mode is on = AVISO: O Modo de Economia da Bateria está ativado +WARNING: Android battery save mode is on = AVISO: O Modo de Economia da Bateria do Android está habilitado +WARNING: Battery save mode is on = AVISO: O Modo de Economia da Bateria está habilitado Waves = Ondas YYYYMMDD = AAAAMMDD Theme = Tema Color Tint = Tonalidade da Cor Color Saturation = Saturação das Cores -Show Memory Stick folder = Mostrar a pasta do cartão de memória +Show Memory Stick folder = Mostrar a pasta do Cartão de Memória [Themes] -Dark = Escuro +Dark = Dark Default = Padrão [TextureShaders] -Off = Desativado +Off = Desligado TexMMPX = TexMMPX Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Search] -No settings matched '%1' = Nenhuma das definições combinou com '%1' +No settings matched '%1' = Nenhuma das Definições combinou com '%1' Filtering settings by '%1' = Definições da filtragem do '%1' -Find settings = Encontrar Ddfinições +Find settings = Encontrar Definições Filter = Filtro Clear filter = Limpar filtro -Search term = Termo de pesquisa +Search term = Search term [Upgrade] Details = Detalhes @@ -1375,28 +1257,29 @@ New version of PPSSPP available = Uma nova versão do PPSSPP está disponível %1 choice = %1 escolha %1 heading = %1 cabeçalho %1 radio button = %1 botão do rádio -%1 text field = %1 campo de texto +%1 text field = %1 campo do texto Choices: = Escolhas: List: = Lista: Progress: %1% = Progresso: %1% Screen representation = Representação da tela [VR] -6DoF movement = Movimento 6DoF -Camera type = Tipo de câmera -Distance to 2D menus and scenes = Distância aos menus e cenas 2D -Distance to 3D scenes when VR disabled = Distância às cenas 3D quando a realidade virtual estiver desativada -Experts only = Apenas programadores -Force 72Hz update = Forçar taxa de atualização de 72Hz -Game camera rotation step per frame = Passo da rotação da câmera do jogo por frame -Game camera uses rotation smoothing = A câmera do jogo usa suavização da rotação -Heads-up display detection = Deteção do HUD -Heads-up display scale = Escala do HUD -Manual switching between flat screen and VR using SCREEN key = Alternar manualmente entre tela plana e realidade virtual usando a tecla da tela -Map controller movements to keys = Mapear movimentos do comando para teclas -Map HMD rotations on keys instead of VR camera = Mapear rotação HMD nas teclas em vez de na câmera de realidade virtual -Motion needed to generate action = Movimento necessário para gerar ação -Stereoscopic vision (Experimental) = Visão estereoscópica (experimental) -Virtual reality = Realidade Virtual -VR camera = Câmera de realidade virtual -VR controllers = Comandos de realidade virtual +% of native FoV = % of native FoV +6DoF movement = 6DoF movement +Camera type = Camera type +Distance to 2D menus and scenes = Distance to 2D menus and scenes +Experts only = Experts only +Field of view scale = Field of view scale +Force 72Hz update = Force 72Hz update +Game camera rotation step per frame = Game camera rotation step per frame +Game camera uses rotation smoothing = Game camera uses rotation smoothing +Heads-up display detection = Heads-up display detection +Heads-up display scale = Heads-up display scale +Manual switching between flat screen and VR using SCREEN key = Manual switching between flat screen and VR using SCREEN key +Map controller movements to keys = Map controller movements to keys +Map HMD rotations on keys instead of VR camera = Map HMD rotations on keys instead of VR camera +Motion needed to generate action = Motion needed to generate action +Stereoscopic vision (Experimental) = Stereoscopic vision (Experimental) +Virtual reality = Virtual reality +VR camera = VR camera +VR controllers = VR controllers diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 50043e288..b4c64a988 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Format intern audio (necesită restartare) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (mai lent) Auto = Automat Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrare Calibrated = Calibrated Calibration = Calibrare -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Clasic Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Raza zonei moarte Disable D-Pad diagonals (4-way touch) = Dezactivare diagonale D-Pad (touch in 4 direcții) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Controale Touch pe Ecran Portrait = Portret Portrait Reversed = Portret intors PSP Action Buttons = Butoane acțiune PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivitate Shape = Shape Show Touch Pause Menu Button = Arată buton meniu pauză -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -231,7 +167,6 @@ Log Console = &Log Console Memory View... = Memory &View... More Settings... = &More Settings... Nearest = &Nearest -Recent = &Recent Skip Buffer Effects = &Skip buffer effects Off = &Off Open Chat = Open Chat @@ -270,6 +205,7 @@ Texture Filtering = Te&xture Filtering Texture Scaling = &Texture Scaling Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = &Vertex Cache VSync = VS&ync Vulkan = Vulkan Window Size = &Window Size @@ -283,11 +219,8 @@ Backspace = Backspace Block address = Block address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -298,11 +231,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Enable debug logging Enter address = Enter address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -312,10 +242,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Log level Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Next No block = No block -Off = Off Prev = Previous Random = Random Replace textures = Replace textures @@ -333,12 +261,10 @@ Stats = Stats System Information = System information Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -346,14 +272,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Înapoi -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Ignoră Center = Center -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Schimbarea modului GPU necesită restart. Restart acum? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Alege folder pt. salvări PPSSPP Confirm Overwrite = Vrei să suprascrii datele? @@ -373,46 +295,33 @@ DeleteConfirmGameConfig = Chiar vrei să ștergi setările pt. acest joc? DeleteFailed = Nu s-au putut șterge datele. Deleting = Ştergere în progres\nVă rugăm așteptați... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Enable all -Enabled = Enabled Enter = Confirmare -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Stop GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Încarcă Load completed = Încărcare Completă Loading = Se încarcă\nAșteptați... LoadingFailed = Nu s-au putut încărca datele. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Mișcă Move Down = Move Down Move Up = Move Up Network Connection = Conexiune la rețea NEW DATA = DATE NOI No = Nu -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Date vechi salvate detectate Options = Options -Password = Password Remove = Remove Reset = Resetare Resize = Modificare marime -Restart = Restart Retry = Reîncearcă Save = Salvează Save completed = Salvare Completă @@ -421,7 +330,6 @@ SavingFailed = Nu s-au putut salva datele. Search = Search seconds, 0:off = secunde, 0 = off Select = Selectează -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -432,11 +340,7 @@ Supported = Supported There is no data = Salvare inexistentă Toggle All = Schimbă tot Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Când salvezi, va încărca pe un PSP, dar nu un PPSSPP mai vechi When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Da @@ -502,23 +406,18 @@ ZIP file detected (Require WINRAR) = Fișierul e compresat(ZIP).\nVă rog decomp [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Ștergere -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Creează configurare joc Create Shortcut = Creează scurtătură Delete Game = Ștergere joc Delete Game Config = Ștergere configurare joc Delete Save Data = Ștergere salvare Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Joc -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Setări joc Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Instalare date -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -528,8 +427,6 @@ Remove From Recent = Ștergere de la "Recent" SaveData = Salvare Setting Background = Setting background Show In Folder = Arată în folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -624,7 +521,6 @@ Must Restart = Trebuie să resartezi PPSSPP pt. ca această schimbare să aibă Native device resolution = Rezoluție nativă dispozitiv Nearest = Apropiată No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects @@ -659,7 +555,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Filtru texturi Texture Filtering = Filtrare texturi -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Scalare texturi Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -670,6 +565,8 @@ Upscale Level = Nivel Suprascalare Upscale Type = Tip Suprascalare UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Stocare vertecși +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Mărime ecran @@ -686,12 +583,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Configurare automată Autoconfigure for device = Configurare automată pt. dispozitiv Bind All = Bind All Clear All = Curătă tot -Combo mappings are not enabled = Combo mappings are not enabled Default All = Înapoi la inițial Map a new key for = Configurează o nouă tastă pentru Map Key = Map key @@ -748,7 +643,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Schimbare axe Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -761,7 +665,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Dpad Jos Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -774,7 +677,6 @@ None = None Note = Note OpenChat = Open chat Pause = Pauză -Previous Slot = Previous Slot R = R RapidFire = Foc-rapid Record = Record @@ -804,7 +706,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Repede inainte Up = Dpad Sus @@ -814,7 +715,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -847,6 +747,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Schimbă adresa MAC Change proAdhocServer Address = Schimbă adresa IP a serverului PRO ad hoc (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -880,6 +785,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Rețea inițializată +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -890,9 +796,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -902,23 +810,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Trișare Continue = Continuă @@ -945,7 +836,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -953,7 +843,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -974,7 +863,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1178,11 +1066,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1191,9 +1078,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1205,7 +1090,7 @@ System Information = System information System Name = Name System Version = System version Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Version information @@ -1288,7 +1173,6 @@ Record Audio = Record audio Record Display = Record display Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Adu la setări PPSSPP inițiale -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1301,7 +1185,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulare întârzieri UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1356,11 +1239,12 @@ Download = Descarcă New version of PPSSPP available = Nouă versiune de PPSSPP disponibilă. [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index a96135ba0..ecc25deb8 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Попытка не удалась -%1: Attempt started = %1: Попытка началась -%1 achievements, %2 points = %1 достижений, %2 очков -Account = Аккаунт -Achievement progress = Прогресс достижения -Achievement unlocked = Достижение разблокировано -Achievements = Достижения -Achievements are disabled = Достижения отключены -Achievements enabled = Достижения включены -Achievements with active challenges = Достижения с активными испытаниями -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Почти завершенные достижения -Around me = Вокруг меня -Can't log in to RetroAchievements right now = Сейчас невозможно войти в RetroAchievements -Challenge indicator = Индикатор испытания -Contacting RetroAchievements server... = Подключение к серверу RetroAchievements... -Customize = Настроить -Earned = Вы разблокировали %1 из %2 достижений и получили %3 из %4 очков -Encore Mode = Режим повтора -Failed logging in to RetroAchievements = Не удалось войти в RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Не удалось подключиться к RetroAchievements. Достижения не будут разблокированы. -Failed to identify game. Achievements will not unlock. = Не удалось опознать игру. Достижения не будут разблокированы. -Hardcore Mode (no savestates) = Режим испытания (без сохранений состояния) -Hardcore Mode = Режим испытания -How to use RetroAchievements = Как пользоваться RetroAchievements -In Encore mode - listings may be wrong below = В режиме повтора - списки ниже могут быть неверными -Leaderboard attempt started or failed = Попытка занесения в таблицу лидеров началась или не удалась -Leaderboard result submitted = Результат занесен в таблицу лидеров -Leaderboard score submission = Занесение очков в таблицу лидеров -Leaderboard submission is enabled = Занесение в таблицу лидеров включено -Leaderboard tracker = Трекер таблицы лидеров -Leaderboards = Таблицы лидеров -Links = Ссылки -Locked achievements = Заблокированные достижения -Log bad memory accesses = Логировать нарушения доступа к памяти -Mastered %1 = Получен %1 -Notifications = Уведомления -Recently unlocked achievements = Недавно разблокированные достижения -Reconnected to RetroAchievements. = Повторно подключено к RetroAchievements. -Register on www.retroachievements.org = Зарегистрироваться на www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements недоступен для данной игры -RetroAchievements website = Веб-сайт RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = Состояние загружено без данных о достижениях -Save states not available in Hardcore Mode = Сохранение состояний недоступно в режиме испытаний -Sound Effects = Звуковые эффекты -Statistics = Статистика -Submitted %1 for %2 = Занесено %1 для %2 -Syncing achievements data... = Синхронизация данных о достижениях... -Test Mode = Тестовый режим -This feature is not available in Hardcore Mode = Данная возможность недоступна в режиме испытаний -This game has no achievements = У данной игры нет достижений -Top players = Лучшие игроки -Unlocked achievements = Разблокированные достижения -Unofficial achievements = Неофициальные достижения -Unsupported achievements = Неподдерживаемые достижения - [Audio] Alternate speed volume = Громкость при другой скорости Audio backend = Аудио бэкенд (нужен перезапуск) Audio Error = Ошибка звука -Audio file format not supported. Must be WAV. = Формат аудиофайла не поддерживается. Он должен быть WAV. AudioBufferingForBluetooth = Буфер, подходящий для Bluetooth (медленнее) Auto = Авто Device = Устройство @@ -95,7 +36,6 @@ Calibrate Analog Stick = Калибровка аналогового стика Calibrate = Калибровка Calibrated = Откалиблированный Calibration = Калибровка -Circular low end radius = Круговой радиус нижнего предела Circular stick input = Круговой ввод стика Classic = Классический Confine Mouse = Не давать мыши выходить за пределы окна @@ -108,10 +48,8 @@ Deadzone radius = Радиус мертвой зоны Disable D-Pad diagonals (4-way touch) = Отключить крестовину по диагонали Disable diagonal input = Отключить диагональный ввод Double tap = Двойное нажатие -Enable analog stick gesture = Включить жест аналогового стика Enable gesture control = Включить настройку жестов Enable standard shortcut keys = Включить стандартные сочетания клавиш -frames = кадров Gesture = Жест Gesture mapping = Настройка жестов Glowing borders = Подсветка краёв @@ -140,7 +78,6 @@ OnScreen = Элементы управления на экране Portrait = Портретная Portrait Reversed = Портретная (перевернутая) PSP Action Buttons = Кнопки действий PSP -Rapid fire interval = Интервал турбокнопки Raw input = Прямой ввод Repeat mode = Режим повтора Reset to defaults = По умолчанию @@ -149,7 +86,6 @@ Sensitivity (scale) = Чувствительность (шкала) Sensitivity = Чувствительность Shape = Форма Show Touch Pause Menu Button = Показывать кнопку паузы -Sticky D-Pad (easier sweeping movements) = Прилипающий D-Pad (облегченные масштабные движения) Swipe = Свайпы Swipe sensitivity = Чувствительность свайпов Swipe smoothing = Сглаживание свайпов @@ -195,7 +131,7 @@ Direct3D9 = Direct3D &9 Direct3D11 = &Direct3D 11 Disassembly = &Дизассемблер... Discord = Discord -Display Layout && Effects = Редактор расположения экрана и эффектов... +Display Layout && Effects = Редактор расположения экрана... Display Rotation = Ориентация экрана Dump Next Frame to Log = Сохранить &кадр в логе Emulation = &Эмуляция @@ -230,7 +166,6 @@ Log Console = Консоль отладки Memory View... = Просмотрщик па&мяти... More Settings... = &Ещё настройки... Nearest = &Ближайший -Recent = &Recent Skip Buffer Effects = &Пропускать эффекты (небуферированный, быстрее) Off = В&ыключено Open Chat = Открыть чат @@ -269,6 +204,7 @@ Texture Filtering = &Фильтрация текстур Texture Scaling = &Масштабирование текстур Use Lossless Video Codec (FFV1) = Использовать видеокодек без потерь (FFV1) Use output buffer for video = Использовать выходной буфер для видео +Vertex Cache = &Вершинный кэш VSync = Вертикальная син&хронизация Vulkan = Vulkan Window Size = Размер &окна @@ -282,11 +218,8 @@ Backspace = Стереть Block address = Адрес блока By Address = По адресу Copy savestates to memstick root = Копировать состояния сохранений в корень карты памяти -Create frame dump = Создать дамп кадра Create/Open textures.ini file for current game = Создать/открыть файл textures.ini для текущей игры Current = Текущий -Debug overlay = Оверлей отладки -Debug stats = Статистика отладки Dev Tools = Инструменты разработчика DevMenu = Меню разраб. Disabled JIT functionality = Отключение функционала JIT @@ -297,11 +230,8 @@ Enable driver bug workarounds = Включить обход ошибок дра Enable Logging = Включить отладочное логирование Enter address = Ввести адрес FPU = FPU -Fragment = Фрагмент -Frame timing = Время кадра Framedump tests = Тест дампов кадров Frame Profiler = Профайлер кадров -GPU Allocator Viewer = Просмотрщик аллокатора ГП GPU Driver Test = Проверка драйвера ГП GPU log profiler = Профилировщик логов ГП GPU Profile = Профиль ГП @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Логировать статистику про Log Level = Уровень отладки Log View = Отображение логов Logging Channels = Параметры логирования -Multi-threaded rendering = Многопоточный рендеринг Next = Следующий No block = Нет блока -Off = Выкл. Prev = Предыдущий Random = Случайный Replace textures = Подменять текстуры @@ -332,12 +260,10 @@ Stats = Статистика System Information = Информация о системе Texture ini file created = Создан файл textures.ini Texture Replacement = Подмена текстур -Audio Debug = Отладка аудио -Control Debug = Отладка управления +Toggle Audio Debug = Включить/выключить отладку аудио +Toggle Control Debug = Включить/выключить отладку управления Toggle Freeze = Запустить/остановить Touchscreen Test = Тест сенсорного экрана -Ubershaders = Убершейдеры -Vertex = Вершина VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * разр. PSP Active = Активно Back = Назад -Bottom Center = Внизу в центре -Bottom Left = Внизу слева -Bottom Right = Внизу справа Cancel = Отмена Center = По центру -Center Left = В центре слева -Center Right = В центре справа -Changing this setting requires PPSSPP to restart. = Изменение этого параметра требует перезапуска PPSSPP. +ChangingGPUBackends = Для изменения бэкенда ГП требуется перезапуск. Перезапустить сейчас? +ChangingInflightFrames = Для изменения буферирования команд графики требуется перезапуск. Перезапустить сейчас? Channel: = Канал: Choose PPSSPP save folder = Выбрать папку с сохранениями Confirm Overwrite = Вы хотите перезаписать данные? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Вы уверены, что хотите удалит DeleteFailed = Не удалось удалить данные. Deleting = Удаление\nПожалуйста, подождите... Disable All = Отключить все -Disabled = Отключено Dumps = Дампы Edit = Изменить Enable All = Включить все -Enabled = Включено Enter = Ввод -Failed to connect to server, check your internet connection. = Не удалось подключиться к серверу, проверьте ваше интернет-соединение. -Failed to log in, check your username and password. = Не удалось войти, проверьте ваши имя пользователя и пароль. Filter = Фильтр Finish = Сохранить GE Frame Dumps = Дампы кадров GE Grid = Сетка Inactive = Неактивно -Installing... = Установка... InternalError = Произошла внутренняя ошибка. -Links = Ссылки Load = Загрузить Load completed = Загрузка завершена Loading = Загрузка\nПожалуйста, подождите... LoadingFailed = Невозможно загрузить даные. -Log in = Войти -Log out = Выйти -Logged in! = Вход совершен! -Logging in... = Вход... Move = Положение Move Down = Сдвинуть вверх Move Up = Сдвинуть вниз Network Connection = Сетевое подключение NEW DATA = Новое сохранение No = Нет -None = Нет ObtainingIP = Получение IP-адреса.\nПожалуйста, подождите... OK = OK Old savedata detected = Старый формат сохранений обнаружен Options = Опции -Password = Пароль Remove = Удалить Reset = Сбросить Resize = Размер -Restart = Перезапуск Retry = Снова Save = Сохранить Save completed = Сохранение завершено. @@ -420,7 +329,6 @@ SavingFailed = Не удалось сохранить. Search = Поиск seconds, 0:off = секунд, 0 = выкл. Select = Выбрать -Settings = Настройки Shift = Сдвинуть Skip = Пропустить Snap = Разметка @@ -431,11 +339,7 @@ Supported = Поддерживается There is no data = Нет данных Toggle All = Переключить все Toggle List = Переключить список -Top Center = Вверху в центре -Top Left = Вверху слева -Top Right = Вверу справа Unsupported = Не поддерживается -Username = Имя пользователя When you save, it will load on a PSP, but not an older PPSSPP = Когда вы сохранитесь, оно может быть загружено на PSP, но не на старой версии PPSSPP When you save, it will not work on outdated PSP Firmware anymore = Когда вы сохранитесь, оно больше не будет работать на устаревших версиях прошивки PSP Yes = Да @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = файл сжат (ZIP).\nПожалуйс [Game] Asia = Азия Calculate CRC = Вычислить CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Удалить -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Создать конфиг Create Shortcut = Создать ярлык Delete Game = Удалить игру Delete Game Config = Удалить конфиг Delete Save Data = Удалить сохранения Europe = Европа -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Игра -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Настройки игры -Homebrew = Homebrew +Homebrew = Хоумбрю Hong Kong = Гонконг InstallData = Установить данные -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Япония Korea = Корея MB = Мб @@ -527,8 +426,6 @@ Remove From Recent = Удалить из недавних SaveData = Сохранения Setting Background = Установка фона Show In Folder = Показать в папке -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = США Use UI background = Использовать фон интерфейса @@ -571,7 +468,7 @@ Balanced = Сбалансированно Bicubic = Бикубический Both = Оба Buffer graphics commands (faster, input lag) = Команды буферированной графики (быстрее, задержка ввода) -BufferedRenderingRequired = Предупреждение: данная игра несовместима с опцией "Пропускать эффекты (небуферированный)" +BufferedRenderingRequired = Предупреждение: для этой игры требуется буферированный режим рендеринга. Camera = Камера Camera Device = Устройство камеры Cardboard Screen Size = Размер экрана (в % от области видимости) @@ -588,7 +485,7 @@ Device = Устройство Direct3D 9 = Direct3D 9 Direct3D 11 = Direct3D 11 Disabled = Отключено -Display Layout && Effects = Редактор расположения экрана и эффектов +Display Layout && Effects = Редактор расположения экрана Display Resolution (HW scaler) = Разрешение экрана (аппаратное) Enable Cardboard VR = Включить Cardboard VR FPS = FPS @@ -623,7 +520,6 @@ Must Restart = Вы должны перезапустить PPSSPP, чтобы Native device resolution = Разрешение устройства Nearest = Ближайший No buffer = Нет буфера -Render all frames = Render all frames Show Battery % = Показывать % заряда батареи Show Speed = Показывать скорость Skip Buffer Effects = Пропускать эффекты (небуферированный) @@ -658,7 +554,6 @@ Stereo rendering = Стереорендеринг Stretch = Растягивание Texture Filter = Текстурный фильтр Texture Filtering = Фильтрация текстур -Texture replacement pack activated = Пакет замены текстур активирован Texture Scaling = Масштабирование текстур Texture Shader = Текстурный шейдер Turn off Hardware Tessellation - unsupported = Выключите настройку "Аппаратная тесселяция": не поддерживается @@ -669,6 +564,8 @@ Upscale Level = Уровень масштабирования Upscale Type = Тип масштабирования UpscaleLevel Tip = Нагружает ЦП. Масштабирование может происходить с задержкой для предотвращения заиканий Use all displays = Задействовать все экраны +Vertex Cache = Вершинный кэш +VertexCache Tip = Быстрее, но может вызывать мерцание VSync = Вертикальная синхронизация Vulkan = Vulkan Window Size = Размер окна @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP-архив повреждён Zip file does not contain PSP software = В ZIP-файле отсутсвует ПО для PSP [KeyMapping] -Allow combo mappings = Разрешать раскладки комбо Autoconfigure = Автоконфиг Autoconfigure for device = Автоконфиг для устройства Bind All = Настроить всё Clear All = Очистить все -Combo mappings are not enabled = Раскладки комбо не включены Default All = По умолчанию Map a new key for = Назначить кнопку для Map Key = Назначить кнопку @@ -704,14 +599,14 @@ Browse = Обзор... Buy PPSSPP Gold = PPSSPP Gold Choose folder = Выберите папку Credits = Авторы -PPSSPP Homebrew Store = Магазин homebrew для PPSSPP +PPSSPP Homebrew Store = Магазин хоумбрю PPSSPP Exit = Выход Game Settings = Настройки Games = Игры Give PPSSPP permission to access storage = Дать доступ к хранилищу данных -Homebrew & Demos = Homebrew и демо +Homebrew & Demos = Хоумбрю и демо How to get games = Как получить игры? -How to get homebrew & demos = Как получить homebrew и демо? +How to get homebrew & demos = Как получить хоумбрю и демо? Load = Открыть... Loading... = Загрузка... PinPath = Закрепить @@ -747,7 +642,16 @@ Audio/Video Recording = Запись аудио/видео AxisSwap = Смена осей Circle = Кружок Cross = Крестик -Custom %d = Пользовательская %d +Custom 1 = Пользовательская 1 +Custom 10 = Пользовательская 10 +Custom 2 = Пользовательская 2 +Custom 3 = Пользовательская 3 +Custom 4 = Пользовательская 4 +Custom 5 = Пользовательская 5 +Custom 6 = Пользовательская 6 +Custom 7 = Пользовательская 7 +Custom 8 = Пользовательская 8 +Custom 9 = Пользовательская 9 D-pad down = D-pad вниз D-pad left = D-pad влево D-pad right = D-pad вправо @@ -760,7 +664,6 @@ Display Portrait Reversed = Портретная ор-я (перевернута Double tap button = Двойное нажатие на кнопку Down = Вниз Dpad = Крестовина -Exit App = Exit App Frame Advance = Перемотка кадров Hold = Hold Home = Home @@ -773,9 +676,8 @@ None = Нет Note = Нота OpenChat = Открыть чат Pause = Пауза -Previous Slot = Предыдущий слот R = R -RapidFire = Турбокнопка +RapidFire = Турбо кнопка Record = Запись Remote hold = Удалённый hold Rewind = Возврат @@ -803,7 +705,6 @@ Texture Dumping = Дамп текстур Texture Replacement = Подмена текстур Toggle Fullscreen = Полноэкр. режим Toggle mode = Переключить режим -Toggle WLAN = Переключить WLAN Triangle = Треугольник Fast-forward = Перемотка вперед Up = Вверх @@ -816,6 +717,11 @@ AdHoc Server = Ad-hoc сервер AdhocServer Failed to Bind Port = Не удалось привязать порт ad-hoc сервера AM: Data from Unknown Port = AM: Данные от неизвестного порта Auto = Авто +Bottom Center = Внизу в центре +Bottom Left = Внизу слева +Bottom Right = Внизу справа +Center Left = В центре слева +Center Right = В центре справа Change Mac Address = Изменить MAC-адрес Change proAdhocServer Address = Изменить IP-адрес ad-hoc сервера (localhost = множество экземпляров) ChangeMacSaveConfirm = Сгенерировать новый MAC-адрес? @@ -849,6 +755,7 @@ Invalid IP or hostname = Некорректный IP или имя хоста Minimum Timeout = Минимальный таймаут (задержка в мс, 0 = по умолчанию) Misc = Прочее (по умолчанию = совместимость с PSP) Network Initialized = Сеть активирована +None = Нет Please change your Port Offset = Пожалуйста, измените ваше смещение порта Port offset = Смещение порта (0 = совместимость с PSP) Open PPSSPP Multiplayer Wiki Page = Открыть wiki-страницу мультиплеера PPSSPP @@ -859,9 +766,11 @@ Quick Chat 3 = Быстрый чат 3 Quick Chat 4 = Быстрый чат 4 Quick Chat 5 = Быстрый чат 5 QuickChat = Быстрый чат -Randomize = Случайный Send = Отправить Send Discord Presence information = Отправлять информацию об игре в Discord +Top Center = Вверху в центре +Top Left = Вверху слева +Top Right = Вверу справа Unable to find UPnP device = Невозможно найти устройство UPnP UPnP (port-forwarding) = UPnP (проброс портов) UPnP need to be reinitialized = Необходимо перезапустить UPnP @@ -871,23 +780,6 @@ Validating address... = Проверка адреса... WLAN Channel = Канал WLAN You're in Offline Mode, go to lobby or online hall = Вы в автономном режиме, зайдите в лобби или в комнату в Интернете -[PSPSettings] -Auto = Автоматически -Chinese (simplified) = Китайский упрощенный -Chinese (traditional) = Китайский традиционный -Dutch = Нидерландский -English = Английский -French = Французский -Game language = Язык игры -German = Немецкий -Italian = Итальянский -Japanese = Японский -Korean = Корейский -Games often don't support all languages = Игры часто не поддерживают все языки -Portuguese = Португальский -Russian = Русский -Spanish = Испанский - [Pause] Cheats = Читы Continue = Продолжить @@ -914,7 +806,6 @@ Animation speed (0 -> disable) = Скорость анимации (0 -> disable Aspect = Соотношение Black border = Черные рамки Bloom = Свечение -BloomNoBlur = Bloom (без размытия) Brightness = Яркость Cartoon = Мультипликация CatmullRom = Бикубический (Catmull-Rom) апскейлер @@ -922,7 +813,6 @@ ColorCorrection = Цветокоррекция ColorPreservation = Сохранение цвета Contrast = Контрастность CRT = ЭЛТ-развертка -FakeReflections = Имитация отражений FXAA = Сглаживание FXAA Gamma = Гамма GreenLevel = Green level @@ -943,7 +833,6 @@ SSAA(Gauss) = SSAA (Гаусс) Strength = Сила Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = Бикубическое масштабирование UpscaleSpline36 = Масштабирование Spline36 VideoSmoothingAA = Сглаживание видео Vignette = Виньетирование @@ -990,7 +879,6 @@ written = Написан на C++ для скорости и портируем [MemStick] Already contains PSP data = Уже содержит данные PSP -Cancelled - try again = Отменено - попробуйте еще раз Create or Choose a PSP folder = Создайте или выберите папку PSP Current = Текущая DataCanBeShared = Данные могут передаваться между обычным PPSSPP и Gold @@ -1177,11 +1065,10 @@ GPU Flags = Флаги ГП GPU Information = Информация о ГП High precision float range = Диапазон точных дробных чисел High precision int range = Диапазон точных целых чисел -Icon cache = Кэш иконок JIT available = JIT доступен Lang/Region = Язык/регион Memory Page Size = Размер страницы памяти -Native resolution = Родное разрешение +Native Resolution = Родное разрешение No GPU driver bugs detected = Ошибок драйвера ГП не обнаружено OGL Extensions = Расширения OGL OpenGL ES 2.0 Extensions = Расширения OpenGL ES 2.0 @@ -1190,9 +1077,7 @@ OpenGL Extensions = Расширения OpenGL Optimal frames per buffer = Оптимально кадров на буфер Optimal sample rate = Оптимальная частота дискретизации OS Information = Информация об ОС -Pixel resolution = Пиксельное разрешение PPSSPP build = Сборка PPSSPP -Present modes = Режимы представления Refresh rate = Частота обновления Release = Релизная RW/RX exclusive = Захват RW/RX @@ -1204,7 +1089,7 @@ System Information = Информация о системе System Name = Название System Version = Версия системы Threads = Потоки -UI resolution = Разрешение интерфейса +UI Resolution = Разрешение интерфейса Vendor = Производитель Vendor (detected) = Производитель (обнаруженный) Version Information = Информация о версии @@ -1240,10 +1125,10 @@ Day Light Saving = Летнее время DDMMYYYY = ДДММГГГГ Decrease size = Уменьшить размер Developer Tools = Инструменты разработчика -Display Extra Info = Показывать дополнительную ниформацию -Display Games on a grid = Показывать "Игры" в виде сетки -Display Homebrew on a grid = Показывать "Homebrew и демо" в виде сетки -Display Recent on a grid = Показывать "Недавние" в виде сетки +Display Extra Info = Отображать дополнительную ниформацию +Display Games on a grid = Отображать "Игры" в сетке +Display Homebrew on a grid = Отображать "Хоумбрю и демо" в сетке +Display Recent on a grid = Отображать "Недавние" в сетке Dynarec (JIT) = Динамическая рекомпиляция (JIT) Emulation = Эмуляция Enable Cheats = Включить коды @@ -1258,7 +1143,7 @@ Floating symbols = Парящие символы Force real clock sync (slower, less lag) = Принудительная синхронизация реальной частоты ЦП (медленнее, меньше лагов) Games list settings = Настройки списка игр General = Основные -Grid icon size = Размер ярлыков в виде сетки +Grid icon size = Размер ярлыков в режиме сетки Help the PPSSPP team = Помочь команде PPSSPP Host (bugs, less lag) = Хост (возможны баги, меньше лагов) Ignore bad memory accesses = Игнорировать ошибки доступа к памяти @@ -1287,7 +1172,6 @@ Record Audio = Запись звука Record Display = Запись видео Reset Recording on Save/Load State = Сбрасывать запись при сохранении/загрузке Restore Default Settings = Сбросить настройки PPSSPP -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Частота сохранения состояний Save path in installed.txt = Путь до сохранений в installed.txt Save path in My Documents = Путь до сохранений в "Мои документы" @@ -1300,7 +1184,6 @@ Show ID = Показывать ID Show Memory Stick folder = Показать папку Memory Stick Show region flag = Показывать флаг региона Simulate UMD delays = Имитировать задержки UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Слот 1 Slot 2 = Слот 2 Slot 3 = Слот 3 @@ -1355,11 +1238,12 @@ Download = Загрузить New version of PPSSPP available = Доступна новая версия PPSSPP [VR] +% of native FoV = % стандартного угла обзора 6DoF movement = Движение 6DoF Camera type = Тип камеры Distance to 2D menus and scenes = Расстояние до 2D-меню и сцен -Distance to 3D scenes when VR disabled = Расстояние до 3D-сцен при отключенной ВР Experts only = Только для экспертов +Field of view scale = Масштаб угла обзора Force 72Hz update = Принудительная частота обновления 72 Гц Game camera rotation step per frame = Шаг поворота внутриигровой камеры за 1 кадр Game camera uses rotation smoothing = При повороте внутриигровой камеры используется сглаживание diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 286512e26..12c6c9759 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1,66 +1,7 @@ -[Achievements] -%1 achievements, %2 points = %1 achievements, %2 poäng -%1: Attempt started = %1: Topplisteförsök startat -%1: Attempt failed = %1: Topplisteförsök misslyckades -Account = Inloggning -Achievement progress = Achievement-progress -Achievement unlocked = Achievement avklarat! -Achievements = Achievements -Achievements are disabled = Achievements är avstängda -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Nästan avklarade achievements -Around me = Around me -Can't log in to RetroAchievements right now = Kan inte logga in till RetroAchievements just nu -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Kontaktar RetroAchievements' server... -Customize = Anpassa -Earned = Du har tjänat %1 av %2 achievements, och %3 of %4 poäng -Encore Mode = Encore-läge (kan ta achievements igen) -Failed logging in to RetroAchievements = Misslyckades logga in till RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Misslyckades logga in RetroAchievements. Achievements kommer ej kunna avklaras. -Failed to identify game. Achievements will not unlock. = Kunde inte identifiera spel. Achievements kommer ej kunna avklaras. -Hardcore Mode (no savestates) = Utmanings-läge (inga sparade state) -Hardcore Mode = Utmanings-läge -How to use RetroAchievements = Hur man använder RetroAchievements -In Encore mode - listings may be wrong below = I Encore-läge - saker kan visas fel nedan -Leaderboard attempt started or failed = Topplisteförsök påbörjat eller misslyckat -Leaderboard result submitted = Topplisteresultat inskickat -Leaderboard score submission = Inskickning av topplisteresultat -Leaderboard submission is enabled = Skickar in poäng till topplistor -Leaderboard tracker = Topplisteresultatvisare -Leaderboards = Topplistor -Links = Länkar -Locked achievements = Låsta achievements -Log bad memory accesses = Logga felaktiga minnesåtkomster -Mastered %1 = Klarade av %1! -Notifications = Notifications -Recently unlocked achievements = Nyligen avklarade achievements -Reconnected to RetroAchievements. = Åter uppkopplad till RetroAchievements. -Register on www.retroachievements.org = Registrera på www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements finns inte tillgängliga för detta spel -RetroAchievements website = RetroAchievements webbsida -Rich Presence = Visa vad du spelar live på webbsidan -Save state loaded without achievement data = Sparad state laddad utan achievement-data -Save states not available in Hardcore Mode = Sparade states inte tillgängliga i utmaningsläge -Sound Effects = Ljudeffekter -Statistics = Statistik -Submitted %1 for %2 = Skickade in %1 for %2 -Syncing achievements data... = Synkar achievementdata... -Test Mode = Test-läge -This feature is not available in Hardcore Mode = Denna feature är inte tillgänglig i utmaningsläge -This game has no achievements = Detta spel har inga achievements -Top players = Toppspelare -Unlocked achievements = Upplåsta achievements -Unofficial achievements = Inofficiella achievements -Unsupported achievements = Icke-stödda achievements - [Audio] Alternate speed volume = Volym vid alternativ hastighet Audio backend = Uppspelningsteknik (ändring kräver omstart!) Audio Error = Ljudfel -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) Auto = Auto Device = Enhet @@ -95,12 +36,11 @@ Calibrate Analog Stick = Kalibrera analog styrspak Calibrate = Kalibrera Calibrated = Kalibrerad Calibration = Kalibrering -Circular low end radius = Circulär inner-radie Circular stick input = Cirkulär analog input Classic = Klassisk Confine Mouse = Stäng in muspekaren i fönstret Control Mapping = Kontrollmappning -Custom Key Setting = Anpassa knapp +Custom Key Setting = Custom Key Setting Customize = Anpassa Customize Touch Controls = Anpassad layout... D-PAD = D-Pad @@ -108,10 +48,8 @@ Deadzone radius = Dödzons-radie Disable D-Pad diagonals (4-way touch) = Slå av D-Pad-diagonaler (4-vägs touch) Disable diagonal input = Blockera diagonal input Double tap = Dubbel-tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Gest-kontroll Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gest Gesture mapping = Gest-mappning Glowing borders = Lysande kanter @@ -140,7 +78,6 @@ OnScreen = Touch-kontroller på skärmen Portrait = Porträtt Portrait Reversed = Porträtt omvänt PSP Action Buttons = PSP action-knappar -Rapid fire interval = Rapid fire interval Raw input = Rå input Repeat mode = Repetitionsläge Reset to defaults = Återställ till standardvärden @@ -149,7 +86,6 @@ Sensitivity (scale) = Känslighet (skala) Sensitivity = Känslighet Shape = Form Show Touch Pause Menu Button = Visa touch-knapp för pause -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe-känslighet Swipe smoothing = Swipe-utjämning @@ -186,7 +122,7 @@ Backend = Renderare Bicubic = Bikubisk Break = Bryt Break on Load = Stoppa direkt efter laddning -Buy Gold = Köp Guld +Buy Gold = Buy Gold Control Mapping... = Kontrollmappning... Copy PSP memory base address = Kopiera bas-addressen till PSP'n minne Debugging = Debuggning @@ -230,7 +166,6 @@ Log Console = Loggkonsol Memory View... = Minnesvy... More Settings... = Mer inställningar... Nearest = Nearest -Recent = &Recent Skip Buffer Effects = &Skippa buffereffekter Off = Av Open Chat = Öppna chat @@ -269,6 +204,7 @@ Texture Filtering = Texturfiltrering Texture Scaling = Texturskalning Use Lossless Video Codec (FFV1) = &Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = Vertexcache VSync = VSync Vulkan = Vulkan Window Size = Fönsterstorlek @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Blockaddress By Address = Per address Copy savestates to memstick root = Kopiera save states till roten av memstick -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Aktuellt -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Avstängd JIT-funktionalitet @@ -297,11 +230,8 @@ Enable driver bug workarounds = Tillåt workarounds för drivrutins-buggar Enable Logging = Debugloggning Enter address = Address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump-tester Frame Profiler = Frame-profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU drivrutins-test GPU log profiler = GPU logg-profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Loggnivå Log View = Log view Logging Channels = Loggkanaler -Multi-threaded rendering = Multi-threaded rendering Next = Nästa No block = Inget block -Off = Off Prev = Föregående Random = Slump Replace textures = Ersätt texturer @@ -332,12 +260,10 @@ Stats = Stats System Information = Systeminformation Texture ini file created = Texture ini file created Texture Replacement = Ersätt texturer -Audio Debug = Audio debug -Control Debug = Control Debug +Toggle Audio Debug = Toggla audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggla freeze Touchscreen Test = Touchskärm-test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Aktiv Back = Tillbaka -Bottom Center = Underkant centrerad -Bottom Left = Underkant vänster -Bottom Right = Underkant höger Cancel = Avbryt Center = Centrera -Center Left = Centrerad vänster -Center Right = Centrerad höger -Changing this setting requires PPSSPP to restart. = Att ändra denna inställning kräver att PPSSPP startas om. +ChangingGPUBackends = PPSSPP måste starta om för att byta GPU-backend. Vill du starta om nu? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Kanal: Choose PPSSPP save folder = Välj folder att spara i Confirm Overwrite = Vill du skriva över datan? @@ -362,7 +284,6 @@ ConnectingAP = Kopplar upp till acceesspunkten.\nVänta... ConnectingPleaseWait = Kopplar upp.\nVänta... ConnectionName = Uppkopplingsnamn Corrupted Data = Korrupt data -#Default = Default Delete = Radera Delete all = Radera allt Delete completed = Borttaget. @@ -373,46 +294,33 @@ DeleteConfirmGameConfig = Vill du verkligen ta bort inställningarna för det h DeleteFailed = Misslyckades ta bort data. Deleting = Tar bort\nVänta... Disable All = Stäng av allt -Disabled = Av Dumps = Dumps -Edit = Redigera +Edit = Edit Enable All = Slå på allt -Enabled = På Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Färdig GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inaktiv -Installing... = Installing... InternalError = Ett internt fel har upptäckts. -Links = Links Load = Ladda Load completed = Laddat. Loading = Laddar\nVänta... LoadingFailed = Kunde inte ladda data. -Log in = Logga in -Log out = Logga ut -Logged in! = Logged in! -Logging in... = Logging in... Move = Flytta Move Down = Flytta ner Move Up = Flytta upp Network Connection = Nätverksuppkoppling NEW DATA = NY DATA No = Nej -None = Ingen -ObtainingIP = Hämtar IP-address.\nVänta... +ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Gammal savedata upptäckt Options = Inställningar -Password = Lösenord Remove = Ta bort Reset = Återställ Resize = Ändra storlek -Restart = Starta om Retry = Försök igen Save = Spara Save completed = Sparat. @@ -421,7 +329,6 @@ SavingFailed = Kunde inte spara data. Search = Sök seconds, 0:off = sek, 0: av Select = Välj -Settings = Inställningar Shift = Skift Skip = Skip Snap = Snap @@ -432,11 +339,7 @@ Supported = Stödd There is no data = Det finns ingen data. Toggle All = Vänd alla Toggle List = Toggle list -Top Center = Överkant centrerad -Top Left = Överkant vänster -Top Right = Överkant höger Unsupported = Stöds ej -Username = Användarnamn When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Ja @@ -502,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Räkna ut CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Ta bort -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Skapa spelconfig Create Shortcut = Skapa genväg Delete Game = Ta bort spel Delete Game Config = Ta bort spelconfig Delete Save Data = Ta bort sparad data Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Spel -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Spelinställningar Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Installerad data -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -528,8 +426,6 @@ Remove From Recent = Ta bort från "Senast spelat" SaveData = Sparad data Setting Background = Sätter UI-bakgrund Show In Folder = Visa i mapp -Time Played: %1h %2m %3s = Spelad tid: %1h %2m %3s -Uncompressed = Okomprimerat USA = USA Use UI background = Använd UI-bakgrund @@ -624,7 +520,6 @@ Must Restart = Starta om PPSSPP för att ändringen ska få effekt. Native device resolution = Native device resolution Nearest = Närmast No buffer = Ingen buffer -Render all frames = Render all frames Show Battery % = Visa batteri-% Show Speed = Visa hastighet Skip Buffer Effects = Skippa buffereffekter (snabbare, risk för fel) @@ -659,7 +554,6 @@ Stereo rendering = Stereo-rendering Stretch = Sträck ut Texture Filter = Texturfilter Texture Filtering = Texturfiltrering -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Texturskalning Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported @@ -670,6 +564,8 @@ Upscale Level = Uppskalningsnivå Upscale Type = Uppskalningstyp UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Använd alla displayer +Vertex Cache = Vertexcache +VertexCache Tip = Faster, but may cause temporary flicker VSync = VSync Vulkan = Vulkan Window Size = Fönsterstorlek @@ -686,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Autokonfiguration Autoconfigure for device = Autokonfigurera för enhet Bind All = Bind All Clear All = Rensa -Combo mappings are not enabled = Combo mappings are not enabled Default All = Återställ allt Map a new key for = Mappa ny knapp för Map Key = Mappa tangent @@ -744,11 +638,20 @@ An.Up = Analog Upp Analog limiter = Analog limiter Analog speed = Analog speed Analog Stick = Analog-sticka -Audio/Video Recording = Audio/Video-inspelning +Audio/Video Recording = Audio/Video recording AxisSwap = Byt axlar Circle = Cirkel Cross = X -Custom %d = Anpassad %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -759,29 +662,27 @@ Display Landscape Reversed = Display Landscape Reversed Display Portrait = Display Portrait Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button -Down = D-pad Ner -Dpad = D-pad -Exit App = Exit App +Down = Dpad Ner +Dpad = Dpad Frame Advance = Stega frame Hold = Hold Home = Home L = L -Left = D-pad Vänster +Left = Dpad Vänster Load State = Ladda State Mute toggle = Mute toggle Next Slot = Nästa slot None = None -Note = Not -OpenChat = Öppna chat +Note = Note +OpenChat = Open chat Pause = Paus -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire -Record = Spela in +Record = Record Remote hold = Remote hold -Rewind = Spola tillbaka -Right = D-pad Höger -Right Analog Stick = Analog-sticka höger +Rewind = Rewind +Right = Dpad Höger +Right Analog Stick = Right Analog Stick RightAn.Down = RightAn.Down RightAn.Left = RightAn.Left RightAn.Right = RightAn.Right @@ -790,7 +691,7 @@ Rotate Analog (CCW) = Rotate analog (CCW) Rotate Analog (CW) = Rotate analog (CW) Save State = Spara State Screen = Skärm -Screenshot = Skärmdump +Screenshot = Screenshot Select = Select SpeedToggle = Speed toggle Square = Kvadrat @@ -799,12 +700,11 @@ Swipe Down = Swipe Down Swipe Left = Swipe Left Swipe Right = Swipe Right Swipe Up = Swipe Up -tap to customize = klicka för att anpassa -Texture Dumping = Textur-dumpning -Texture Replacement = Textur-ersättning +tap to customize = tap to customize +Texture Dumping = Texture dumping +Texture Replacement = Texture replacement Toggle Fullscreen = Växla fullskärm -Toggle mode = Toggla läge -Toggle WLAN = Toggle WLAN +Toggle mode = Toggle mode Triangle = Triangel Fast-forward = Snabbspola Up = Dpad Upp @@ -817,52 +717,60 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Ändra Mac-adress Change proAdhocServer Address = Ändra proAdhocServer-adress (localhost = multiple instances) -ChangeMacSaveConfirm = Generera en ny MAC-address? -ChangeMacSaveWarning = Vissa spel kollar MAC-address när de laddar savedata, så detta kan förstöra saves +ChangeMacSaveConfirm = Generate a new MAC address? +ChangeMacSaveWarning = Some games verify the MAC address when loading savedata, so this may break old saves. Chat = Chat -Chat Button Position = Chatt-knappens position -Chat Here = Chatta här -Chat message = Chatt-meddelande -Chat Screen Position = Chatt-rutans position -Disconnected from AdhocServer = Bortkopplad från Adhoc-servern -DNS Error Resolving = DNS fel vid addressresolving +Chat Button Position = Chat button position +Chat Here = Chat here +Chat message = Chat message +Chat Screen Position = Chat screen position +Disconnected from AdhocServer = Disconnected from ad hoc server +DNS Error Resolving = DNS error resolving Enable built-in PRO Adhoc Server = Enable built-in PRO Adhoc Server -Enable network chat = Nätverkschatt +Enable network chat = Enable network chat Enable networking = Nätverk/wlan (beta) Enable UPnP = Enable UPnP (need a few seconds to detect) -EnableQuickChat = Snabbchat -Enter a new PSP nickname = Mata in ett nytt PSP-nickname +EnableQuickChat = Enable quick chat +Enter a new PSP nickname = Enter a new PSP nickname Enter Quick Chat 1 = Snabbchat 1 Enter Quick Chat 2 = Snabbchat 2 Enter Quick Chat 3 = Snabbchat 3 Enter Quick Chat 4 = Snabbchat 4 Enter Quick Chat 5 = Snabbchat 5 Error = Error -Failed to Bind Localhost IP = Misslyckades binda localhost-IP -Failed to Bind Port = Misslyckades binda port -Failed to connect to Adhoc Server = Misslyckades koppla upp till adhoc-servern +Failed to Bind Localhost IP = Failed to bind localhost IP +Failed to Bind Port = Failed to bind port +Failed to connect to Adhoc Server = Failed to connect to ad hoc server Forced First Connect = Forced first connect (faster connect) -GM: Data from Unknown Port = GM: Data från okänd port +GM: Data from Unknown Port = GM: Data from Unknown Port Hostname = Hostname Invalid IP or hostname = Ogiltigt IP eller hostname -Minimum Timeout = Minimal timeout (override in ms, 0 = default) -Misc = Miscellaneous (default = PSP-kompatibilitet) +Minimum Timeout = Minimum timeout (override in ms, 0 = default) +Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Nätverk initierat -Please change your Port Offset = Vänligen ändra din port-offset -Port offset = Port offset (0 = PSP-kompatibilitet) -Open PPSSPP Multiplayer Wiki Page = Öppna PPSSPP Multiplayer Wiki Page -proAdhocServer Address: = Adhoc server-address: +None = None +Please change your Port Offset = Please change your port offset +Port offset = Port offset(0 = PSP compatibility) +Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page +proAdhocServer Address: = Ad hoc server address: Quick Chat 1 = Snabbchat 1 Quick Chat 2 = Snabbchat 2 Quick Chat 3 = Snabbchat 3 Quick Chat 4 = Snabbchat 4 Quick Chat 5 = Snabbchat 5 QuickChat = Snabbchat -Randomize = Randomize Send = Skicka Send Discord Presence information = Visa Discord "Rich Presence"-information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -898,7 +806,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Svart kant Bloom = Bloom-effekt -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -906,7 +813,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Gamma = Gamma GreenLevel = Grön-nivå @@ -922,12 +828,11 @@ RedBlue = Röd/Blå glasögon Saturation = Färgmättnad Scanlines = Scan-linjer Sharpen = Skärpa -SideBySide = Sida vid sida (SBS) +SideBySide = Side by side (SBS) SSAA(Gauss) = Supersampling AA (Gauss) Strength = Styrka Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = UpscaleSpline36 VideoSmoothingAA = VideoSmoothingAA Vignette = Vignett @@ -972,26 +877,8 @@ Twitter @PPSSPP_emu = Twitter @PPSSPP_emu website = Kolla in webbsidan: written = Skriven i C++ - prestanda och portabilitet -[PSPSettings] -Auto = Auto -Chinese (simplified) = Kinesiska (förenklad) -Chinese (traditional) = Kinesiska (traditionell) -Dutch = Holländska -English = Engelska -French = Franska -Game language = Språk i spel -Games often don't support all languages = Games often don't support all languages -German = Tyska -Italian = Italienska -Japanese = Japanska -Korean = Koreanska -Portuguese = Portugisiska -Russian = Ryska -Spanish = Spanska - [MemStick] Already contains PSP data = Innehåller redan PSP-data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Skapa eller välj en PSP-mapp Current = Nuvarande DataCanBeShared = Data kan delas mellan PPSSPP vanlig/Gold @@ -1124,12 +1011,12 @@ State load undone = State load ogjort Untitled PSP game = Untitled PSP game [Search] -Clear filter = Rensa filter +Clear filter = Clear filter Filter = Filter -Filtering settings by '%1' = Filtrerar inställningar efter '%1' -Find settings = Sök inställningar -No settings matched '%1' = Inga inställningar matchade '%1' -Search term = Sökterm +Filtering settings by '%1' = Filtering settings by '%1' +Find settings = Find settings +No settings matched '%1' = No settings matched '%1' +Search term = Search term [Store] Already Installed = Redan installerad @@ -1163,9 +1050,9 @@ CPU Information = CPU-information CPU Name = Name D3DCompiler Version = D3DCompiler version Debug = Debug -Debugger Present = Debugger närvarande -Depth buffer format = Depth buffer-format -Device Info = Device-information +Debugger Present = Debugger present +Depth buffer format = Depth buffer format +Device Info = Device info Directories = Directories Display Color Formats = Display Color Formats Display Information = Display information @@ -1178,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU-information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available -Lang/Region = Språk/Region +Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1191,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS-information -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP bygge -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1205,7 +1089,7 @@ System Information = Systeminformation System Name = Name System Version = Systemversion Threads = Trådar -UI resolution = UI-upplösning +UI Resolution = UI-upplösning Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Versionsinformation @@ -1217,7 +1101,7 @@ Vulkan Features = Vulkan features 12HR = 12HR 24HR = 24HR Auto = Auto -Auto Load Savestate = Ladda savestate automatiskt +Auto Load Savestate = Auto load savestate AVI Dump started. = AVI dump started AVI Dump stopped. = AVI dump stopped Cache ISO in RAM = Cachea hela ISO:n i RAM @@ -1288,7 +1172,6 @@ Record Audio = Spela in audio till fil Record Display = Spela in video till fil Reset Recording on Save/Load State = Reset recording on Save/Load state Restore Default Settings = Återställ standard-inställningar -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = Sparkatalog från installed.txt Save path in My Documents = Sparkatalog i Dokument @@ -1301,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Visa Memory Stick-mappen Show region flag = Visa region-flaggor Simulate UMD delays = Simulera UMD-fördröjningar -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1320,7 +1202,7 @@ USB = USB Use Lossless Video Codec (FFV1) = Använd förlust-fri video codec (FFV1) Use O to confirm = Använd O för att bekräfta Use output buffer (with overlay) for recording = Use output buffer (with overlay) for recording -Use system native keyboard = Använd systemets tangentbord för text-input +Use system native keyboard = Use system native keyboard Use X to confirm = Använd X för att bekräfta VersionCheck = Kolla efter nya versioner av PPSSPP WARNING: Android battery save mode is on = WARNING: Android battery save mode is On @@ -1356,18 +1238,19 @@ Download = Ladda ner New version of PPSSPP available = Ny version av PPSSPP tillgänglig [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF rörelse Camera type = Kameratyp Distance to 2D menus and scenes = Avstånd till 2D-menyer och scener -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view-skala Force 72Hz update = Tvinga 72Hz uppdateringsfrekvens Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing Heads-up display detection = Heads-up display detection Heads-up display scale = Heads-up display scale Manual switching between flat screen and VR using SCREEN key = Manual switching between flat screen and VR using SCREEN key -Map controller movements to keys = Mappa kontroller-rörelser till knappar +Map controller movements to keys = Map controller movements to keys Map HMD rotations on keys instead of VR camera = Map HMD rotations on keys instead of VR camera Motion needed to generate action = Motion needed to generate action Stereoscopic vision (Experimental) = Stereoscopic vision (Experimental) diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index f25bcdccb..81f11eb3b 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Kahaliling bilis ng tunog Audio backend = Tunog ng instrumento (kailangan pang ulitin) Audio Error = Tunog ng pagkakamali -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth maayos na daloy (mabagal) Auto = Awto Device = Kagamitan @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Klasiko Confine Mouse = Trap mouse within window/display area @@ -108,10 +48,8 @@ Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Glowing borders @@ -140,7 +78,6 @@ OnScreen = Pindutan sa screen Portrait = Patayo Portrait Reversed = Pabaliktad na patayo PSP Action Buttons = PSP action buttons -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Sensitivity Shape = Hugis Show Touch Pause Menu Button = Ipakita ang pause menu button -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Mahagip Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Log Console Memory View... = Memory View... More Settings... = Karagdagang settings... Nearest = Nearest -Recent = &Recent Skip Buffer Effects = Skip buffer effects Off = Off Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Texture Filtering Texture Scaling = Texture Scaling Use Lossless Video Codec (FFV1) = Use lossless video codec (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = Vertex Cache VSync = VSync Vulkan = Vulkan Window Size = Window Size @@ -282,11 +218,8 @@ Backspace = Backspace Block address = I-Block ang address By Address = By address Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Create/Open textures.ini file for current game Current = Kasalukuyan -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Development tools DevMenu = DevMenu Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Paganahin ang Debug Logging Enter address = Ilagay ang address FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Log dropped frame statistics Log Level = Level ng Log Log View = Log view Logging Channels = Logging channels -Multi-threaded rendering = Multi-threaded rendering Next = Susunod No block = No block -Off = Off Prev = Nagdaan Random = Random Replace textures = Replace textures @@ -332,12 +260,10 @@ Stats = Stats System Information = Impormasyon tungkol sa system Texture ini file created = Texture ini file created Texture Replacement = Texture replacement -Audio Debug = Audio Debug -Control Debug = Control Debug +Toggle Audio Debug = Toggle audio debug +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Toggle freeze Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP res Active = Active Back = Bumalik -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Kanselahin Center = Gitna -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Kapag pinalitan ang GPU backends,\nKailangan mong I-restart ang PPSSPP. Magpatuloy? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Piliin ang PPSSPP save folder Confirm Overwrite = Nais mo bang patungan ang datos? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Sigurado ka bang burahin ang settings ng larong ito? DeleteFailed = Hindi mabura ang datos. Deleting = Binubura...\nSandali lamang... Disable All = Disable all -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Paganahin lahat -Enabled = Enabled Enter = Pumasok -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Tapusin GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Inactive -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = I-Load Load completed = Kumpletong na-i load. Loading = Sandali lamang... LoadingFailed = Loading ng datos ay pumalya. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Galawin Move Down = Move Down Move Up = Move Up Network Connection = Network Connection NEW DATA = BAGONG DATOS No = Hindi -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = Sige Old savedata detected = Nahanap ang lumang savedata Options = Options -Password = Password Remove = Remove Reset = Ibalik Resize = Resize -Restart = Restart Retry = Ulitin Save = Save Save completed = Kumpletong na-i save. @@ -420,7 +329,6 @@ SavingFailed = Hindi ma-i save ang datos. Search = Hanapin seconds, 0:off = segundo, 0 = off Select = Piliin -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Supported There is no data = Walang Datos Toggle All = Toggle all Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Unsupported -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Kapag iyong na-i save, gagana ito mismo sa PSP\npero hindi sa lumang bersyon ng PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Oo @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompres [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Kumpirmahin ang pag bura -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Gumawa ng game config Create Shortcut = Gumawa ng shortcut Delete Game = Burahin ang laro Delete Game Config = Burahin ang game config Delete Save Data = Burahin ang save data Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Laro -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Ayos ng laro Homebrew = Homebrew Hong Kong = Hong Kong InstallData = InstallData -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Alisin mula sa "Recent" SaveData = SaveData Setting Background = Setting background Show In Folder = Ipakita sa folder -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Use UI background @@ -623,7 +520,6 @@ Must Restart = Kailangan i-restart ang PPSSPP upang maging epiktibo ito Native device resolution = Native device resolution Nearest = Pinakamalapit No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Skip buffer effects (non-buffered, mabilis) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Iunat Texture Filter = Panala ng Texture Texture Filtering = Pagsala sa Texture -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Pagsukat sa Texture Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": hindi suportado @@ -669,6 +564,8 @@ Upscale Level = Antas ng upscale Upscale Type = Uri ng upscale UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays +Vertex Cache = Vertex Cache +VertexCache Tip = Mabilis, pero mag kaka flicker ng temporary VSync = VSync Vulkan = Vulkan Window Size = Window size @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file ay hindi naglalaman ng PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Auto configure Autoconfigure for device = Autoconfigure for device Bind All = Bind All Clear All = Burahin lahat -Combo mappings are not enabled = Combo mappings are not enabled Default All = Ibalik lahat sa dati Map a new key for = Map a new key for Map Key = Map key @@ -747,7 +642,16 @@ Audio/Video Recording = Audio/Video recording AxisSwap = Axis swap Circle = Circle Cross = Cross -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Baba Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Hold Home = Home @@ -773,7 +676,6 @@ None = None Note = Note OpenChat = Open chat Pause = Hinto -Previous Slot = Previous Slot R = R RapidFire = RapidFire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Toggle fullscreen Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Triangle Fast-forward = Fast-forward Up = Taas @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Baguhin ang MAC Address Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Network initialized +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Mandaya Continue = Ituloy @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Cartoon CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT scanlines -FakeReflections = FakeReflections FXAA = FXAA Antialiasing Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Supersampling AA (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Upscaler VideoSmoothingAA = VideoSmoothingAA Vignette = Vignette @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = GPU information High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Lang/Region Memory Page Size = Memory page size -Native resolution = Native resolution +Native Resolution = Native resolution No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = OGL extensions OpenGL ES 2.0 Extensions = OpenGL ES 2.0 extensions @@ -1190,9 +1077,7 @@ OpenGL Extensions = OpenGL extensions Optimal frames per buffer = Optimal frames per buffer Optimal sample rate = Optimal sample rate OS Information = OS impormasyon -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP build -Present modes = Present modes Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive @@ -1204,7 +1089,7 @@ System Information = Bersiyon impormasyon System Name = Pangalan ng sistema System Version = Sistema bersiyon Threads = Threads -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Vendor Vendor (detected) = Vendor (detected) Version Information = Bersiyon impormasyon @@ -1287,7 +1172,6 @@ Record Audio = I-record ang Audio Record Display = I-record ang Display Reset Recording on Save/Load State = Reset Recording on Save/Load state Restore Default Settings = Ibalik ang settings sa dati nitong ayos -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Rewind Snapshot Interval (mem hog) Save path in installed.txt = I-save sa direksyon na installed.txt Save path in My Documents = I-save sa direksyon na "Aking Dokumento" @@ -1300,7 +1184,6 @@ Show ID = Ipakita ang ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Ipakita ang rehiyon ng watawat Simulate UMD delays = Simulate UMD Delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Download New version of PPSSPP available = Meron nang bagong bersiyon ang PPSSPP [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index e3895af89..8ff6524d6 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: ส่งข้อมูลไปยังกระดานแต้มผู้นำล้มเหลว -%1: Attempt started = %1: เริ่มการส่งข้อมูลไปยังกระดานแต้มผู้นำแล้ว -%1 achievements, %2 points = %1 เป้าหมายความสำเร็จ, %2 แต้ม -Account = บัญชีผู้ใช้งาน -Achievement progress = ความคืบหน้าเป้าหมายความสำเร็จ -Achievement unlocked = ตอนเป้าหมายความสำเร็จถูกปลดล็อค -Achievements = เป้าหมายความสำเร็จ -Achievements enabled = เปิดใช้งาน เป้าหมายความสำเร็จ -Achievements are disabled = ปิดใช้งาน เป้าหมายความสำเร็จ -Achievements with active challenges = เป้าหมายความสำเร็จพร้อมด้วยโหมดท้าทาย -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = เป้าหมายความสำเร็จใกล้จะเสร็จสมบูรณ์ -Around me = รอบตัวฉัน -Can't log in to RetroAchievements right now = ไม่สามารถล็อกอินเข้าไปยัง RetroAchievements ได้ในขณะนี้ -Challenge indicator = ตัวบ่งชี้ความท้าทาย -Contacting RetroAchievements server... = กำลังเชื่อมต่อกับเซิร์ฟเวอร์ RetroAchievements... -Customize = ปรับแต่ง -Earned = คุณได้รับ %1 of %2 เป้าหมายความสำเร็จ, และ %3 ของ %4 แต้ม -Encore Mode = โหมดคำราม -Failed logging in to RetroAchievements = ล้มเหลวในการเข้าใช้งานไปยัง RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = ล้มเหลวในการเข้าใช้งานไปยัง RetroAchievements เป้าหมายความสำเร็จอาจจะไม่ถูกปลดล็อค -Failed to identify game. Achievements will not unlock. = ล้มเหลวในการระบุข้อมูลเกม เป้าหมายความสำเร็จอาจจะไม่ถูกปลดล็อค -Hardcore Mode (no savestates) = โหมดท้าทาย (ไม่มีเซฟสเตท) -Hardcore Mode = โหมดท้าทาย -How to use RetroAchievements = วิธีใช้งาน RetroAchievements -In Encore mode - listings may be wrong below = ในโหมดคำราม - รายชื่อด้านล่างอาจจะผิด -Leaderboard attempt started or failed = เริ่มต้น/ล้มเหลว ไปยังกระดานแต้มผู้นำ -Leaderboard result submitted = ส่งคะแนนไปยังกระดานแต้มผู้นำแล้ว -Leaderboard score submission = ตอนส่งคะแนนไปยังกระดานแต้มผู้นำ -Leaderboard submission is enabled = เปิดใช้งานการส่งคะแนนไปยังกระดานแต้มผู้นำ -Leaderboard tracker = ตัวติดตามกระดานแต้มผู้นำ -Leaderboards = กระดานแต้มผู้นำ -Links = ลิงก์ -Locked achievements = เป้าหมายความสำเร็จที่ยังถูกล็อคเอาไว้ -Log bad memory accesses = เก็บค่าการเข้าถึงหน่วยความจำที่ไม่ดี -Mastered %1 = เชี่ยวชาญ %1 -Notifications = การแจ้งเตือน -Recently unlocked achievements = เป้าหมายความสำเร็จที่ถูกปลดล็อคล่าสุด -Reconnected to RetroAchievements. = กำลังเชื่อมต่ออีกครั้งไปยัง RetroAchievements -Register on www.retroachievements.org = สมัครได้ที่ www.retroachievements.org -RetroAchievements are not available for this game = ไม่สามารถใช้งาน RetroAchievements กับเกมนี้ได้ -RetroAchievements website = เว็บไซต์ RetroAchievements -Rich Presence = Rich Presence -Save state loaded without achievement data = โหลดเซฟสเตทแล้วโดยที่ไม่มีข้อมูลเป้าหมายความสำเร็จ -Save states not available in Hardcore Mode = ไม่สามารถใช้งานเซฟสเตทได้ในโหมดท้าทาย -Sound Effects = เสียงเอฟเฟ็คท์ -Statistics = สถิติ -Submitted %1 for %2 = ส่ง %1 สำหรับ %2 -Syncing achievements data... = กำลังซิงก์ข้อมูล เป้าหมายความสำเร็จ... -Test Mode = โหมดทดสอบ -This feature is not available in Hardcore Mode = ฟีเจอร์นี้ไม่สามารถปรับใช้งานได้ในโหมดท้าทาย -This game has no achievements = เกมนี้ไม่มีเป้าหมายความสำเร็จ -Top players = ผู้เล่นชั้นนำ -Unlocked achievements = เป้าหมายความสำเร็จที่ถูกปลดล็อคแล้ว -Unofficial achievements = เป้าหมายความสำเร็จอย่างไม่เป็นทางการ -Unsupported achievements = เป้าหมายความสำเร็จที่ไม่รองรับ - [Audio] Alternate speed volume = ระดับเสียงในโหมดเร่งความเร็ว Audio backend = รูปแบบเสียงที่สนับสนุน (จำเป็นต้องรีสตาร์ท) Audio Error = ระบบเสียงเกิดข้อผิดพลาด -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = บลูทูธ-เฟรนด์ลี่ บัฟเฟอร์ (ช้ากว่า) Auto = อัตโนมัติ Device = อุปกรณ์ @@ -95,11 +36,10 @@ Calibrate Analog Stick = ปรับค่าความคลาดเคล Calibrate = สอบเทียบสมดุล Calibrated = ค่าความคลาดเคลื่อนที่ปรับ Calibration = ปรับค่าความคลาดเคลื่อน -Circular low end radius = รัศมีต่ำสุดของการหมุนปุ่ม -Circular stick input = ค่านำเข้าการหมุนปุ่ม +Circular stick input = ค่านำเข้าหมุนปุ่ม Classic = แบบดั้งเดิม Confine Mouse = จำกัดเมาส์ภายในหน้าต่าง/พื้นที่แสดงผล -Control Mapping = เปลี่ยนแปลงค่าการควบคุม +Control Mapping = เปลี่ยนแปลงค่าควบคุม Custom Key Setting = ติดตั้งปุ่มคอมโบปรับแต่ง Customize = ปรับแต่ง Customize Touch Controls = ปรับแต่งปุ่มควบคุมสัมผัสหน้าจอ @@ -108,10 +48,8 @@ Deadzone radius = รัศมีของ Deadzone Disable D-Pad diagonals (4-way touch) = ปิดการใช้งานปุ่มลูกศรในแนวทแยง (สัมผัส 4 ทิศทาง) Disable diagonal input = ปิดการใช้งานอนาล็อกในแนวทแยง Double tap = แตะสองครั้ง -Enable analog stick gesture = เปิดใช้ควบคุมการปัดอนาล็อก -Enable gesture control = เปิดใช้ควบคุมการปัดหน้าจอสัมผัส +Enable gesture control = เปิดการควบคุมปัดหน้าจอสัมผัส Enable standard shortcut keys = เปิดการใช้งานปุ่มคีย์ลัดแบบพื้นฐาน -frames = เฟรม Gesture = ปัดจอ Gesture mapping = เซ็ตปุ่มควบคุมปัดหน้าจอสัมผัส Glowing borders = แบบขอบทึบแสง @@ -140,7 +78,6 @@ OnScreen = ปรับใช้หน้าจอควบคุมแบบป Portrait = แนวตั้ง Portrait Reversed = แนวตั้งกลับด้าน PSP Action Buttons = ปุ่มแอ็คชั่นของ PSP -Rapid fire interval = ปุ่มยิงรัวอย่างรวดเร็ว Raw input = ค่าตั้งต้น Repeat mode = โหมดปุ่มย้ำ Reset to defaults = คืนค่าเริ่มต้น @@ -149,7 +86,6 @@ Sensitivity = ความไวต่อการตอบสนอง Sensitivity (scale) = ความไวการตอบสนอง Shape = กรอบปุ่ม Show Touch Pause Menu Button = แสดงปุ่มหยุดสำหรับเข้าหน้าเมนู -Sticky D-Pad (easier sweeping movements) = ปุมลูกศรแบบหนืด (การกดกวาดปุ่มทำได้ง่ายขึ้น) Swipe = ปัดหน้าจอ Swipe sensitivity = ความแรงที่ใช้ปัดหน้าจอ Swipe smoothing = ความลื่นไหลในการปัดหน้าจอ @@ -169,6 +105,7 @@ X = แกน X Y = แกน Y [CwCheats] +#Add Cheat = เพิ่มสูตรโกง # This one is not used Cheats = การใช้สูตรโกง Edit Cheat File = ปรับแต่งไฟล์สูตรโกง Import Cheats = นำเข้าจากไฟล์สูตรโกง @@ -230,7 +167,6 @@ Log Console = เก็บค่าคอนโซล Memory View... = มุมมองค่าความจำ... More Settings... = การตั้งค่าอื่นๆ... Nearest = แบบใกล้เคียง -Recent = &Recent Skip Buffer Effects = ข้ามการใช้บัฟเฟอร์เอฟเฟ็คท์ (ปิดบัฟเฟอร์) Off = ปิด Open Chat = เปิดหน้าต่างแชท @@ -269,6 +205,7 @@ Texture Filtering = การกรองพื้นผิว Texture Scaling = การปรับพื้นผิว Use Lossless Video Codec (FFV1) = ใช้โค้ด FFV1 บันทึกวีดีโอ เพื่อรักษาความคมชัด Use output buffer for video = ใช้การส่งออกบัฟเฟอร์ในการบันทึกวีดีโอ +Vertex Cache = เวอร์เท็กซ์ แคช VSync = ควบคุมช่วงของเฟรมเรทให้คงที่ Vulkan = วัลแคน Window Size = ขนาดของหน้าจอ @@ -282,11 +219,8 @@ Backspace = ถอยหลัง Block address = บล็อคค่าที่อยู่ By Address = โดยค่าที่อยู่ Copy savestates to memstick root = คัดลอกเซฟสเตทไปยังต้นทางของเม็มสติ๊ก -Create frame dump = สร้างไฟล์เฟรมดั๊มพ์ Create/Open textures.ini file for current game = สร้าง/เปิด ไฟล์ textures.ini ของเกมนี้ Current = ค่าดั้งเดิม -Debug overlay = ตัวแสดงช่วยแก้ไขบั๊ก -Debug stats = สถานะการแก้ไขจุดบกพร่อง Dev Tools = เครื่องมือนักพัฒนา DevMenu = เมนูผู้พัฒนา Disabled JIT functionality = ปิดฟังก์ชั่นการทำงานของระบบ JIT @@ -297,11 +231,8 @@ Enable Logging = เปิดใช้งานการเก็บค่าแ Enable driver bug workarounds = เปิดใช้งานการแก้ขัดปัญหาไดรเวอร์บั๊ก Enter address = ใส่ค่าที่อยู่ FPU = FPU -Fragment = แฟร็กเม้นต์ Framedump tests = ทดสอบไฟล์เฟรมดั๊มพ์ Frame Profiler = รายละเอียดของเฟรม -Frame timing = ช่วงเวลาของเฟรม -GPU Allocator Viewer = ตัวแสดงการจัดสรร GPU GPU Driver Test = ทดสอบไดรเวอร์ GPU GPU log profiler = ตัวแสดงค่าโปรไฟล์ GPU GPU Profile = โปรไฟล์ GPU @@ -311,10 +242,8 @@ Log Dropped Frame Statistics = เก็บสถิติค่าเฟรม Log Level = เก็บค่าระดับ Log View = เก็บค่ามุมมอง Logging Channels = ช่องทางเก็บค่าข้อมูล -Multi-threaded rendering = การเรนเดอร์แบบมัลติเธรด Next = ถัดไป No block = ไม่ต้องบล็อค -Off = ปิด Prev = ถอยกลับ Random = สุ่ม Replace textures = แทนที่พื้นผิวจากแหล่งที่เก็บข้อมูล @@ -332,12 +261,10 @@ Stats = สถิติ System Information = ข้อมูลโดยรวมของระบบ Texture ini file created = ไฟล์ Texture.ini ได้ถูกสร้างแล้ว Texture Replacement = การแทนที่พื้นผิว -Audio Debug = แก้ไขจุดบกพร่องของเสียง -Control Debug = แก้ไขจุดบกพร่องการควบคุม +Toggle Audio Debug = แก้ไขจุดบกพร่องของเสียง +Toggle Control Debug = แก้ไขจุดบกพร่องการควบคุม Toggle Freeze = ปุ่มแช่แข็ง Touchscreen Test = ทดสอบหน้าจอสัมผัส -Ubershaders = อูเบอร์เฉดเดอร์ -Vertex = เวอร์เท็ค VFPU = VFPU [Dialog] @@ -345,14 +272,10 @@ VFPU = VFPU * PSP res = * ขนาดจอ PSP Active = เปิดการทำงาน Back = ย้อนกลับ -Bottom Center = มุมล่างกลางจอ -Bottom Left = มุมล่างซ้ายจอ -Bottom Right = มุมล่างขวาจอ Cancel = ยกเลิก Center = กึ่งกลาง -Center Left = มุมกลางซ้ายจอ -Center Right = มุมกลางขวาจอ -Changing this setting requires PPSSPP to restart. = การเปลี่ยนการตั้งค่านี้จำเป็นต้องรีสตาร์ท PPSSPP +ChangingGPUBackends = เมื่อเปลี่ยนแปลงรูปแบบการสนับสนุนของจีพียู\nกรุณาเริ่ม PPSSPP ใหม่อีกครั้งนึง ต้องการรีสตาร์ทเลยไหม? +ChangingInflightFrames = การเปลี่ยนแปลงค่าควบคุมกราฟิกบัฟเฟอร์จำเป็นต้องเริ่ม PPSSPP\nใหม่อีกครั้งนึง ต้องการรีสตาร์ทเลยไหม? Channel: = แชลนอล: Choose PPSSPP save folder = เลือกโฟลเดอร์สำหรับเก็บข้อมูลเซฟของ PPSSPP Confirm Overwrite = ต้องการให้เขียนทับซ้ำกับข้อมูลเดิมเลยหรือไม่? @@ -372,46 +295,33 @@ DeleteConfirmGameConfig = คุณแน่ใจนะว่าต้องก DeleteFailed = ไม่สามารถลบข้อมูลนี้ได้ Deleting = กำลังลบข้อมูล\nโปรดรอ... Disable All = ปิดใช้งานทั้งหมด -Disabled = ปิดการใช้งาน Dumps = ไฟล์ดั๊มพ์ Edit = แก้ไข Enable All = เปิดใช้งานทั้งหมด -Enabled = Enabled Enter = ยืนยัน -Failed to connect to server, check your internet connection. = ล้มเหลวในการเชื่อมต่อกับเซิร์ฟเวอร์ โปรดเช็คการเชื่อมต่ออินเตอร์เน็ต -Failed to log in, check your username and password. = ล้มเหลวในการเข้าใช้งาน โปรดเช็ค ชื่อผู้ใช้งาน กับ รหัสผ่าน ดูก่อน Filter = ตัวกรอง Finish = สิ้นสุด GE Frame Dumps = ไฟล์กราฟิกเอนจิ้นเฟรมดั๊มพ์ Grid = กริด Inactive = ปิดการทำงาน -Installing... = กำลังติดตั้ง... InternalError = เกิดข้อผิดพลาดภายใน -Links = ลิงก์ Load = โหลด Load completed = โหลดข้อมูลสำเร็จ Loading = กำลังโหลด\nโปรดรอ... LoadingFailed = ไม่สามารถโหลดข้อมูลนี้ได้ -Log in = เข้าใช้งาน -Log out = ออกจากการใช้งาน -Logged in! = เข้าใช้งานแล้ว! -Logging in... = กำลังเข้าใช้งาน... Move = ย้าย Move Down = ย้ายลงล่าง Move Up = ย้ายขึ้นบน Network Connection = การเชื่อมต่อเครือข่าย NEW DATA = ข้อมูลใหม่ No = ไม่ใช่ -None = ไม่มี ObtainingIP = กำลังรับไอพี\nโปรดรอสักครู่... OK = ตกลง Old savedata detected = ตรวจพบข้อมูลเซฟเก่า Options = ตัวเลือก -Password = รหัสผ่าน Remove = ลบออก Reset = รีเซ็ต Resize = ขนาด -Restart = เริ่มต้นใหม่ Retry = ลองใหม่ Save = บันทึก Save completed = บันทึกข้อมูลสำเร็จ @@ -420,7 +330,6 @@ SavingFailed = ไม่สามารถบันทึกข้อมูล Search = ค้นหา seconds, 0:off = วินาที, 0 = ปิด Select = เลือก -Settings = การตั้งค่า Shift = เปลี่ยน Skip = ข้าม Snap = ขยับ @@ -431,11 +340,7 @@ Supported = รองรับ There is no data = ไม่มีข้อมูล Toggle All = ทั้งหมด Toggle List = รายการ -Top Center = มุมบนกลางจอ -Top Left = มุมบนซ้ายจอ -Top Right = มุมบนขวาจอ Unsupported = ไม่รองรับ -Username = ชื่อผู้ใช้งาน When you save, it will load on a PSP, but not an older PPSSPP = เซฟเกมของคุณนั้น สามารถนำไปโหลดผ่านบนเครื่อง PSP ได้\nแต่นำไปใช้กับ PPSSPP ที่เวอร์ชั่นเก่ากว่าไม่ได้ When you save, it will not work on outdated PSP Firmware anymore = เซฟเกมของคุณนั้น ไม่สามารถนำไปใช้กับเครื่อง PSP ที่ใช้เฟิร์มแวร์รุ่นเก่าได้ Yes = ใช่ @@ -501,23 +406,18 @@ ZIP file detected (Require WINRAR) = ไฟล์นี้ถูกบีบอ [Game] Asia = AS (โซนเอเชีย) Calculate CRC = คำนวณค่า CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = ยืนยันการลบ -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = สร้างการตั้งค่าเฉพาะเกม Create Shortcut = สร้างทางลัด Delete Game = ลบเกม Delete Game Config = ลบการตั้งค่าเฉพาะเกม Delete Save Data = ลบข้อมูลเซฟที่บันทึกไว้ Europe = EU (โซนยุโรป) -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = ขนาดไฟล์เกม -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = ตั้งค่าเกม Homebrew = Homebrew (เกมโฮมบริว) Hong Kong = HK (โซนฮ่องกง) InstallData = ข้อมูลที่ถูกติดตั้ง -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = JP (โซนญี่ปุ่น) Korea = เกาหลี MB = เมกกะไบต์ @@ -527,8 +427,6 @@ Remove From Recent = ลบออกจากในหน้า "ล่าสุ SaveData = ขนาดข้อมูลเซฟ Setting Background = การตั้งค่าพื้นหลัง Show In Folder = แสดงในโฟลเดอร์ -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA (โซนอเมริกา) Use UI background = ใช้เป็นภาพพื้นหลัง @@ -633,7 +531,6 @@ Percent of FPS = อิงจากเปอร์เซ็นต์เฟรม Performance = ประสิทธิภาพ Postprocessing shaders = กระบวนการทำงานปรับเฉดแสงสี Recreate Activity = สร้างกิจกรรมใหม่ -Render all frames = Render all frames Render duplicate frames to 60hz = แสดงผลเฟรมซ้ำให้ถึง 60 เฮิร์ตซ RenderDuplicateFrames Tip = ช่วยให้ภาพดูลื่นตาขึ้น ในเกมที่ใช้เฟรมเรทต่ำ Rendering Mode = โหมดที่ใช้ในการแสดงผล @@ -658,7 +555,6 @@ Stereo rendering = การแสดงผลแบบสามมิติ Stretch = ดึงเต็มจอ Texture Filter = ตัวกรองพื้นผิว Texture Filtering = การกรองพื้นผิว -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = การปรับสเกลพื้นผิว Texture Shader = โทนแสงสีพื้นผิว Turn off Hardware Tessellation - unsupported = ปิด "ฮาร์ดแวร์ เทสเซลเลชั่น" แล้ว เนื่องจากไม่สนับสนุนการทำงาน @@ -669,6 +565,8 @@ Upscale Level = เพิ่มระดับสเกลภาพ Upscale Type = รูปแบบการเพิ่มสเกลภาพ UpscaleLevel Tip = ซีพียูทำงานหนักขึ้น บางสเกลภาพอาจเกิดอาการหน่วงจนถึงขั้นไม่แสดงผล Use all displays = ใช้กับหน้าจอการแสดงผลทั้งหมด +Vertex Cache = เวอร์เท็ค แคช +VertexCache Tip = เร็วขึ้น แต่อาจทำให้เกิดอาการภาพกระพริบชั่วครั้งชั่วคราว VSync = ควบคุมช่วงของเฟรมเรทให้คงที่ Vulkan = วัลแคน Window Size = ขนาดของหน้าจอ @@ -685,12 +583,10 @@ Zip archive corrupt = ไฟล์ ZIP ไม่สมบูรณ์ (เสี Zip file does not contain PSP software = ไฟล์ ZIP นี้ ไม่มีข้อมูลซอฟแวร์ของเกม PSP [KeyMapping] -Allow combo mappings = เซ็ตปุมคอมโบ Autoconfigure = ค่าอัตโนมัติ Autoconfigure for device = กำหนดค่าให้อัตโนมัติสำหรับอุปกรณ์นี้ Bind All = เซ็ตปุ่มทั้งหมด Clear All = ล้างทั้งหมด -Combo mappings are not enabled = เซ็ตปุ่มคอมโบยังไม่ได้เปิดใช้งาน Default All = คืนค่าเดิมทั้งหมด Map a new key for = ปรับปุ่มใหม่สำหรับ Map Key = ตั้งค่าปุ่ม @@ -747,7 +643,16 @@ Audio/Video Recording = อัดบันทึกวีดีโอ/เสี AxisSwap = สลับด้านแกน Circle = วงกลม Cross = กากบาท -Custom %d = ปุ่มปรับแต่ง %d +Custom 1 = ปุ่มปรับแต่ง 1 +Custom 2 = ปุ่มปรับแต่ง 2 +Custom 3 = ปุ่มปรับแต่ง 3 +Custom 4 = ปุ่มปรับแต่ง 4 +Custom 5 = ปุ่มปรับแต่ง 5 +Custom 6 = ปุ่มปรับแต่ง 6 +Custom 7 = ปุ่มปรับแต่ง 7 +Custom 8 = ปุ่มปรับแต่ง 8 +Custom 9 = ปุ่มปรับแต่ง 9 +Custom 10 = ปุ่มปรับแต่ง 10 D-pad down = ปุ่มลูกศรลง D-pad left = ปุ่มลูกศรซ้าย D-pad right = ปุ่มลูกศรขวา @@ -760,7 +665,6 @@ Display Portrait Reversed = หน้าจอแนวตั้งกลับ Double tap button = กดเบิ้ลสองทีที่ปุ่ม Down = ลูกศรลง Dpad = ลูกศร -Exit App = Exit App Fast-forward = เร่งความเร็ว Frame Advance = เฟรมขั้นสูง Hold = ระงับ @@ -774,7 +678,6 @@ None = ไม่มี Note = หมายเหตุ OpenChat = เปิดแชท Pause = หยุดชั่วคราว -Previous Slot = ช่องสเตทอันที่แล้ว R = อาร์ RapidFire = กดรัวต่อเนื่อง Record = บันทึกหน้าจอ @@ -804,7 +707,6 @@ Texture Dumping = บันทึกพื้นผิว Texture Replacement = แทนที่พื้นผิว Toggle Fullscreen = ปรับเต็มหน้าจอ Toggle mode = โหมดสับเปลี่ยน -Toggle WLAN = เรียกใช้ WLAN Triangle = สามเหลี่ยม Up = ลูกศรขึ้น Vol + = เพิ่มเสียง @@ -813,7 +715,6 @@ Wlan = เครือข่าย [MemStick] Already contains PSP data = มีข้อมูลอยู่ข้างในนั้น -Cancelled - try again = ถูกยกเลิกแล้ว - ลองอีกครั้ง Create or Choose a PSP folder = สร้างหรือเลือกโฟลเดอร์เก็บข้อมูล PSP Current = ที่ใช้อยู่ DataCanBeShared = ข้อมูลสามารถใช้งานร่วมกันได้ ทั้งใน PPSSPP ตัวสีฟ้า/สีทอง @@ -846,6 +747,11 @@ AdHoc Server = เซิร์ฟเวอร์ Adhoc AdhocServer Failed to Bind Port = เซิร์ฟเวอร์ Adhoc ล้มเหลวในการเชื่อมโยงพอร์ต AM: Data from Unknown Port = AM: ข้อมูลมาจากพอร์ตที่ไม่รู้จัก Auto = อัตโนมัติ +Bottom Center = มุมล่างกลางจอ +Bottom Left = มุมล่างซ้ายจอ +Bottom Right = มุมล่างขวาจอ +Center Left = มุมกลางซ้ายจอ +Center Right = มุมกลางขวาจอ Change Mac Address = เปลี่ยนค่าที่อยู่ Mac Change proAdhocServer Address = เปลี่ยนไอพีที่อยู่ของเซิร์ฟเวอร์ Pro Adhoc (localhost = แลนในเครื่องเดียวกัน) ChangeMacSaveConfirm = ต้องการสร้างค่า MAC address ใหม่? @@ -879,6 +785,7 @@ Invalid IP or hostname = ไอพี หรือ ชื่อโฮสต์ Minimum Timeout = เวลาขั้นต่ำที่ใช้เชื่อมต่อ (แทนที่ค่าความหน่วงในมิลลิวินาที) Misc = อื่นๆ (ค่าดั้งเดิม = ดีสุดแล้ว) Network Initialized = เริ่มการทำงานของเครือข่ายเรียบร้อย +None = ไม่มี Please change your Port Offset = กรุณาเปลี่ยนค่าของพอร์ตชดเชย Port offset = พอร์ตชดเชย (0 = ค่าเริ่มต้นของ PSP) Open PPSSPP Multiplayer Wiki Page = ไปที่หน้าเว็บ PPSSPP Ad-Hoc Wiki @@ -889,9 +796,11 @@ Quick Chat 3 = แชทด่วน 3 Quick Chat 4 = แชทด่วน 4 Quick Chat 5 = แชทด่วน 5 QuickChat = แชทด่วน -Randomize = กดสุ่มค่า Send = ส่ง Send Discord Presence information = แสดงชื่อเกมที่กำลังเล่นอยู่ไปยังแอพ Discord +Top Center = มุมบนกลางจอ +Top Left = มุมบนซ้ายจอ +Top Right = มุมบนขวาจอ Unable to find UPnP device = ไม่พบอุปกรณ์ UPnP UPnP (port-forwarding) = โพรโตคอล UPnP (ฟอร์เวิร์ด พอร์ต อัตโนมัติ) UPnP need to be reinitialized = UPnP จำเป็นต้องเริ่มการทำงานใหม่ @@ -901,23 +810,6 @@ Validating address... = กำลังตรวจสอบที่อยู WLAN Channel = ช่องสัญญาณ WLAN You're in Offline Mode, go to lobby or online hall = คุณอยู่ในโหมดออฟไลน์ ต้องเข้าไปในล็อบบี้หรือออนไลน์ฮอลล์ก่อน -[PSPSettings] -Auto = อัตโนมัติ -Chinese (simplified) = จีน (ตัวย่อ) -Chinese (traditional) = จีน (ตัวเต็ม) -Dutch = เนเธอร์แลนด์ -English = อังกฤษ -French = ฝรั่งเศส -Game language = ภาษาที่ใช้กับเกม -German = เยอรมัน -Italian = อิตาลี -Japanese = ญี่ปุ่น -Korean = เกาหลี -Games often don't support all languages = ในบางเกมอาจจะไม่รองรับทุกภาษา -Portuguese = โปรตุเกส -Russian = รัสเซีย -Spanish = สเปน - [Pause] Cheats = สูตรโกง Continue = ดำเนินการต่อ @@ -944,21 +836,19 @@ Animation speed (0 -> disable) = ความเร็วอนิเมชั Aspect = ทิศทาง Black border = ขอบดำ Bloom = ภาพสว่างขึ้น -BloomNoBlur = ภาพสว่างขึ้น (ไม่เบลอ) Brightness = แสงสว่าง Cartoon = ภาพออกแนวการ์ตูน -CatmullRom = Bicubic (Catmull-Rom) Upscaler +CatmullRom = ภาพอัพสเกลแบบไบคิวบิค (แคทมิว-รอม) ColorCorrection = ภาพสีสมจริง ColorPreservation = การเก็บรักษาสีเดิม Contrast = ความคมชัด CRT = ภาพออกโทนเหลืองขึ้นเส้น -FakeReflections = ภาพเงาสะท้อนลวงตา FXAA = ภาพเน้นลบขอบรอยหยัก Gamma = แกมม่า GreenLevel = ระดับสีเขียว Intensity = ความเข้มของแสง LCDPersistence = ภาพ LCD แบบค้างคา -MitchellNetravali = Bicubic (Mitchell-Netravali) Upscaler +MitchellNetravali = ภาพอัพสเกลแบบไบคิวบิค (มิทเชลล์-เนทราวาลิ) Natural = ภาพเน้นสีธรรมชาติ NaturalA = ภาพเน้นสีธรรมชาติ (ไม่เบลอ) Off = ปิด @@ -973,7 +863,6 @@ SSAA(Gauss) = ภาพเน้นความละเอียดให้ส Strength = ความเด่นชัด Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = ภาพอัพสเกลแบบไบคิวบิค UpscaleSpline36 = ภาพลดความละเอียด เน้นสเกลคมขึ้น VideoSmoothingAA = ภาพในฉากคัตซีนดูเนียนยิ่งขึ้น Vignette = ภาพเน้นขอบหม่น @@ -1148,14 +1037,12 @@ Uninstall = ถอนการติดตั้ง (none detected) = (ไม่มีการตรวจพบ) 3D API = แอพพลิเคชั่น โปรแกรม อินเตอร์เฟซ สามมิติ ABI = แอพพลิเคชั่น ไบนารี่ อินเตอร์เฟซ -Achievement tests = ทดสอบเป้าหมายความสำเร็จ API Version = เวอร์ชั่นของแอพพลิเคชั่น โปรแกรม อินเตอร์เฟซ Audio Information = ข้อมูลของระบบเสียง Board = ชื่อบอร์ด Build Config = การกำหนดค่า Build Configuration = การกำหนดค่าที่ถูกสร้างไว้ Built by = สร้างโดย -Clear = ล้างแคช Compressed texture formats = รูปแบบการบีบอัดเท็คเจอร์ Core Context = บริบทของแกน Cores = จำนวนแกน @@ -1163,7 +1050,6 @@ CPU Extensions = ส่วนขยายซีพียู CPU Information = ข้อมูลของหน่วยประมวลผลหลัก CPU Name = ชื่อหน่วยประมวลผลหลัก D3DCompiler Version = เวอร์ชั่นตัวคอมไพล์ของ D3D -Data size = ขนาดข้อมูล Debug = แก้ไขบั๊ก Debugger Present = ตัวช่วยแก้ไขบั๊ก Depth buffer format = รูปแบบบัฟเฟอร์ความลึก @@ -1175,26 +1061,16 @@ DPI = DPI Driver bugs = ไดรเวอร์บั๊ก Driver Version = เวอร์ชั่นของไดรเวอร์ EGL Extensions = ส่วนขยายอีจีแอล -Error = เอ๋อ -Failure = ล้มเหลว Frames per buffer = จำนวนเฟรมต่อบัฟเฟอร์ GPU Flags = แฟล็กของหน่วยประมวลผลกราฟิก GPU Information = ข้อมูลของหน่วยประมวลผลกราฟิก High precision float range = ขอบเขตจำนวนทศนิยมช่วงค่าความแม่นยำสูง High precision int range = ขอบเขตจำนวนเต็มช่วงค่าความแม่นยำสูง -Icon cache = แคชไอคอน -Image data count = จำนวนข้อมูลรูปภาพ -Info = ข้อมูล -Internals = ข้อมูลภายใน JIT available = JIT ใช้งานได้ Lang/Region = ภาษา/ภูมิภาค -Leaderboard tracker: Hide = การติดตามกระดานแต้มผู้นำ: ซ่อน -Leaderboard tracker: Show = การติดตามกระดานแต้มผู้นำ: แสดง -Leaderboard tracker: Update = การติดตามกระดานแต้มผู้นำ: อัพเดท Memory Page Size = ขนาดหน้าของหน่วยความจำ -Native resolution = ความละเอียดดั้งเดิม +Native Resolution = ความละเอียดดั้งเดิม No GPU driver bugs detected = ไม่พบไดรเวอร์บั๊กใน GPU รุ่นนี้ -Notification tests = ทดสอบการแจ้งเตือน OGL Extensions = ส่วนขยายโอจีแอล OpenGL ES 2.0 Extensions = ส่วนขยายของโอเพ่นจีแอล อีเอส 2.0 OpenGL ES 3.0 Extensions = ส่วนขยายของโอเพ่นจีแอล อีเอส 3.0 @@ -1202,30 +1078,24 @@ OpenGL Extensions = ส่วนขยายของโอเพ่นจีแ Optimal frames per buffer = จำนวนเฟรมต่อบัฟเฟอร์ที่เหมาะสม Optimal sample rate = อัตราค่าความถี่เสียงที่เหมาะสม OS Information = ข้อมูลของระบบปฏิบัติการ -Pixel resolution = ความละเอียดจุดภาพบนหน้าจอ PPSSPP build = รูปแบบ PPSSPP -Present modes = โหมดนำเสนอ -Progress tests = ทดสอบความคืบหน้า Refresh rate = อัตราการรีเฟรชของหน้าจอ Release = ใช้งาน RW/RX exclusive = RW/RX แบบพิเศษ Sample rate = อัตราค่าความถี่เสียง Shading Language = ภาษาของเฉดเดอร์ Storage = พื้นที่เก็บข้อมูล -Success = สำเร็จ Sustained perf mode = โหมดประสิทธิภาพที่ยั่งยืน System Information = ข้อมูลโดยรวมของระบบ System Name = ชื่อระบบ System Version = เวอร์ชั่นของระบบ -Texture count = จำนวนเท็คเจอร์ Threads = จำนวนเธรด -UI resolution = ความละเอียดของอินเตอร์เฟซ Vendor = ชื่อหน่วยประมวลผลกราฟิก Vendor (detected) = ผู้จัดจำหน่าย (ที่ตรวจพบ) Version Information = ข้อมูลของเวอร์ชั่น Vulkan Extensions = ส่วนขยายของวัลแคน Vulkan Features = ฟีเจอร์วัลแคน -Warning = คำเตือน +UI Resolution = ความละเอียดของอินเตอร์เฟซ [System] (broken) = (เสียหาย) @@ -1251,7 +1121,7 @@ Date Format = รูปแบบวันที่ Day Light Saving = เวลาออมแสง DDMMYYYY = วัน/เดือน/ปี Decrease size = ลดขนาดไอคอน -Developer Tools = เครื่องมือผู้พัฒนา +Developer Tools = เครื่องมือสำหรับนักพัฒนา Display Extra Info = แสดงข้อมูลเพิ่มเติม Display Games on a grid = แสดงแบบกริดในแถบ "เกมอื่นๆ" Display Homebrew on a grid = แสดงแบบกริดในแถบ "เกมโฮมบริว" @@ -1303,7 +1173,6 @@ Record Audio = อัดบันทึกเสียง Record Display = อัดบันทึกวีดีโอ Reset Recording on Save/Load State = เริ่มการอัดบันทึกไฟล์ใหม่ เมื่อกดเซฟ/โหลดสเตทเกม Restore Default Settings = รีเซ็ตการตั้งค่าของ PPSSPP ทั้งหมด -RetroAchievements = RetroAchievements Rewind Snapshot Interval = เซฟสเตทพื้นหลังแบบอัตโนมัติ (สูบแรม) Save path in installed.txt = บันทึกข้อมูลตามเส้นทางที่เลือกไว้ Save path in My Documents = บันทึกข้อมูลไว้ที่ My Documents @@ -1316,7 +1185,6 @@ Show ID = แสดงไอดี/เวอร์ชั่นเกม Show Memory Stick folder = แสดงโฟลเดอร์เม็มโมรี่สติ๊ก Show region flag = แสดงรูปธงโซนเกม Simulate UMD delays = จำลองความหน่วงเหมือนแผ่น UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = เซฟช่องที่ 1 Slot 2 = เซฟช่องที่ 2 Slot 3 = เซฟช่องที่ 3 @@ -1372,11 +1240,11 @@ Download = ดาวน์โหลด New version of PPSSPP available = PPSSPP เวอร์ชั่นใหม่พร้อมให้ดาวน์โหลดแล้ว! [VR] +% of native FoV = % ของค่า FoV ดั้งเดิม 6DoF movement = การเคลื่อนไหวแบบ 6DoF -Camera type = ปรับแต่งประเภทมุมกล้อง Distance to 2D menus and scenes = ระยะห่างจากเมนูสองมิติ และฉาก -Distance to 3D scenes when VR disabled = ระยะห่างจากฉากสามมิติ เมื่อ VR ถูกปิดใช้งาน Experts only = สำหรับผู้เชี่ยวชาญเท่านั้น +Field of view scale = สเกลของมุมมองพื้นที่รอบตัว Force 72Hz update = บังคับรีเฟรชเรทไปที่ 72Hz Game camera rotation step per frame = สเต็ปการหมุนมุมกล้องเกมต่อเฟรม Game camera uses rotation smoothing = มุมกล้องเกมใช้การหมุนแบบนุ่มนวล @@ -1385,6 +1253,7 @@ Heads-up display scale = สเกลขนาดของ HUD Manual switching between flat screen and VR using SCREEN key = สลับโหมดระหว่าง จอแบน และ VR โดยใช้ปุ่ม SCREEN Map controller movements to keys = เซ็ตปุ่มควบคุมด้วยท่าทางผ่านจอย Map HMD rotations on keys instead of VR camera = เซ็ตการควบคุมการหมุน HMD โดยใช้ปุ่มกด แทนการใช้กล้อง VR +Camera type = ปรับแต่งประเภทมุมกล้อง Motion needed to generate action = จำเป็นต้องขยับท่าทางเพื่อเซ็ตปุ่มที่ต้องการ Stereoscopic vision (Experimental) = มุมมองภาพแบบสามมิติ (ขั้นทดสอบ) Virtual reality = ความเป็นจริงเสมือน diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 35d46f3fd..578859884 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternatif hız hacmi Audio backend = Ses alttabanı (Yeniden başlatma gerekir) Audio Error = Ses Hatası -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth uyumlu arabellek (daha yavaş) Auto = Otomatik Device = Cihaz @@ -95,7 +36,6 @@ Calibrate Analog Stick = Analog Çubuğu Kalibre Et Calibrate = Kalibre Calibrated = Kalibre edildi Calibration = Kalibrasyon -Circular low end radius = Circular low end radius Circular stick input = Dairesel çubuk girişi Classic = Klasik Confine Mouse = Fareyi belirli bir pencere/görüntü alanı içinde sınırla @@ -108,10 +48,8 @@ Deadzone radius = Ölü bölge yarıçapı Disable D-Pad diagonals (4-way touch) = D-Pad'i devre dışı bırak (4'lü Yön Tuşları) Disable diagonal input = Diyagonal girişi devre dışı bırak Double tap = Çift dokunma -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Hareket kontrolünü etkinleştir Enable standard shortcut keys = Standart kısayol tuşlarını etkinleştir -frames = frames Gesture = Hareket Gesture mapping = Hareket kontrollerini düzenle Glowing borders = Parlayan kenarlar @@ -140,7 +78,6 @@ OnScreen = Dokunmatik ekran kontrolleri Portrait = Dikey Portrait Reversed = Ters dikey PSP Action Buttons = PSP eylem tuşları -Rapid fire interval = Rapid fire interval Raw input = Saf girdi Repeat mode = Tekrar modu Reset to defaults = Varsayılanlara sıfırla @@ -149,7 +86,6 @@ Sensitivity (scale) = Hassasiyet (ölçek) Sensitivity = Hassasiyet Shape = Şekil Show Touch Pause Menu Button = Duraklama menüsü tuşunu göster -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Kaydır Swipe sensitivity = Kaydırma hassasiyeti Swipe smoothing = Pürüzsüz kaydırma @@ -232,7 +168,6 @@ Log Console = &Günlük Konsolu Memory View... = Bellek &Görünümü... More Settings... = &Daha Fazla Ayar... Nearest = &En Yakın -Recent = &Recent Skip Buffer Effects = &Arabellek efektlerini atla (arabelleğe alınmaz, daha hızlıdır) Off = &Kapalı Open Chat = Open Chat @@ -271,6 +206,7 @@ Texture Filtering = Doku Filtreleme Texture Scaling = &Doku Ölçekleme Use Lossless Video Codec (FFV1) = &Kayıpsız video kodek'i kullan (FFV1) Use output buffer for video = Video için çıkış arabelleğini kullan +Vertex Cache = &Vertex Önbellek VSync = Dikey Eşleme (VSync) Vulkan = Vulkan Window Size = &Pencere Boyutu @@ -284,11 +220,8 @@ Backspace = Silme Tuşu Block address = Adresi engelle By Address = Adrese Göre Copy savestates to memstick root = Durum kayıtlarını hafıza kartına kopyalayın -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Şu anki oyun için textures.ini dosyası Oluştur/Aç Current = Current -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Geliştirme araçları DevMenu = DevMenu Disabled JIT functionality = JIT işlevselliğini devre dışı bırakın @@ -299,11 +232,8 @@ Enable driver bug workarounds = Sürücü hatası geçici çözümlerini etkinle Enable Logging = Hata ayıklama günlüğünü etkinleştirin Enter address = Adres Gir FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump testleri Frame Profiler = Frame profiler -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU sürücü testi GPU log profiler = GPU log profiler GPU Profile = GPU profili @@ -313,10 +243,8 @@ Log Dropped Frame Statistics = Düşen kare istatistiklerini günlüğe kaydet Log Level = Günlük seviyesi Log View = Günlük görünümü Logging Channels = Günlük kanalları -Multi-threaded rendering = Multi-threaded rendering Next = Sonraki No block = No block -Off = Off Prev = Önceki Random = Rastgele Replace textures = Dokuları değiştir @@ -334,12 +262,10 @@ Stats = İstatistikler System Information = Sistem bilgisi Texture ini file created = Texture ini file created Texture Replacement = Doku değiştirme -Audio Debug = Ses hata ayıklamasını -Control Debug = Control Debug +Toggle Audio Debug = Ses hata ayıklamasını Aç/Kapat +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Donmayı Aç/Kapa Touchscreen Test = Dokunmatik ekran testi -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -347,14 +273,10 @@ VFPU = VFPU * PSP res = * PSP Çözünürlüğü Active = Etkin Back = Geri -Bottom Center = Orta alt -Bottom Left = Sol alt -Bottom Right = Sağ alt Cancel = İptal Center = Merkez -Center Left = Sol orta -Center Right = Sağ orta -Changing this setting requires PPSSPP to restart. = Bu ayarın değiştirilmesi, PPSSPP'nin yeniden başlatılmasını gerektirir. +ChangingGPUBackends = GPU arkaucunu değiştirmek için PPSSPP'nin yeniden başlatılması gerek. Şimdi yeniden başlatılsın mı? +ChangingInflightFrames = Grafik komut arabelleğini değiştirmek, PPSSPP'nin yeniden başlatılmasını gerektirir. Şimdi yeniden başlat? Channel: = Kanal: Choose PPSSPP save folder = PPSSPP kayıt dosyası seç Confirm Overwrite = Veriyi üstüne yazmak istiyor musun? @@ -374,46 +296,33 @@ DeleteConfirmGameConfig = Bu oyun için ayarları silmek istediğine emin misin? DeleteFailed = Veri silinemedi. Deleting = Siliniyor\nLütfen Bekleyin... Disable All = Hepsini devre dışı bırak -Disabled = Disabled Dumps = Dökümler Edit = Düzenle Enable All = Hepsini etkinleştir -Enabled = Enabled Enter = Gir -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filtre Finish = Bitir GE Frame Dumps = GE Kare Dökümleri Grid = Izgara Inactive = Ektin değil -Installing... = Installing... InternalError = Dahili bir hata oluştu. -Links = Links Load = Yükle Load completed = Yükleme tamamlandı. Loading = Yükleniyor\nLütfen Bekleyin... LoadingFailed = Veri yüklenemedi. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Taşı Move Down = Move Down Move Up = Move Up Network Connection = Ağ Bağlantısı NEW DATA = YENİ VERİ No = Hayır -None = Hiçbiri ObtainingIP = IP adresi alınıyor.\nLütfen bekleyin... OK = Tamam Old savedata detected = Eski kayıt bulundu. Options = Ayarlar -Password = Password Remove = Remove Reset = Sıfırla Resize = Yeniden Boyutlandır -Restart = Tekrar başlat Retry = Yeniden Dene Save = Kaydet Save completed = Kaydedildi. @@ -422,7 +331,6 @@ SavingFailed = Veri kaydedilemiyor. Search = Ara seconds, 0:off = saniye, 0 = off Select = Seç -Settings = Settings Shift = Shift Skip = Geç Snap = Hizala @@ -433,11 +341,7 @@ Supported = Destekleniyor There is no data = Veri yok. Toggle All = Hepsini değiştir Toggle List = Listeyi değiştir -Top Center = Orta üst -Top Left = Sol üst -Top Right = Sağ üst Unsupported = Desteklenmiyor -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Kayıt aldığında almış olduğunuz kayıt PSP'de yüklenebilecek ama eski bir PPSSPP sürümünde yüklenemeyecek. When you save, it will not work on outdated PSP Firmware anymore = Kaydettiğinde artık eski PSP yazılımı üzerinde çalışmayacaktır. Yes = Evet @@ -503,23 +407,18 @@ ZIP file detected (Require WINRAR) = Dosya sıkıştırlmış (ZIP).\nLütfen il [Game] Asia = Asya Calculate CRC = CRC'yi Hesapla -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Sil -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Oyun için yapılandırma dosyası oluştur Create Shortcut = Kısayol oluştur Delete Game = Oyunu Sil Delete Game Config = Oyun ayarını sil Delete Save Data = Oyun kaydını sil Europe = Avrupa -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Oyun -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Oyun ayarları Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Veri yükle -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japonya Korea = Kore MB = MB @@ -529,8 +428,6 @@ Remove From Recent = Geçmişten sil SaveData = Kayıt Setting Background = Arkaplan ayarlanıyor Show In Folder = Dosyada göster -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = ABD Use UI background = Arayüz arkaplanı olarak kullan @@ -625,7 +522,6 @@ Must Restart = Bu değişikliğin uygulanması için PPSSPP'yi yeniden başlatma Native device resolution = Yerel aygıt çözünürlüğü Nearest = En yakın No buffer = Arabellek/tampon bellek yok -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Arabellek efektlerini atla (arabelleğe alınmaz, daha hızlıdır) @@ -660,7 +556,6 @@ Stereo rendering = Stereo rendering Stretch = Serbest tam ekran (sünme) Texture Filter = Doku filtreleme Texture Filtering = Doku filtreleme -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Doku ölçekleme Texture Shader = Doku gölgelendiricisi Turn off Hardware Tessellation - unsupported = "Donanım mozaikleme"yi kapatın: desteklenmiyor @@ -671,6 +566,8 @@ Upscale Level = Ölçeklendirme seviyesi Upscale Type = Ölçeklendirme türü UpscaleLevel Tip = CPU ağır - takılmayı önlemek için bazı yeniden ölçeklendirmeler gecikebilir Use all displays = Tüm ekranları kullan +Vertex Cache = Vertex önbellek +VertexCache Tip = Daha hızlıdır, ancak geçici ekran titremesine neden olabilir VSync = Dikey eşleme (Vsync) Vulkan = Vulkan Window Size = Pencere boyutu @@ -687,12 +584,10 @@ Zip archive corrupt = ZIP arşivi bozuk Zip file does not contain PSP software = ZIP dosyası PSP yazılımı içermiyor [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Otomatik ayarla Autoconfigure for device = Cihaz için otomatik ayarla Bind All = Hepsini Bağla Clear All = Hepsini Temizle -Combo mappings are not enabled = Combo mappings are not enabled Default All = Varsayılana Döndür Map a new key for = Yeni bir tuş girin Map Key = Tuş girin @@ -749,7 +644,16 @@ Audio/Video Recording = Ses/Video kaydı AxisSwap = Eksenleri değiştir Circle = Çember (O) Cross = Çapraz (X) -Custom %d = Özel %d +Custom 1 = Özel 1 +Custom 10 = Özel 10 +Custom 2 = Özel 2 +Custom 3 = Özel 3 +Custom 4 = Özel 4 +Custom 5 = Özel 5 +Custom 6 = Özel 6 +Custom 7 = Özel 7 +Custom 8 = Özel 8 +Custom 9 = Özel 9 D-pad down = D-pad aşağı D-pad left = D-pad sol D-pad right = D-pad sağ @@ -762,7 +666,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Düğmeye çift basın Down = Dpad Aşağı Dpad = Dpad -Exit App = Exit App Frame Advance = Frame advance Hold = Basılı tut Home = Ev @@ -775,7 +678,6 @@ None = Hiçbiri Note = Not OpenChat = Chat'i Aç Pause = PPSSPP Menüsü -Previous Slot = Previous Slot R = R RapidFire = Seri Ateş Record = Record @@ -805,7 +707,6 @@ Texture Dumping = Doku Dökümü Texture Replacement = Doku değiştirme Toggle Fullscreen = Tam ekran Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Üçgen Fast-forward = Fast-forward Up = Dpad Yukarı @@ -815,7 +716,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Zaten PSP verisi içeriyor -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Bir PSP klasörü oluştur veya seç Current = Current DataCanBeShared = Veri PPSSPP normal/Gold arasında paylaşılabilir @@ -848,6 +748,11 @@ AdHoc Server = Ad hoc sunucusu AdhocServer Failed to Bind Port = Ad hoc sunucusu portu bağlayamadı AM: Data from Unknown Port = AM: Bilinmeyen Porttan Veri Auto = Otomatik +Bottom Center = Orta alt +Bottom Left = Sol alt +Bottom Right = Sağ alt +Center Left = Sol orta +Center Right = Sağ orta Change Mac Address = MAC adresini değiştir Change proAdhocServer Address = PRO Ad Hoc Server IP adresini değiştir (localhost = çoklu örnek) ChangeMacSaveConfirm = Generate a new MAC address? @@ -881,6 +786,7 @@ Invalid IP or hostname = Geçersiz IP veya host adı Minimum Timeout = En düşük zaman aşımı (ms cinsinden geçersiz kılma, 0 = varsayılan) Misc = Çeşitli (varsayılan = PSP uyumluluğu) Network Initialized = Network Switch +None = Hiçbiri Please change your Port Offset = Lütfen Port Offset'i değiştirin Port offset = Port offset(0 = PSP uyumluluğu) Open PPSSPP Multiplayer Wiki Page = PPSSPP Ad-Hoc Wiki Sayfası @@ -891,9 +797,11 @@ Quick Chat 3 = Hızlı sohbet 3 Quick Chat 4 = Hızlı sohbet 4 Quick Chat 5 = Hızlı sohbet 5 QuickChat = Hızlı sohbet -Randomize = Randomize Send = Gönder Send Discord Presence information = Discord "Rich Presence" bilgisi gönder +Top Center = Orta üst +Top Left = Sol üst +Top Right = Sağ üst Unable to find UPnP device = UPnP cihazı bulunamıyor UPnP (port-forwarding) = UPnP (port yönlendirme) UPnP need to be reinitialized = UPnP'nin yeniden başlatılması gerekiyor @@ -903,23 +811,6 @@ Validating address... = Adres doğrulanıyor... WLAN Channel = WLAN Kanalı You're in Offline Mode, go to lobby or online hall = Çevrimdışı moddasınız, lobiye veya çevrimiçi salona gidin -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Hileler Continue = Devam @@ -945,7 +836,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Siyah çerçeve Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Parlaklık Cartoon = Çizgi film CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -953,7 +843,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Karşıtlık CRT = CRT tarama çizgileri -FakeReflections = FakeReflections FXAA = FXAA Kenar Yumuşatma Gamma = Gamma GreenLevel = Green level @@ -974,7 +863,6 @@ SSAA(Gauss) = Süper örneklemeli Kenar Yumuşatma (Gauss) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Yeniden Ölçeklendirici VideoSmoothingAA = VideoSmoothingAA Vignette = Vinyet @@ -1178,11 +1066,10 @@ GPU Flags = GPU Flags GPU Information = GPU bilgisi High precision float range = High precision float range High precision int range = High precision int range -Icon cache = Icon cache JIT available = JIT available Lang/Region = Dil/Bölge Memory Page Size = Bellek sayfa boyutu -Native resolution = Yerel çözünürlük +Native Resolution = Yerel çözünürlük No GPU driver bugs detected = GPU sürücü hatası algılanmadı OGL Extensions = OGL eklentileri OpenGL ES 2.0 Extensions = OpenGL ES 2.0 eklentileri @@ -1191,9 +1078,7 @@ OpenGL Extensions = OpenGL eklentileri Optimal frames per buffer = Optimum tampon başına çerçeveler Optimal sample rate = Optimum örnekleme hızı OS Information = İşletim sistemi bilgisi -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP derlemesi -Present modes = Present modes Refresh rate = Yenileme hızı Release = Release RW/RX exclusive = RW/RX'e özel @@ -1205,7 +1090,7 @@ System Information = Sistem bilgisi System Name = Ad System Version = Sistem sürümü Threads = İzlekler -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Üretici Vendor (detected) = Üretici (tespit edildi) Version Information = Sürüm bilgisi @@ -1288,7 +1173,6 @@ Record Audio = Sesi kaydet Record Display = Görüntüyü kaydet Reset Recording on Save/Load State = Kaydet/Yükle durumunda kaydı sıfırla Restore Default Settings = Varsayılan ayarları yükle -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Geri sarma görüntüsü sıklığı (mem hog) Save path in installed.txt = Yolu installed.txt'ye kaydet Save path in My Documents = Dosyaları "Belgeler"'e kaydet @@ -1301,7 +1185,6 @@ Show ID = ID'yi göster Show Memory Stick folder = Hafıza Kartı klasörünü göster Show region flag = Bölge bayrağını göster Simulate UMD delays = UMD gecikmelerini simule et -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1356,11 +1239,12 @@ Download = İndir New version of PPSSPP available = PPSSPP'nin yeni versiyonu mevcut [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 958eaff8e..1d807475e 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Гучність при альтернативній швидкості Audio backend = Бекенд аудіо (потрібне перезавантаження) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Буфер, який підходить для Bluetooth (повільніше) Auto = Авто Device = Пристрій @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Калібрувати Calibrated = Calibrated Calibration = Калібрування -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Класичний Confine Mouse = Не давати миші виходити за межі екрану @@ -108,10 +48,8 @@ Deadzone radius = Радіус мертвої зони Disable D-Pad diagonals (4-way touch) = Вимкнути хрестовину по діагоналі Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Тонкі границі (підсвічування) @@ -140,7 +78,6 @@ OnScreen = Елементи управління на екрані Portrait = Портретна Portrait Reversed = Портретна (перевернута) PSP Action Buttons = Кнопки дій PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Чутливість Shape = Shape Show Touch Pause Menu Button = Показувати кнопку меню -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Консоль журналу (log) Memory View... = Переглядач па&м'яті... More Settings... = &Ще налаштування... Nearest = &Найближчий -Recent = &Recent Skip Buffer Effects = &Пропустити ефекти (небуферований, швидше) Off = В&имкнено Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = &Фільтрація текстур Texture Scaling = &Масштабування текстур Use Lossless Video Codec (FFV1) = &Використовувати відеокодек без втрат (FFV1) Use output buffer for video = Використовувати вихідний буфер для відео +Vertex Cache = &Вершинний кеш VSync = Вертикальна син&хронізація Vulkan = Vulkan Window Size = Розмір &вікна @@ -282,11 +218,8 @@ Backspace = Стерти Block address = Адреса блоку By Address = За адресою Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Створити/Відкрити файл textures.ini для поточної гри Current = Поточний -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Інструменти розробника DevMenu = Меню розроб. Disabled JIT functionality = Вимкнений функціонал JIT @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Ввімкнути логування Enter address = Введіть адресу FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Профілі кадрів -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = Перевірка драйверу GPU GPU log profiler = GPU log profiler GPU Profile = Профіль GPU @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Лог статистики пропущених Log Level = Лог рівня Log View = Лог виду Logging Channels = Параметри логування -Multi-threaded rendering = Multi-threaded rendering Next = Наступний No block = Немає блоку -Off = Off Prev = Попередній Random = Випадковий Replace textures = Заміна текстур @@ -332,12 +260,10 @@ Stats = Статистика System Information = Інформація про систему Texture ini file created = Texture ini file created Texture Replacement = Заміна текстур -Audio Debug = Налагодження аудіо -Control Debug = Control Debug +Toggle Audio Debug = Ввімкнути/Вимкнути налагодження аудіо +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Запустити/Зупинити Touchscreen Test = Тест сенсорного екрану -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * дозв. PSP Active = Активно Back = Назад -Bottom Center = Знизу центрально -Bottom Left = Знизу ліворуч -Bottom Right = Знизу праворуч Cancel = Відміна Center = По центру -Center Left = Центр ліворуч -Center Right = Центр праворуч -Changing this setting requires PPSSPP to restart. = Зміна буферизації графічних команд вимагає перезавантажити PPSSPP. Перезавантажити зараз? +ChangingGPUBackends = Зміна бекенду GPU вимагає перезавантажити PPSSPP. Перезавантажити зараз? +ChangingInflightFrames = Зміна буферизації графічних команд вимагає перезавантажити PPSSPP. Перезавантажити зараз? Channel: = Channel: Choose PPSSPP save folder = Виберіть папку для збереження Confirm Overwrite = Ви хочете перезаписати дані? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Параметри налаштування для ц DeleteFailed = Неможливо видалити дані. Deleting = Видалення\nБудь ласка, зачекайте... Disable All = Вимкнути все -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Ввімкнути все -Enabled = Enabled Enter = Введення -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Зберегти GE Frame Dumps = GE Frame Dumps Grid = Сітка Inactive = Неактивно -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Завантажити Load completed = Завантаження завершене Loading = Завантаження\nБудь ласка, зачекайте... LoadingFailed = Не вдалося завантажити дані. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Положення Move Down = Move Down Move Up = Move Up Network Connection = Підключення до мережі NEW DATA = Нове збереження No = Ні -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Виявлено старий формат збережень Options = Опції: -Password = Password Remove = Remove Reset = Скинути Resize = Розмір -Restart = Restart Retry = Повторити Save = Зберегти Save completed = Збереження завершено. @@ -420,7 +329,6 @@ SavingFailed = Неможливо зберегти дані. Search = Search seconds, 0:off = секунд, 0 = вимк. Select = Вибрати -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Підтримується There is no data = Немає даних Toggle All = Переключити все Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = Не підтримується -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Коли ви збережетесь, це може завантажуватись на PSP, але не старій версії PPSSPP When you save, it will not work on outdated PSP Firmware anymore = Коли ви бережетесь, це більше не буде працювати на старих версіях прошивки PSP Yes = Так @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = Файл стиснуто (ZIP).\nБудь [Game] Asia = Азія Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Видалити -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Створити конфіг Create Shortcut = Створити ярлик Delete Game = Видалити гру Delete Game Config = Видалити конфіг Delete Save Data = Видалити збереження Europe = Європа -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Гра -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Налаштування гри Homebrew = Homebrew Hong Kong = Гонконг InstallData = Встановити дані -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Японія Korea = Корея MB = МБ @@ -527,8 +426,6 @@ Remove From Recent = Видалити з останніх SaveData = Збереження Setting Background = Налаштування фону Show In Folder = Показати в теці -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = США Use UI background = Використати фон інтерфейсу @@ -623,7 +520,6 @@ Must Restart = Ви повинні перезавантажити PPSSPP, щоб Native device resolution = Роздільна здатність пристрою Nearest = Найближчий No buffer = Без буфера -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Пропускати ефекти (небуференізованний, швидше) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Розтягнення Texture Filter = Фільтр текстур Texture Filtering = Фільтрація текстур -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Масштабування текстур Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Вимкніть "апаратна тесселляція": не підтримується @@ -669,6 +564,8 @@ Upscale Level = Рівень масштабування Upscale Type = Тип масштабування UpscaleLevel Tip = Процесор завантажений - деяке масштабування може затягнутися, щоб уникнути заїкання Use all displays = Використовувати всі екрани +Vertex Cache = Вершинний кеш +VertexCache Tip = Швидше, але може спричинити тимчасове мерехтіння VSync = Вертикальна синхронізація Vulkan = Vulkan Window Size = Розмір вікна @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP архів пошкоджено Zip file does not contain PSP software = ZIP-файл не містить програмного забезпечення PSP [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Авто конфіг Autoconfigure for device = Авто конфіг для пристрою Bind All = Bind All Clear All = Очистити все -Combo mappings are not enabled = Combo mappings are not enabled Default All = Скинути все Map a new key for = Призначити кнопку для Map Key = Карта кнопки @@ -747,7 +642,16 @@ Audio/Video Recording = Запис аудіо / відео AxisSwap = Обмін осей Circle = Коло Cross = Хрестик -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Вниз Dpad = Хрестовина -Exit App = Exit App Frame Advance = Завантаження кадру заздалегідь Hold = Утримувати Home = Додому @@ -773,7 +676,6 @@ None = None Note = Примітка OpenChat = Відкритий чат Pause = Пауза -Previous Slot = Previous Slot R = R RapidFire = Турбо кнопка Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Демпінг текстури Texture Replacement = Заміна текстури Toggle Fullscreen = Повноекранний режим Toggle mode = Режим перемикання -Toggle WLAN = Toggle WLAN Triangle = Трикутник Fast-forward = Швидко вперед Up = Вгору @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Знизу центрально +Bottom Left = Знизу ліворуч +Bottom Right = Знизу праворуч +Center Left = Центр ліворуч +Center Right = Центр праворуч Change Mac Address = Змінити Mac-адресу Change proAdhocServer Address = Спеціальна адреса серверу (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Недійсне IP або ім'я хоста Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Мережа ініціалізована +None = None Please change your Port Offset = Please change your port offset Port offset = Зсув порту (0 = сумісність з PSP) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Швидкий чат 3 Quick Chat 4 = Швидкий чат 4 Quick Chat 5 = Швидкий чат 5 QuickChat = Швидкий чат -Randomize = Randomize Send = Надіслати Send Discord Presence information = Відправляти інформацію про гру в Discord +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Підтвердження адреси... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = Ви перебуваєте в офлайн-режимі, переходите у лоббі чи онлайн-режим -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = Чит-коди Continue = Продовжити @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Bloom -BloomNoBlur = Bloom (no blur) Brightness = Яскравість Cartoon = Мультиплікація CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Корекція кольорів ColorPreservation = Color preservation Contrast = Контраст CRT = Кінескоп 1 -FakeReflections = FakeReflections FXAA = FXAA згладжування Gamma = Гамма GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = SSAA (Гаусс) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Високоякісний Spline36 VideoSmoothingAA = Згладжування відео (VSAA) Vignette = Віньєтка @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = Інформація про GPU High precision float range = High precision float range High precision int range = Внутрішній діапазон високої точності -Icon cache = Icon cache JIT available = JIT available Lang/Region = Мова/Регіон Memory Page Size = Розмір сторінки пам'яті -Native resolution = Рідне розширення +Native Resolution = Рідне розширення No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Розширення OGL OpenGL ES 2.0 Extensions = Розширення OpenGL ES 2.0 @@ -1190,9 +1077,7 @@ OpenGL Extensions = Розширення OpenGL Optimal frames per buffer = Оптимально кадрів на буфер Optimal sample rate = Оптимальна частота вибірки OS Information = Інформація про ОС -Pixel resolution = Pixel resolution PPSSPP build = Збірка PPSSPP -Present modes = Present modes Refresh rate = Частота оновлення Release = Реліз RW/RX exclusive = Ексклюзивний RW/RX @@ -1204,7 +1089,7 @@ System Information = Інформація про систему System Name = Назва System Version = Версія системи Threads = Потоки -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Виробник Vendor (detected) = Виробник (знайдений) Version Information = Інформація про версію @@ -1287,7 +1172,6 @@ Record Audio = Запис аудіо Record Display = Запис відео Reset Recording on Save/Load State = Скидати запис при збереженні / завантаженні Restore Default Settings = Скинути налаштування -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Змінити частоту кадрів (багато пам'яті) Save path in installed.txt = Шлях до збережень в installed.txt Save path in My Documents = Шлях до збережень в Моїх документах @@ -1300,7 +1184,6 @@ Show ID = Показати ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Показати прапор регіону Simulate UMD delays = Імітувати затримки UMD -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Слот 1 Slot 2 = Слот 2 Slot 3 = Слот 3 @@ -1355,11 +1238,12 @@ Download = Завантажити New version of PPSSPP available = Доступна нова версія PPSSPP [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index 9103577f6..73255b064 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1: Attempt failed -%1: Attempt started = %1: Attempt started -%1 achievements, %2 points = %1 achievements, %2 points -Account = Account -Achievement progress = Achievement progress -Achievement unlocked = Achievement unlocked -Achievements = Achievements -Achievements are disabled = Achievements are disabled -Achievements enabled = Achievements enabled -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = Around me -Can't log in to RetroAchievements right now = Can't log in to RetroAchievements right now -Challenge indicator = Challenge indicator -Contacting RetroAchievements server... = Contacting RetroAchievements server... -Customize = Customize -Earned = You have unlocked %1 of %2 achievements, and earned %3 of %4 points -Encore Mode = Encore Mode -Failed logging in to RetroAchievements = Failed logging in to RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = Hardcore Mode (no savestates) -Hardcore Mode = Hardcore Mode -How to use RetroAchievements = How to use RetroAchievements -In Encore mode - listings may be wrong below = In Encore mode - listings may be wrong below -Leaderboard attempt started or failed = Leaderboard attempt started or failed -Leaderboard result submitted = Leaderboard result submitted -Leaderboard score submission = Leaderboard score submission -Leaderboard submission is enabled = Leaderboard submission is enabled -Leaderboard tracker = Leaderboard tracker -Leaderboards = Leaderboards -Links = Links -Locked achievements = Locked achievements -Log bad memory accesses = Log bad memory accesses -Mastered %1 = Mastered %1 -Notifications = Notifications -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = Register on www.retroachievements.org -RetroAchievements are not available for this game = RetroAchievements are not available for this game -RetroAchievements website = RetroAchievements website -Rich Presence = Rich Presence -Save state loaded without achievement data = Save state loaded without achievement data -Save states not available in Hardcore Mode = Save states not available in Hardcore Mode -Sound Effects = Sound Effects -Statistics = Statistics -Submitted %1 for %2 = Submitted %1 for %2 -Syncing achievements data... = Syncing achievements data... -Test Mode = Test Mode -This feature is not available in Hardcore Mode = This feature is not available in Hardcore Mode -This game has no achievements = This game has no achievements -Top players = Top players -Unlocked achievements = Unlocked achievements -Unofficial achievements = Unofficial achievements -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = Alternate speed volume Audio backend = Âm thanh backend (hãy khởi động lại.) Audio Error = Audio Error -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = Bluetooth-friendly buffer (chậm) Auto = Tự động Device = Device @@ -95,7 +36,6 @@ Calibrate Analog Stick = Calibrate Analog Stick Calibrate = Chỉnh cân bằng Calibrated = Calibrated Calibration = Đã chỉnh xong -Circular low end radius = Circular low end radius Circular stick input = Circular stick input Classic = Cổ điển Confine Mouse = hiển thị chuột @@ -108,10 +48,8 @@ Deadzone radius = Bán kính vùng chết Disable D-Pad diagonals (4-way touch) = Tắt D-Pad chéo (chạm 4 hướng) Disable diagonal input = Disable diagonal input Double tap = Double tap -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = Enable gesture control Enable standard shortcut keys = Enable standard shortcut keys -frames = frames Gesture = Gesture Gesture mapping = Gesture mapping Glowing borders = Ánh sáng đường viền @@ -140,7 +78,6 @@ OnScreen = Hiện điều khiển cảm ứng trên màn hình Portrait = Chiều dọc Portrait Reversed = Chiều dọc đảo ngược PSP Action Buttons = Nút hành động của PSP -Rapid fire interval = Rapid fire interval Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults @@ -149,7 +86,6 @@ Sensitivity (scale) = Sensitivity (scale) Sensitivity = Độ nhạy Shape = Shape Show Touch Pause Menu Button = Hiện phím dừng -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing @@ -230,7 +166,6 @@ Log Console = Log Console Memory View... = Xem bộ nhớ... More Settings... = Các thiết lập khác... Nearest = Gần nhất -Recent = &Recent Skip Buffer Effects = Bỏ qua hiệu ứng đệm (Không bộ nhớ đệm, nhanh hơn) Off = Tắt Open Chat = Open Chat @@ -269,6 +204,7 @@ Texture Filtering = Bộ lọc texture Texture Scaling = Scaling texture (thu nhỏ) Use Lossless Video Codec (FFV1) = Sử dụng codec video lossless (FFV1) Use output buffer for video = Use output buffer for video +Vertex Cache = Bộ đệm điểm VSync = Đồng bộ Vulkan = Vulkan Window Size = Kích cỡ màn hình @@ -282,11 +218,8 @@ Backspace = Backspace Block address = Chặn địa chỉ By Address = Theo địa chỉ Copy savestates to memstick root = Copy save states to Memory Stick root -Create frame dump = Create frame dump Create/Open textures.ini file for current game = Tạo/Mở tệp textures.ini cho game hiện tại Current = Hiện tại -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = Công cụ NPH DevMenu = Menu NPH Disabled JIT functionality = Disabled JIT functionality @@ -297,11 +230,8 @@ Enable driver bug workarounds = Enable driver bug workarounds Enable Logging = Cho phép ghi nhật ký debug Enter address = Nhập địa chỉ FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = Framedump tests Frame Profiler = Khung hồ sơ -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU driver test GPU log profiler = GPU log profiler GPU Profile = GPU profile @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = Khung nhật ký thống kê Log Level = Cấp nhật ký Log View = Xem nhật ký Logging Channels = Kênh nhật ký -Multi-threaded rendering = Multi-threaded rendering Next = Tiếp tục No block = không chặn -Off = Off Prev = Trở lại Random = Ngẫu nhiên Replace textures = Thay thế textures @@ -332,12 +260,10 @@ Stats = Thống kê System Information = Thông tin hệ thống Texture ini file created = Texture ini file created Texture Replacement = Thay thế Texture -Audio Debug = Chế độ gỡ lỗi âm thanh -Control Debug = Control Debug +Toggle Audio Debug = Chuyển qua chế độ debug âm thanh +Toggle Control Debug = Toggle Control Debug Toggle Freeze = Chuyển qua chế độ đóng băng Touchscreen Test = Touchscreen test -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP như thật Active = Hoạt động Back = Trở lại -Bottom Center = Bottom center -Bottom Left = Bottom left -Bottom Right = Bottom right Cancel = Hủy Center = Trung tâm -Center Left = Center left -Center Right = Center right -Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. +ChangingGPUBackends = Đổi thư viện đồ họa cho GPU yêu cầu phải khởi động lại PPSSPP.\nBạn có muốn khởi động lại ngay không? +ChangingInflightFrames = Changing graphics command buffering requires PPSSPP to restart. Restart now? Channel: = Channel: Choose PPSSPP save folder = Chọn thư mục save của PPSSPP Confirm Overwrite = Bạn có muốn ghi đè lên dữ liệu này không? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = Bạn có muốn xóa thiết lập\nđối với game DeleteFailed = Không thể xóa dữ liệu này. Deleting = Đang xóa\nXin đợi... Disable All = Vô hiệu hóa tất cả -Disabled = Disabled Dumps = Dumps Edit = Edit Enable All = Cho phép tất cả -Enabled = Enabled Enter = Enter -Failed to connect to server, check your internet connection. = Failed to connect to server, check your internet connection. -Failed to log in, check your username and password. = Failed to log in, check your username and password. Filter = Filter Finish = Hoàn thành GE Frame Dumps = GE Frame Dumps Grid = Grid Inactive = Không hoạt động -Installing... = Installing... InternalError = An internal error has occurred. -Links = Links Load = Load Load completed = Đã load xong. Loading = Đang load\nXin đợi... LoadingFailed = Không thể load dữ liệu này. -Log in = Log in -Log out = Log out -Logged in! = Logged in! -Logging in... = Logging in... Move = Di chuyển Move Down = Move Down Move Up = Move Up Network Connection = Kết nối mạng NEW DATA = DỮ LIỆU MỚI No = Không -None = None ObtainingIP = Obtaining IP address.\nPlease wait... OK = OK Old savedata detected = Phát hiện dữ liệu cũ Options = Tùy chọn -Password = Password Remove = Remove Reset = Mặc định Resize = Thay đổi kích thước -Restart = Restart Retry = Thử lại Save = Lưu Save completed = Đã lưu xong. @@ -420,7 +329,6 @@ SavingFailed = Không thể lưu dữ liệu này. Search = Search seconds, 0:off = giây, 0 = tắt Select = Lựa chọn -Settings = Settings Shift = Shift Skip = Skip Snap = Snap @@ -431,11 +339,7 @@ Supported = Được hỗ trợ There is no data = Không có dữ liệu. Toggle All = Tất cả Toggle List = Toggle list -Top Center = Top center -Top Left = Top left -Top Right = Top right Unsupported = không hổ trợ -Username = Username When you save, it will load on a PSP, but not an older PPSSPP = Khi bạn save, nó có thể load được trên máy PSP, nhưng lại không thể load được trên PPSSPP phiên bản cũ When you save, it will not work on outdated PSP Firmware anymore = Khi bạn save, nó sẽ không hoạt động trên máy PSP đã lỗi thời. Yes = Có @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = đây là file nén (ZIP).\nXin hãy giải [Game] Asia = Asia Calculate CRC = Calculate CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = Xóa -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = Tạo thiết lập cho game Create Shortcut = Tạo lối tắt Delete Game = Xóa trò chơi Delete Game Config = Xóa thiết lập cho game Delete Save Data = Xóa dữ liệu save Europe = Europe -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = Trò chơi -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = Cấu hình trò chơi Homebrew = Homebrew Hong Kong = Hong Kong InstallData = Cài đặt dữ liệu -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = Japan Korea = Korea MB = MB @@ -527,8 +426,6 @@ Remove From Recent = Xóa danh sách trò chơi gần đây SaveData = Dữ liệu save Setting Background = Cài đặt nền Show In Folder = Hiện trong thư mục -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = USA Use UI background = Sử dụng nền UI @@ -623,7 +520,6 @@ Must Restart = Bạn cần khởi động lại PPSSPP để những thay đổi Native device resolution = Độ phân giải tự nhiên. Nearest = Gần nhất No buffer = No buffer -Render all frames = Render all frames Show Battery % = Show Battery % Show Speed = Show Speed Skip Buffer Effects = Bỏ qua hiệu ứng đệm (không bộ nhớ đệm, nhanh hơn) @@ -658,7 +554,6 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Bộ lọc họa tiết Texture Filtering = Lọc texture -Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Họa tiết rộng Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Tắt "phần cứng tessellation": không hổ trợ @@ -669,6 +564,8 @@ Upscale Level = Cấp cao Upscale Type = Loại cao cấp UpscaleLevel Tip = CPU nặng - một số tỷ lệ có thể bị hoãn để tránh lỗi. Use all displays = Sử dụng tất cả các hiển thị +Vertex Cache = Bộ đệm điểm +VertexCache Tip = Nhanh hơn, nhưng có thể gây ra nhấp nháy VSync = Đồng bộ Vulkan = Vulkan Window Size = Kích cỡ cửa sổ @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP archive corrupt Zip file does not contain PSP software = ZIP file does not contain PSP software [KeyMapping] -Allow combo mappings = Allow combo mappings Autoconfigure = Tự động thiết lập Autoconfigure for device = Tự động thiết lập với thiết bị này Bind All = Bind All Clear All = Xóa tất cả -Combo mappings are not enabled = Combo mappings are not enabled Default All = Trả lại thiết lập gốc Map a new key for = Nhập nút mới cho Map Key = bản đồ nút @@ -747,7 +642,16 @@ Audio/Video Recording = Ghi Audio/Video AxisSwap = Hoán đổi trục Circle = Tròn Cross = Cross (chéo) -Custom %d = Custom %d +Custom 1 = Custom 1 +Custom 10 = Custom 10 +Custom 2 = Custom 2 +Custom 3 = Custom 3 +Custom 4 = Custom 4 +Custom 5 = Custom 5 +Custom 6 = Custom 6 +Custom 7 = Custom 7 +Custom 8 = Custom 8 +Custom 9 = Custom 9 D-pad down = D-pad down D-pad left = D-pad left D-pad right = D-pad right @@ -760,7 +664,6 @@ Display Portrait Reversed = Display Portrait Reversed Double tap button = Double tap button Down = Xuống Dpad = Dpad -Exit App = Exit App Frame Advance = Khung trước Hold = Giữ Home = Nhà @@ -773,7 +676,6 @@ None = None Note = Chú ý OpenChat = Open chat Pause = Tạm dừng -Previous Slot = Previous Slot R = R RapidFire = Rapid-fire Record = Record @@ -803,7 +705,6 @@ Texture Dumping = Texture dumping Texture Replacement = Texture replacement Toggle Fullscreen = Chuyển toàn màn hình Toggle mode = Toggle mode -Toggle WLAN = Toggle WLAN Triangle = Tam giác Fast-forward = Fast-forward Up = Lên @@ -813,7 +714,6 @@ Wlan = WLAN [MemStick] Already contains PSP data = Already contains PSP data -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = Create or Choose a PSP folder Current = Current DataCanBeShared = Data can be shared between PPSSPP regular/Gold @@ -846,6 +746,11 @@ AdHoc Server = Ad hoc server AdhocServer Failed to Bind Port = Ad hoc server failed to bind port AM: Data from Unknown Port = AM: Data from Unknown Port Auto = Auto +Bottom Center = Bottom center +Bottom Left = Bottom left +Bottom Right = Bottom right +Center Left = Center left +Center Right = Center right Change Mac Address = Đổi địa chỉ MAC Change proAdhocServer Address = Change PRO ad hoc server IP address (localhost = multiple instances) ChangeMacSaveConfirm = Generate a new MAC address? @@ -879,6 +784,7 @@ Invalid IP or hostname = Invalid IP or hostname Minimum Timeout = Minimum timeout (override in ms, 0 = default) Misc = Miscellaneous (default = PSP compatibility) Network Initialized = Mạng đã được khởi tạo +None = None Please change your Port Offset = Please change your port offset Port offset = Port offset(0 = PSP compatibility) Open PPSSPP Multiplayer Wiki Page = Open PPSSPP Multiplayer Wiki Page @@ -889,9 +795,11 @@ Quick Chat 3 = Quick chat 3 Quick Chat 4 = Quick chat 4 Quick Chat 5 = Quick chat 5 QuickChat = Quick chat -Randomize = Randomize Send = Send Send Discord Presence information = Send Discord "Rich Presence" information +Top Center = Top center +Top Left = Top left +Top Right = Top right Unable to find UPnP device = Unable to find UPnP device UPnP (port-forwarding) = UPnP (port forwarding) UPnP need to be reinitialized = UPnP need to be reinitialized @@ -901,23 +809,6 @@ Validating address... = Validating address... WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall -[PSPSettings] -Auto = Auto -Chinese (simplified) = Chinese (simplified) -Chinese (traditional) = Chinese (traditional) -Dutch = Dutch -English = English -French = French -Game language = Game language -German = German -Italian = Italian -Japanese = Japanese -Korean = Korean -Games often don't support all languages = Games often don't support all languages -Portuguese = Portuguese -Russian = Russian -Spanish = Spanish - [Pause] Cheats = cheat Continue = Tiếp tục @@ -944,7 +835,6 @@ Animation speed (0 -> disable) = Animation speed (0 -> disable) Aspect = Aspect Black border = Black border Bloom = Tăng độ nét -BloomNoBlur = Bloom (no blur) Brightness = Brightness Cartoon = Hoạt họa CatmullRom = Bicubic (Catmull-Rom) Upscaler @@ -952,7 +842,6 @@ ColorCorrection = Color correction ColorPreservation = Color preservation Contrast = Contrast CRT = CRT đường quét -FakeReflections = FakeReflections FXAA = Chống răng cưa FXAA Gamma = Gamma GreenLevel = Green level @@ -973,7 +862,6 @@ SSAA(Gauss) = Siêu mẫu AA (cốt) Strength = Strength Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = UpscaleBicubic UpscaleSpline36 = Spline36 Cao cấp VideoSmoothingAA = Video mịn AA Vignette = Đen góc @@ -1177,11 +1065,10 @@ GPU Flags = GPU Flags GPU Information = Thông tin GPU High precision float range = High precision float range High precision int range = Phạm vi int chính xác cao -Icon cache = Icon cache JIT available = JIT available Lang/Region = ngôn ngữ/Vùng Memory Page Size = Kích cỡ bộ nhớ -Native resolution = Độ phân giải gốc +Native Resolution = Độ phân giải gốc No GPU driver bugs detected = No GPU driver bugs detected OGL Extensions = Tiện ích OGL OpenGL ES 2.0 Extensions = Tiện ích OpenGL ES 2.0 @@ -1190,9 +1077,7 @@ OpenGL Extensions = Tiện ích OpenGL Optimal frames per buffer = Khung tối ưu cho mỗi bộ đệm Optimal sample rate = Tỷ lệ mẫu tối ưu OS Information = Tiện ích OS -Pixel resolution = Pixel resolution PPSSPP build = Xây dựng PPSSPP -Present modes = Present modes Refresh rate = Tần số làm mới Release = Giải phóng RW/RX exclusive = Độc quyền RW/RX @@ -1204,7 +1089,7 @@ System Information = Thông tin hệ thống System Name = Tên System Version = System version Threads = Chủ đề -UI resolution = UI resolution +UI Resolution = UI Resolution Vendor = Nhà cung cấp Vendor (detected) = Nhà cung cấp (phát hiện) Version Information = Thông tin phiên bản @@ -1287,7 +1172,6 @@ Record Audio = Ghi audio Record Display = Hiển thị ghi Reset Recording on Save/Load State = Đặt lại ghi trên trạng thái Save/Load. Restore Default Settings = Chỉnh các thiết lập về mặc định -RetroAchievements = RetroAchievements Rewind Snapshot Interval = Tần số Rewind snapshot Save path in installed.txt = Save path in installed.txt Save path in My Documents = Save path in My Documents @@ -1300,7 +1184,6 @@ Show ID = Show ID Show Memory Stick folder = Show Memory Stick folder Show region flag = Show region flag Simulate UMD delays = Simulate UMD delays -Simulate UMD slow reading speed = Simulate UMD slow reading speed Slot 1 = Slot 1 Slot 2 = Slot 2 Slot 3 = Slot 3 @@ -1355,11 +1238,12 @@ Download = Tải về New version of PPSSPP available = Đã có phiên bản mới của PPSSPP [VR] +% of native FoV = % of native FoV 6DoF movement = 6DoF movement Camera type = Camera type Distance to 2D menus and scenes = Distance to 2D menus and scenes -Distance to 3D scenes when VR disabled = Distance to 3D scenes when VR disabled Experts only = Experts only +Field of view scale = Field of view scale Force 72Hz update = Force 72Hz update Game camera rotation step per frame = Game camera rotation step per frame Game camera uses rotation smoothing = Game camera uses rotation smoothing diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index d947c12cc..7f752718d 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1,71 +1,12 @@ -[Achievements] -%1: Attempt failed = %1: 排行榜失败,再接再厉吧! -%1: Attempt started = %1: 排行榜尝试开始! -%1 achievements, %2 points = %1成就,%2点数 -Account = 账号 -Achievement progress = 成就进度 -Achievement unlocked = 成就达成! -Achievements = 成就 -Achievements are disabled = 未启用成就功能 -Achievements enabled = 启用成就功能 -Achievements with active challenges = 附有挑战的成就 -Allow Save State in Hardcore Mode (but not Load State) = 允许硬核模式下存档 (仅不允许读档) -Almost completed achievements = 即将达成的成绩 -Around me = 与我接近的 -Can't log in to RetroAchievements right now = 暂时无法登录到RetroAchievements -Challenge indicator = 挑战提示 -Contacting RetroAchievements server... = 连接RetroAchievements服务器… -Customize = 自定义 -Earned = 您已经达成全部%2个成就中的%1个,已获得全部%4点数中的%3。 -Encore Mode = 回味模式 -Failed logging in to RetroAchievements = 未能登录到RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = 未连接到服务器,成就不会解锁。 -Failed to identify game. Achievements will not unlock. = 未能识别游戏,成就不能解锁。 -Hardcore Mode (no savestates) = 硬核模式 (无即时存档) -Hardcore Mode = 硬核模式 -How to use RetroAchievements = 如何使用RetroAchievements -In Encore mode - listings may be wrong below = 回味模式 - 下面列表中可能错误 -Leaderboard attempt started or failed = 排行榜挑战状态显示 -Leaderboard result submitted = 排行榜结果上传完成 -Leaderboard score submission = 排行榜分数提交 -Leaderboard submission is enabled = 排名上传已启用 -Leaderboard tracker = 排行榜查看 -Leaderboards = 排行榜 -Links = 链接 -Locked achievements = 待解锁的成就 -Log bad memory accesses = 记录损坏的内存访问 -Mastered %1 = 已取得%1 -Notifications = 通知 -Recently unlocked achievements = 最近解锁的成就 -Reconnected to RetroAchievements. = 重新连接RetroAchievements。 -Register on www.retroachievements.org = 在www.retroachievements.org注册 -RetroAchievements are not available for this game = RetroAchievements暂未收录这款游戏 -RetroAchievements website = RetroAchievements网站 -Rich Presence = 展示详细信息 -Save state loaded without achievement data = 读取即时存档时不带成就数据 -Save states not available in Hardcore Mode = 硬核模式下禁用即时存档 -Sound Effects = 音效 -Statistics = 统计 -Submitted %1 for %2 = 正在提交%1到%2 -Syncing achievements data... = 同步成就数据中… -Test Mode = 测试模式 -This feature is not available in Hardcore Mode = 硬核模式下此功能不可用 -This game has no achievements = 此游戏没有成就列表 -Top players = 速度排名 -Unlocked achievements = 解锁的成就 -Unofficial achievements = 自定义成就 -Unsupported achievements = 不支持的成绩 - [Audio] Alternate speed volume = 备选速度时的音量 Audio backend = 音频引擎 Audio Error = 音频错误 -Audio file format not supported. Must be WAV. = 音频文件格式不支持,必须是WAV。 -AudioBufferingForBluetooth = 适合蓝牙缓冲区 (更慢) +AudioBufferingForBluetooth = 适合蓝牙缓冲区(更慢) Auto = 自动 Device = 设备 Disabled = 禁用 -DSound (compatible) = DirectSound (兼容) +DSound (compatible) = DirectSound(兼容) Enable Sound = 开启声音 Global volume = 全局音量 Microphone = 麦克风 @@ -74,7 +15,7 @@ Mute = 静音 Reverb volume = 混响音量 Use new audio devices automatically = 自动使用新的音频设备 Use global volume = 使用全局音量 -WASAPI (fast) = WASAPI (快) +WASAPI (fast) = WASAPI(快) [Controls] Analog Binding = 摇杆绑定 @@ -95,52 +36,48 @@ Calibrate Analog Stick = 校准摇杆 Calibrate = 校准 Calibrated = 校准后 Calibration = 校准 -Circular low end radius = 环形起步半径 Circular stick input = 环四周摇杆输入 Classic = 传统 -Confine Mouse = 鼠标限制在窗口 +Confine Mouse = 固定鼠标在显示区域内 Control Mapping = 按键映射 Custom Key Setting = 自定义键位设置 Customize = 自定义… Customize Touch Controls = 编辑触屏布局… D-PAD = 方向键 Deadzone radius = 死区半径 -Disable D-Pad diagonals (4-way touch) = 禁用方向键对角线输入 +Disable D-Pad diagonals (4-way touch) = 禁用对角线输入(方向键) Disable diagonal input = 禁用对角线方向输入 Double tap = 双击 -Enable analog stick gesture = 使用滑动操作摇杆 -Enable gesture control = 使用触屏手势操作 +Enable gesture control = 启用体感操作 Enable standard shortcut keys = 启用标准快捷键 -frames = 帧 -Gesture = 触屏手势 -Gesture mapping = 手势操作 -Glowing borders = 细边框 (发光) +Gesture = 体感 +Gesture mapping = 体感映射 +Glowing borders = 细边框(发光) HapticFeedback = 按键震动 Hide touch analog stick background circle = 隐藏摇杆圈 Icon = 图标 Ignore gamepads when not focused = 后台运行时忽略手柄 -Ignore Windows Key = 屏蔽Windows键 +Ignore Windows Key = 忽略Windows键 Invert Axes = 轴反转 Invert Tilt along X axis = 沿X轴倾斜反转 Invert Tilt along Y axis = 沿Y轴倾斜反转 Keep this button pressed when right analog is pressed = 移动右摇杆时长按此键 -Keyboard = 键盘设定 -L/R Trigger Buttons = L/R触发按钮 -Landscape = 横屏 -Landscape Auto = 自动横屏 -Landscape Reversed = 横屏反转 +Keyboard = 键盘专用设定 +L/R Trigger Buttons = L/R 按钮 +Landscape = 横向 +Landscape Auto = 自动横向 +Landscape Reversed = 横向反转 Low end radius = 起步半径 Mouse = 鼠标设置 Mouse sensitivity = 鼠标灵敏度 Mouse smoothing = 鼠标平滑度 -MouseControl Tip = 可以在按键映射界面按下“M”图标来映射鼠标。 +MouseControl Tip = 可以在按键映射界面按下'M'图标来映射鼠标。 None (Disabled) = 无 (禁用) Off = 关闭 OnScreen = 屏幕虚拟键 -Portrait = 竖屏 -Portrait Reversed = 竖屏反转 -PSP Action Buttons = PSP动作键 -Rapid fire interval = 连发间隔 +Portrait = 纵向 +Portrait Reversed = 纵向反转 +PSP Action Buttons = PSP 动作键 Raw input = 原始输入 Repeat mode = 连发模式 Reset to defaults = 重置为默认 @@ -149,7 +86,6 @@ Sensitivity (scale) = 灵敏度(倍率) Sensitivity = 灵敏度 Shape = 外形 Show Touch Pause Menu Button = 显示暂停按键 -Sticky D-Pad (easier sweeping movements) = 按下方向键可滑动 Swipe = 滑动 Swipe sensitivity = 滑动灵敏度 Swipe smoothing = 滑动平滑度 @@ -159,7 +95,7 @@ Tilt Input Type = 重力操作模式 Tilt Sensitivity along X axis = 沿X轴倾斜灵敏度 Tilt Sensitivity along Y axis = 沿Y轴倾斜灵敏度 To Calibrate = 以喜欢的角度握住设备,然后按“校准”。 -Toggle mode = 开关模式 (只需按一次) +Toggle mode = 开关模式(只需按一次) Touch Control Visibility = 显示的按键 Use custom right analog = 自定义右摇杆用途 Use Mouse Control = 使用鼠标控制 @@ -178,279 +114,247 @@ Refresh Rate = 刷新率 [DesktopUI] # If your language does not show well with the default font, you can use Font to specify a different one. # Just add it to your language's ini file and uncomment it (remove the # by Font). -Auto Max Quality = 自动最佳质量(&Q) +Auto Max Quality = 自动最佳质量 (&Q) Copy PSP memory base address = 复制PSP内存基址(&A) Font = 微软雅黑 -About PPSSPP... = 关于PPSSPP…(&A) -Auto = 自动(&A) -Backend = 渲染引擎(需要PPSSPP重新启动)(&B) -Bicubic = 双三次(&B) +About PPSSPP... = 关于PPSSPP (&A)... +Auto = 自动 (&A) +Backend = 渲染引擎(需要PPSSPP重新启动) (&B) +Bicubic = 双三次 (&B) Break = 停止 Break on Load = 载入后停止 -Buy Gold = 购买黄金版(&G) -Control Mapping... = 按键映射…(&O) -Debugging = 调试(&D) -Deposterize = 色调融合(&D) -Direct3D9 = Direct3D 9 -Direct3D11 = Direct3D 11 -Disassembly = 反汇编…(&D) +Buy Gold = 购买黄金版 (&G) +Control Mapping... = 按键映射 (&O)... +Debugging = 调试 (&D) +Deposterize = 色调融合 (&D) +Direct3D9 = Direct3D 9 (&9) +Direct3D11 = Direct3D11 (&11) +Disassembly = 反汇编 (&D)... Discord = Discord -Display Layout && Effects = 屏幕布局和滤镜编辑… +Display Layout && Effects = 屏幕布局和滤镜编辑... Display Rotation = 显示旋转 -Dump Next Frame to Log = 转储下一帧到日志(&U) -Emulation = 模拟(&E) -Enable Cheats = 启用金手指(&C) -Enable Sound = 开启声音(&O) -Exit = 退出(&X) -Extract File... = 提取文件…(&X) -File = 文件(&F) -Frame Skipping = 跳帧(&F) +Dump Next Frame to Log = 转储下一帧到日志 (&U) +Emulation = 模拟 (&E) +Enable Cheats = 启用金手指 (&C) +Enable Sound = 开启声音 (&O) +Exit = 退出 (X) +Extract File... = 提取文件 (&X)... +File = 文件 (&F) +Frame Skipping = 跳帧 (&F) Frame Skipping Type = 跳帧方式 -Fullscreen = 全屏幕(&L) -Game Settings = 游戏设置(&G) -GE Debugger... = GE调试器…(&R) -GitHub = GitHub -Hardware Transform = 硬件几何变换(&H) -Help = 帮助(&H) -Hybrid = 混合(&H) -Hybrid + Bicubic = 混合+双三次(&Y) -Ignore Illegal Reads/Writes = 忽略读写错误(&I) +Fullscreen = 全屏幕 (&L) +Game Settings = 游戏设置 (&G) +GE Debugger... = GE 调试器 (&R)... +GitHub = Git&Hub +Hardware Transform = 硬件几何变换 (&H) +Help = 帮助 (&H) +Hybrid = 混合 (&H) +Hybrid + Bicubic = 混合+双三次 (&y) +Ignore Illegal Reads/Writes = 忽略读写错误 (&I) Ignore Windows Key = 忽略Windows键 -Keep PPSSPP On Top = 窗口总在最前(&K) +Keep PPSSPP On Top = 窗口总在最前 (&K) Landscape = 横向 Landscape reversed = 横向反转 -Language... = 语言…(&N) -Linear = 线性过滤(&L) -Load = 载入…(&L) -Load .sym File... = 载入.sym文件…(&A) -Load Map File... = 载入内存镜像文件…(&M) -Load State = 快速读档(&O) -Load State File... = 载入即时存档…(&L) -Log Console = 控制台日志(&L) -Memory View... = 查看内存…(&V) -More Settings... = 更多设置…(&M) -Nearest = 邻近取样(&N) -Recent = 最近游戏(&R) -Skip Buffer Effects = 跳过缓冲效果(更快)(&S) -Off = 关闭(&O) +Language... = 语言 (&n)... +Linear = 线性过滤 (&L) +Load = 载入 (&L)... +Load .sym File... = 载入.sym文件 (&A)... +Load Map File... = 载入内存镜像文件 (&M)... +Load State = 快速读档 (&O) +Load State File... = 载入即时存档 (&L)... +Log Console = 控制台日志 (&L) +Memory View... = 查看内存 (&V)... +More Settings... = 更多设置 (&M)... +Nearest = 邻近取样 (&N) +Skip Buffer Effects = 跳过缓冲效果(更快) (&S) +Off = 关闭 (&O) Open Chat = 聊天窗口 -Open Directory... = 打开路径…(&D) -Open from MS:/PSP/GAME... = 从MS:/PSP/GAME处打开…(&P) -Open Memory Stick = 打开记忆棒(&M) +Open Directory... = 打开路径(&D)... +Open from MS:/PSP/GAME... = 从MS:/PSP/GAME处打开 (&P)... +Open Memory Stick = 打开记忆棒 (&M) Open New Instance = 双开模拟器 -OpenGL = OpenGL -Pause = 暂停(&P) -Pause When Not Focused = 后台运行时自动暂停(&P) +OpenGL = OpenGL(&O) +Pause = 暂停 (&P) +Pause When Not Focused = 后台运行时自动暂停 (&P) Portrait = 纵向 Portrait reversed = 纵向反转 -PPSSPP Forums = PPSSPP官方论坛(&F) -Record = 录制(&R) -Record Audio = 录制音频(&A) -Record Display = 录制视频(&D) -Rendering Mode = 渲染模式(&O) -Rendering Resolution = 渲染分辨率(&R) -Reset = 重置(&E) -Reset Symbol Table = 重置符号表(&R) -Run = 运行(&R) -Save .sym File... = 保存sym文件…(&E) -Save Map File... = 保存内存镜像文件…(&S) +PPSSPP Forums = PPSSPP官方论坛 (&F) +Record = 录制 (&R) +Record Audio = 录制音频 (&A) +Record Display = 录制视频 (&D) +Rendering Mode = 渲染模式 (&O) +Rendering Resolution = 渲染分辨率 (&R) +Reset = 重置 (&E) +Reset Symbol Table = 重置符号表 (&R) +Run = 运行 (&R) +Save .sym File... = 保存.sym文件 (&E)... +Save Map File... = 保存内存镜像文件 (&S)... Save State = 快速存档 (&A) -Save State File... = 保存即时存档…(&S) -Savestate Slot = 即时存档插槽(&T) -Screen Scaling Filter = 屏幕缩放方法(&E) -Show Debug Statistics = 显示调试信息(&G) -Show FPS Counter = 显示帧率(&F) -Skip Number of Frames = 按帧数量 -Skip Percent of FPS = 按帧率比例 -Stop = 停止(&S) +Save State File... = 保存即时存档 (&S)... +Savestate Slot = 即时存档插槽 (&T) +Screen Scaling Filter = 屏幕缩放方法 (&E) +Show Debug Statistics = 显示调试信息 (&G) +Show FPS Counter = 显示帧率 (&F) +Skip Number of Frames = 跳过帧的数量 +Skip Percent of FPS = 跳过帧率的百分比 +Stop = 停止 (&S) Switch UMD = 切换UMD光盘 -Take Screenshot = 屏幕截图(&T) -Texture Filtering = 纹理过滤方法(&X) -Texture Scaling = 纹理缩放方法(&T) -Use Lossless Video Codec (FFV1) = 使用无损视频编码器(FFV1)(&U) -Use output buffer for video = 录制包括输出缓冲 -VSync = 垂直同步(&Y) +Take Screenshot = 屏幕截图 (&T) +Texture Filtering = 纹理过滤方法 (&X) +Texture Scaling = 纹理缩放方法 (&T) +Use Lossless Video Codec (FFV1) = 使用无损视频编码器(FFV1) (&U) +Use output buffer for video = 录制时使用输出缓冲 +Vertex Cache = 顶点缓存 (&V) +VSync = 垂直同步 (&Y) Vulkan = Vulkan -Window Size = 窗口大小(&W) -www.ppsspp.org = 访问www.ppsspp.org(&P) +Window Size = 窗口大小 (&W) +www.ppsspp.org = 访问www.ppsspp.org (&P) xBRZ = &xBRZ [Developer] -Allocator Viewer = 分配器查看器 (Vulkan) +Allocator Viewer = Allocator查看器(Vulkan) Allow remote debugger = 允许远程调试器 Backspace = 退格键 Block address = 内存块地址 By Address = 通过地址定位 Copy savestates to memstick root = 拷贝即时存档至记忆棒根路径 -Create frame dump = 创建帧转储 Create/Open textures.ini file for current game = 创建/打开当前游戏的textures.ini文件 Current = 当前 -Debug overlay = 调试叠加层 -Debug stats = 调试统计 Dev Tools = 开发者工具 DevMenu = 开发者菜单 Disabled JIT functionality = 已禁用的JIT功能 -Draw Frametimes Graph = 帧时间图表 -Dump Decrypted Eboot = 载入游戏时保存已解密的eboot.bin +Draw Frametimes Graph = 显示帧时间统计图 +Dump Decrypted Eboot = 载入游戏时保存已解密的EBOOT.BIN Dump next frame to log = 转储下一帧到日志 Enable driver bug workarounds = 启用GPU驱动错误解决方法 Enable Logging = 启用调试日志 Enter address = 输入地址 FPU = FPU -Fragment = 片段着色器 -Frame timing = 帧时间统计信息 Framedump tests = 帧转储测试 Frame Profiler = 帧分析器 -GPU Allocator Viewer = GPU分配器查看 GPU Driver Test = GPU驱动程序测试 GPU log profiler = GPU日志分析器 GPU Profile = GPU分析器 -Jit Compare = JIT比较 +Jit Compare = Jit比较 JIT debug tools = JIT调试工具 -Log Dropped Frame Statistics = 记录丢帧统计信息 +Log Dropped Frame Statistics = 记录丢弃帧统计信息 Log Level = 日志等级 Log View = 日志视图 -Logging Channels = 日志记录分类 -Multi-threaded rendering = 多线程渲染 +Logging Channels = 记录日志分类 Next = 下一个 No block = 没有内存块 -Off = 关闭 Prev = 之前 Random = 随机 Replace textures = 纹理替换 Reset = 重置 Reset limited logging = 重置受限日志 -RestoreDefaultSettings = 您确定要将所有设置恢复到默认?\n该操作无法撤销。\n操作将在PPSSPP重新启动后生效。 -RestoreGameDefaultSettings = 您确定要将此游戏设置\n恢复为PPSSPP默认吗? +RestoreDefaultSettings = 您确定要将所有设置恢复到默认?\n该操作无法撤销。\n操作将在PPSSPP重新启动后生效。 +RestoreGameDefaultSettings = 您确定要将此游戏设置\n恢复为PPSSPP默认吗? Resume = 恢复 Run CPU Tests = 运行CPU测试 Save new textures = 保存新纹理 Shader Viewer = 着色器查看器 Show Developer Menu = 显示开发者菜单 -Show on-screen messages = 屏幕上方显示消息 +Show on-screen messages = 显示屏幕上方消息 Stats = 统计数据 System Information = 系统信息 Texture ini file created = 创建纹理ini文件 Texture Replacement = 纹理替换 -Audio Debug = 切换音频调试 -Control Debug = 切换操纵调试 +Toggle Audio Debug = 切换音频调试 +Toggle Control Debug = 切换操纵调试 Toggle Freeze = 切换冻结 Touchscreen Test = 触屏测试 -Ubershaders = 超着色器 -Vertex = 顶点着色器 VFPU = VFPU [Dialog] -%d seconds = %d秒 +%d seconds = %d 秒 * PSP res = * PSP分辨率 Active = 激活 Back = 返回 -Bottom Center = 正下方 -Bottom Left = 左下方 -Bottom Right = 右下方 Cancel = 取消 Center = 中心 -Center Left = 左中间 -Center Right = 右中间 -Changing this setting requires PPSSPP to restart. = 设置生效需要重新启动PPSSPP。 -Channel: = 信道: +ChangingGPUBackends = 更改引擎模式需要重启PPSSPP。立刻重启吗? +ChangingInflightFrames = 更改缓冲图形命令需要重启PPSSPP。立刻重启吗? +Channel: = 信道: Choose PPSSPP save folder = 选择PPSSPP存档的文件夹 -Confirm Overwrite = 您要覆盖这个存档吗? -Confirm Save = 您要保存到这个存档吗? -ConfirmLoad = 您要载入这个存档吗? -ConnectingAP = 连接到接入点。\n请稍候… -ConnectingPleaseWait = 连接中。\n请稍候… +Confirm Overwrite = 您要覆盖这个存档吗? +Confirm Save = 您要保存到这个存档吗? +ConfirmLoad = 您要载入这个存档吗? +ConnectingAP = 连接到接入点.\n请稍候... +ConnectingPleaseWait = 连接中.\n请稍候... ConnectionName = 连接名称 Corrupted Data = 数据损坏 Delete = 删除 Delete all = 全部删除 Delete completed = 已删除。 -DeleteConfirm = 存档将被删除。\n您确定要继续吗? -DeleteConfirmAll = 将删除此游戏的所有存档。\n您确定要这样做吗? -DeleteConfirmGame = 将删除此游戏的文件,且不能复原。\n您确定要这样做吗? -DeleteConfirmGameConfig = 您确定要删除此游戏的设置吗? +DeleteConfirm = 存档将被删除。\n您确定要继续吗? +DeleteConfirmAll = 将删除此游戏的所有存档。\n您确定要这样做吗? +DeleteConfirmGame = 将删除此游戏的文件, 且不能复原。\n您确定要这样做吗? +DeleteConfirmGameConfig = 您确定要删除此游戏的设置吗? DeleteFailed = 无法删除存档。 -Deleting = 删除中。\n请稍候… +Deleting = 删除中\n请稍候... Disable All = 全部禁用 -Disabled = 禁用 Dumps = 转储 Edit = 编辑 Enable All = 全部启用 -Enabled = 启用 Enter = 确定 -Failed to connect to server, check your internet connection. = 未连接到服务器,请检查网络情况 -Failed to log in, check your username and password. = 无法登录,请检查账号密码 Filter = 筛选 Finish = 完成 GE Frame Dumps = GE帧转储 Grid = 网格尺寸 Inactive = 未激活 -Installing... = 安装中… -InternalError = 发生内部错误。 -Links = 链接 +InternalError = 发生内部错误. Load = 载入 Load completed = 已载入。 -Loading = 载入中\n请稍候… +Loading = 载入中\n请稍候... LoadingFailed = 无法载入存档。 -Log in = 登录 -Log out = 退出 -Logged in! = 登录成功! -Logging in... = 登录中… Move = 移动位置 Move Down = 移至下层 Move Up = 移至上层 Network Connection = 网络连接 NEW DATA = 新建存档 No = 否 -None = 无 -ObtainingIP = 获取IP地址。\n请稍候… +ObtainingIP = 获取IP地址.\n请稍候... OK = 确定 Old savedata detected = 检测到旧版本的存档数据 Options = 选项 -Password = 密码 Remove = 删除 Reset = 重置 Resize = 调整大小 -Restart = 重启 Retry = 重试 Save = 保存 Save completed = 保存完成。 -Saving = 保存中。\n请稍候… +Saving = 保存中\n请稍候... SavingFailed = 无法保存存档。 Search = 搜索 -seconds, 0:off = 秒后,0=不隐藏 +seconds, 0:off = 每n秒,0=不回档 Select = 选择 -Settings = 设置 Shift = 翻页 Skip = 跳过 Snap = 网格对齐 Space = 空格键 -SSID = 网络名称 +SSID = SSID Submit = 提交 Supported = 支持 There is no data = 存档不存在。 Toggle All = 全选/不选 Toggle List = 显示列表 -Top Center = 正上方 -Top Left = 左上方 -Top Right = 右上方 Unsupported = 不支持 -Username = 用户名 -When you save, it will load on a PSP, but not an older PPSSPP = 当您保存后,它只会在PSP实机上载入,而不是旧版本的PPSSPP -When you save, it will not work on outdated PSP Firmware anymore = 当您保存后,它无法在过时的PSP固件上运行 +When you save, it will load on a PSP, but not an older PPSSPP = 当您保存后, 它只会在PSP实机上载入, 而不是旧版本的PPSSPP +When you save, it will not work on outdated PSP Firmware anymore = 当您保存后, 它无法在过时的PSP固件上运行 Yes = 是 Zoom = 放大 [Error] -7z file detected (Require 7-Zip) = 这是7Z压缩文件。\n请试着使用7-zip或WinRAR进行解压缩。 +7z file detected (Require 7-Zip) = 这是7ZIP压缩文件。\n请试着使用 7-zip或WinRAR进行解压缩。 A PSP game couldn't be found on the disc. = 光盘中找不到PSP游戏。 Cannot boot ELF located outside mountRoot. = 无法启动位于mountRoot之外的ELF文件。 Could not save screenshot file = 无法保存屏幕截图文件 -D3D9or11 = 使用Direct3D 9?(或“否”以使用Direct3D 11) -D3D11CompilerMissing = 没有找到D3DCompiler_47.dll, 请安装它或者按下“确认”键来尝试使用Direct3D 9代替它。 +D3D9or11 = 使用Direct3D 9? (或"否"以使用Direct3D 11) +D3D11CompilerMissing = 没有找到D3DCompiler_47.dll, 请安装它或者按下"确认"键来尝试使用Direct3D 9代替它。 D3D11InitializationError = Direct3D 11初始化出错 -D3D11Missing = 您的操作系统没有包含D3D11。请运行Windows更新。\n\n请按下“确认”键来尝试使用Direct3D 9代替它。 -D3D11NotSupported = 您的图形处理器似乎并不支持Direct3D 11。\n\n您想尝试使用Direct3D 9来代替它吗? +D3D11Missing = 您的操作系统没有包含D3D11。请运行Windows Update。\n\n按下"确认"键来尝试使用Direct3D 9代替它。 +D3D11NotSupported = 您的图形处理器似乎并不支持Direct3D 11。\n\n您想尝试使用Direct3D 9来代替它吗? Disk full while writing data = 写入数据时磁盘已满 ELF file truncated - can't load = ELF文件被截断 - 无法加载 Error loading file = 无法加载游戏: @@ -459,85 +363,78 @@ Failed initializing CPU/Memory = 初始化CPU或内存失败 Failed to load executable: = 无法加载可执行文件: File corrupt = 文件损坏 Game disc read error - ISO corrupt = 游戏光盘读取错误:ISO损坏。 -GenericAllStartupError = PPSSPP无法使用任何图形后端启动,请尝试升级图形和其他驱动程序。 -GenericBackendSwitchCrash = 启动时PPSSPP崩溃了。\n\n这通常意味着图形驱动程序问题,请尝试升级图形驱动程序。\n\n图形后端已切换: -GenericDirect3D9Error = 初始化图像失败,请尝试更新您的显卡驱动程序和DirectX 9运行库。\n\n是否尝试切换到OpenGL模式?\n\n错误信息: +GenericAllStartupError = PPSSPP无法使用任何图形后端启动。 尝试升级图形和其他驱动程序. +GenericBackendSwitchCrash = 启动时PPSSPP崩溃了.\n\n这通常意味着图形驱动程序问题。 尝试升级图形驱动程序.\n\n图形后端已切换: +GenericDirect3D9Error = 初始化图像失败。尝试更新您的显卡驱动程序和DirectX 9运行库。\n\n是否尝试切换到OpenGL模式?\n\n错误信息: GenericGraphicsError = 图像错误 -GenericOpenGLError = 初始化图像失败,请尝试更新您的显卡驱动程序。\n\n是否尝试切换到DirectX 9模式?\n\n错误信息: -GenericVulkanError = 初始化图像失败,请尝试更新您的显卡驱动程序。\n\n是否尝试切换到OpenGL模式?\n\n错误信息: -InsufficientOpenGLDriver = 检测到显卡驱动不支持OpenGL 2.0!\n\n您想尝试使用DirectX吗?\n\nDirectX目前只兼容较少游戏,但在您的GPU也可能是唯一的选择。\n\n有关更多信息,请访问论坛https://forums.ppsspp.org。\n\n +GenericOpenGLError = 初始化图像失败。尝试更新您的显卡驱动程序。\n\n是否尝试切换到DirectX 9模式?\n\n错误信息: +GenericVulkanError = 初始化图像失败。尝试更新您的显卡驱动程序。\n\n是否尝试切换到OpenGL模式?\n\n错误信息: +InsufficientOpenGLDriver = 检测到显卡驱动不支持OpenGL 2.0!\n\n您想尝试使用DirectX吗?\n\nDirectX目前只兼容较少游戏, 但在您的GPU也可能是唯一的选择。\n\n有关更多信息,请访问论坛https://forums.ppsspp.org。\n\n Just a directory. = 这只是个文件夹。 Missing key = 缺失密钥 -MsgErrorCode = 错误代码: -MsgErrorSavedataDataBroken = 保存数据已损坏。 -MsgErrorSavedataMSFull = 记忆棒已满,检查您的存储空间。 -MsgErrorSavedataNoData = 警告:未找到保存数据。 -MsgErrorSavedataNoMS = 未插入记忆棒。 -No EBOOT.PBP, misidentified game = 找不到eboot.pbp,无法正确识别游戏。 +MsgErrorCode = 错误代码: +MsgErrorSavedataDataBroken = 保存数据已损坏. +MsgErrorSavedataMSFull = 记忆棒已满.检查您的存储空间. +MsgErrorSavedataNoData = 警告:未找到保存数据. +MsgErrorSavedataNoMS = 未插入记忆棒. +No EBOOT.PBP, misidentified game = 找不到EBOOT.PBP, 无法正确识别游戏。 Not a valid disc image. = 光盘镜像无效。 -OpenGLDriverError = OpenGL驱动程序错误 +OpenGLDriverError = OpenGL 驱动程序错误 PPSSPP doesn't support UMD Music. = PPSSPP不支持UMD音乐。 PPSSPP doesn't support UMD Video. = PPSSPP不支持UMD视频。 -PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPP只能运行PSP游戏,不能运行PS1或2的游戏。 +PPSSPP plays PSP games, not PlayStation 1 or 2 games. = PPSSPP只能运行PSP游戏, 不能运行PS1或2的游戏。 PPSSPPDoesNotSupportInternet = PPSSPP目前不支持连接互联网以获取DLC、PSN或游戏的更新。 PS1 EBOOTs are not supported by PPSSPP. = PPSSPP不支持由PS1 EBOOT生成的游戏镜像。 -PSX game image detected. = 这是MODE2镜像,PPSSPP不支持PS1游戏。 +PSX game image detected. = 这是MODE2镜像。PPSSPP不支持PS1游戏。 RAR file detected (Require UnRAR) = 这是RAR压缩文件。\n请尝试使用UnRAR进行解压缩。 RAR file detected (Require WINRAR) = 这是RAR压缩文件。\n请尝试使用WinRAR进行解压缩。 Running slow: try frameskip, sound is choppy when slow = 运行速度慢:可以尝试跳帧, 减速时声音会不连贯 Running slow: Try turning off Software Rendering = 运行速度慢:可以尝试关闭软件渲染 Save encryption failed. This save won't work on real PSP = 存档加密失败。此存档将无法在PSP实机使用 -textures.ini filenames may not be cross-platform = “textures.ini”文件名可能不是多平台的。 +textures.ini filenames may not be cross-platform = "textures.ini"文件名可能不是多平台的。 This is a saved state, not a game. = 这是一个即时存档,不是游戏。 This is save data, not a game. = 这是一个存档,不是游戏。 -Unable to create cheat file, disk may be full = 无法创建金手指文件,磁盘可能已满 +Unable to create cheat file, disk may be full = 无法创建金手指文件,磁盘可能已满 Unable to initialize rendering engine. = 无法初始化渲染引擎。 -Unable to write savedata, disk may be full = 无法写入存档数据,磁盘可能已满 -Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = 警告:显存已满,减少分辨率提升并切换到慢速缓存模式。 -Warning: Video memory FULL, switching to slow caching mode = 警告:显存已满,切换到慢速缓存模式。 +Unable to write savedata, disk may be full = 无法写入存档数据, 磁盘可能已满 +Warning: Video memory FULL, reducing upscaling and switching to slow caching mode = 警告:显存已满, 减少分辨率提升并切换到慢速缓存模式。 +Warning: Video memory FULL, switching to slow caching mode = 警告:显存已满, 切换到慢速缓存模式。 ZIP file detected (Require UnRAR) = 这是ZIP压缩文件。\n请尝试使用UnRAR进行解压缩。 ZIP file detected (Require WINRAR) = 这是ZIP压缩文件。\n请尝试使用WinRAR进行解压缩。 [Game] Asia = 亚洲 Calculate CRC = 计算CRC码 -Click "Calculate CRC" to verify ISO = 点击"计算CRC码"可校验ISO ConfirmDelete = 确认删除 -CRC checksum does not match, bad or modified ISO = CRC校验与原版不符, 此ISO已被修改或损坏 Create Game Config = 建立游戏配置 Create Shortcut = 创建快捷方式 Delete Game = 删除游戏 Delete Game Config = 删除游戏配置 Delete Save Data = 删除存档 Europe = 欧洲 -File size incorrect, bad or modified ISO = 文件大小与原版不符, 此ISO已被修改或损坏 Game = 游戏 -Game ID unknown - not in the ReDump database = 未知的游戏ID - ReDump数据库未收录 Game Settings = 游戏设置 Homebrew = 自制游戏 Hong Kong = 香港 InstallData = 安装数据 -ISO OK according to the ReDump project = ISO通过ReDump数据库校验 Japan = 日本 Korea = 韩国 MB = MB -One moment please... = 请稍候… +One moment please... = 请稍等... Play = 启动 -Remove From Recent = 从最近游玩中删除 +Remove From Recent = 从"最近的游戏"中删除 SaveData = 存档 Setting Background = 设置背景 Show In Folder = 在文件夹中显示 -Time Played: %1h %2m %3s = 游玩时间:%1小时 %2分 %3秒 -Uncompressed = 已解压 USA = 美国 Use UI background = 使用背景为壁纸 [Graphics] % of the void = %的边框 % of viewport = %的视区 -%, 0:unlimited = %,0 = 无限制 +%, 0:unlimited = %, 0 = 无限制 (supersampling) = (超级采样) -(upscaling) = (提升放大) +(upscaling) = (放大) 1x PSP = 1倍PSP 2x = 2倍 2x PSP = 2倍PSP @@ -558,11 +455,11 @@ Aggressive = 激进 Alternative Speed = 备选速度1 Alternative Speed 2 = 备选速度2 Anisotropic Filtering = 各向异性过滤 -Antialiasing (MSAA) = 抗锯齿 (MSAA) -Aspect Ratio = 宽高比例 +Antialiasing (MSAA) = 抗锯齿(MSAA) +Aspect Ratio = 宽高比 Auto = 自动 -Auto (1:1) = 自动 (1:1) -Auto (same as Rendering) = 自动 (同渲染分辨率) +Auto (1:1) = 自动(1:1) +Auto (same as Rendering) = 自动(同渲染分辨率) Auto FrameSkip = 自动跳帧 Auto Max Quality = 自动最佳质量 Auto Scaling = 自动缩放 @@ -570,13 +467,13 @@ Backend = 渲染引擎 Balanced = 均衡 Bicubic = 双三次 Both = 全部显示 -Buffer graphics commands (faster, input lag) = 缓冲图形命令 (更快,增加输入延迟) -BufferedRenderingRequired = 警告:此游戏需要关闭“跳过缓冲效果”。 +Buffer graphics commands (faster, input lag) = 缓冲图形命令(更快, 增加输入延迟) +BufferedRenderingRequired = 警告:此游戏需要关闭"跳过缓冲效果"。 Camera = 摄像头 Camera Device = 摄像头设备 -Cardboard Screen Size = 屏幕大小 (视区%) -Cardboard Screen X Shift = 水平% -Cardboard Screen Y Shift = 垂直% +Cardboard Screen Size = 屏幕大小(视区%) +Cardboard Screen X Shift = 水平 % +Cardboard Screen Y Shift = 垂直 % Cardboard VR Settings = Google Cardboard VR设置 Cheats = 金手指 CPU Core = CPU核心模式 @@ -597,60 +494,59 @@ Frame Skipping = 跳帧 Frame Skipping Type = 跳帧方式 FullScreen = 全屏幕 Geometry shader culling = 几何着色器剔除 -GPUReadbackRequired = 警告:此游戏需要关闭“跳过GPU块传输”。 -Hack Settings = 渲染修正 (可能引发故障) +GPUReadbackRequired = 警告: 此游戏需要"跳过GPU块传输"设置为关闭 +Hack Settings = 渲染修正(可能引发故障) Hardware Tessellation = 硬件曲面细分 Hardware Transform = 硬件几何变换 -hardware transform error - falling back to software = 硬件几何变换错误,改回软件模式 -HardwareTessellation Tip = 使用硬件绘制曲线,采用固定的质量 +hardware transform error - falling back to software = 硬件几何变换错误, 改回软件模式 +HardwareTessellation Tip = 使用硬件绘制曲线, 采用固定的质量 High = 高质量 Hybrid = 混合 Hybrid + Bicubic = 混合+双三次 Ignore camera notch when centering = 忽略摄像头挖孔 -Integer scale factor = 整倍缩放 +Integer scale factor = 整倍像素缩放 Internal Resolution = 内部分辨率 -Lazy texture caching = 减少缓存存取 (提速) -Lazy texture caching Tip = 更快,在一些游戏里引起文字渲染错误 +Lazy texture caching = 减少缓存存取(提速) +Lazy texture caching Tip = 更快, 在一些游戏里引起文字渲染错误 Linear = 线性过滤 Low = 低质量 -LowCurves = 贝塞尔曲线质量 (提速) -LowCurves Tip = 适用于极少部分游戏,控制曲线的细节程度 -Lower resolution for effects (reduces artifacts) = 降低特效分辨率 (减少特效错误) +LowCurves = 贝塞尔曲线质量(提速) +LowCurves Tip = 适用于极少部分游戏, 控制曲线的细节程度 +Lower resolution for effects (reduces artifacts) = 降低特效分辨率(减少特效错误) Manual Scaling = 手动缩放 Medium = 中质量 Mode = 渲染模式 Must Restart = 重启PPSSPP才能使这项设置生效。 -Native device resolution = 屏幕原生的分辨率 +Native device resolution = 本机原生的分辨率 Nearest = 邻近取样 No buffer = 不缓冲 -Render all frames = 逐帧渲染 -Show Battery % = 显示电量% +Show Battery % = 显示电量 % Show Speed = 显示速度 -Skip Buffer Effects = 跳过缓冲效果 (更快) +Skip Buffer Effects = 跳过缓冲效果(更快) None = 不显示 Number of Frames = 帧的数量 Off = 关闭 OpenGL = OpenGL Overlay Information = 叠加信息 Partial Stretch = 部分拉伸 -Percent of FPS = 帧率的比例 +Percent of FPS = 帧率的百分比 Performance = 性能选项 Postprocessing shaders = 后处理着色器 Recreate Activity = 重建进程 Render duplicate frames to 60hz = 渲染重复帧至60Hz -RenderDuplicateFrames Tip = 在较低帧率的游戏中,使帧生成更平滑 +RenderDuplicateFrames Tip = 在较低帧率的游戏中, 使帧生成更平滑 Rendering Mode = 渲染模式 Rendering Resolution = 渲染分辨率 -RenderingMode NonBuffered Tip = 更快,在某些游戏中丢失特效 +RenderingMode NonBuffered Tip = 更快, 在某些游戏中丢失特效 Rotation = 方向 Safe = 安全 Screen Scaling Filter = 缩放方法 Show Debug Statistics = 显示调试信息 Show FPS Counter = 显示帧率 Skip GPU Readbacks = 跳过GPU块传输 -Software Rendering = 软件渲染 (慢) +Software Rendering = 软件渲染(慢) Software Skinning = 软件蒙皮 -SoftwareSkinning Tip = 将模型绘制转移至CPU,在较多游戏中更快,但也有减速的反例 +SoftwareSkinning Tip = 将模型绘制转移至CPU, 在较多游戏中更快, 但也有减速的反例 Speed = 运行速度 Speed Hacks = 提速修正 (引起画面错误) Stereo display shader = 立体显示模式 @@ -658,17 +554,18 @@ Stereo rendering = 立体渲染 Stretch = 拉伸 Texture Filter = 纹理过滤方法 Texture Filtering = 纹理过滤 -Texture replacement pack activated = 已使用纹理替换包 Texture Scaling = 纹理缩放 -Texture Shader = 纹理着色器 (GPU) -Turn off Hardware Tessellation - unsupported = 关闭“硬件曲面细分”:不支持 +Texture Shader = 纹理着色器 +Turn off Hardware Tessellation - unsupported = 关闭"硬件曲面细分":不支持 Unlimited = 无限制 -Up to 1 = 最高为1帧 -Up to 2 = 最高为2帧 +Up to 1 = 最高为1 +Up to 2 = 最高为2 Upscale Level = 纹理缩放级别 -Upscale Type = 纹理缩放 (CPU) -UpscaleLevel Tip = CPU负担大。某些缩放会延后,以减少卡顿 +Upscale Type = 纹理缩放方法 +UpscaleLevel Tip = CPU负担大--某些缩放会延迟, 以减少卡顿 Use all displays = 使用全部显示器 +Vertex Cache = 顶点缓存 +VertexCache Tip = 略微提速, 可能造成暂时模型闪烁或丢失 VSync = 垂直同步 Vulkan = Vulkan Window Size = 窗口大小 @@ -677,27 +574,25 @@ xBRZ = xBRZ [InstallZip] Delete ZIP file = 删除ZIP文件 Install = 安装 -Install game from ZIP file? = 从ZIP文件安装游戏? -Install textures from ZIP file? = 从ZIP文件安装纹理包? -Installed! = 安装完成! +Install game from ZIP file? = 从ZIP文件安装游戏? +Install textures from ZIP file? = 从ZIP文件安装纹理包? +Installed! = 安装完成! Texture pack doesn't support install = 此纹理包不支持安装 -Zip archive corrupt = ZIP文档损坏 +Zip archive corrupt = ZIP 文档损坏 Zip file does not contain PSP software = ZIP文件不包含PSP软件 [KeyMapping] -Allow combo mappings = 多键合一 Autoconfigure = 自动配置 Autoconfigure for device = 根据设备配置 Bind All = 全部绑定 Clear All = 全部清除 -Combo mappings are not enabled = 请打开多键合一 Default All = 恢复默认 Map a new key for = 输入一个新按键: Map Key = 按键映射 Map Mouse = 鼠标映射 Replace = 替换现有 Show PSP = PSP 布局 -You can press ESC to cancel. = 可以按下Esc键取消 +You can press ESC to cancel. = 可以按下 ESC 键取消 [MainMenu] Browse = 浏览... @@ -710,10 +605,10 @@ Game Settings = 游戏设置 Games = 载入新游戏 Give PPSSPP permission to access storage = 给予PPSSPP访问存储空间的权限 Homebrew & Demos = 自制游戏与试玩 -How to get games = 如何获得游戏? -How to get homebrew & demos = 如何获得自制游戏与试玩? -Load = 载入游戏… -Loading... = 读取中… +How to get games = 如何获得游戏? +How to get homebrew & demos = 如何获得自制游戏与试玩? +Load = 载入游戏... +Loading... = 载入中... PinPath = 置顶文件夹 PPSSPP can't load games or save right now = PPSSPP现在不能载入游戏或存档 Recent = 最近的游戏 @@ -736,10 +631,10 @@ Search = 搜索 [MappableControls] Alt speed 1 = 备选速度1 Alt speed 2 = 备选速度2 -An.Down = 左摇杆:下 -An.Left = 左摇杆:左 -An.Right = 左摇杆:右 -An.Up = 左摇杆:上 +An.Down = 左摇杆:下 +An.Left = 左摇杆:左 +An.Right = 左摇杆:右 +An.Up = 左摇杆:上 Analog limiter = 摇杆限制 Analog speed = 摇杆控速 Analog Stick = 左摇杆 @@ -747,25 +642,33 @@ Audio/Video Recording = 录制音频视频 AxisSwap = 摇杆/方向键互换 Circle = 圆圈键 Cross = 叉键 -Custom %d = 自定义%d -D-pad down = 方向键:下 -D-pad left = 方向键:左 -D-pad right = 方向键:右 -D-pad up = 方向键:上 +Custom 1 = 预设1 +Custom 10 = 预设10 +Custom 2 = 预设2 +Custom 3 = 预设3 +Custom 4 = 预设4 +Custom 5 = 预设5 +Custom 6 = 预设6 +Custom 7 = 预设7 +Custom 8 = 预设8 +Custom 9 = 预设9 +D-pad down = 方向键:下 +D-pad left = 方向键:左 +D-pad right = 方向键:右 +D-pad up = 方向键:上 DevMenu = 开发者菜单 -Display Landscape = 横屏显示 -Display Landscape Reversed = 横屏反转显示 -Display Portrait = 竖屏显示 -Display Portrait Reversed = 竖屏翻反转显示 -Double tap button = 双击时按键 -Down = 方向键:下 +Display Landscape = 横向显示 +Display Landscape Reversed = 横向反转显示 +Display Portrait = 纵向显示 +Display Portrait Reversed = 纵向反转显示 +Double tap button = 双击键 +Down = 方向键:下 Dpad = 方向键 -Exit App = 关闭模拟器 Frame Advance = 逐帧播放 Hold = 锁键 Home = Home键 L = L -Left = 方向键:左 +Left = 方向键:左 Load State = 载入即时存档 Mute toggle = 静音 Next Slot = 下个即时存档槽 @@ -773,18 +676,17 @@ None = 无 Note = 音效键♪ OpenChat = 打开聊天 Pause = 暂停界面 -Previous Slot = 上个即时存档槽 R = R RapidFire = 连发键 Record = 录制 Remote hold = 锁键(遥控器) Rewind = 读取倒带 -Right = 方向键:右 +Right = 方向键:右 Right Analog Stick = 右摇杆 -RightAn.Down = 右摇杆:下 -RightAn.Left = 右摇杆:左 -RightAn.Right = 右摇杆:右 -RightAn.Up = 右摇杆:上 +RightAn.Down = 右摇杆:下 +RightAn.Left = 右摇杆:左 +RightAn.Right = 右摇杆:右 +RightAn.Up = 右摇杆:上 Rotate Analog (CCW) = 旋转摇杆(逆时针) Rotate Analog (CW) = 旋转摇杆(顺时针) Save State = 保存即时存档 @@ -803,64 +705,67 @@ Texture Dumping = 纹理转储 Texture Replacement = 纹理替换 Toggle Fullscreen = 切换全屏 Toggle mode = 切换模式 -Toggle WLAN = 切换WLAN Triangle = 三角键 Fast-forward = 加速(长按) -Up = 方向键:上 +Up = 方向键:上 Vol + = 音量+键 Vol - = 音量-键 Wlan = WLAN键 [MemStick] Already contains PSP data = 已含有PSP数据 -Cancelled - try again = 已取消 - 请再次重试 Create or Choose a PSP folder = 创建或者选择PSP文件夹 Current = 目前 DataCanBeShared = 数据可以在普通版/黄金版之间共用 DataCannotBeShared = 数据无法在普通版/黄金版之间共用! -DataWillBeLostOnUninstall = 警告!卸载PPSSPP后全部数据将丢失! -DataWillStay = 卸载PPSSPP时数据能保留。 +DataWillBeLostOnUninstall = 警告!卸载PPSSPP将丢失全部数据! +DataWillStay = 卸载PPSSPP时会保留数据。 Done! = 完成! EasyUSBAccess = USB连接更简单 -Failed to move some files! = 无法移动部分文件! +Failed to move some files! = 无法移动部分文件! Failed to save config = 无法保存配置! Free space = 可用空间 Manually specify PSP folder = 手动指定PSP文件夹 -MemoryStickDescription = 选择PSP文件的存放位置 (记忆棒) +MemoryStickDescription = 选择PSP文件的存放位置(记忆棒) Move Data = 移动PSP数据 Selected PSP Data Folder = 选择PSP数据文件夹 No data will be changed = 数据不会更改 PPSSPP will restart after the change = 完成设置后会重启PPSSPP Skip for now = 暂时跳过 -Starting move... = 开始移动… +Starting move... = 开始移动... That folder doesn't work as a memstick folder. = 您选择的文件夹无法作为记忆棒路径。 USBAccessThrough = USB连接时请打开Android/data/org.ppsspp.ppsspp/files USBAccessThroughGold = USB连接时请打开Android/data/org.ppsspp.ppssppgold/files Use App Private Data = 在APP内置的路径中保存 Use PSP folder at root of storage = 在手机路径中保存PSP文件 -Welcome to PPSSPP! = 欢迎使用PPSSPP! -WhatsThis = 这个设置有什么用? +Welcome to PPSSPP! = 欢迎使用PPSSPP! +WhatsThis = 这个设置有什么用? [Networking] AdHoc Server = Ad Hoc服务器 -AdhocServer Failed to Bind Port = 无法绑定Ad Hoc服务器端口 -AM: Data from Unknown Port = AM:来自未知端口的数据 +AdhocServer Failed to Bind Port = 无法绑定Adhoc服务器端口 +AM: Data from Unknown Port = AM:来自未知端口的数据 Auto = 自动 +Bottom Center = 正下方 +Bottom Left = 左下方 +Bottom Right = 右下方 +Center Left = 左中间 +Center Right = 右中间 Change Mac Address = 更改MAC地址 -Change proAdhocServer Address = 更改PRO Ad Hoc服务器IP地址 +Change proAdhocServer Address = 更改 PRO Ad Hoc 服务器IP地址 ChangeMacSaveConfirm = 确认随机生成新的MAC地址? -ChangeMacSaveWarning = 部分游戏会在载入存档时会验证MAC地址,\n可能会破坏存档,建议备份您的存档。 +ChangeMacSaveWarning = 一些游戏会在载入存档时会验证MAC地址,这可能会破坏原有的存档。 Chat = 聊天 Chat Button Position = 聊天按钮位置 -Chat Here = 在此处聊天 +Chat Here = 在这里聊天 Chat message = 聊天消息 Chat Screen Position = 聊天窗口位置 -Disconnected from AdhocServer = 与Ad Hoc服务器断开连接 +Disconnected from AdhocServer = 与Adhoc服务器断开连接 DNS Error Resolving = DNS解析错误 -Enable built-in PRO Adhoc Server = 启用内置PRO Ad Hoc服务器 +Enable built-in PRO Adhoc Server = 启用内置 PRO Ad Hoc 服务器 Enable network chat = 启用聊天 Enable networking = 启用联网/无线网络 -Enable UPnP = 启用UPnP (需要几秒钟检测) +Enable UPnP = 启用UPnP(需要几秒钟来检测) EnableQuickChat = 启用快速聊天 Enter a new PSP nickname = 输入新的PSP昵称 Enter Quick Chat 1 = 输入快速聊天1 @@ -872,15 +777,16 @@ Error = 错误 Failed to Bind Localhost IP = 无法绑定本地主机IP Failed to Bind Port = 无法绑定端口 Failed to connect to Adhoc Server = 无法连接Adhoc服务器 -Forced First Connect = 强制首次连接 (更快的连接) -GM: Data from Unknown Port = GM:来自未知端口的数据 +Forced First Connect = 强制首次连接(更快的连接) +GM: Data from Unknown Port = GM:来自未知端口的数据 Hostname = 主机名 Invalid IP or hostname = IP或主机名是无效的 -Minimum Timeout = 最小超时 (以毫秒为单位,0=默认值) -Misc = 其他 (默认=兼容PSP) +Minimum Timeout = 最小超时(以毫秒为单位,0=默认值) +Misc = 其他(默认=兼容PSP) Network Initialized = 网络已初始化 +None = 无 Please change your Port Offset = 请更改您的端口偏移 -Port offset = 端口偏移 (0 = 兼容PSP) +Port offset = 端口偏移(0 = 兼容PSP) Open PPSSPP Multiplayer Wiki Page = PPSSPP多人联机Wiki页面 MultiplayerHowToURL = https://github.com/hrydgard/ppsspp/wiki/如何使用PPSSPP多人联机游戏 proAdhocServer Address: = 服务器地址(localhost=模拟器双开联机) @@ -890,34 +796,19 @@ Quick Chat 3 = 快速聊天3 Quick Chat 4 = 快速聊天4 Quick Chat 5 = 快速聊天5 QuickChat = 快速聊天 -Randomize = 随机生成 Send = 发送 Send Discord Presence information = 发送 Discord 在线状态 -Unable to find UPnP device = 未找到UPnP设备 -UPnP (port-forwarding) = UPnP (端口转发) +Top Center = 正上方 +Top Left = 左上方 +Top Right = 右上方 +Unable to find UPnP device = 找不到UPnP设备 +UPnP (port-forwarding) = UPnP(端口转发) UPnP need to be reinitialized = UPnP 需要重新初始化 -UPnP use original port = UPnP 使用原始端口 (启用=兼容PSP) -UseOriginalPort Tip = 可能不适合某些游戏或设备,详见百科页面 -Validating address... = 正在验证地址… +UPnP use original port = UPnP 使用原始端口(启用=兼容PSP) +UseOriginalPort Tip = 可能不适合某些游戏或设备,详见Wiki +Validating address... = 正在验证地址... WLAN Channel = WLAN信道 -You're in Offline Mode, go to lobby or online hall = 您现在处于离线模式,请进入房间或在线大厅 - -[PSPSettings] -Auto = 自动 -Chinese (simplified) = 简体中文 -Chinese (traditional) = 繁体中文 -Dutch = 荷兰语 -English = 英语 -French = 法语 -Game language = 游戏语言 -German = 德语 -Italian = 意大利语 -Japanese = 日语 -Korean = 韩语 -Games often don't support all languages = 仅较少游戏支持切换语言 -Portuguese = 葡萄牙语 -Russian = 俄语 -Spanish = 西班牙语 +You're in Offline Mode, go to lobby or online hall = 您现在处于离线模式, 请进入房间或在线大厅 [Pause] Cheats = 金手指 @@ -935,24 +826,22 @@ Undo last load = 撤销加载 Undo last save = 撤销保存 [PostShaders] -(duplicated setting, previous slider will be used) = (重复,将使用上面的设置值) -4xHqGLSL = 4xHQ像素风缩放 -5xBR = 5xBR像素风缩放 -5xBR-lv2 = 5xBR-lv2像素风缩放 +(duplicated setting, previous slider will be used) = (重复, 将使用上面的设置值) +4xHqGLSL = 4xHQ 像素风缩放 +5xBR = 5xBR 像素风缩放 +5xBR-lv2 = 5xBR-lv2 像素风缩放 AAColor = AA-Color Amount = 数量 -Animation speed (0 -> disable) = 动画速度(0=禁用) +Animation speed (0 -> disable) = 动画速度(0->禁用) Aspect = 孔径比例 Black border = 黑色描边 Bloom = 泛光 -BloomNoBlur = 泛光(无模糊) Brightness = 亮度 Cartoon = 卡通 ColorCorrection = 颜色修正 ColorPreservation = 颜色保留 Contrast = 对比度 CRT = CRT 扫描线 -FakeReflections = 假反射效果 FXAA = FXAA(快速近似抗锯齿) Gamma = 伽马值 GreenLevel = 绿色等级 @@ -968,27 +857,26 @@ Saturation = 色彩 Scanlines = 扫描线(CRT) Sharpen = 锐化 SideBySide = 双目渲染 -SSAA(Gauss) = SSAA(超级采样抗锯齿-高斯采样) +SSAA(Gauss) = SSAA(超级采样抗锯齿-高斯) Strength = 强度 Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = 双三插值缩放 UpscaleSpline36 = Spline36缩放 VideoSmoothingAA = 视频平滑抗锯齿 Vignette = 暗角 -MitchellNetravali = Mitchell-Netravali双三插值缩放 -CatmullRom = Catmull-Rom双三插值缩放 +MitchellNetravali = Mitchell-Netravali 双三插值缩放 +CatmullRom = Catmull-Rom 双三插值缩放 [PSPCredits] all the forum mods = 论坛所有的管理员 build server = 编译服务器 Buy Gold = 购买黄金版 -check = 同时请浏览我们的海豚Dolphin模拟器,最好用的Wii/NGC模拟器 -CheckOutPPSSPP = 浏览我们的PPSSPP,一款超级棒的PSP模拟器:https://www.ppsspp.org/ -contributors = 贡献者: +check = 同时请查阅海豚模拟器, 最好用的Wii/NGC模拟器 +CheckOutPPSSPP = 查阅PPSSPP, 一款超级棒的PSP 模拟器:https://www.ppsspp.org/ +contributors = 参与者: created = 作者: Discord = Discord -info1 = PPSSPP只用于教学研究,不应被用于商业用途。 +info1 = PPSSPP只用于教学研究, 不应被用于商业用途。 info2 = 请确认您持有游戏镜像的正版拷贝: info3 = 这可以是您购买了游戏的UMD光盘, info4 = 或者通过PSP在PSN商店购买的数字版游戏。 @@ -1000,22 +888,22 @@ PPSSPP Forums = PPSSPP官方论坛 Privacy Policy = 隐私政策 Share PPSSPP = 分享PPSSPP specialthanks = 鸣谢: -specialthanksKeithGalocy = 的硬件工作和指导,他来自NVIDIA +specialthanksKeithGalocy = 的硬件工作和指导, 他来自NVIDIA specialthanksMaxim = 的出色的Atrac3+解码器工作 testing = 负责测试 -this translation by = 翻译人员: +this translation by = 界面汉化: title = 效率高、移植性好的PSP模拟器 tools = 使用的第三方开源库: -# 在这里添加PPSSPP界面汉化人员的名单。 -# 1-6这6行用于添加汉化人员名单。 -# 不需要的行留空,一行4个人这样的排版看起来比较合适。 -translators1 = sum2012、kaienfr、raven02、aquanull -translators2 = xiwo4525、wuspring、zzq920817、W-MS -translators3 = xzapk、Arthur200000、Playhi、PeaceShi -translators4 = Nargacuga、driver1998、xujibbs、Croden1999 +# 在这里添加PPSSPP界面汉化人员的名单 +# translators1-6这6行用于添加汉化人员名单 for up to 6 lines of translator credits. +# 不需要的行留空,一行4个人这样的排版看起来比较合适. +translators1 = sum2012, kaienfr, raven02, aquanull, xiwo4525 +translators2 = wuspring, zzq920817, W-MS, xzapk, Arthur200000 +translators3 = Playhi, PeaceShi, Nargacuga, driver1998 +translators4 = xujibbs translators5 = translators6 = -Twitter @PPSSPP_emu = 推特 (Twitter) +Twitter @PPSSPP_emu = Twitter website = 请查阅官方网站 written = 使用C++编写以保证速度与移植性 @@ -1028,43 +916,43 @@ Remote Port = 远程端口 Remote Server = 远程服务器 Remote Subdirectory = 远程子路径 RemoteISODesc = 您最近列表中的游戏将被共享 -RemoteISOLoading = 已连接,正在载入游戏列表… -RemoteISOScanning = 扫描中…在您的服务器设备上点击“共享游戏” -RemoteISOScanningTimeout = 扫描中…请检查您防火墙的设置 +RemoteISOLoading = 已连接, 正在载入游戏列表... +RemoteISOScanning = 扫描中...在您的服务器设备上点击"共享游戏" +RemoteISOScanningTimeout = 扫描中...请检查您防火墙的设置 RemoteISOWifi = 说明: 请将设备连接到同一Wi-Fi网络下 -RemoteISOWinFirewall = 警告:Windows防火墙正在阻挡游戏共享 +RemoteISOWinFirewall = 警告: Windows防火墙正在阻挡游戏共享 Settings = 设置 -Share Games (Server) = 共享游戏 (服务器) +Share Games (Server) = 共享游戏(服务器) Share on PPSSPP startup = PPSSPP启动时共享 Stop Sharing = 停止共享 -Stopping.. = 正在停止… +Stopping.. = 正在停止... [Reporting] Bad = 很差 -FeedbackCRCCalculating = 游戏CRC:计算中… -FeedbackCRCValue = 游戏CRC:%1 +FeedbackCRCCalculating = 游戏CRC: 计算中... +FeedbackCRCValue = 游戏CRC: %1 FeedbackDelayInfo = 您的数据正在后台提交。 FeedbackDesc = 这款游戏兼容性怎样?请告诉我们和社区! -FeedbackDisabled = 需要启用“向服务器报告兼容性问题”选项 +FeedbackDisabled = 需要启用"向服务器报告兼容性问题"选项 FeedbackIncludeCRC = 注意:将使用少部分电量发送CRC校验码 FeedbackIncludeScreen = 同时发送一张截图 FeedbackSubmitDone = 您的数据已提交。 -FeedbackSubmitFail = 无法向服务器提交数据,请尝试更新PPSSPP。 -FeedbackThanks = 感谢您的反馈! +FeedbackSubmitFail = 无法向服务器提交数据。尝试更新PPSSPP。 +FeedbackThanks = 感谢您的反馈! Gameplay = 游戏过程正常 Graphics = 画面无错误 Great = 非常好 In-game = 能进游戏 -In-game Description = 游戏能够运行,但问题太多,不能愉快通关 -Menu/Intro = 仅在主界面/开头动画 -Menu/Intro Description = 看到个菜单,但无法正常游玩 -Nothing = 无法运行 -Nothing Description = 完全无法游玩,启动直接黑屏或者崩溃 +In-game Description = 游戏是能够运行,但BUG太多,不能开心通关 +Menu/Intro = 卡主界面 +Menu/Intro Description = 看到个菜单,然后没了 +Nothing = 啥也没有 +Nothing Description = 直接黑屏或者崩溃 OK = 还行 Open Browser = 打开反馈网站 Overall = 总体概括 Perfect = 非常完美 -Perfect Description = 游戏全程完美模拟——太赞了! +Perfect Description = 游戏全程完美模拟——太赞了! Plays = 基本可玩 Plays Description =游戏大部分都可玩,偶尔有一些小错误但不影响 ReportButton = 报告反馈 @@ -1074,41 +962,41 @@ Submit Feedback = 提交反馈 SuggestionConfig = 请参阅网站上的报告以了解最佳设置。 SuggestionCPUSpeed0 = 请禁用修改CPU速度设置。 SuggestionDowngrade = 请降级到较旧的PPSSPP版本 (请报告这个错误)。 -SuggestionsFound = 其他用户报告了更佳的结果,点击“查看所有反馈”了解更多详情。 +SuggestionsFound = 其他用户报告了更佳的结果。点击"查看所有反馈"了解更多详情。 SuggestionsNone = 其他用户也不能运行该游戏。 -SuggestionsWaiting = 提交中, 并检查其他用户的反馈… +SuggestionsWaiting = 提交中, 并检查其他用户的反馈... SuggestionUpgrade = 请更新到较新版本的PPSSPP SuggestionVerifyDisc = 请检查您的ISO是否为光盘的正确拷贝。 -Unselected Overall Description = 这款游戏各方面表现怎样? +Unselected Overall Description = 这款游戏各方面表现怎样? View Feedback = 查看所有反馈 [Savedata] Date = 日期 Filename = 文件名 No screenshot = 没有截图 -None yet. Things will appear here after you save. = 暂无,在你保存后将会在此出现存档。 -Nothing matching '%1' was found. = 没有找到关于“%1”的结果 +None yet. Things will appear here after you save. = 暂无。在你保存后将会在此出现存档。 +Nothing matching '%1' was found. = 没有找到关于"%1"的结果 Save Data = 保存的存档 Save States = 保存的即时存档 Savedata Manager = 存档数据管理器 -Showing matches for '%1'. = 找到符合“%1”的搜索结果。 +Showing matches for '%1'. = 找到符合"%1"的搜索结果。 Size = 大小 [Screen] Cardboard VR OFF = Cardboard VR关闭 -Chainfire3DWarning = 警告:检测到Chainfire3D (3D神器),可能会导致问题。 +Chainfire3DWarning = 警告:检测到Chainfire3D(3D 神器), 可能会导致问题。 Failed to load state = 无法载入即时存档 Failed to save state = 无法保存即时存档 -fixed = 速度:预设1 -GLToolsWarning = 警告:检测到GLTools,可能会导致问题。 +fixed = 速度:备选 +GLToolsWarning = 警告:检测到GLTools,可能会导致问题。 In menu = 在菜单中 -Load savestate failed = 无法读取即时存档 -Loaded State = 已读取即时存档 -Loaded. Game may refuse to save over different savedata. = 已读取,游戏可能无法保存在别的存档中。 -Loaded. Game may refuse to save over newer savedata. = 已读取,游戏可能无法保存在进度提前的存档。 -Loaded. Save in game, restart, and load for less bugs. = 已读取,请在游戏中存档并重启, 再次读档以减少bug。 -LoadStateDoesntExist = 即时存档读取失败:存档不存在 -LoadStateWrongVersion = 即时存档读取失败:存档是旧版本PPSSPP的 +Load savestate failed = 无法载入即时存档 +Loaded State = 已载入即时存档 +Loaded. Game may refuse to save over different savedata. = 已载入。游戏可能无法保存在别的存档中。 +Loaded. Game may refuse to save over newer savedata. = 已载入。游戏可能无法保存在进度提前的存档。 +Loaded. Save in game, restart, and load for less bugs. = 已载入。请在游戏中存档, 重开, 再次读档以减少bug。 +LoadStateDoesntExist = 即时存档载入失败:存档不存在 +LoadStateWrongVersion = 即时存档载入失败:存档是旧版本PPSSPP的 norewind = 没有可用的倒带自动即时存档。 Playing = 游戏中 PressESC = 按下ESC键打开暂停菜单。 @@ -1118,9 +1006,9 @@ Save State Failed = 无法保存即时存档 Saved State = 已保存即时存档 saveNewTextures_false = 纹理转储已停止。 saveNewTextures_true = 开始转储新纹理。 -SpeedCustom2 = 速度:预设2 +SpeedCustom2 = 速度:备选2 standard = 速度:标准 -State load undone = 撤销即时存档读取 +State load undone = 撤销即时存档载入 Untitled PSP game = 无标题的PSP游戏 [Store] @@ -1128,31 +1016,31 @@ Already Installed = 已安装 Connection Error = 网络错误 Install = 安装 Launch Game = 开始游戏 -Loading... = 载入中… +Loading... = 载入中... MB = MB Size = 大小 Uninstall = 卸载 [SysInfo] %0.2f Hz = %0.2f Hz -%d (%d per core, %d cores) = %d (每核心%d线程,共%d核心) +%d (%d per core, %d cores) = %d (每核心%d线程, %d核心) %d bytes = %d字节 %d Hz = %d Hz (none detected) = (未检测到) 3D API = 3D API -ABI = 架构 +ABI = ABI API Version = API版本 Audio Information = 音频信息 -Board = 主板型号 +Board = 主板 Build Config = 编译配置 Build Configuration = 编译配置 Built by = 编译者 Compressed texture formats = 压缩纹理格式 Core Context = 核心上下文 Cores = 核心数 -CPU Extensions = CPU扩展 -CPU Information = CPU信息 -CPU Name = CPU名称 +CPU Extensions = CPU 扩展 +CPU Information = CPU 信息 +CPU Name = CPU 名称 D3DCompiler Version = D3DCompiler版本 Debug = 调试 Debugger Present = 调试器已连接 @@ -1161,7 +1049,7 @@ Device Info = 设备信息 Directories = 目录 Display Color Formats = 显示颜色格式 Display Information = 显示信息 -DPI = 像素密度 +DPI = DPI Driver Version = 驱动版本 EGL Extensions = EGL扩展 Frames per buffer = 每缓冲区帧数 @@ -1169,40 +1057,37 @@ GPU Flags = GPU特性 GPU Information = GPU信息 High precision float range = 高精度浮点范围 High precision int range = 高精度整数范围 -Icon cache = 图标缓存 JIT available = JIT可用 Lang/Region = 语言/区域 Memory Page Size = 内存页大小 -Native resolution = 原生分辨率 -OGL Extensions = OGL扩展 +Native Resolution = 原生分辨率 +OGL Extensions = OGL 扩展 OpenGL ES 2.0 Extensions = OpenGL ES 2.0扩展 OpenGL ES 3.0 Extensions = OpenGL ES 3.0扩展 OpenGL Extensions = OpenGL扩展 Optimal frames per buffer = 最佳每缓冲区帧数 Optimal sample rate = 最佳采样率 OS Information = OS信息 -Pixel resolution = 像素分辨率 PPSSPP build = PPSSPP编译版本 -Present modes = 帧呈现模式 Refresh rate = 刷新率 Release = 发布版 RW/RX exclusive = RW/RX独占 Sample rate = 采样率 Shading Language = 着色语言 Storage = 存储 -Sustained perf mode = 持续性能模式 +Sustained perf mode = 持久性能模式 System Information = 系统信息 System Name = 系统名称 System Version = 系统版本 Threads = 线程数 -UI resolution = UI分辨率 +UI Resolution = UI 分辨率 Vendor = 型号 -Vendor (detected) = 品牌 +Vendor (detected) = 型号(检测到的) Version Information = 版本信息 -Vulkan Extensions = Vulkan扩展 -Vulkan Features = Vulkan特性 -Driver bugs = 驱动检测 -No GPU driver bugs detected = GPU驱动运行正常 +Vulkan Extensions = Vulkan 扩展 +Vulkan Features = Vulkan 特性 +Driver bugs = 驱动错误 +No GPU driver bugs detected = 未发现GPU驱动错误 [System] (broken) = (损坏) @@ -1213,24 +1098,23 @@ Auto Load Savestate = 自动载入即时存档 AVI Dump started. = AVI转储开始 AVI Dump stopped. = AVI转储停止 Cache ISO in RAM = 在内存中缓存完整ISO -Change CPU Clock = 修改PSP的CPU频率 (不稳定) -RetroAchievements = RetroAchievements +Change CPU Clock = 修改PSP的CPU频率(不稳定) Rewind Snapshot Interval = 倒带快照间隔 Color Tint = 颜色色调 Color Saturation = 饱和度 -Error: load undo state is from a different game = 错误:撤回的即时存档是来自不同游戏的 -Failed to load state for load undo. Error in the file system. = 无法撤回加载即时存档,文件系统有错误。 +Error: load undo state is from a different game = 错误:撤回的即时存档是来自不同游戏的 +Failed to load state for load undo. Error in the file system. = 无法撤回加载即时存档。文件系统有错误。 Floating symbols = 飘动按键 Game crashed = 游戏发生崩溃。 Language = 语言设置 Memory Stick folder = 记忆棒目录 Memory Stick size = 记忆棒大小 Change Nickname = 修改昵称 -ChangingMemstickPath = 游戏存档、即时存档及其它数据不会复制到新路径。\n\n确定要修改记忆棒文件夹吗? +ChangingMemstickPath = 游戏存档、即时存档及其它数据不会复制到新路径。\n\n确定要修改记忆棒文件夹吗? ChangingMemstickPathInvalid = 目标路径不能用于保存记忆棒数据。 Cheats = 作弊设置 Clear Recent = 清除最近的游戏 -Clear Recent Games List = 清除“最近的游戏”内容 +Clear Recent Games List = 清除"最近的游戏"内容 Clear UI background = 清除壁纸 Confirmation Button = 确认按钮 Date Format = 日期格式 @@ -1239,23 +1123,23 @@ DDMMYYYY = 日/月/年 Decrease size = 减小尺寸 Developer Tools = 开发者工具 Display Extra Info = 显示额外信息 -Display Games on a grid = 用图标显示“游戏” -Display Homebrew on a grid = 用图标显示“自制与试玩” -Display Recent on a grid = 用图标显示“最近的游戏” -Dynarec (JIT) = 动态重编译 (JIT) +Display Games on a grid = "游戏"用图标显示 +Display Homebrew on a grid = "自制与试玩"用图标显示 +Display Recent on a grid = "最近的游戏"用图标显示 +Dynarec (JIT) = 动态重编译(JIT) Emulation = 模拟设置 Enable Cheats = 开启金手指 Enable Compatibility Server Reports = 向服务器报告兼容性问题 -Failed to load state. Error in the file system. = 无法载入即时存档,文件系统出错。 -Failed to save state. Error in the file system. = 无法保存即时存档,文件系统出错。 -Fast (lag on slow storage) = 快速模式 (存储低速时有延迟) -Fast Memory = 快速内存 (不稳定) -Force real clock sync (slower, less lag) = 强制同步实际时钟 (降低延迟,很慢) +Failed to load state. Error in the file system. = 无法载入即时存档。文件系统出错。 +Failed to save state. Error in the file system. = 无法保存即时存档。文件系统出错。 +Fast (lag on slow storage) = 快速模式(存储低速时有延迟) +Fast Memory = 快速内存(不稳定) +Force real clock sync (slower, less lag) = 强制同步实际时钟(降低延迟,很慢) Games list settings = 游戏列表设置 General = 常规设置 Grid icon size = 图标方格尺寸 Help the PPSSPP team = 帮助PPSSPP团队 -Host (bugs, less lag) = 主机模式 (有错误,较少延迟) +Host (bugs, less lag) = 主机模式(有错误,较少延迟) Ignore bad memory accesses = 忽略错误内存访问 Increase size = 增大尺寸 Interpreter = 解释器 @@ -1263,7 +1147,7 @@ IO timing method = I/O计时方法 IR Interpreter = IR解释器 Memory Stick Folder = 记忆棒文件夹 Memory Stick inserted = 插入记忆棒 -MHz, 0:default = MHz, 默认设置为0 +MHz, 0:default = MHz, 默认为0 MMDDYYYY = 月/日/年 Moving background = 动态壁纸 Newest Save = 最新的即时存档 @@ -1271,46 +1155,45 @@ No animation = 静态壁纸 Not a PSP game = 这不是一个PSP游戏 Off = 关闭 Oldest Save = 最旧的即时存档 -Path does not exist! = 路径不存在! -PSP Memory Stick = PSP存储 -PSP Model = PSP机型 -PSP Settings = PSP设置 +Path does not exist! = 路径不存在! +PSP Memory Stick = PSP 储存 +PSP Model = PSP 机型 +PSP Settings = PSP 设置 PSP-1000 = PSP-1000 PSP-2000/3000 = PSP-2000/3000 Recent games = 最近的游戏 Record Audio = 录制音频 Record Display = 录制视频 Reset Recording on Save/Load State = 保存/载入存档时重置录制 -Restore Default Settings = 恢复默认PPSSPP设置 +Restore Default Settings = 恢复默认 PPSSPP 设置 Rewind Snapshot Interval = 倒带快照频率 -Save path in installed.txt = 记忆棒目录使用“installed.txt” -Save path in My Documents = 记忆棒目录使用“我的文档” +Save path in installed.txt = 记忆棒目录使用"installed.txt" +Save path in My Documents = 记忆棒目录使用"我的文档" Savestate Slot = 即时存档插槽 Savestate slot backups = 即时存档备份 -Screenshots as PNG = 将截图保存为PNG格式 +Screenshots as PNG = 将截图保存为 PNG 格式 Set Memory Stick folder = 设置记忆棒文件夹 -Set UI background... = 设置壁纸… +Set UI background... = 设置壁纸... Show ID = 游戏ID Show region flag = 地区标识 -Simulate UMD delays = 模拟UMD延迟 -Simulate UMD slow reading speed = 模拟UMD慢速读取 +Simulate UMD delays = 模拟 UMD 延迟 Slot 1 = 插槽1 Slot 2 = 插槽2 Slot 3 = 插槽3 Slot 4 = 插槽4 Slot 5 = 插槽5 Storage full = 存储空间已满 -Sustained performance mode = 持续性能模式 (使长时间运行的应用运行更流畅) +Sustained performance mode = 持久性能模式(使长时间运行的应用运行更流畅) Time Format = 时间格式 Transparent UI background = 透明游戏背景 UI = 用户界面 UI background animation = 背景动画 UI Sound = 按键音效 -undo %c = 备份%c -USB = USB路径 -Use Lossless Video Codec (FFV1) = 使用无损视频编码器 (FFV1) +undo %c = 备份 %c +USB = USB +Use Lossless Video Codec (FFV1) = 使用无损视频编码器(FFV1) Use O to confirm = 使用按键O -Use output buffer (with overlay) for recording = 录制输出缓冲区 (包含叠加信息) +Use output buffer (with overlay) for recording = 录制使用输出缓冲(包括叠加信息) Use system native keyboard = 使用系统原生键盘 Use X to confirm = 使用按键X VersionCheck = 检查PPSSPP新版本 @@ -1340,39 +1223,40 @@ Default = 默认 %1 text field = %1文本框 Choices: = 选择: List: = 列表: -Progress: %1% = 进度:%1% +Progress: %1% = 进度: %1% Screen representation = 屏幕显示 [Upgrade] Details = 详细内容 Dismiss = 忽略 Download = 下载 -New version of PPSSPP available = 检测到新版本的PPSSPP +New version of PPSSPP available = 有新版本PPSSPP可用 [Search] -Filtering settings by '%1' = 查找“%1”的结果 +Filtering settings by '%1' = 查找"%1"的结果 Find settings = 查找选项 Filter = 搜索 Clear filter = 取消筛选 -No settings matched '%1' = 没有找到选项“%1” +No settings matched '%1' = 没有找到选项"%1" Search term = 搜索关键词 [VR] +% of native FoV = 原生视角的% 6DoF movement = 6自由度移动 Camera type = 相机类型 -Distance to 2D menus and scenes = 2D菜单和场景的距离 -Distance to 3D scenes when VR disabled = 3D场景的距离 (VR关闭时) +Distance to 2D menus and scenes = 2D 菜单和场景的距离 Experts only = 专家模式 +Field of view scale = 视角比例 Force 72Hz update = 强制72Hz刷新 -Game camera rotation step per frame = 游戏视角每帧灵敏度 -Game camera uses rotation smoothing = 游戏视角平滑转动 +Game camera rotation step per frame = Game camera rotation step per frame +Game camera uses rotation smoothing = Game camera uses rotation smoothing Heads-up display detection = HUD检测 Heads-up display scale = HUD比例 -Manual switching between flat screen and VR using SCREEN key = 使用SCREEN键切换荧幕模式和VR模式 -Map controller movements to keys = 映射控制器移动到键位 -Map HMD rotations on keys instead of VR camera = 映射头显转动到键位,而不是VR视角 +Manual switching between flat screen and VR using SCREEN key = Manual switching between flat screen and VR using SCREEN key +Map controller movements to keys = 映射控制器移动到关键点 +Map HMD rotations on keys instead of VR camera = Map HMD rotations on keys instead of VR camera Motion needed to generate action = 产生动作的感应值 -Stereoscopic vision (Experimental) = 立体视觉 (实验性) +Stereoscopic vision (Experimental) = 立体视觉(实验性) Virtual reality = 虚拟现实 -VR camera = VR视角 -VR controllers = VR控制器 +VR camera = VR 相机 +VR controllers = VR 控制器 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index e5abafed0..309bdb169 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1,66 +1,7 @@ -[Achievements] -%1: Attempt failed = %1:嘗試失敗 -%1: Attempt started = %1:嘗試開始 -%1 achievements, %2 points = %1 個成就,%2 個點數 -Account = 帳戶 -Achievement progress = 成就進度 -Achievement unlocked = 成就已解鎖 -Achievements = 成就 -Achievements are disabled = 成就已停用 -Achievements enabled = 成就已啟用 -Achievements with active challenges = Achievements with active challenges -Allow Save State in Hardcore Mode (but not Load State) = Allow Save State in Hardcore Mode (but not Load State) -Almost completed achievements = Almost completed achievements -Around me = 我的位置 -Can't log in to RetroAchievements right now = 目前無法登入至 RetroAchievements -Challenge indicator = 挑戰指示器 -Contacting RetroAchievements server... = 正在聯絡 RetroAchievements 伺服器… -Customize = 自訂 -Earned = 您已經取得 %1/%2 個成就,以及 %3/%4 個點數 -Encore Mode = Encore 模式 -Failed logging in to RetroAchievements = 無法登入至 RetroAchievements -Failed to connect to RetroAchievements. Achievements will not unlock. = Failed to connect to RetroAchievements. Achievements will not unlock. -Failed to identify game. Achievements will not unlock. = Failed to identify game. Achievements will not unlock. -Hardcore Mode (no savestates) = 挑戰模式 (無存檔) -Hardcore Mode = 挑戰模式 -How to use RetroAchievements = 如何使用 RetroAchievements -In Encore mode - listings may be wrong below = 在 Encore 模式中 - 下方的清單可能有誤 -Leaderboard attempt started or failed = 排行榜嘗試已經開始或失敗 -Leaderboard result submitted = 排行榜結果已提交 -Leaderboard score submission = 排行榜分數提交 -Leaderboard submission is enabled = 排行榜提交已啟用 -Leaderboard tracker = 排行榜追蹤器 -Leaderboards = 排行榜 -Links = 連結 -Locked achievements = 已鎖定的成就 -Log bad memory accesses = 記憶體存取記錄錯誤 -Mastered %1 = 已達成 %1 -Notifications = 通知 -Recently unlocked achievements = Recently unlocked achievements -Reconnected to RetroAchievements. = Reconnected to RetroAchievements. -Register on www.retroachievements.org = 在 www.retroachievements.org 上註冊 -RetroAchievements are not available for this game = RetroAchievements 無法在這個遊戲中使用 -RetroAchievements website = RetroAchievements 網站 -Rich Presence = Rich Presence -Save state loaded without achievement data = 儲存存檔 (無成就資料) 已載入 -Save states not available in Hardcore Mode = 儲存存檔無法在挑戰模式中使用 -Sound Effects = 音效 -Statistics = 統計資料 -Submitted %1 for %2 = 已為 %2 提交 %1 -Syncing achievements data... = 正在同步成就資料… -Test Mode = 測試模式 -This feature is not available in Hardcore Mode = 此功能無法在挑戰模式中使用 -This game has no achievements = 這個遊戲沒有成就 -Top players = 頂級玩家 -Unlocked achievements = 已解鎖的成就 -Unofficial achievements = 非官方成就 -Unsupported achievements = Unsupported achievements - [Audio] Alternate speed volume = 替代速度音量 Audio backend = 音訊後端 (需要重新啟動) Audio Error = 音訊錯誤 -Audio file format not supported. Must be WAV. = Audio file format not supported. Must be WAV. AudioBufferingForBluetooth = 藍牙友好緩衝區 (更慢) Auto = 自動 Device = 裝置 @@ -95,7 +36,6 @@ Calibrate Analog Stick = 校正類比搖桿 Calibrate = 校正 Calibrated = 已校正 Calibration = 校正 -Circular low end radius = 圓形低端半徑 Circular stick input = 圓形搖桿輸入 Classic = 傳統 Confine Mouse = 在視窗/顯示區域內截獲滑鼠 @@ -108,10 +48,8 @@ Deadzone radius = 死區半徑 Disable D-Pad diagonals (4-way touch) = 停用方向鍵對角線 (四向觸控) Disable diagonal input = 停用對角線輸入 Double tap = 點兩下 -Enable analog stick gesture = Enable analog stick gesture Enable gesture control = 啟用手勢控制 Enable standard shortcut keys = 啟用標準快速鍵 -frames = 影格 Gesture = 手勢 Gesture mapping = 手勢對應 Glowing borders = 發光框線 @@ -140,7 +78,6 @@ OnScreen = 螢幕觸控控制 Portrait = 直向 Portrait Reversed = 直向反轉 PSP Action Buttons = PSP 動作按鈕 -Rapid fire interval = 快速開火間隔 Raw input = 原始輸入 Reset to defaults = 重設為預設值 Screen Rotation = 螢幕旋轉 @@ -148,7 +85,6 @@ Sensitivity = 敏感度 Sensitivity (scale) = 敏感度 (比例) Shape = 圖形 Show Touch Pause Menu Button = 顯示暫停選單按鈕 -Sticky D-Pad (easier sweeping movements) = Sticky D-Pad (easier sweeping movements) Swipe = 滑動 Swipe sensitivity = 滑動敏感度 Swipe smoothing = 滑動平滑度 @@ -230,7 +166,6 @@ Log Console = 記錄主控台(&L) Memory View... = 記憶體檢視(&V)… More Settings... = 更多設定(&M)… Nearest = 鄰近取樣(&N) -Recent = 最近(&R) Skip Buffer Effects = 跳過緩衝區效果(&S) Off = 關閉(&O) Open Chat = 開啟聊天 @@ -269,6 +204,7 @@ Texture Filtering = 紋理過濾(&X) Texture Scaling = 紋理縮放(&T) Use Lossless Video Codec (FFV1) = 使用不失真視訊轉碼器 (FFV1)(&U) Use output buffer for video = 為視訊使用輸出緩衝區 +Vertex Cache = 頂點快取(&V) VSync = 垂直同步(&Y) Vulkan = Vulkan Window Size = 視窗大小(&W) @@ -282,11 +218,8 @@ Backspace = 退格鍵 Block address = 區塊位址 By Address = 依位址 Copy savestates to memstick root = 複製存檔至記憶棒根目錄 -Create frame dump = Create frame dump Create/Open textures.ini file for current game = 為目前遊戲建立/開啟 textures.ini 檔案 Current = 目前 -Debug overlay = Debug overlay -Debug stats = Debug stats Dev Tools = 開發工具 DevMenu = 開發選單 Disabled JIT functionality = 停用 JIT 功能 @@ -297,11 +230,8 @@ Enable driver bug workarounds = 啟用驅動程式錯誤因應措施 Enable Logging = 啟用偵錯記錄 Enter address = 輸入位址 FPU = FPU -Fragment = Fragment -Frame timing = Frame timing Framedump tests = 影格傾印測試 Frame Profiler = 影格分析工具 -GPU Allocator Viewer = GPU Allocator Viewer GPU Driver Test = GPU 驅動程式測試 GPU Profile = GPU 設定檔 GPU log profiler = GPU 記錄分析工具 @@ -311,10 +241,8 @@ Log Dropped Frame Statistics = 記錄捨棄影格統計資料 Log Level = 記錄層級 Log View = 記錄檢視 Logging Channels = 記錄通道 -Multi-threaded rendering = 多執行緒轉譯 Next = 下一個 No block = 沒有區塊 -Off = Off Prev = 上一個 Random = 隨機 Replace textures = 取代紋理 @@ -332,12 +260,10 @@ Stats = 統計資料 System Information = 系統資訊 Texture ini file created = 紋理 ini 檔案已建立 Texture Replacement = 紋理取代 -Audio Debug = 音訊偵錯 -Control Debug = 控制偵錯 +Toggle Audio Debug = 切換音訊偵錯開關 +Toggle Control Debug = 切換控制偵錯開關 Toggle Freeze = 切換凍結開關 Touchscreen Test = 觸控式螢幕測試 -Ubershaders = Ubershaders -Vertex = Vertex VFPU = VFPU [Dialog] @@ -345,14 +271,10 @@ VFPU = VFPU * PSP res = * PSP 解析度 Active = 啟用 Back = 返回 -Bottom Center = 正下 -Bottom Left = 左下 -Bottom Right = 右下 Cancel = 取消 Center = 中心 -Center Left = 正左 -Center Right = 正右 -Changing this setting requires PPSSPP to restart. = 變更此設定需要重新啟動 PPSSPP。 +ChangingGPUBackends = 變更 GPU 後端需要重新啟動 PPSSPP,要立即重新啟動嗎? +ChangingInflightFrames = 變更圖形命令緩衝處理需要重新啟動 PPSSPP,要立即重新啟動嗎? Channel: = 頻道: Choose PPSSPP save folder = 選擇 PPSSPP 存檔資料夾 Confirm Overwrite = 要覆寫這個存檔的資料嗎? @@ -372,46 +294,33 @@ DeleteConfirmGameConfig = 您確定要刪除這個遊戲的全部設定嗎? DeleteFailed = 無法刪除資料 Deleting = 正在刪除\n請稍候… Disable All = 全部停用 -Disabled = 已停用 Dumps = 傾印 Edit = 編輯 Enable All = 全部啟用 -Enabled = 已啟用 Enter = 輸入 -Failed to connect to server, check your internet connection. = 無法連線至伺服器,請檢查您的網際網路連線。 -Failed to log in, check your username and password. = 無法登入,請檢查您的使用者名稱和密碼。 Filter = 篩選器 Finish = 完成 GE Frame Dumps = GE 影格傾印 Grid = 格狀 Inactive = 未啟用 -Installing... = Installing... InternalError = 發生內部錯誤 -Links = Links Load = 載入 Load completed = 載入完成 Loading = 正在載入\n請稍候… LoadingFailed = 無法載入資料 -Log in = 登入 -Log out = 登出 -Logged in! = 已登入! -Logging in... = 正在登入… Move = 移動 Move Down = 下移 Move Up = 上移 Network Connection = 網路連線 NEW DATA = 新存檔 No = 否 -None = 無 ObtainingIP = 正在取得 IP 位址\n請稍候… OK = 確定 Old savedata detected = 偵測到舊版存檔資料 Options = 選項 -Password = 密碼 Remove = 移除 Reset = 重設 Resize = 調整大小 -Restart = 重新啟動 Retry = 重試 Save = 儲存 Save completed = 儲存完成 @@ -420,7 +329,6 @@ SavingFailed = 無法儲存資料 Search = 搜尋 seconds, 0:off = 秒,0 = 關閉 Select = 選取 -Settings = 設定 Shift = 移位 Skip = 跳過 Snap = 貼齊 @@ -431,11 +339,7 @@ Supported = 支援 There is no data = 沒有資料 Toggle All = 切換全部 Toggle List = 切換清單 -Top Center = 正上 -Top Left = 左上 -Top Right = 右上 Unsupported = 不支援 -Username = 使用者名稱 When you save, it will load on a PSP, but not an older PPSSPP = 在您儲存後,它將會只能在 PSP 上載入,而非舊版 PPSSPP When you save, it will not work on outdated PSP Firmware anymore = 在您儲存後,它將無法在已過期的 PSP 韌體上運作 Yes = 是 @@ -501,23 +405,18 @@ ZIP file detected (Require WINRAR) = 檔案已壓縮 (ZIP)\n請先解壓縮 (嘗 [Game] Asia = 亞州 Calculate CRC = 計算 CRC -Click "Calculate CRC" to verify ISO = Click "Calculate CRC" to verify ISO ConfirmDelete = 刪除 -CRC checksum does not match, bad or modified ISO = CRC checksum does not match, bad or modified ISO Create Game Config = 建立遊戲組態 Create Shortcut = 建立捷徑 Delete Game = 刪除遊戲 Delete Game Config = 刪除遊戲組態 Delete Save Data = 刪除存檔資料 Europe = 歐洲 -File size incorrect, bad or modified ISO = File size incorrect, bad or modified ISO Game = 遊戲 -Game ID unknown - not in the ReDump database = Game ID unknown - not in the ReDump database Game Settings = 遊戲設定 Homebrew = 自製遊戲 Hong Kong = 香港 InstallData = 資料安裝 -ISO OK according to the ReDump project = ISO OK according to the ReDump project Japan = 日本 Korea = 南韓 MB = MB @@ -527,8 +426,6 @@ Remove From Recent = 從「最近遊玩」中移除 SaveData = 儲存資料 Setting Background = 設定背景 Show In Folder = 在資料夾中顯示 -Time Played: %1h %2m %3s = Time Played: %1h %2m %3s -Uncompressed = Uncompressed USA = 美國 Use UI background = 使用 UI 背景 @@ -623,7 +520,6 @@ Must Restart = 您必須重新啟動 PPSSPP 以使這項變更生效 Native device resolution = 原生裝置解析度 Nearest = 鄰近取樣 No buffer = 無緩衝 -Render all frames = Render all frames Show Battery % = 顯示電池百分比 Show Speed = 顯示速度 Skip Buffer Effects = 跳過緩衝區效果 @@ -658,7 +554,6 @@ Stereo rendering = 立體轉譯 Stretch = 延伸 Texture Filter = 紋理濾鏡 Texture Filtering = 紋理濾鏡 -Texture replacement pack activated = 紋理取代套件已啟用 Texture Scaling = 紋理縮放 Texture Shader = 紋理著色器 Turn off Hardware Tessellation - unsupported = 關閉「硬體鑲嵌」:不支援 @@ -669,6 +564,8 @@ Upscale Level = 放大層級 Upscale Type = 放大類型 UpscaleLevel Tip = CPU 負載過重 - 部分縮放可能會延遲以避免間斷 Use all displays = 使用所有顯示器 +Vertex Cache = 頂點快取 +VertexCache Tip = 更快,但可能會造成暫時閃爍 VSync = 垂直同步 Vulkan = Vulkan Window Size = 視窗大小 @@ -685,12 +582,10 @@ Zip archive corrupt = ZIP 封存損毀 Zip file does not contain PSP software = ZIP 檔案不包含 PSP 軟體 [KeyMapping] -Allow combo mappings = 允許組合對應 Autoconfigure = 自動設定 Autoconfigure for device = 自動設定裝置 Bind All = 全部繫結 Clear All = 全部清除 -Combo mappings are not enabled = 組合對應未啟用 Default All = 重設為預設值 Map a new key for = 對應新按鍵: Map Key = 對應按鍵 @@ -747,7 +642,16 @@ Audio/Video Recording = 音訊/視訊錄製 AxisSwap = 軸交換 Circle = ○ Cross = × -Custom %d = 自訂 %d +Custom 1 = 自訂 1 +Custom 2 = 自訂 2 +Custom 3 = 自訂 3 +Custom 4 = 自訂 4 +Custom 5 = 自訂 5 +Custom 6 = 自訂 6 +Custom 7 = 自訂 7 +Custom 8 = 自訂 8 +Custom 9 = 自訂 9 +Custom 10 = 自訂 10 D-pad down = 方向鍵 - 下 D-pad left = 方向鍵 - 左 D-pad right = 方向鍵 - 右 @@ -756,7 +660,6 @@ DevMenu = 開發選單 Double tap button = 點兩下按鈕 Down = 方向鍵 - 下 Dpad = 方向鍵 -Exit App = Exit App Frame Advance = 逐影格 Hold = 固定 Home = PS 按鈕 @@ -769,7 +672,6 @@ None = 無 Note = 聲音按鈕 OpenChat = 開啟聊天 Pause = 暫停 -Previous Slot = 上一存檔插槽 R = R RapidFire = 快速開火 Record = 錄製 @@ -799,7 +701,6 @@ Texture Dumping = 紋理傾印 Texture Replacement = 紋理取代 Toggle Fullscreen = 切換全螢幕 Toggle mode = 切換模式 -Toggle WLAN = Toggle WLAN Triangle = △ Fast-forward = 快轉 Up = 方向鍵 - 上 @@ -816,6 +717,11 @@ AdHoc Server = 臨機操作伺服器 AdhocServer Failed to Bind Port = 臨機操作伺服器無法繫結連接埠 AM: Data from Unknown Port = AM:來自不明連接埠的資料 Auto = 自動 +Bottom Center = 正下 +Bottom Left = 左下 +Bottom Right = 右下 +Center Left = 正左 +Center Right = 正右 Change Mac Address = 變更 MAC 位址 ChangeMacSaveConfirm = 產生新的 MAC 位址? ChangeMacSaveWarning = 某些遊戲在載入儲存資料時會驗證 MAC 位址,這可能會損毀舊存檔 @@ -849,6 +755,7 @@ Invalid IP or hostname = 無效的 IP 或主機名稱 Minimum Timeout = 最小逾時 (單位為毫秒,0 = 預設) Misc = 雜項 (預設 = PSP 相容性) Network Initialized = 網路已初始化 +None = 無 Please change your Port Offset = 請變更您的連接埠位移 Port offset = 連接埠位移 (0 = PSP 相容性) Open PPSSPP Multiplayer Wiki Page = 開啟 PPSSPP 多人遊戲維基頁面 @@ -859,9 +766,11 @@ Quick Chat 3 = 快速聊天 3 Quick Chat 4 = 快速聊天 4 Quick Chat 5 = 快速聊天 5 QuickChat = 快速聊天 -Randomize = 隨機 Send = 傳送 Send Discord Presence information = 傳送 Discord「Rich Presence」資訊 +Top Center = 正上 +Top Left = 左上 +Top Right = 右上 Unable to find UPnP device = 找不到 UPnP 裝置 UPnP (port-forwarding) = UPnP (連接埠轉送) UPnP need to be reinitialized = UPnP 需要重新初始化 @@ -871,23 +780,6 @@ Validating address... = 正在驗證位址… WLAN Channel = WLAN 頻道 You're in Offline Mode, go to lobby or online hall = 您目前處於離線模式,請前往大廳或線上大廳 -[PSPSettings] -Auto = 自動 -Chinese (simplified) = 簡體中文 -Chinese (traditional) = 繁體中文 -Dutch = 荷蘭文 -English = 英文 -French = 法文 -Game language = 遊戲語言 -German = 德文 -Italian = 義大利文 -Japanese = 日文 -Korean = 韓文 -Games often don't support all languages = 遊戲通常不支援所有語言 -Portuguese = 葡萄牙文 -Russian = 俄文 -Spanish = 西班牙文 - [Pause] Cheats = 密技 Continue = 繼續 @@ -913,14 +805,12 @@ Amount = 數量 Aspect = 長寬 Black border = 黑色框線 Bloom = 光圈 -BloomNoBlur = 綻開 (無模糊) Brightness = 亮度 Cartoon = 卡通 ColorCorrection = 色彩修正 ColorPreservation = 色彩保留 Contrast = 對比度 CRT = CRT 掃描線 -FakeReflections = 假反射 FXAA = FXAA 消除鋸齒 Gamma = 色差補正 GreenLevel = 綠色色階 @@ -940,7 +830,6 @@ SSAA(Gauss) = 超級取樣 AA (高斯) Strength = 強度 Tex4xBRZ = 4xBRZ TexMMPX = MMPX -UpscaleBicubic = 雙立方放大 UpscaleSpline36 = Spline36 放大 VideoSmoothingAA = 視訊平滑 AA Vignette = 暈影 @@ -990,7 +879,6 @@ written = 使用 C++ 編寫,以保證建置速度和相容性 [MemStick] Already contains PSP data = 已包含 PSP 資料 -Cancelled - try again = Cancelled - try again Create or Choose a PSP folder = 建立或選擇 PSP 資料夾 Current = 目前 DataCanBeShared = 資料可在 PPSSPP 標準版/黃金版之間共用 @@ -1168,11 +1056,10 @@ GPU Flags = GPU 旗標 GPU Information = GPU 資訊 High precision float range = 高精確度浮點數範圍 High precision int range = 高精確度整數範圍 -Icon cache = 圖示快取 JIT available = 可用 JIT Lang/Region = 語言/區域 Memory Page Size = 記憶體分頁大小 -Native resolution = 原生解析度 +Native Resolution = 原生解析度 No GPU driver bugs detected = 未偵測到 GPU 驅動程式錯誤 OGL Extensions = OGL 擴充 OpenGL ES 2.0 Extensions = OpenGL ES 2.0 擴充 @@ -1181,9 +1068,7 @@ OpenGL Extensions = OpenGL 擴充 Optimal frames per buffer = 最佳每緩衝區影格數 Optimal sample rate = 最佳取樣率 OS Information = OS 資訊 -Pixel resolution = Pixel resolution PPSSPP build = PPSSPP 組建 -Present modes = Present modes Refresh rate = 重新整理速率 Release = 發行版本 RW/RX exclusive = RW/RX 排除 @@ -1195,7 +1080,7 @@ System Information = 系統資訊 System Name = 系統名稱 System Version = 系統版本 Threads = 執行緒 -UI resolution = UI 解析度 +UI Resolution = UI 解析度 Vendor = 廠商 Vendor (detected) = 廠商 (偵測到) Version Information = 版本資訊 @@ -1277,7 +1162,6 @@ Record Audio = 錄製音訊 Record Display = 錄製視訊 Reset Recording on Save/Load State = 儲存/載入存檔時重設錄製 Restore Default Settings = 將 PPSSPP 設定重設為預設值 -RetroAchievements = RetroAchievements Rewind Snapshot Interval = 倒轉快照間隔 Save path in installed.txt = 儲存路徑於 installed.txt Save path in My Documents = 儲存路徑於「我的文件」 @@ -1289,7 +1173,6 @@ Set UI background... = 設定 UI 背景… Show ID = 顯示 ID Show region flag = 顯示區域旗幟 Simulate UMD delays = 模擬 UMD 延遲 -Simulate UMD slow reading speed = 模擬UMD慢速讀取 Slot 1 = 插槽 1 Slot 2 = 插槽 2 Slot 3 = 插槽 3 @@ -1356,11 +1239,12 @@ Progress: %1% = 進度:%1% Screen representation = 螢幕呈現 [VR] +% of native FoV = % 於原生視野 6DoF movement = 六自由度移動 Camera type = 相機類型 Distance to 2D menus and scenes = 2D 選單及場景距離 -Distance to 3D scenes when VR disabled = VR 停用時的 3D 場景距離 Experts only = 僅限專家 +Field of view scale = 視野縮放 Force 72Hz update = 強制 72Hz 更新 Game camera rotation step per frame = 遊戲相機每影格旋轉步數 Game camera uses rotation smoothing = 遊戲相機使用旋轉平滑 diff --git a/assets/redump.csv b/assets/redump.csv deleted file mode 100644 index 52bff6c23..000000000 --- a/assets/redump.csv +++ /dev/null @@ -1,2810 +0,0 @@ -ID,System,Title,Foreign Title,Category,Region,Serial,Version,Size,CRC32,MD5,SHA1 -440,Sony PlayStation Portable,Ghost in the Shell: Stand Alone Complex,,Games,USA,ULUS-10020,1.01,793280512,52321d57,5e01db6af5e15cf78879bf7a372e6b00,3f1f2f27b3c6928c32b747ccf86e5c45e2add7f7 -609,Sony PlayStation Portable,WipEout Pure,,Games,Europe,UCES-00001,1.01,352714752,430725bf,181d349bb577f0cc4aafdc54d9aea96b,710a189ebece7af3a1e796fdcd070302ee562097 -628,Sony PlayStation Portable,Open Season,,Games,Europe,ULES-00507,1.01,1105395712,c9e330d4,295e3a333a5fa34f002d5556fa780337,b08356c7c53d2542630ee771a4b69cba3a119c26 -651,Sony PlayStation Portable,Untold Legends: Brotherhood of the Blade,,Games,Europe,ULES-00046,1.01,407601152,ba671bd0,73860c73de3354b3bd108824fbb94f55,9b1c25bc9528a2709b6e0a542828d1ce67f50a61 -685,Sony PlayStation Portable,Need for Speed: Carbon: Own the City,,Games,Asia,ULAS-42080,1.00,894173184,1b3c86c8,75cc723c9e2a52ab710d7067cb60eff6,22627aea82e75fd53f01dd80cd0e073956c7169e -687,Sony PlayStation Portable,Fired Up,,Games,"Europe, Australia","UCES-00015, UCES-00015/ANZ",1.02,238026752,6d0257c5,37a0f2fb73a3163d6f57686117491bb9,7317fc4e958a906197ea52ac665807a734becb88 -688,Sony PlayStation Portable,MediEvil: Resurrection,,Games,Europe,UCES-00006,1.03,1454571520,88060384,2206513ebb5247312ca2bea69ec9bc7d,76535938a8845ad736458306b56816b81ae44846 -698,Sony PlayStation Portable,Lumines: Puzzle Fusion,,Games,USA,"ULUS 10002, ULUS 10002GH",1.01,209911808,3348b8a2,4f8f437b9f33c963276534bc35b9fa53,d1b8010db963235c3c9e9ac9d26a656a7b67b2c8 -708,Sony PlayStation Portable,Ridge Racer,,Games,"Europe, Australia",UCES-00002,1.00,906362880,079a3889,72fff94c5b048e63047e8eae0e2771ec,384393cb2b2296933257153d6fabef5b5488bc6a -767,Sony PlayStation Portable,Midnight Club 3: DUB Edition,,Games,USA,ULUS-10021,1.00,1652424704,cac66b91,31d345faa24187df9e8c828ff41ebb33,ee604fbd6dcb61f5509397001ed67275ef30117a -783,Sony PlayStation Portable,Full Auto 2: Battlelines,,Games,Europe,ULES-00754,1.00,469336064,940f9756,0bff57a8a247e2fb20367e562cc6dfb6,27c8d6913f66c811334355db7a245ec5268594ef -809,Sony PlayStation Portable,Retail Sampler No. 3 for PSP,,Demos,Europe,UCED-00499,1.02,507510784,81bb2dfa,a4b42d29ed28776dafd87d70c76e89a2,4b073c9493cda3c1e6934d0f270761dc27f3a4e5 -850,Sony PlayStation Portable,Grand Theft Auto: Vice City Stories,,Games,USA,"ULUS 10160GH, ULUS-10160",1.03,1696006144,f705a610,f3734cd9ef8fa3f8daf07d0550481092,c339a62ee9b68804f3faa56142bf8486c5bebd8f -852,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,Europe,"ULES-00151, ULES-00151#2, ULES-00151/P",3.00,1255243776,7a884c02,cf40e781475451db431769f9ea0f7998,dd1ba43aaa64dfb13346d6fdbb2a3bfd604e6518 -856,Sony PlayStation Portable,Untold Legends: The Warrior's Code,,Games,USA,ULUS-10086,1.02,1053720576,70035cb5,b45ec5747f1074dcb4c99e907cef0619,8e689cc6d73ac4438724cd5c7ebee65c4cae4fd5 -1197,Sony PlayStation Portable,Star Wars: Lethal Alliance,,Games,Europe,ULES-00599,1.01,896598016,02d2189e,f1f4cc8398298eb6e4d215b19350bf12,5e8fccf8dd84ff627423182bc6f9772dd01b9d4f -1198,Sony PlayStation Portable,The Lord of the Rings: Tactics,,Games,USA,ULUS-10038,1.00,554139648,7ca3c10e,91e8d1181c0d10bf50c3b800fe613667,d2532c131e2e38a79f2b695e72ebbfdffbc7096f -1199,Sony PlayStation Portable,Brothers in Arms: D-Day,,Games,"Europe, Australia",ULES-00608,1.01,1453326336,93ccffeb,76ef60dd2d1b53e91d7c34e5fa0b9f27,029341fa2412322d8db50a17a562042f5ef69b62 -1200,Sony PlayStation Portable,Need for Speed: Most Wanted: 5-1-0,,Games,Asia,ULAS-42031,1.00,926580736,b44c94f1,50a602964fab41e26c9ca5193dd7c923,ba938761d68acb46f62912e2a7b33abbf34d94b4 -1213,Sony PlayStation Portable,Miami Vice: The Game,Полиция Майами. Отдел нравов,Games,Russia,ULES-00376,1.01,350945280,3d7286ef,78bd9e8ec1f816f166e15456bc6385ff,b012261a2ea4c87dd2bf75e0b4c5e4cbb5d5c619 -1214,Sony PlayStation Portable,The Sims 2: Pets,,Games,Asia,ULAS-42085,1.00,1670709248,650ef5b1,3e4730ca5cfc5467a6655501a453e836,c7db1820b559ee63c823a1dc730f023fef802734 -1243,Sony PlayStation Portable,Lumines: Puzzle Fusion,,Games,Europe,ULES-00043,1.01,336166912,32a634f0,650d547440a69eeda8bef2719650e601,5a26dc8698185f678fab6ff4388086b4e3299278 -1281,Sony PlayStation Portable,Peter Jackson's King Kong: The Official Game of the Movie,,Games,Europe,ULES-00225,1.01,573702144,5760e2c7,0479cca05492d0426c4b5fbf5403ed92,0a9bf92830176e5cd0815f5e0e3b141d4adae7b3 -1285,Sony PlayStation Portable,Tom Clancy's Splinter Cell: Essentials,,Games,"Europe, Australia",ULES-00281,1.02,1812332544,66b943d9,81a8e1669656ff99a110e9a623107c87,5dae82b4835c474eeea26895a1a007237e027107 -1286,Sony PlayStation Portable,Pursuit Force,,Games,Europe,"UCES-00019, UCES-00019/9162315",1.00,1352892416,e708d084,0cc2ecedb3c98b04af6cb029f0f168f8,c2cc27677c281d31d6100483e0d5185aa6aa9bf1 -1287,Sony PlayStation Portable,Kingdom of Paradise,,Games,USA,UCUS-98623,1.00,1081999360,aec0d9bc,6ec92800cc2d8ea9f7c0ca5013dba4b0,0288fe7e12e53f9eff3b2d27d4337fde8b2f67b7 -1288,Sony PlayStation Portable,NBA Street Showdown,,Games,Asia,ULAS-42003,1.00,1181679616,32577dd3,03542d8bacea66cd11e5ba21305887ef,a8a83490867523fb4695e68b3a3bbebd63b24889 -1345,Sony PlayStation Portable,Grand Theft Auto: Vice City Stories,,Games,Europe,"ULES-00502, ULES-00502/P",1.02,1696006144,b44ac795,bf17f0cabd2f3d9ba3c30413c070758e,7cd0600e7f12b8fcef0872062ad381a41be963e5 -1346,Sony PlayStation Portable,Killzone: Liberation,,Games,Europe,"UCES-00279, UCES-00279/P",1.00,581664768,57f4d17f,8d99308813ba3924b8c90c6b86b15134,01b5b12c38bf7ba6d2ff5d30a5459f1bf6b5bb2a -1391,Sony PlayStation Portable,Lumines II,,Games,Europe,ULES-00553,1.00,1179385856,fd014b71,03e7f52602364d131f00c90ca31fa60a,e7c4515411db0a2a8f2b03f06abac7f842344b46 -1397,Sony PlayStation Portable,Killzone: Liberation,,Games,USA,UCUS-98646,1.00,581632000,a4f123eb,88d913fdf33172a3cfdb857b5c92be5b,dda1a72c28ccdd8ddd2f3cbfd2fa3188962b0458 -1398,Sony PlayStation Portable,Metal Gear Ac!d²,Metal Gear Acid 2,Games,Europe,ULES-00284,1.01,917340160,324b1018,f43c903c00242896563c5b84de0d4e55,443e21fe55607252cc59c2a80e94f524876af24f -1452,Sony PlayStation Portable,Need for Speed: Most Wanted: 5-1-0,,Games,Europe,ULES-00196,1.00,932020224,108bff5d,bdcfcd52eb0df1e0d39aace243275090,11c87efd7b14b6ada89791cf4aacec6fa6c02579 -1493,Sony PlayStation Portable,Need for Speed: Carbon: Own the City,,Games,Europe,"ULES-00576, ULES-00576/P",1.00,894173184,4095534a,5548cb8d4691c499e3f9642ccb4a5067,7210e758ce4bc944dd0547e989afe094f4054c34 -1500,Sony PlayStation Portable,Lara Croft Tomb Raider: Legend,,Games,Europe,"ULES-00283, ULES-00283#",1.01,1515028480,09d3414b,a3140e419800a92188426fddaeb226d6,0499a2e3a0f73501001c61c4ca1de0b855390dce -1529,Sony PlayStation Portable,Tekken: Dark Resurrection,,Games,"Europe, Australia","UCES-00356, UCES-00356#, UCES-00356/ANZ#, UCES-00356/P",2.00,1791524864,a401c076,d4d260cb51467f5dcb59d6071b4dfdad,e3dcad724c175d6c2de88cd3e3652b7e2e4d5a11 -1534,Sony PlayStation Portable,Formula One 06,,Games,Europe,UCES-00238,1.01,1743552512,37471f23,18ddb109d6d8659dd6efc6dc4f59af2f,9ec67d27613a6caff98571782b64d27ca206b1a7 -1557,Sony PlayStation Portable,Pro Evolution Soccer 6,,Games,Europe,"ULES-00476, ULES-00476/P",1.03,1248329728,b4d00e7a,dba85542c6ba9c2fc1532a7622775901,e5adf0b1a8386a5a33a358c39e7aa76d6a7c54b6 -1621,Sony PlayStation Portable,The Sims 2,,Games,Europe,ULES-00211,1.00,1114636288,f8ed1db8,349450486b708b259d2491eaa43cd1ac,3d66addd3717f6591557f8ee73983df667ba3002 -1622,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,Europe,ULES-00151,2.00,1255243776,824b2938,04c3e22762121ca59e8d6b83a0855211,be971bd5a7400fd09fd52bc053d1f8be77d18b74 -1690,Sony PlayStation Portable,TMNT,,Games,USA,ULUS 10243,1.01,953221120,65523c74,64e7f8fac99da8913fbd65a5b1761967,7f60b7a79a84c33d33b8ddaf464a489936a30174 -1722,Sony PlayStation Portable,DreamWorks Shrek the Third,,Games,Europe,ULES-00812,1.01,509444096,94aa2e13,b466d5655d854eec6a5f7ebc5f7eac8b,f947c6e8ef170c9a87416a9dc69f8e82ad43227f -1723,Sony PlayStation Portable,Coded Arms: Contagion,,Games,USA,ULUS-10184,1.04,547225600,c9842017,5f99c4bf5b2620a0100c1e8c976e72fa,c187dc04d784b279ccb2ed2401dc072ee8195a72 -1771,Sony PlayStation Portable,Burnout Legends,,Games,Europe,ULES-00125#,2.00,505905152,2a70c088,4577a0a3b8a210ed689075151ceba97b,35774432b3a4b3d7ba5ac01e1b61c0947f983ec7 -1772,Sony PlayStation Portable,Star Wars: Battlefront II,,Games,"Europe, Australia","ULES-00183, ULES-00183/P",1.01,738656256,e767aa58,b33c91697a53335fbff93d02e0f229c2,14a7d807c8654c976443036033335b7b2ac42609 -1776,Sony PlayStation Portable,Disney · Pixar Ratatouille,Disney · Пиксар Рататуй,Games,Russia,ULES-00748#,1.00,906362880,0df8fd04,7ec425c2279ab94230aed8e9e75016e0,1cce82f9d27aebf6fe66d729994899352b4c9233 -1889,Sony PlayStation Portable,SWAT: Target Liberty,,Games,Europe,ULES-00927,1.00,886865920,e46fd50a,5516d499de6cb0d04b7fdb81ff9a55b7,bc6d5510fae1d9fd8146dc505885bd39d141cd88 -1890,Sony PlayStation Portable,Silent Hill Origins,,Games,Europe,ULES-00869,1.00,804683776,f1707c09,3f2609aaefb049daf2ed220a5ca2a8ed,8a51460105e4097615f3aefc41e86b379d68412d -1951,Sony PlayStation Portable,Transformers: The Game,,Games,Europe,ULES-00823,1.02,816644096,46582952,132e1fcb9bfd13ec43d980fd5b077cd3,1c47bc38c2971c7d5dd1b4d1a251f872a50a488a -2023,Sony PlayStation Portable,Salamander Portable,沙羅曼蛇PORTABLE,Games,"Japan, Asia","ULAS-42090, ULJM-05219",1.01,239370240,4b01200b,d7161b3b67960f4d705d13fbea288af1,b8ec7f21612c9c97f803a60665c4390956754ee0 -2026,Sony PlayStation Portable,Puyo Puyo Fever,ぷよぷよフィーバー,Games,Japan,ULJM-05007,1.02,141590528,3c441a35,65e1630af575011b2e7e23e3d121fa0d,d17cc056626618e0a637a7663dacc75d84bc3deb -2029,Sony PlayStation Portable,Star Soldier,スターソルジャー,Games,Japan,"ULJM 05026, ULJM 05235",1.01,77955072,c3aa8e4e,a7fa76bb98580b198800fe1c8fd2de33,c3510b1cb826f9296cf95499f1bfd0d58c29622c -2058,Sony PlayStation Portable,Armored Core: Formula Front International,アーマード・コア フォーミュラフロント インターナショナル,Games,Japan,ULJS-19001,1.00,900595712,7d6e1b46,33d9ddca21e660585f44f803d30200c0,107ad3157488e23e1ad8d0d6dd2a642d38c3472d -2059,Sony PlayStation Portable,Blokus Club Portable with Bumpy Trot,ブロックス倶楽部ポータブル with バンピートロット 体験版,Demos,Japan,ULJM-91007,1.01,102334464,1bab57df,5aac3250f0ccda03224849eac547e3d9,e0ac66c205d4d971ff50c60d983105bf01827558 -2060,Sony PlayStation Portable,Capcom Special Taikenban 3 in 1,カプコンスペシャル 体験版 3in1,Demos,Japan,ULJM-91004,1.00,132874240,e1fa6097,f9ebd34dd246692c04168cae5cdd06ba,f92f7685b018e7be7ac91afc423aa021ec31443d -2061,Sony PlayStation Portable,Densha de Go! Pocket: Yamanotesen-hen,電車でGO!ポケット: 山手線編,Games,Japan,ULJM 05039,1.03,510328832,e54520ba,180b7773e3e1337d2d360baa6c847c7b,d08f6dee57bd68a0f42aa820547f615cb332f16f -2062,Sony PlayStation Portable,Kotoba no Puzzle: Mojipittan Daijiten,ことばのパズル もじぴったん大辞典,Games,Japan,"ULJS 00002, ULJS 19003",1.00,56918016,06452fde,901f1c5c36c6b1ec018677dad6e36728,107a46fa17163cd400bfcbb717ffecd43d8e2e13 -2063,Sony PlayStation Portable,Irem Taikenban Shuu 2007 Kaki Tokubetsugou,アイレム体験版集2007夏季特別号,Demos,Japan,ULJM-91011,1.01,239435776,775d890c,9964087eac33f0bc8c3630f32c3398e8,c1da6c726366b9dd550a25e138608a46f6027d88 -2107,Sony PlayStation Portable,Spider-Man: Friend or Foe,Spider-Man: Amici o Nemici,Games,Europe,ULES-00899,1.01,877133824,f039522f,c5c77f9d0b5a98b92455191a65a9934e,00e49466bdb5dca2ebd6d93f81f34520d59b6226 -2108,Sony PlayStation Portable,Juiced 2: Hot Import Nights,,Games,Europe,ULES-00928,1.00,1134362624,4a720419,4dfcc2d4005daba80e25980872274b14,11e14c94821d45c76ed1517b1fe80d9c833fe91b -2132,Sony PlayStation Portable,Puzzle Quest: Challenge of the Warlords,,Games,Europe,ULES-00720,1.01,136085504,21c7d2db,b7f839c47cdfc8aacdf0c2408dd10072,7e2b872220ab69823b29e7cf25df7b15b80bc685 -2133,Sony PlayStation Portable,Irregular Hunter X,イレギュラーハンターX,Games,"Japan, Asia","UCAS 40207, ULAS 42036, ULJM 05043, ULJM 05226",1.02,469991424,182e8118,1ffd630ace76491292673c65503816eb,326e7e0a231ea24badbb00c9e17ab946ab74ceb1 -2154,Sony PlayStation Portable,Namco Museum,ナムコミュージアム,Games,"Japan, Asia","UCAS 40166, ULJS 00012, ULJS 19006",1.02,164397056,fb7d60d8,6a5bf45342d0c63b89453c350f1f23c2,67f6c831a3f22d65322cb964d711a2c51e8dd306 -2155,Sony PlayStation Portable,Final Fantasy,ファイナルファンタジー,Games,"Japan, Asia","UCAS-40146, UCKS 45056, ULJM-05241, ULJM-05514",1.01,198115328,683018b7,04dec99245f83ca50d5e8812438946e5,f246ad981b4b0153d988bfddf59ef6e555408846 -2193,Sony PlayStation Portable,Mahjong Fight Club,麻雀格闘倶楽部,Games,Japan,"ULJM 05002, ULJM 08005",1.01,162004992,9eb925fb,13d83cbc9b61774649e3a0f43a7cd582,293c57e773ac36112d287ca184206627727605e0 -2236,Sony PlayStation Portable,Harry Potter and the Order of the Phoenix,,Games,Asia,ULAS-42104,1.00,763461632,e0f6366a,f902247831432c81aaeff546fbd90e50,56b8bdbde5c5850f179f28816fc870aba59dc881 -2237,Sony PlayStation Portable,Puyo Puyo Fever 2,ぷよぷよフィーバー2,Games,Japan,ULJM 05058,1.01,219348992,5a84975c,ee43e6fb184f4e33673d600fb79d5d19,b6b01099b4ad71a76c3f01087448cc24f85890da -2241,Sony PlayStation Portable,"Warhammer 40,000: Squad Command",,Games,Europe,ULES-00873,1.01,887259136,fc88ceec,4fba4928d18db959895edb4e502708a7,0ae26f6ad7cc8a112ccf13f920baf03e8ce97c94 -2292,Sony PlayStation Portable,Fight Night Round 3,,Games,Asia,ULAS-42044,1.00,1137737728,3338a88d,93c01953e3c3086bcbad7937b4bbd0ae,5a86fae23f70e1033a09a78fdb2d6874508c0e89 -2293,Sony PlayStation Portable,Final Fantasy Tactics: The War of the Lions,,Games,Europe,ULES-00850,1.00,418873344,0f7ae43c,4b97913c0423b879a9321febaeb4892a,5104e61a886c1fb62fae98fa3bf96e1b0c545dc6 -2517,Sony PlayStation Portable,Monster Hunter Freedom 2,,Games,Europe,ULES-00851,1.01,845905920,76a20e8c,bf0951e879e1adfef608d0a8a4690223,bee1ee210bf5686c5eeb2875e44325b5300e8551 -2656,Sony PlayStation Portable,FIFA 08,,Games,Europe,ULES-00891,1.01,1307475968,a1c0eed3,b0e9aed139fe305f04d68c80df21e256,8cbb7f4599194c26b71e300c9e873abc3edfa02c -2672,Sony PlayStation Portable,Field Commander,,Games,"Europe, Australia",ULES-00335,1.01,1805254656,404ddc78,8ed6d1fdc0fabe67918f1d995c7901b0,2205263b3f59af29cff5630b3dcce2b4e985bbf4 -2785,Sony PlayStation Portable,Spider-Man 2,,Games,Europe,ULES-00022,1.01,337772544,1950edec,e7819ee7e2d5087871da4a8b2fa97860,de85fb6f4a38024fe1cd7c9f7455be7a1726ab24 -2786,Sony PlayStation Portable,The Simpsons Game,,Games,Europe,ULES-00975,1.00,764739584,f467a286,b335a3cba33480a1a43da190d9fd9276,266944d0643eff7ed4f3c28e8414e74239f0e9c8 -2794,Sony PlayStation Portable,Ace Combat X: Skies of Deception,エースコンバットX: スカイズ・オブ・デセプション,Games,"Japan, Asia","UCAS 40120, ULJS 00086",1.01,1121026048,c603f12c,ea292930f6785c7faf93a46396a29f05,0c5ab4cb4bc4590a512a9f4f72c8e0f652f384c7 -2806,Sony PlayStation Portable,Crash Tag Team Racing,,Games,Europe,"ULES-00168, ULES-00168#2, ULES-00168/E, ULES-00168/P",1.00,1535836160,dfb63b73,fbd6371a417f74aac12a33c462ebc5ec,92a47a790f2d230196638c43fa86b6637b70b874 -2807,Sony PlayStation Portable,Marvel: Ultimate Alliance,,Games,Europe,ULES-00542,1.01,1773764608,5ff7bb23,3b347a5919d60724f6fbfb5ea578a96d,fa9d561f2c6a4f085e3701351083a7a596fc82a1 -2809,Sony PlayStation Portable,Final Fantasy: 20th Anniversary Edition,,Games,USA,ULUS-10251,1.00,198115328,a3d9cf51,b14575e19147f4e3571a7757d13de473,764a480fe78779ced7c9c0e16ab277cce486ade1 -2815,Sony PlayStation Portable,World Series of Poker,,Games,USA,ULUS-10047,1.00,345178112,99eb5b8b,c1bce446026e3e78f40753fb585052a9,c15288eaca86b8e17f6343d6b7b8a76fd3e425ce -2816,Sony PlayStation Portable,Mortal Kombat: Unchained,,Games,USA,ULUS-10102,1.03,1568899072,e17678e0,ee09a9d9cebe1586b969b00bdaa9d436,cd2470cd1b2a602c2b34837cfd54045d66dd56f1 -2817,Sony PlayStation Portable,Valkyrie Profile: Lenneth,,Games,USA,ULUS-10107,1.00,710410240,344d20af,0fc8df647c15d2d154759e2a1f6cfe8e,bc3762ccecf7ce8e5975b779265a18eb4817c8d3 -2836,Sony PlayStation Portable,Virtua Tennis 3,,Games,Europe,ULES-00763,1.00,582156288,7ede3589,55890b337a6be6a4e40f886675e22cdf,8046a0f2b328f843e84a463844cc78d210decb6a -2853,Sony PlayStation Portable,WipEout Pulse,,Games,Asia,"UCAS-40179, UCKS-45078",1.00,456884224,794790be,4903d7f706bfae1bceeb3bed4b675276,6b43396c41158a3bddf0ffea9c6bd7eb1f38cc31 -2917,Sony PlayStation Portable,Medal of Honor: Heroes 2,,Games,Europe,ULES-00955,1.00,1226768384,8c5b08a4,8e203dcc18aea84b4de28c2c08663511,98decffb3a578a307a75f6e4b6c2a5aba02ee9c2 -2930,Sony PlayStation Portable,Beowulf: The Game,,Games,Europe,ULES-00992,1.00,1260945408,44568cca,34d26f318f82252a1eca1bd4ae9b8864,083260cc7419de68544c9e7e4cf489775d2c4cd7 -2974,Sony PlayStation Portable,Jet de Go! Pocket,ジェットでGO!ポケット,Games,Asia,UCAS-40175,1.02,673447936,0888d8d4,82325fa8e80fe40e344a56ac8e898d39,13338aa0030a7199f2f5d63e49ad642e25848a45 -2975,Sony PlayStation Portable,Dragon Quest & Final Fantasy in Itadaki Street Portable,ドラゴンクエスト&ファイナルファンタジーinいただきストリートポータブル,Games,Japan,"ULJM 05127, ULJM-05321",1.02,309166080,f4d7331e,dfb9219dd39b7b0be49a57f617bf3dc8,3825e6db28d116924af345a3ea107055a7b8a078 -2978,Sony PlayStation Portable,Kuru Kuru Chameleon,くるくるカメレオン,Games,Japan,ULJM-05067,1.01,69566464,f2ce978a,0f5ca49c9268903fb0be3ed26986a166,9dd3b4a356c2155e142e6fb00bea7bebfe2d446f -2979,Sony PlayStation Portable,Gradius Portable,グラディウスポータブル,Games,Japan,"ULJM 05091, ULJM 05222",1.03,338821120,0070d32a,03310f92f5f8e6f00babc67a9aa658e4,1d3dc284eddf7f27e0e96b31f4f5dce2f8181740 -2985,Sony PlayStation Portable,Tekken: Dark Resurrection,鉄拳 Dark Resurrection,Games,"Japan, Asia","UCAS-40164, ULJS 00048",1.06,1748762624,9d925a8b,610a5558857906e2bbf1352d96d5ddd4,b44231d21fac1e999be4c699dd7cb5cd00a80667 -2986,Sony PlayStation Portable,NBA Live 06,NBAライブ06,Games,Japan,ULJM 05182,1.03,1302102016,b0c7f908,dcf7b8f07545bd9dd35e693cfaa7db4f,3e93025012150886e23b101bb92dd3423f5bef7c -2987,Sony PlayStation Portable,Piposaru Academia 2: Aiai Saruge Janken Battle,ピポサルアカデミ~ア2: あいあいサルゲ~ジャンケンバトル,Games,Japan,"UCJS 10020, UCJS 18009",1.00,347865088,99a91fbe,ddb05d3ccd9006ad079f802e31117895,0e1b4e57519a09351563493f9f5f076ff2752896 -3001,Sony PlayStation Portable,TalkMan-shiki Shabelingual Eikaiwa for Kids!,TalkMan式 しゃべリンガル英会話 for Kids!,Educational,Japan,UCJS-10053,1.00,327286784,99d5ca09,5c904027fe5e60afa8367650153eb166,1a253afe213be838eec5911bec3751c95ada7e13 -3016,Sony PlayStation Portable,Xyanide: Resurrection,,Games,Asia,UCAS-40182,1.01,1567227904,5cf3beae,4f783eee9d1cfe9091bd843f2347914f,4fd6e8e278bd83843bd682d2c730185fc33306b5 -3061,Sony PlayStation Portable,Hard Rock Casino,,Games,Europe,ULES-00638,1.01,364085248,d9f76e04,88b91da4b02d21df056447814d1186bc,d5cc35d74d6eda7c1bd1aa688cc19cebbca81a85 -3070,Sony PlayStation Portable,Innocent Life: Shin Bokujou Monogatari,イノセントライフ ~ 新牧場物語,Games,Japan,ULJS 00119,1.01,207060992,ff16b632,b66d7b6cf751e55c80cec85d287c664e,c3b24e4c8f3a8ce03fe6d8ce8abcf2c55ae7cb26 -3072,Sony PlayStation Portable,Karakuri,カラクリ,Demos,Japan,ULJM 91001,1.01,553287680,19e00773,d8d43431120f13c73a270a3cc14fbf19,e4f686efedf6cf1976016cb90c84b5c6d9ef4528 -3075,Sony PlayStation Portable,Simple 2500 Series Portable!! Vol. 11: The Puzzle Quest: Agaria no Kishi,SIMPLE2500シリーズポータブル!! Vol.11 THE パズルクエスト ~アガリアの騎士~,Games,Japan,ULJS-00114,1.01,147521536,ca558618,86ee78423e6382c1f1c2edc2706d0ae4,6f7569ba30f5135aabc93eb4dbe889295e61a6df -3090,Sony PlayStation Portable,Shin Sangoku Musou,真・三國無双,Games,"Japan, Asia","ULAS 42008, ULJM 05003, ULJM 08008, ULJM 08017",1.01,199950336,8f727dbf,8ba7409b9ae72d95729184409ccd7cda,ea8fb5e101f7de2ecfc9d23c7187f05034d84671 -3111,Sony PlayStation Portable,Moegaku @ Portable,もえがく@ポータブル,Games,Japan,ULJM-05174,1.02,459964416,69e29924,64a4681f3ecb08e9c0cb7611fe65351f,e4943860e17c85d41cc9e83befe4d326a12a5ae3 -3112,Sony PlayStation Portable,Musou Orochi,無双OROCHI,Games,"Japan, Korea","ULJM 05314, ULKS 46174",1.02,906362880,4f6efb0b,97f59d1ca445235e2a431b67f2c53a0b,56b93f0c4a02f3044008bcb2b0b39fef3e8cc9eb -3144,Sony PlayStation Portable,Worms: Open Warfare 2,,Games,Europe,ULES-00819,1.01,196870144,d9bbf442,4e7b222c959a801c9a68a10fe5343387,bef541d1865f8cb3d09fbc5ace66fa986432122a -3145,Sony PlayStation Portable,Pursuit Force: Extreme Justice,,Games,Europe,"UCES-00694, UCES-00694 #3",1.03,1634467840,5ab18e1f,28d1de619c71594671bd1b7046e0d50e,c93d5c61a0e05ba222eaa24a0e2de9743469547d -3146,Sony PlayStation Portable,Chronicle of Dungeon Maker,クロニクルオブダンジョンメーカー,Games,Asia,UCAS-40176,1.01,150372352,6f49c328,ed5fe34b338fdd18f690b971ca99db06,3e5eee6f4534c397d11c80cc75b76956b2722b0d -3147,Sony PlayStation Portable,Saru! Get You! Piposaru Racer,サルゲッチュ ピポサルレーサー,Games,"Japan, Asia","UCAS 40134, UCJS 18016",1.00,259948544,35deb473,7ba79450daa4b917cc349ca46fb801a4,67e2656bf9269e0d66c0e1ff57f5e4e4492bb9b5 -3148,Sony PlayStation Portable,Monster Hunter Portable,モンスターハンターポータブル,Games,Japan,"ULJM 05066, ULJM 08010, ULJM 08014",1.03,745799680,24760064,64de03b9101204955771335c5bb618f3,c1371e6562fae925194c28823c9a785879c5578f -3192,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,USA,"ULUS-10041, ULUS-10041GH",3.00,1255243776,b78703cc,7230bf9f55d89a34913f817b6e8a4fc4,826dba2aeb56007c0e916d517c71855cfd494f73 -3197,Sony PlayStation Portable,Burnout Legends,バーンアウト レジェンド,Games,Japan,ULJM 05228,1.01,505905152,a9bec173,f59f9cfd83070bd2f2532d2615f6e3e2,371f481a74e2a0d96d3b940eab607a46506b9189 -3198,Sony PlayStation Portable,Makai Senki Disgaea Portable: Tsuushin Taisen Hajimemashita.,魔界戦記ディスガイアポータブル:通信対戦はじめました。,Games,"Japan, Korea","UCKS 45079, ULJS 00113",1.01,901513216,f3536088,02cedafe3b20fcdbbb49b919276f9b84,d7935854b669b1d7b9fec50c6c7bf525ad96c6aa -3199,Sony PlayStation Portable,Kanji Trainer Portable,京都大学 阿辻哲次教授監修 財団法人日本漢字能力検定協会協力 漢字トレーナー ポータブル,Games,Japan,ULJM-05201,1.01,75497472,c1671220,77f4eb7cc4702c281609e3517c28ab78,f493c1f72bac4e0bff159c5f01704c962450db18 -3214,Sony PlayStation Portable,Syphon Filter: Dark Mirror,,Games,Europe,"UCES-00310, UCES-00310/UK",1.00,1775894528,642627bb,d8715783c35dddf46f323277d61799fb,11c3793e440ee2f47a3fb410530d8b3376a392f2 -3241,Sony PlayStation Portable,Dora-Slot: Oki Slot Ou! Pioneer 12,ドラスロット:沖スロ王! パイオニア12,Games,Japan,ULJM-05069,1.04,125435904,0b7d4b07,e7aa12fdb4d06a0389f7d80630578065,afe5a211842688d3ebeb92fedce7867f5acda3fd -3242,Sony PlayStation Portable,FIFA Soccer,피파 축구,Games,Korea,ULKS 46011,1.00,1235451904,00357311,d3b29b9214842188cebebf899b74f18b,d52e12b42ae715291da3766e40a7b25cec589453 -3247,Sony PlayStation Portable,Metal Gear Solid: Portable Ops Plus,METAL GEAR SOLID PORTABLE OPS +,Games,Asia,ULAS-42123,1.01,1248067584,5168c0f7,68a45d65d1a083c95d76ef91be920671,f3a62b739bd2d60d08ff6bae771cd4a9245f0646 -3260,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 5,PlayStation Spot 専用 UMD Vol.5,Demos,Japan,UCJX-90021,1.00,273350656,585266d5,b2762065b492d209319549496e56b36b,73c645fa227b8aa9ba87551159e7b8f67971b790 -3261,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 6,PlayStation Spot 専用 UMD Vol.6,Preproduction,Japan,UCJX-90023,1.00,151191552,fe175807,675b22d929493adfcec876faeed1403e,067b719ee5b46ce6ff0ed03d28e21a4f7dca64e3 -3262,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 7,PlayStation Spot 専用 UMD Vol.7,Demos,Japan,UCJX-90024,1.00,192970752,e25cafe4,546a574e458ba62a4c815c94b6c5d70a,c91eb57852357e521c4d06ffd2a37ea2d0b00472 -3274,Sony PlayStation Portable,Valkyrie Profile: Lenneth,,Games,Europe,ULES-00724,1.00,709296128,f92bb2c3,e9d33865c356adc5ce3c95382cb9da39,218fe336854a9334089049a03f78221fbc8ef30f -3313,Sony PlayStation Portable,Sakura Taisen 1 & 2,サクラ大戦1&2,Games,"Japan, Asia","ULAS 42049, ULJM 05292",1.01,1756037120,d110d424,973ca4e120ff9c2fd19d28df2be815d9,8495f4ab07f8a73bd2ecfa359ef6bb75b2905a69 -3331,Sony PlayStation Portable,Bomberman: Bakufuu Sentai Bombermen,ボンバーマン: 爆風戦隊ボンバーメ~ン,Games,Japan,UCJS-10030,1.01,438337536,22848986,4d3245f0be16f9f8b8e4da9fa12fa265,17867d4f9eefccb11a0b4f461b53e81a96646fc3 -3336,Sony PlayStation Portable,Dora-Slot: Kyojin no Hoshi II,ドラスロット: 巨人の星II,Games,Japan,ULJM-05027,2.02,64356352,6266f2ce,0bb6c55242d2f2db854369ff0bcabc70,494b3e115ef80351c1d30fd8703ce07fdec5c05d -3345,Sony PlayStation Portable,Need for Speed: Underground Rivals,,Games,"Europe, Australia","ULES-00025, ULES-00025/AUS",1.00,885194752,c3f38f58,601f6fc381fe8848431b9dd2532170a9,d9f385bb1dd17a2df386ddd706bccb5f56aa010f -3346,Sony PlayStation Portable,Gangs of London,,Games,Europe,UCES-00113,1.00,1084162048,d182b1ab,7274aeb8f1e3291cebd3f9b701294368,01a840e782c217fb85bfa7683371c81ead008850 -3354,Sony PlayStation Portable,Ridge Racer 2,,Games,"Europe, Australia","UCES-00422, UCES-00422/9680673, UCES-00422/ANZ, UCES-00422/P",1.00,1523023872,510f8bfa,d7f46b419cc046e28832b0e273e27c0a,56dd3b5b53c9f3d3e719b5c23bf0fdcb571adf1a -3358,Sony PlayStation Portable,Jeanne d'Arc,ジャンヌ・ダルク,Demos,Japan,UCJX 90019,1.01,270270464,7c6bdd2d,95f6dc775b87c9a71b95ccfe1ebd03fb,123d0437dcfb62840bfb8961ff3884128813ae84 -3365,Sony PlayStation Portable,Coded Arms: Contagion,,Games,Asia,ULAS-42099,1.04,547225600,dfb2cbf0,31938950cc529710008d5e7a8dee467c,ada30c1fac9f979718eae6dbb461a5719ca0a5f6 -3367,Sony PlayStation Portable,Boku no Watashi no Katamari Damacy,僕の私の塊魂,Games,Japan,"ULJS 00033, ULJS 19009",1.01,1769144320,05e040a4,44b02d52f0f88b88bf30ee33cde59c8c,de2a96672eb3b95a09252de2a346ac715f91ed5f -3398,Sony PlayStation Portable,TalkMan Euro! TalkMan Europa Gengo-ban,TalkMan EURO! トークマン ヨーロッパ言語版,Educational,Japan,"UCJS 10034, UCJS 18020",1.03,1802960896,ab5126df,a5aeac2384409d3427b36a2650c7f321,3b3868f877f9cd2f904a70f1f30b48156152deae -3399,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,グランドセフトオート: リバティーシティストーリーズ,Games,Japan,"ULJM 05255, ULJM 05359",1.01,1320943616,ebf2e5f0,00f1215e94c7a607d2d9d0ab3c1eeaaf,cf2fbdce5b0747cec95889ebbd7a075c17dd5c7a -3403,Sony PlayStation Portable,Little Aid Portable,リトルエイドポータブル,Games,Japan,ULJM-05249,1.02,1472888832,e06c0049,3d651aa1d743a338a79471cbc992a6a0,294199f3c802780dc5a34f143d864d7c60cb2ed9 -3437,Sony PlayStation Portable,Irem Taikenban Shuu 2008 Shunki Tokubetsugou,アイレム体験版集2008春季特別号,Demos,Japan,ULJM-91013,1.01,285638656,fe1db62a,6b32f8b8d2cdbe1bfeca66926d3a1a15,b072864967229fbf3fa8006f90fc0423877b9963 -3454,Sony PlayStation Portable,Exit,,Games,Europe,ULES-00285,1.01,135233536,8865d8a8,3cab464c34921a812b23f30d563ee951,1004c059240770df67025f798690638df1e6c9cf -3455,Sony PlayStation Portable,Tekken: Dark Resurrection,,Games,Europe,"UCES-00356, UCES-00356/9620587",1.00,1791524864,c02eab89,251abff38ceb80e493331389a5e69207,66eb9b07114d0ca428629e98e50aeee409c7dd91 -3462,Sony PlayStation Portable,Metal Gear Solid: Digital Graphic Novel,,Games,Europe,ULES-00382,1.01,1606418432,aaca6171,ca48678be052e2282e1ff3efc0ad3f91,30f4517e3e78de5296c96cdf6d80045073048ec1 -3475,Sony PlayStation Portable,Metal Gear Ac!d,Metal Gear Acid,Games,Europe,ULES-00008,1.01,324534272,b5a65b76,f690e5a274eac6d061b5941e72990ec0,2d2e5604297ac922f4a117952315ea91348af174 -3478,Sony PlayStation Portable,Metal Gear Solid: Portable Ops,メタルギアソリッドポータブルオプス,Games,Japan,ULJM-05285,1.00,1396736000,1ef5a86c,60d1fc90df502d758756408eb972bf6d,a830b8e0a15698d64b65ba04bd92c3cd78f8efa1 -3479,Sony PlayStation Portable,Metal Gear Solid: Portable Ops Plus,メタルギアソリッドポータブルオプス+,Games,Japan,"ULJM 05261, ULJM 05284",1.03,1260257280,43352a4d,d7f10410b443e3b01b0ba3db8d86d0ba,8a0ac9baf4e72f4ee510682c53d57b48a78a2aa4 -3480,Sony PlayStation Portable,Need for Speed: ProStreet,,Games,Europe,ULES-01019,1.00,896270336,62f6d1eb,f45a976893ae1f039622c8d5bd88f595,8a12441da59d807e44dd5d2fc0e03e530f5cd3c2 -3495,Sony PlayStation Portable,Mobile Train Simulator: Keisei Toei Asakusa Keikyuusen,Mobile Train Simulator: 京成・都営浅草・京急線,Games,Japan,ULJM-05085,1.02,1747550208,176ff909,faad729af5bfb8625faf7bd0653829b7,8190a1dbcfb6b8cb177d417f737135a5209b5243 -3565,Sony PlayStation Portable,LocoRoco,,Games,"Europe, Australia","UCES-00304, UCES-00304/9611073, UCES-00304/ANZ, UCES-00304/P",1.01,727023616,33d54b2d,9cc876ca3624aea6377855094db84a28,8fcef1a91c6fa729f9ad4bbb4caf13a97e576148 -3577,Sony PlayStation Portable,Yu-Gi-Oh! GX: Tag Force 2,,Games,USA,ULUS-10302,1.02,1812725760,bc22481b,d03f5a02ad2d2fef16a42186e951d86e,413343d34de214796fd238dd1477c0b52670e39c -3587,Sony PlayStation Portable,ProStroke Golf: World Tour 2007,,Games,USA,ULUS-10209,1.01,809402368,fcdc67fa,3b9fa2202d7ba2fde22451be4691b94f,ebccf212d83c92e3885d4c3fb93addc6945d8864 -3590,Sony PlayStation Portable,Ace Combat X: Skies of Deception,,Games,Europe,"UCES-00423, UCES-00423#, UCES-00423/P",1.00,1121026048,55fd9ab2,ff092f3bf00794e67194cd4926e1f99c,5db575b0d5b942006d27208dad5f3ba54862acf6 -3600,Sony PlayStation Portable,Gitaroo Man Lives!,,Games,Europe,ULES-00383,1.02,1642004480,aad5eaca,2ba736348ba7ec8acd8d07090168288f,3fb1d96cdc302b28f0edbd6f6b0ab9374581ef1a -3601,Sony PlayStation Portable,Castlevania: The Dracula X Chronicles,,Games,USA,ULUS-10277,1.02,1111359488,26316f37,9734bc89f4956324c28df897e25f1a71,ecdb3675c7238c0e94d256801aa7655b24f47cac -3602,Sony PlayStation Portable,WipEout Pulse,,Games,"Europe, Australia","UCES-00465, UCES-00465/ANZ, UCES-00465/P",1.01,456851456,6901cb57,e297f0b8d5359c18b2ca3677eff2b714,d359418b5a5d818cfc46408756cb2b7c0131b6b4 -3604,Sony PlayStation Portable,Ultimate Ghosts'n Goblins,,Games,Europe,"ULES-00419, ULES-00419/0990919",1.00,464715776,df3737b8,cfb342a7b2b63c9e031af5c4b5719186,ed5b8f30a0c0a12cb149638578b069196a6627aa -3605,Sony PlayStation Portable,Metal Gear Solid: Portable Ops,,Games,Europe,"ULES-00645, ULES-00645#, ULES-00645/7061831",1.01,1568440320,f461c537,251b1e18f3ba0a331c65417d7dbfeb72,2171cd736af5ca3d9f1e7779f941529bbc96d7dc -3672,Sony PlayStation Portable,Tales of Eternia,,Games,Europe,"ULES-00176, ULES-00176#",2.02,666894336,7099c9d5,f6b0ca760a807ba3616dbbec1bd992cf,925458f647402cd61a3756123ff2308741135fb7 -3673,Sony PlayStation Portable,Breath of Fire III,,Games,Europe,"ULES-00193, ULES-00193/E",1.00,403374080,63a2b884,56036ebdbdb5bae40cde681baa1b9c9c,67bc068408616a5aca49649329e784e32d4afdbe -3674,Sony PlayStation Portable,Death Jr.,,Games,USA,ULUS-10027,1.01,435159040,30791916,10903edf07932b2acafa3f9b2e80d786,d1ff8c52c0952a8d2ed53005df6a8f72a7d7a2f9 -3687,Sony PlayStation Portable,Bokujou Monogatari: Harvest Moon: Boy & Girl,牧場物語ハーベストムーン ボーイ&ガール,Games,Japan,"ULJS 00034, ULJS 19008",1.04,328695808,64c56292,2e6cd642e3c6cac5b57d41d7f1d437a0,34110debfd424f74016c71db66fa135a9291a1e0 -3733,Sony PlayStation Portable,50 Cent: Bulletproof: G-Unit Edition,,Games,USA,ULUS-10128,1.02,1686241280,1b727582,4b1e9d532f0d39cedf0abe2461e2ebdc,d7d526ea0a95f854b3411e381871de852ff7df2f -3756,Sony PlayStation Portable,7 Wonders of the Ancient World,,Games,USA,ULUS-10227,1.01,77332480,08ca1d87,7ab4026dfcb78aa043478da7018b0554,b17d4d0c6c6be49eab6487c5a8936ab4c538a50e -3832,Sony PlayStation Portable,The Godfather: Mob Wars,,Games,Asia,ULAS-42054,1.00,1377566720,2115f2db,1fb9903c47ff9aa4c103a0f59f9c84c5,3cfd349c99c93c0505b898325ac20e64281af1b1 -3839,Sony PlayStation Portable,Tiger Woods PGA Tour 06,,Games,Asia,ULAS-42020,1.00,1301020672,3fef1de2,13cd60bf1770a859a9c7b9925e389acf,13df342908ddeccc5c42dfc7c909680a688ae037 -3840,Sony PlayStation Portable,300: March to Glory,,Games,Europe,ULES-00766,1.01,953974784,afbe2776,eea03aa5d932a1ab7cd6d4b6a4b4b2c8,d8c2a8a821a3a57dd1fde91adf687a9f01b58343 -3841,Sony PlayStation Portable,God of War: Chains of Olympus,,Games,USA,UCUS 98653,1.00,1605664768,b9b62ab0,4c2e65edc45205ec0f0fa3998c7e1a25,ee976a5de0f205297166a622bc9bfd42fa3822f8 -3842,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,,Games,USA,"ULUS-10336, ULUS-10336GH",1.00,1716715520,4c7e2442,a36a1884647146c607215134e1836228,374b34d632f169a5b08fdcd51d1363cef53b3a4c -3843,Sony PlayStation Portable,Aliens vs. Predator: Requiem,,Games,Europe,ULES-00972,1.00,396492800,01a2a136,70c25187c3404496fa92120212a7b15c,505b45c8a56b43d5d5c19ab2103756dfc39ce708 -3876,Sony PlayStation Portable,Downstream Panic!,,Games,USA,ULUS-10322,1.00,469860352,98bf9e8d,f5f8cce22ae8a309cabebb9328859ee0,65c5a3921c75b0406075852ab549aae0cbb97de5 -3877,Sony PlayStation Portable,Diner Dash: Sizzle & Serve,,Games,USA,ULUS-10264,1.01,137527296,c0c6e2da,6f991c7d87e5185d0dff13c3229116e7,f8542e67310381262c206c66104ba429f34e13ef -3898,Sony PlayStation Portable,Scarface: Money. Power. Respect.,,Games,USA,ULUS-10148,1.01,578519040,eb922542,976435a818e65d6751f92574105c3c43,eb00eba249dee2c4392c2c9905a7270b6f105c2e -3908,Sony PlayStation Portable,Chameleon,,Games,USA,ULUS-10267,1.01,69926912,ccfd3bfc,5f95a241aad636f11ad064c327a3c2a6,6e4f66c1c4cb2dadadb5b38b48a445cbd3caf11c -4014,Sony PlayStation Portable,Chili Con Carnage,,Games,Europe,"ULES-00629, ULES-00629/0029248",1.00,852066304,6f608dea,bf96ae9a7899aab9ba5318d509bad36c,0d82922b5d419708bca242c93b3f93d287b469d7 -4015,Sony PlayStation Portable,Pump It Up: Zero Portable,펌프 잇 업: 제로 포터블,Games,Korea,ULKS-46146,1.04,1801650176,19ea8a42,9a719c7cdde950071d125401a29a4d4c,fc5162a11c7355ca194e35a71d87ead00ccf8f42 -4016,Sony PlayStation Portable,Pump It Up: Exceed Portable,펌프 잇 업: 익시드 포터블,Games,Korea,ULKS-46042,1.02,836599808,90b368f3,4242f44dab25ec0e8f8c577049d53fe8,90df0b8deebb8ce1fb513c15fc1f7e85b734b2eb -4019,Sony PlayStation Portable,Minna no Golf-jou Vol. 2 (Disc 1),みんなのGOLF場 Vol.2,Games,Japan,UCJS 10064,1.02,1738833920,de629947,b64ea4303c954e8edaf14f5ecf6cddd3,a88a765f211e2c07c67366f5a9ed995a9ef03649 -4020,Sony PlayStation Portable,Minna no Golf-jou Vol. 2 (Disc 2),みんなのGOLF場 Vol.2,Games,Japan,UCJS 10065,1.02,1530200064,31555cf4,66ecfa3e31ea74d3ab636827c263a5ac,e6794326fb5ba1b168c448f02ced761fdd595a45 -4027,Sony PlayStation Portable,LEGO Star Wars II: The Original Trilogy,,Games,Europe,"ULES-00479, ULES-00479/P",1.02,1312817152,938650f8,db59ff05d883d704805b75f1874ea84f,e98c1957a548eb6aa9b440841ab6fdf75e40440c -4048,Sony PlayStation Portable,Minna no Golf-jou Vol. 3 (Disc 1),みんなのGOLF場 Vol.3,Games,Japan,UCJS 10067,1.00,1632370688,9c927aba,4243dd29b45559a13dda3136f0ecdd79,e900cc79df8cc52f19cac996450104df8c35f07a -4049,Sony PlayStation Portable,Minna no Golf-jou Vol. 3 (Disc 2),みんなのGOLF場 Vol.3,Games,Japan,UCJS 10068,1.00,1591836672,d79afdee,4fd90072b5de00bad7e4b710c9948d83,27bea291a8df473b8b580a2978e11d9e0a791ce2 -4050,Sony PlayStation Portable,Derby Time 2006,ダービータイム2006,Games,Japan,UCJS 10027,1.03,227377152,2e2cc9a9,8463bd36d4d4d6bd7c7e37f214c66b33,eb00a18f3650e31b6b3c90d1a64da0afd8d464d1 -4059,Sony PlayStation Portable,Field Commander,,Games,USA,ULUS 10088,1.00,1199013888,0a0fc839,8ff489f13f8654f4b35038cafe968888,945b911e2e85bd876b5603c9bbb9a6bc7be21ec7 -4060,Sony PlayStation Portable,Burnout Legends,,Games,USA,ULUS-10025GH,2.00,505905152,91068ea9,13e1b91cc025fd39c65f332ea40f31d6,ee3830a0d4e619b304a8ff960a6f0583543c9a45 -4062,Sony PlayStation Portable,Sonic Rivals 2,,Games,USA,ULUS 10323,1.01,515866624,b0d2a040,ab7f4d53a1b93ec5498d2392b99a1978,8351dec13e1048b15579b4499fb6b04d883e030a -4112,Sony PlayStation Portable,Yggdra Union,ユグドラユニオン,Demos,Japan,ULJM 91012,1.00,330727424,43a7d4f1,0505e1d89639f6511789de8f28f948fe,dda7c9433d4398d1682bd58f2caf482b7e243d9e -4115,Sony PlayStation Portable,Tobidase! Trouble Hanafuda Douchuuki,とびだせ!トラぶる花札道中記,Games,Japan,ULJM 05207,1.02,449511424,ca9e9747,f589408bcf964b56847f8cd5bb432f0e,c06cb709355e10feb0c4af5982a179584a1084c5 -4118,Sony PlayStation Portable,Hot Shots Golf: Open Tee 2,,Games,Asia,UCAS-40213,1.00,942899200,12a87a73,de907db7e8601a179bbaafeab3961029,4fc38bafc074facc6073eda1f01eacad08726c66 -4122,Sony PlayStation Portable,Mind Quiz: Exercise Your Brain,,Games,Europe,ULES-00555,1.01,83525632,3db7a639,b9f688569021f61b01ae3cbceefe33bd,1f33a3f88de96339b9794fdb0cebb6d2c031e6d7 -4138,Sony PlayStation Portable,Final Fantasy II: 20th Anniversary Edition,,Games,"USA, Canada","ULUS 10263, ULUS 10263-F",1.00,287342592,541fa240,9ac65ede66cdc40ff791f8be7709b0c2,bbd97b3aafa741bcaae738d8a0e1466574f7072d -4141,Sony PlayStation Portable,Gensou Suikoden I & II,幻想水滸伝Ⅰ&Ⅱ ,Games,Japan,ULJM-05086,2.00,849149952,d64b83ad,d25e287aae12c1aa6882983578ffa046,f248605b242b63df0d0730b5bf39c5fc0f8a7c5b -4169,Sony PlayStation Portable,Untold Legends: Brotherhood of the Blade,,Games,USA,ULUS-10003,1.02,855015424,31d8d99d,6716e0d22aef7a07fb61508fe618e983,dd4e24822aacade3c8de9777b99760a733860317 -4185,Sony PlayStation Portable,B-Boy,,Games,Europe,UCES-00249,1.00,1775534080,72c1b493,d489955e453030520affff6e3e04d588,0319989e11e82afe505da65c9f00e72085a85935 -4191,Sony PlayStation Portable,AI Shougi,AI将棋,Games,Japan,ULJS 00101,2.00,25001984,2ae71ff1,a68bfb1fb79bb7a3c1dd06fac06ef05e,ddf8562b1ed76d95a9a80736e270643a19a19532 -4224,Sony PlayStation Portable,Secret Agent Clank,,Games,Asia,UCAS-40218,1.01,1516077056,5d599e22,19aa7ead37bd5ad21adc31a261ef7825,7f8df0d33017d728a1b80bd7b134561f763df914 -4256,Sony PlayStation Portable,Blade Dancer: Lineage of Light,,Games,USA,ULUS-10124,1.01,388628480,e14f71f1,fbf3eab0d2f6f7451d4654175c7558b5,419555f44a90476f422bdcad0e8e0582772ea0bb -4257,Sony PlayStation Portable,Gradius Collection,,Games,USA,ULUS-10103,1.01,349437952,0da989a2,aeeaf803cc284de1d17f75f23ff4e768,086cad4bd3a5312ffaa839f4109c33266032abc6 -4258,Sony PlayStation Portable,Mega Man: Maverick Hunter X,,Games,USA,ULUS-10068,1.01,470515712,d6a7005f,4efa02c0de296d192ae3b8b1f1fdf4da,ef19fda8cbf86c401fa24c20347c17a429720a69 -4259,Sony PlayStation Portable,Dragoneer's Aria,,Games,USA,ULUS-10291,1.00,388104192,0c43a987,db9ec0a815424ba20def9652eb1b8201,180bbb61d3b081b492a3fb6b8bb325c9bf551c4b -4260,Sony PlayStation Portable,Metal Gear Ac!d,Metal Gear Acid,Games,USA,ULUS-10006,1.00,201392128,088b4aa7,5f58207712359a233f9d46951bc292b3,d29eaba896be28c2575ead246bdaa3a9712929d4 -4261,Sony PlayStation Portable,Shinkyoku Soukai Polyphonica: 0~4 wa Full Pack,神曲奏界ポリフォニカ 0~4話フルパック,Games,Japan,ULJM-05347,1.02,880967680,ddb9f52f,52d484798306d9a3116f46c6ab83f41d,9dcf036b5d6373c013fddca6d893c0b3fdc298df -4296,Sony PlayStation Portable,Virtua Tennis: World Tour,,Games,Europe,ULES-00126,1.00,388890624,cb7ba251,e43eb9385dde15fe32c9d2f27836030b,8a9b71ec8f8757e1441d761f337e03a375969139 -4338,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,France,ULES-00734,1.01,906362880,3dbeb0af,1d1ad2a2a48768691facd71e09b9d026,420814d7c802a0a22283cae2f1b4e7d5d4cabb53 -4348,Sony PlayStation Portable,PoPoLoCrois,,Games,Europe,ULES-00291,1.01,1056440320,887086e3,5a728261e0691df65494c1d7244c731c,534085718a83c226b6fc7d012577afb4650cf3ed -4355,Sony PlayStation Portable,World Tour Soccer 2,,Demos,Europe,UCED-00350,1.00,906362880,2f8aca84,6adaa87ba34229badb704d2d647f2435,0654a87908a83e1f372d6b7e20066b42c6431b43 -4378,Sony PlayStation Portable,B-Boy,,Demos,Europe,"UCED-00432, UCED-00432/9681373",1.00,76480512,00762055,049aaf8f7cccb3dd093ddd346ccc5211,a6833890c90997993a17e46c72b737939ea10c5b -4379,Sony PlayStation Portable,LocoRoco,,Demos,Europe,UCED-00365,1.00,48726016,8708594f,f5a7266e73c43792af7ef5ed7ed85f86,0e404de15e3870a1fb823b579a5f2de7d4fa4f84 -4380,Sony PlayStation Portable,PoPoLoCrois,,Games,USA,ULUS-10018,1.03,1259372544,607c1d09,2881ef285d3ad2233237d7aa912155c5,ee5a710e2f5956b24c4a5fca86f21e6c6fcfdad4 -4393,Sony PlayStation Portable,Mortal Kombat: Unchained,,Games,Europe,"ULES-00353, ULES-00353#",1.03,1439170560,0a76110a,aa8873e87e1c9924fbb22b6f93e10de0,493486aebb6e041d63ae56b2d1105352d5954a85 -4394,Sony PlayStation Portable,Mega Man: Maverick Hunter X,,Games,Europe,ULES-00251,1.01,470515712,c8c08481,33c5fa5291b0737cb54898ec6ddb3240,43a29f9b670acd2ebb17f93c1046009c877c010d -4395,Sony PlayStation Portable,Key of Heaven,,Games,Europe,UCES-00178,1.00,1150779392,ffa56a4d,99be6ec5715fde1f82b39c9ae26f4d6d,41147dbe2eacd3afa93e4cf92e682170f171e5f1 -4396,Sony PlayStation Portable,Infected,,Games,Europe,ULES-00338,1.01,902856704,5ee73904,1dc05f9e7ce6541d5f37f5c7b5f47dad,6abf2787092289de1208c3241699a106c390f3c5 -4399,Sony PlayStation Portable,Gurumin: Une Aventure Monstrueuse,,Games,France,ULES-00628,1.02,1104347136,cf3dfbb8,dd12c3ae34de00127e114256e00f74e8,6b5c5e5726404e82a52f63fa6ab50f853ee834c7 -4400,Sony PlayStation Portable,Gradius Collection,,Games,Europe,ULES-00381,1.00,360349696,0a781a87,930902a515a6e069aab5bac6973c3fae,66a932b906f2fee90d8fd73a53442138d279dd46 -4401,Sony PlayStation Portable,Final Fantasy II: 20th Anniversary Edition,,Games,Europe,ULES-00987,1.00,354123776,3c08ae0b,763c9acf981e27793cf64a2031036630,7b9baed6cd99cab24a6382ea3151620ddacbf9b8 -4404,Sony PlayStation Portable,Daxter,,Games,Europe,"UCES-00044, UCES-00044/P",1.00,1405976576,a802cf6e,cfb1e3cc6d999c17ec82eba0a469cf9e,9cc8455edbe337b6ea0058299e2b0f833850519b -4405,Sony PlayStation Portable,Crash Tag Team Racing,,Games,France,ULES-00169,1.00,1540161536,4ac96d6e,8e04b7c6f769fae17521027795a80881,35f220f39425c188522ce9c509419ead2e4b9c9b -4527,Sony PlayStation Portable,Crash of the Titans,,Games,Europe,ULES-00916,1.01,1104805888,41a3a76d,278168c2364755553d7842258a9eec05,3d1e1fb32c01e0584c1bd7fa9cdfe9f0df049ac8 -4528,Sony PlayStation Portable,Castlevania: The Dracula X Chronicles,,Games,Europe,ULES-00841,1.03,1173979136,b05e8f9c,79cb4bf458048efc453889615ac0dd46,25bb86c2c86f29e8a9d09ee0ae2a45fc6252befb -4529,Sony PlayStation Portable,Metal Gear Ac!d²,Metal Gear Acid 2,Games,USA,ULUS-10077,1.00,917307392,0c3ac8cd,84c713bfb1eaeb55372efc2bb7fe0df3,87cebe80a93c4231bdbab26ad630c6d8e2fddab5 -4530,Sony PlayStation Portable,Ridge Racer,,Games,USA,ULUS-10001,1.00,906362880,19735d9e,ef89c58442f1c17ca3d060f0077d67b0,4fd0b59f199697756372ceab4c8c908fa6140cd2 -4531,Sony PlayStation Portable,Me & My Katamari,,Games,USA,ULUS-10094,1.00,1768947712,630c0b2f,a8234b8e63e48a1ce888d3dd89faba56,b84f85de8b7fe7266bc45ae22bd012d7d721d9b1 -4536,Sony PlayStation Portable,Metal Gear Solid: Portable Ops,,Games,USA,ULUS 10202,1.02,1393426432,78c4eabc,843867e814664dedc82252fda1d05e8c,706191720f78fe639eac20d3302d03b36a88e8e9 -4537,Sony PlayStation Portable,LEGO Indiana Jones: The Original Adventures,,Games,Europe,"ULES-01086, ULES-01086#",1.01,1241153536,a7ef30f6,ae086df7bf21a7063f11e61c840d5690,10ad72f71aa05f0a3f20176c35f414660fb43631 -4538,Sony PlayStation Portable,Taiko no Tatsujin Portable,太鼓の達人 ぽ~たぶる,Games,"Japan, Asia","UCAS 40022, ULJS 00020",2.00,430866432,1f46d394,617c36f972cea64db3de83b08da0c411,b1826b481cc0f127999dfc771f9d2e3cbf8a3b2b -4541,Sony PlayStation Portable,Astonishia Story,,Games,Europe,ULES-00363,1.01,115539968,c15489e6,cd16abcc0d0ce44c380ef0fbf8b3d165,ed9990fd19d917ff2e60f44103c7904519bb9bc5 -4542,Sony PlayStation Portable,Capcom Classics Collection Reloaded,,Games,Europe,ULES-00377,1.01,582811648,7b3cb07a,32159e3acd1fa95d63cca544ad341ea2,6f91fd462acae25b1615d508f2683ce9e9b555c1 -4543,Sony PlayStation Portable,Mega Man: Powered Up,,Games,Europe,ULES-00307,1.00,311721984,4f848703,b6a9cbbe447bbe9a2e465683cdf2855e,899af5ad3940187904aceb2d5cf9aec97cab8482 -4544,Sony PlayStation Portable,Puyo Pop Fever,,Games,Europe,ULES-00294,1.01,182878208,1b62ba6f,b8dae0e8e70a4f7350d8e6d4c86ab7ba,14b6b6357ad50978793bdf6e5d5fb904105ddbd1 -4545,Sony PlayStation Portable,PaRappa the Rapper,,Games,"Europe, Australia","UCES-00775, UCES-00775/ANZ",1.00,377290752,e6c28cb8,cbf42ba0bf7579762ddf95bc18a98f8c,dacf134b56bb66178f841b8e228023df34d15968 -4546,Sony PlayStation Portable,Lemmings,,Games,Europe,"UCES 00109/9644064, UCES-00109",1.00,450854912,11bd71f4,91ee5fea79a942803d0223b28437e8e5,3af171f6670c4bf66d26a9000f4642b3929a8b9d -4547,Sony PlayStation Portable,Gunpey,,Games,Europe,ULES-00648,1.00,768344064,1283f69c,38aca3215f9e751994778814fe5ba626,130887e61ed931a5e7324bb6c252071054a12527 -4548,Sony PlayStation Portable,Final Fantasy: 20th Anniversary Edition,,Games,Europe,ULES-00986,1.00,265519104,e49d15b5,049010e99f5c83e624b183131378e082,6b4a31b347d75e8e04b55c01444d75d4f8175bd6 -4549,Sony PlayStation Portable,Everybody's Golf,,Games,Europe,"UCES-00012, UCES-00012/P",1.00,563609600,48d34501,60cd2ff62db73a38291cc7517c15cb1b,b53b101d402129017af7a13b562464f589abd514 -4559,Sony PlayStation Portable,Dead to Rights: Reckoning,,Games,USA,ULUS-10023,1.00,193167360,0cab5a5b,3fb61f0f7bf35f883d4805e6d3dd6bff,3ebc9371e208efc11b900d3fcced9cf9e2c8de52 -4560,Sony PlayStation Portable,Prince of Persia: Revelations,,Games,USA,ULUS 10063,1.01,1696006144,d12deea8,f1f030e66777f3c0811c9d77c38e5724,079a5217c29494c84298be8ce3a8807d00b5081c -4563,Sony PlayStation Portable,Saru! Get You! P!,サルゲッチュP!,Games,"Japan, Asia","UCAS 40090, UCJS 18006, UCJX 90029",2.00,750747648,1056a1db,82f2ffec51c64b01a1f7f54c1395c0b4,b6db439a142a2a7a44439c181945bff414d71cd2 -4564,Sony PlayStation Portable,Parodius Portable,パロディウスポータブル,Games,Japan,ULJM 05220,1.02,382992384,9c536bc0,8c7b8a13d4d7d0df4596aa54b601f51c,06ad24488c1f18c5cba29b9004101cc6830358d7 -4565,Sony PlayStation Portable,TwinBee Portable,ツインビーポータブル,Games,Japan,ULJM 05221,1.01,198639616,6afb1450,0cf653399aa227f56604f396c3b9ff8e,cc4eae1cdc6997f863b610477e947fa81da27e68 -4566,Sony PlayStation Portable,Sampler Disc for PSP Vol. 1,,Demos,USA,UCJB-98301,1.00,1779040256,047eea16,ac7a13ea7d970501e922244ed068deba,05f2028b80728973a22a1eb8075e810755d5cbe0 -4567,Sony PlayStation Portable,Phantasy Star Portable,ファンタシースターポータブル,Demos,Japan,ULJM 91014,1.00,751140864,1df7fafc,84d4a37a8cc8880c14d672a86ed9370d,ea57097bc163b57216684c63a332aa52a9d944c8 -4601,Sony PlayStation Portable,Exit 2,,Games,Europe,ULES-00620,1.01,164659200,fbcfe225,8e8762568ab58f56cd6b23f7c45fbe20,f4ce7bf32e5f070f3c05f477a236bf68178005c7 -4623,Sony PlayStation Portable,The Legend of Heroes: A Tear of Vermillion,,Games,USA,ULUS 10022,1.01,669974528,2d64283d,32f942dcc2760b6643d88c7ce0aca445,3a64a3f7ed6f773824d306ed7e70e7f3a89ef85f -4626,Sony PlayStation Portable,Super Robot Taisen MX Portable,スーパーロボット大戦 MX ポータブル,Games,Japan,ULJS-00041,1.04,1295122432,8a86e33c,448d168edcd3edfe62cdcb9b31c87820,8f0b644a3cfd2a813f32ca9b668bcef4729691b2 -4630,Sony PlayStation Portable,Harvey Birdman: Attorney at Law,,Games,USA,ULUS-10324,1.00,1720614912,da6f3a5a,920750aacb762e00068bf55d6e6d47b4,e90f948fd7ee03d9f49500dce8581f0dea7bd3c7 -4634,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,UCES-01042,1.00,906362880,564fd441,f45f0bf2ef335a3004e0b9631eda47cd,160ffed8360c0bb2388cde8848b0f82800d72501 -4640,Sony PlayStation Portable,Generation of Chaos,,Games,USA,ULUS-10075,1.02,1134854144,6202f2bd,932db9ef1b5dfe31799837841ac0ed79,61287e76dc3962bc18f9de1c0814e814cb61147f -4641,Sony PlayStation Portable,Aedis Eclipse: Generation of Chaos,,Games,USA,ULUS-10242,1.00,668991488,24767759,2e80e2ef6d8b85c6a522eae32525a04b,0311898a53261fd837751d1acd4bb932c06e3c52 -4642,Sony PlayStation Portable,Spectral Souls: Resurrection of the Ethereal Empires,,Games,USA,ULUS-10076,1.00,1207566336,9874e2ab,e14a7f0d0ef32274aab2cd280b304239,fbde14433f42964d89105b819d7004f80b28b874 -4643,Sony PlayStation Portable,Tales of the World: Radiant Mythology,,Games,USA,ULUS-10271,1.00,439713792,94288d85,38243ebc5de9eee1f5d6606b08de9d0e,ee3ff62234297b326ac8ac38ea3042efd8f64586 -4644,Sony PlayStation Portable,Jeanne d'Arc,,Games,USA,UCUS-98700,1.00,1247412224,d15fe905,306f1eb4c983a555f3b548ad7c09386e,87b0e5fdbadaa0741adf5a5007d25d51639e6f9e -4645,Sony PlayStation Portable,Yu-Gi-Oh! GX: Tag Force,,Games,USA,ULUS-10136,1.03,701693952,083c1a14,9c84d00f5a4c19c38c38b45ac1be3cff,2b0ec3ea6bc453c806e4633aeea4ae00287959d2 -4653,Sony PlayStation Portable,Final Fantasy Tactics: The War of the Lions,,Games,USA,"ULUS-10297, ULUS-10297GH",1.00,418873344,0d6a3d9f,18d1169cefed2d5ed77a599694f2f871,5120ff66f78cfd31f6e90d8ef4be8200eca563f7 -4654,Sony PlayStation Portable,Silent Hill Origins,,Games,USA,ULUS-10285,1.00,804683776,29919aa8,7afd545c11362922bcaa14bebe58dde2,196aaec0a2d9299761d8d7fa8639457a0bf9c981 -4655,Sony PlayStation Portable,Kameleon,,Games,Europe,ULES-00369,1.01,71172096,21481259,961b1ffb7adc0e563f7a791c7ebcaba1,f75d1399b82f0545fef05b9908f112aa44c709d8 -4679,Sony PlayStation Portable,Magic Sudoku,,Games,Europe,ULES-00621,1.03,154763264,622868c1,dbc4a3b7ca99c5c0d54726624c47bfa5,68a84c317d4c7b4b5ba94621f01d052d1f491549 -4680,Sony PlayStation Portable,Space Invaders Evolution,,Games,Europe,ULES-00348,1.02,292519936,aaf7f349,8a600e02b556daca11a02b3ba99d3b47,bffe83787986bce6a63144862982a28476fca959 -4681,Sony PlayStation Portable,Star Trek: Tactical Assault,,Games,Europe,ULES-00623,1.00,255197184,7a57eabc,d3ea7b20bbc5ac86c5488d1b173e9167,f0bb102fdf839cc2cdeb713aa7838e06e008f93f -4682,Sony PlayStation Portable,Zendoku,,Games,Europe,ULES-00692,1.02,76120064,8a4d93a1,ddbed74b59f18a01ab4d2eb061dcf1dd,8590d163bf643b828a2587cdfb8a63e71601aa6b -4683,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,,Games,France,ULES-01045,1.00,1738014720,adde1ec8,65c407503790d76c17e8903985fd848b,5ec993aca7dae519d83e61f31a6024ec170b9495 -4690,Sony PlayStation Portable,Mercury Meltdown,,Games,Europe,ULES-00466,1.01,360579072,79416b54,7da9fb71400dd907dbc83aaf3cedf8ff,24aed1b74fb48e8bd9a51b9e9f20ce924ba28ba5 -4710,Sony PlayStation Portable,The Legend of Heroes II: Prophecy of the Moonlight Witch,,Games,USA,ULUS 10125,1.00,1783201792,60e5f1a5,f8e86ae153bb91c21b922e5ef6337f37,b0a3199407c56b921ea3208624d9f1502cf52971 -4711,Sony PlayStation Portable,NBA 08,,Games,USA,UCUS-98699,1.00,906330112,716082cd,3e7bd831fa14c43e5f1a636255634e3c,7a6330333e71258055a67d364041ef0be78aab58 -4712,Sony PlayStation Portable,The Simpsons Game,,Games,USA,ULUS-10295,1.00,764805120,85cb602d,f98771424dc9a7db684a32b6d0c9667c,832a9453f09d9050ab4a0cbe683e791c9b9acc5b -4713,Sony PlayStation Portable,Fight Night Round 3,,Games,USA,"ULUS 10066, ULUS 10066GH",1.00,1137737728,717c15dd,9a3dc8d27f128d9166439cd2cf26e500,554a1112d2ede23673552088f93f2d8cc4677ce4 -4736,Sony PlayStation Portable,Tenchu: Time of the Assassins,,Games,Europe,ULES-00277,1.01,1788116992,1e6ccb89,dad98b7cb7e84f3881d429a3e31817c5,56e617198f46e631f88e74526c35ae735f833d25 -4789,Sony PlayStation Portable,Namco Museum Battle Collection,,Games,Asia,UCAS-40217,1.01,174358528,247d8274,9ed1a2cceaba803bda9c63f9b52018ae,8f3bb18c51608170bd8bb25e9cdbb7e6d689b5f5 -4790,Sony PlayStation Portable,Harry Potter and the Order of the Phoenix,,Games,USA,ULUS-10261,1.00,763461632,efa07038,d601ecf8b4a6388365da49c498d82e98,01e83e67a56006cf9cd86a5f5f300dfb663462cb -4800,Sony PlayStation Portable,Ace Combat X: Skies of Deception,エースコンバットX: スカイズ・オブ・デセプション,Games,Japan,ULJS 19018,2.00,1121026048,5328bf9d,920d5762c327e0f993956390077f0e3e,774a1db26bc8bc079e295ea27e3f2c45e98e72b4 -4801,Sony PlayStation Portable,Phantasy Star Portable,ファンタシースターポータブル,Games,Japan,"ULJM 05309, ULJM 08023",1.01,1150418944,55d78fa7,e50909cb661679161eedd0bf8df81388,a44eceb6bbeebc917d56310a55c051da8ced0aff -4862,Sony PlayStation Portable,Star Wars: The Force Unleashed,,Games,Europe,ULES-00981,1.00,1397489664,556834ce,2f4529ca279344ca996d1fd132959e7f,f8588146917bf24805d1a220a028a99f78018b71 -4863,Sony PlayStation Portable,LEGO Batman: The Videogame,,Games,USA,"ULUS 10380, ULUS 10380GH",1.00,1136689152,b0e191b3,89e8b16689f4effbeb1a18abe80aff85,38f9886f4f3b69d688c9a6f9482fad9f545c16b8 -4866,Sony PlayStation Portable,N Plus,,Games,USA,ULUS-10340,1.02,110886912,559f5c19,8c980a71c2d74a289233f41236c9ba65,313321ab3c432af14869a572b832db2ba330ee60 -4882,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,USA,ULUS-10041,1.05,1255243776,87e2772e,d08daddc86356f2cf5fdfa85cdcd0c91,50c853c43eddd460407c8949e3efd37a0c87b10e -4886,Sony PlayStation Portable,Disgaea: Afternoon of Darkness,,Games,USA,ULUS-10308,1.00,969801728,4e1b2cfa,3fb3a14d033fdb3a60d5e1cd06ab1e25,f701a74bb9d7de8ae5ecb17e2176167f2a09f896 -4891,Sony PlayStation Portable,Twisted Metal: Head-On,,Games,USA,"UCUS-98601, UCUS-98601GH",2.00,838664192,7861ecc5,8103244c663df42e7de228ac37c01024,1df406ad3d456cea9bcde58270ae085683e44f5d -4920,Sony PlayStation Portable,SNK Arcade Classics Vol. 1,,Games,USA,ULUS-10338,1.02,1397620736,673f7361,e924a0483edbc5bd0a995b610ebc9168,6b15bda764c756501e783c6bacb72dbf6f89ddf4 -4952,Sony PlayStation Portable,"Nogizaka Haruka no Himitsu: Cosplay, Hajimemashita: Himitsu no Radio",乃木坂春香の秘密 こすぷれ、はじめました♥ 秘密のラジオ,Games,Japan,ULJS 00161,1.00,192380928,6141a2a6,011dab4630a95562eea6820868859894,6c9825cf5589b48b1cd93a4433c40a7ff46af610 -5065,Sony PlayStation Portable,Disgaea: Afternoon of Darkness,,Games,Asia,UCAS 40223,1.00,969801728,c4e0a4e8,f24df376f8e454c35e36aa809e87d6e0,5c10497368c9e7b7500ff597c1a145ec21b11b70 -5066,Sony PlayStation Portable,Dragoneer's Aria,,Games,Asia,UCAS 40224,1.00,388104192,79cde3b2,d3760de9b531bd0a3e20b1359091be8d,e0c19be27387577f7a2de030dd5f0c5dd7321bc4 -5090,Sony PlayStation Portable,God of War: Chains of Olympus,,Games,"Europe, Australia","UCES-00842, UCES-00842/ANZ, UCES-00842/P",1.00,1651015680,4704d399,0e72ac4ff25bbc3481141671fd59b7ba,9ad18ab173658b79bc73a346ed1aea2c87573b59 -5193,Sony PlayStation Portable,Tony Hawk's Underground 2 Remix,,Games,USA,ULUS-10014,1.01,1216184320,388f6d86,cb85a7f2c90922502622bf2daf716ef5,4862fcdcf59ce1cde80761cc017b91c62ab1f983 -5324,Sony PlayStation Portable,Star Ocean: First Departure,,Games,Europe,ULES-01154,1.00,1150746624,434cfd0f,1f3e0128e5c2f1a10a4a55ccac1d00a1,2c7afac802d2e868980ffdfe0bd5aac8be89c6d6 -5357,Sony PlayStation Portable,Lara Croft Tomb Raider: Anniversary,,Games,Europe,"ULES-00826, ULES-00826/0030381",1.02,1291190272,bd4d5739,eee22318f8a8aed5a473600c39de5a1a,6bbfca4679c2e2a887b4b18efdaa85938115e49e -5373,Sony PlayStation Portable,SSX on Tour,,Games,Europe,"ULES-00192, ULES-00192/FRA",1.00,1414037504,3ae622e9,cb7bc13449fe8faccd7ee563bcc686c2,b177678e847c3e1bdb2f1754fb804fd9de7f506e -5445,Sony PlayStation Portable,Darkstalkers Chronicle: The Chaos Tower,,Games,Europe,ULES-00016,1.00,690782208,ce97d883,f7ca6e843435b9f4d20b75fed8c1397a,e668ddee63951a67c7d6211a27aeedd3d5ddc989 -5472,Sony PlayStation Portable,WipEout Pure,ワイプアウトピュア,Games,Japan,UCJS-10007,1.02,253493248,b2254fa6,3dfe54e6a4f51f23937a9044f4122aa4,923fa9252a59c0fc3948ff051095f6bf71ff93a8 -5473,Sony PlayStation Portable,WipEout Pure,,Games,USA,UCUS-98612,1.04,252968960,fd305564,fcd1476a60705344444d7f2a6c7aeca2,30d4d9bccb5a6615de2a997cd35e74696ae5389b -5474,Sony PlayStation Portable,WipEout Pulse,,Games,USA,UCUS-98712,1.00,456949760,1744839d,df6a43b2ee58506c2618afc9ce3e73fa,8effaaae1c7a400d93ae8da554125e20be045df8 -5476,Sony PlayStation Portable,WipEout Pure,,Games,USA,UCUS-98612GH,2.00,252968960,4502c588,33de1457c7b66662a3ba2712a66882bb,a962afd113f5d178c8acac4a9dc7c3ee7c6b0a26 -5564,Sony PlayStation Portable,Echochrome,,Demos,Europe,UCED-01060/9992851,1.00,195690496,3cdf00c8,81df3cb483951582f6dc98e8bcd93383,d07c62040d59e8b8dbfcb02e0b684909c9aa0a7f -5565,Sony PlayStation Portable,WipEout Pulse,,Preproduction,Europe,UCET-00713/9482154,0.07,404848640,89fc29a8,33216c9e7e01d3ae8f9e9cac679bb0fd,a395d61a858d9f91796b4ba81211437f68b2b15e -5832,Sony PlayStation Portable,PaRappa the Rapper,パラッパラッパー,Games,"Japan, Asia","UCAS 40135, UCJS-10046",1.00,330989568,3564946a,db9d2942f81154a2028561580ad5af72,3e298e86c89c35c3166cfdb654464933b4c76a23 -5846,Sony PlayStation Portable,Midnight Club 3: DUB Edition,,Games,Europe,"ULES-00108, ULES-00108#, ULES-00108/P",1.01,1643380736,2c57a623,211d246f47c87723cdbf3c0a4d1649ef,73f1ed9c6ba8b97227ca25564c0fc3a8d3b7775d -5847,Sony PlayStation Portable,Ace Combat X: Skies of Deception,,Games,USA,ULUS 10176,1.00,1121026048,c41a1a1a,e86516c3815574402622e9e9a849e70a,357e3cc2e0434ccd41650943bd9af71fff00a23e -5848,Sony PlayStation Portable,Gangs of London,,Demos,USA,UCUS 98689,1.01,196214784,e915a134,4924784e93da581c6c7f602eaa591447,2c11dd0cf783853fe1acd4c27835dfdf8e9f48d6 -5849,Sony PlayStation Portable,Gundam Battle Royale,ガンダムバトルロワイヤル,Games,"Japan, Asia","ULAS 42083, ULJS 00083, ULJS 19015",1.02,686456832,efeed69a,cd0d2ea4b4b40790c814e89916a43ab8,d250dff383d7f238c4f7109d1edc67f704e37a8c -5850,Sony PlayStation Portable,Killzone: Liberation,,Demos,USA,UCUS 98670,1.00,72646656,6b395df7,c03fa57d1fa4df93e3ca92fd05bc85a6,21dcbfd2099085bc6196ce6c02e065faf8a4e21e -5851,Sony PlayStation Portable,Lemmings,,Demos,USA,UCUS 98671,1.00,181665792,d4fe1564,289924fcdc8e44b3fd5b07d16f80c797,a2e4718d158efc416912663a387f0299730792d2 -5852,Sony PlayStation Portable,WipEout Pulse,,Preproduction,Europe,UCET-00713,0.02,526581760,247f0941,2d827f7bc9a672815f3bc83311b9d53c,bdacd20b153c04af83a7d027aa94fc27f56b13d0 -6237,Sony PlayStation Portable,Prinny: Can I Really Be the Hero?,,Games,USA,ULUS-10407,1.00,491880448,af9da20b,8b5e9c639c26eafb9fde76843cabb112,f8371f17aab2764baa92ca2a2df4c89c171a6330 -6449,Sony PlayStation Portable,Gundam Battle Tactics,ガンダムバトルタクティクス,Games,Japan,ULJS 00025,1.02,278200320,75830a53,1a986d258399b1e4bf989c0cd3a7d25f,40de09fb4789c49e34adce101bf12e941ba4ff64 -6450,Sony PlayStation Portable,Macross Ace Frontier,マクロスエースフロンティア,Games,Japan,ULJS 00158,1.02,646938624,fba3dbe1,6f6497855583220ac6e320291efcf3be,5ee8c6967cbe36315a339253dea53d6437030228 -6497,Sony PlayStation Portable,Midnight Club: L.A. Remix,,Games,Europe,ULES-01144,1.04,941293568,da5ce22e,730b175c2997a1ca7710c99ddbf8d4ab,ea3f53a8252427c2626124a461e1bfb83df9c822 -6498,Sony PlayStation Portable,Echochrome,,Games,"Europe, Australia","UCES-01011, UCES-01011/ANZ",1.00,195821568,5b63a643,d74e0e9628c674464bf73eeb978984ea,596775f8f7bc7967bbfee7f34f1faf2e208767b2 -6499,Sony PlayStation Portable,Monster Hunter Freedom 2,,Games,Asia,ULAS-42110,1.01,837156864,3b26919f,9dc0de0d6fb1a77707593bdddacc04cd,63c5071ce394d80d45e12b56c481fdac719c8ce4 -6504,Sony PlayStation Portable,Ultimate Board Game Collection,,Games,Asia,UCAS-40238,1.00,199229440,c88de8a7,38f2d6069adf3f3bcc6337bc84b92509,0bb2800a75ede148d069fd6c0ea85875f0939d66 -6515,Sony PlayStation Portable,World Tour Soccer,,Games,USA,UCUS-98613,1.01,520126464,9e9c2c84,5c10383c9c875620f2b7f2c5c2405bf7,055ac5c0f596b2872cbaf6044aea401c10de56f7 -6529,Sony PlayStation Portable,Hayate no Gotoku!! Nightmare Paradise,ハヤテのごとく!! ナイトメアパラダイス,Games,Japan,"ULJM-05415, ULJM-05416",1.02,534577152,3be81c48,c8d0252770c13a1610a62b9cc3fd15f0,0280243586f0fa9446da1212e6ed959d4afdb247 -6637,Sony PlayStation Portable,Prince of Persia: Revelations,,Games,Europe,ULES-00223,1.01,1696792576,d2466fdb,b284f9a30cc553bacbc1c1f759a8a812,2342b55a969d76d717d4393da58af1f95f8ddd44 -6796,Sony PlayStation Portable,FIFA Soccer 09,,Games,USA,ULUS-10369,1.00,1708359680,2621c452,d9691839d07386a6b6f0a4019bc0a2ea,7c5991ea6f99ff03705837e85cd88f26fe128c1a -6982,Sony PlayStation Portable,Rengoku: The Tower of Purgatory,,Games,USA,ULUS-10013,1.01,178978816,b86f96e9,a70730895b3fa359320b13637427a961,a55ecdc0abda829184954dbef2202d3a4ad4fc31 -6983,Sony PlayStation Portable,Need for Speed: Underground Rivals,,Games,USA,ULUS-10007,1.00,884801536,8617d87d,bafdc1c7c0076a5ca42212e45e5f2ea9,ceff8f80e17cde78dfbc18a1a6ff2c5bf323a872 -6984,Sony PlayStation Portable,PQ: Practical Intelligence Quotient,,Games,USA,ULUS-10046,1.01,178651136,c42719e5,ea676645bb62d0bdaecf21b5253fa271,65a5ae87aec7c086717e0797065bfcb2f6614af0 -6985,Sony PlayStation Portable,Sega Mega Drive Collection,,Games,Europe,ULES-00556,1.01,867106816,33102728,3d4c2788c2290147e3c24f10dc73fc84,2cabb0cfd20f0985eee10f34cf2b9bee1598e54a -6986,Sony PlayStation Portable,Need for Speed: Undercover,,Games,Europe,"ULES-01145, ULES-01145/P",1.00,1470758912,50c805aa,3931fcedf70b7a1f862de44daf8b6c71,5afcb4c765c56c951bdb166a1ec391535b89a515 -6989,Sony PlayStation Portable,World Tour Soccer,,Games,Europe,UCES-00003#,2.00,331284480,15f85662,0c08e4c58df822d058f4f2f5dd7d1d6f,4510dd839232d9965ebe9b5d29559482b7a1041f -6990,Sony PlayStation Portable,Yarudora Portable: Sampaguita,互動式動畫AVG: 茉莉花,Games,Asia,UCAS-40034,1.03,1250885632,202e8f43,5ba775f1b6a8947c4eded44c909279e9,b246d7b9b2b8d9daf345e933decc5e589b05ca42 -6991,Sony PlayStation Portable,Yarudora Portable: Kisetsu o Dakishimete,互動式動畫AVG: 擁抱季節,Games,Asia,UCAS-40033,1.03,1256488960,3f981cbd,663fe287e899259deb12bc2f29263a92,d07e9e94ee9670c28ae576a25ca64436f6a18740 -6992,Sony PlayStation Portable,Yarudora Portable: Double Cast,互動式動畫AVG: 雙重角色,Games,Asia,UCAS-40032,1.03,1226801152,242b7792,f9b73e3238e186ef7c3297c1b4d196a5,84c7742d6751698b9dec3883aed4b66489af8352 -6993,Sony PlayStation Portable,Kuru Kuru Chameleon,回轉逆轉變色龍,Games,Asia,UCAS-40053,1.01,69566464,e2dea3f7,115a34ef0f8b3108d74d8feb7f0b0436,b52d5f798810a7648ead10027e8a384706264bd8 -6994,Sony PlayStation Portable,Shin Megami Tensei: Devil Summoner,真・女神転生 デビルサマナー,Games,"Japan, Asia","UCAS 40047, ULJM 05053",1.02,409468928,99ce4130,c369a1fa35489fb580b9c426ea37fb9e,f5f129abbe3a44aadd07ea548314e9d51fc25ab3 -6995,Sony PlayStation Portable,Karakuri,カラクリ,Games,"Japan, Asia","UCAS-40042, ULJS-00029",1.01,328400896,dc965695,d99b844fd52f21975c09cb315623aa83,fc2f9a779bb655831227662ae6470831543f3cb4 -6996,Sony PlayStation Portable,Shinki Gensou: SSII Unlimited Side,新紀 幻想 SSII Unlimited Side,Games,Asia,UCAS 40027,1.04,1701380096,8329c7a5,4e6bb1daf3300d0c2ad475b302a7624e,6620d992ff517d90e317f3b1736f61455daeef92 -7145,Sony PlayStation Portable,Hammerin' Hero,,Games,USA,ULUS-10392,1.01,227966976,46092fcc,ba93b1d981c4541bf8afc987db2519c5,b4dedf79638060084734b0d54d2f8e44882a95cc -7149,Sony PlayStation Portable,Jitsuroku Oniyome Nikki: Shiuchi ni Taeru Otto no Rifujin Taiken Adventure,実録鬼嫁日記~仕打ちに耐える夫の理不尽体験アドベンチャー~,Games,Japan,ULJM 05100,1.02,151388160,bd09a8ea,62a653f8ad37b944ff40a733e03158b3,e94a818de055411d0bd234db7031a279f97cabb6 -7150,Sony PlayStation Portable,Jui: Dr. Touma Jotarou,呪医 Dr.杜馬丈太郎 ,Games,Japan,ULJM-05098,1.02,415072256,31b99070,579f4263f6287287429e1a824ad1a19a,86b31da1f815beca0beba1ebd0580e4dd967009c -7151,Sony PlayStation Portable,Sanguozhi V,三國志Ⅴ,Games,Asia,ULAS-42014,1.02,227213312,b568caef,675b96cec84945034d1e37b610b653cd,482c742e6534ac510a74486bb1b0cdf7cd2540e3 -7152,Sony PlayStation Portable,Simple 2500 Series Portable!! Vol. 2: The Tennis,SIMPLE2500シリーズポータブル!! Vol.2 THE テニス,Games,"Japan, Asia","UCAS 40160, ULJS-00038",1.05,109019136,bf368756,d83c66869638fa0a26a03957cea1b6ae,e295a0aedd1e39a9a94181042c6be5281ca95f1c -7179,Sony PlayStation Portable,Passport to... Prague,,Applications,Europe,UCES-00244,1.00,805896192,893d31dc,17dd5a7447ae7d971e33a17eddc463f6,2674821cfa92fcf3ec533517da36ea16b62b9b13 -7180,Sony PlayStation Portable,Power Stone Collection,,Games,Europe,ULES-00496,1.00,517341184,5514a40b,6aa17db15dfe07db7cc9e1ae5af4e490,54c5b955a7a13c48e56dbad99ffd8831e5da7cf7 -7181,Sony PlayStation Portable,Tiger Woods PGA Tour 06,,Games,Europe,ULES-00153,1.01,1301381120,e56d4d38,74b0bdd2dd97adbe3d24f365e15ec129,a99ed2e6d257f773e8e8c68eb15a1a2ac17dd447 -7182,Sony PlayStation Portable,MLB 08: The Show,,Games,Korea,"UCKS-45085, UCUS-98696",1.00,1452965888,7dd73931,b1145851132f82a18a5f80e1f8ed9ae4,4ce18b7eb26639dcbde83a23706e69d47c47549f -7197,Sony PlayStation Portable,Little Britain: The Video Game,,Games,Europe,ULES-00840,1.03,307265536,3f604077,4c1191d6c35fd6647b14daa58cd51cb6,1bd85607cc7621118d5eee3843d00c81377403bd -7198,Sony PlayStation Portable,SNK Arcade Classics Vol. 1,,Games,Europe,ULES-01105,1.01,1397489664,6b826eb7,7bb22cd18aef8841f6adb9890204ec75,0c2c416a0f99eaf653850f0895fa61ecd6b7d9eb -7247,Sony PlayStation Portable,Kazook,,Games,Europe,ULES-00517,1.01,882933760,c81741b7,8b4bf850dbc608e70300221e7ab746d0,88600808ee3d8cf14244416bce088fdc08c54b83 -7248,Sony PlayStation Portable,Passport to... London,,Applications,Europe,UCES-00240,1.01,835321856,56756627,f5c6dd5c8c58b06a2f84e32c994e3d0c,9b2577a406a637db89ba9189d189e86d7a83b40d -7275,Sony PlayStation Portable,The Sims 2: Castaway,,Games,Europe,"ULES-00945, ULES-00945/1.00, ULES-00945/P",1.00,1034158080,b348fd81,e6588e176dfbe3771fd3e18338160f8f,a72da3aac68a5efb73976d73727681f2b5a10677 -7344,Sony PlayStation Portable,Passport to... Paris,,Applications,Europe,UCES-00241,1.01,825655296,da6766e5,572bf9b906c3fa0bf73ae0bdc7bf6172,af89f8165969fcb63149afa3bceacd497792a82b -7347,Sony PlayStation Portable,Bomberman,,Games,Europe,ULES-00469,1.02,156139520,fab78732,b1f2678d86be1744620228bf858df371,016faf02668ec745bca9b56441d54876e6ee0fb5 -7412,Sony PlayStation Portable,Eyeshield 21: Portable Edition,アイシールド 21: ポータブルエディション,Games,Japan,ULJM-05108,1.01,884768768,39e32455,614a68f5da386a0a9f3bec6908f53a06,e564f298494c6f0495e72e01cc181314953b742c -7440,Sony PlayStation Portable,Shinobido: Tales of the Ninja,,Games,Europe,UCES-00421,1.00,506232832,388f5382,c89033fa51ce5941de10ac34134757c9,2ef4423b926ef1fed68d3950dc55aa6c7eacbb47 -7462,Sony PlayStation Portable,Shin Sangoku Musou: Multi Raid,真・三國無双 MULTI RAID,Games,Japan,ULJM 05427,1.03,1194098688,82d3bed5,5ee2d615c1f86639dc59781af8f8d504,30291c55404333c1deac419976f701f366d89fae -7470,Sony PlayStation Portable,Dungeon Explorer,,Games,Europe,ULES-00847,1.01,1263796224,d750beaa,a5cf1ab5c26cfe00f7f55344ccb76218,7e72c7e139ac16b8f6dfae769df5a55c2edecd9d -7485,Sony PlayStation Portable,Driver 76,,Games,Europe,"ULES-00740, ULES-00740/P",1.01,1447624704,1e4b46ba,9859618d63dbc724c35cdb397341d98c,e986797c3ff90c6c68098edd6e91c9e7e03884ef -7486,Sony PlayStation Portable,Ape Academy 2,,Games,Europe,UCES-00302,1.00,1032093696,849b557e,83a86362f9376c0c7968f0126eb63281,c966efd1f8f950bd8260d0d6c26352c7a1c25a2c -7635,Sony PlayStation Portable,LocoRoco 2,,Games,USA,UCUS-98731,1.00,1805778944,ff009f58,d7f9a8e11887cd516c0bc50347320bd3,6b0ab29b924028be1443786f7c9d33ab9a1a5376 -7833,Sony PlayStation Portable,Passport to... Barcelona,,Applications,Europe,UCES-00242,1.00,821952512,4322f8c0,2039753aec5e05352948d1f1df85c242,6d586b9d3ab1879d65db4d446a8a9811d6c1a797 -7896,Sony PlayStation Portable,Monster Hunter Freedom Unite,,Demos,Europe,ULED-01244/0991411,1.00,300613632,2d72e319,1a30a6fe0c71e3e1be8ecaf68514f494,946341aef8a2447424c08c1d5f4e66278edadd3d -7897,Sony PlayStation Portable,Samurai Warriors: State of War,,Games,Europe,ULES-00297,1.00,328007680,a2e0d307,4dfaf9159cc37cecf24c94dcaba5acd6,d85620b683bf4598b7d72aa732c24592d099415b -7898,Sony PlayStation Portable,Guilty Gear Judgment,,Games,Europe,ULES-00574,1.02,629506048,7278ce5b,e708e209bd64a0000adf4d75a669846b,ef6185f7713416b36e6750710d8c4f0e0766d254 -7957,Sony PlayStation Portable,Everybody's Golf 2,,Games,"Europe, Canada","UCES-00767, UCES-00767/9986553, UCES-00767/ANZ, UCES-00767/E, UCUS-94340",1.00,1343389696,c91632c6,91471ae69f544651f035d02982464f8f,fd85c6aa08b0f725125d8bcfc83c2e9a66ec643f -7958,Sony PlayStation Portable,Midway Arcade Treasures: Extended Play,,Games,Europe,ULES-00180,1.02,650280960,4643cb94,781565b0db977c039c156d03ede83cae,898226bb6b80923560d2dfd7a745a8dc49080a11 -8147,Sony PlayStation Portable,Capcom Classics Collection Remixed,,Games,Europe,ULES-00347,1.01,571441152,f2ea6e56,19a9c79c22a75feb815b31862a0dbb75,352e3b9843fb043a96118f73b9aa9cbf78ffd287 -8185,Sony PlayStation Portable,Major League Baseball 2K9,メジャーリーグベースボール 2K9,Games,Japan,ULJS-00200,1.00,1698398208,ec7663ed,b701c2002744b4ef6d90e1c34526b96e,224f615d8e80a0dd28934217415288b40d815c70 -8186,Sony PlayStation Portable,Need for Speed: Most Wanted: 5-1-0,ニード フォー スピード: モストウォンテッド: 5ー1ー0,Games,Japan,"ULJM 05073, ULJM 05183",1.01,933232640,e3a98662,34f5826a53e568fa704bbba99306a364,7a6f8ee50a0f40858ebdac093dc90f566c620818 -8464,Sony PlayStation Portable,Full Auto 2: Battlelines,,Games,USA,ULUS-10220,1.01,477069312,d40c2828,2279352f232f3b0a42ea1e6a622134c4,37e0468fddafa977b3d0155eb51f7b49c2c1c772 -8465,Sony PlayStation Portable,Alien Syndrome,,Games,USA,ULUS-10245,1.00,494796800,9676e317,e4f35aff46176ac89c54bcbf8fe01a66,79580f0adc214b9cda8665e2e6b8021b63fef8b3 -8466,Sony PlayStation Portable,Star Wars Battlefront: Renegade Squadron,,Games,USA,"ULUS 10292, ULUS 10292GH",1.02,930545664,f050b8f7,8bcf6293c5fa38adf5eb510d2e20296f,37c320cadb45ffd72f7ad311df77ef80535a72d1 -8467,Sony PlayStation Portable,Ape Escape: On the Loose,,Games,USA,UCUS-98609,1.03,749240320,b86783da,43064561a81f300bb93a4df9c74178b0,373098a849dcdc573499a28c89c92b63376e666d -8468,Sony PlayStation Portable,Coded Arms,,Games,USA,ULUS-10019,1.01,183631872,641d7e2a,f834bbc4e7a52001fe00d3676cbecc66,a6674bc7e62feaffcf75b6f318c26cc5d33056f4 -8469,Sony PlayStation Portable,Metal Slug Anthology,,Games,USA,ULUS-10154,1.03,1328939008,5cc9c5dd,315c3765079675cc7a3b9610f9095115,1bd7913662fd3b3ab99903a34341339676464b04 -8470,Sony PlayStation Portable,Monster Hunter Freedom Unite,,Games,USA,"ULUS 10391, ULUS 17008",1.01,886702080,7fded7ad,b8adbe82fcba1ec0d9feaa341f8ee3cc,f5cb0eaebbf5008bd8d486832229ae97a16bbee6 -8471,Sony PlayStation Portable,Star Ocean: First Departure,,Games,USA,ULUS-10374,1.00,1150746624,6229a106,dfa92699b8f5e73ca316eb159a56665f,360667574a93f84ec026cafab750b5158464c414 -8472,Sony PlayStation Portable,Star Ocean: Second Evolution,,Games,USA,ULUS-10375,1.00,1439825920,d4dbb3b7,b5a7e82a0d01786b905a870a8d512b64,def1cd720dd8522dd04b0465691c720f27e6bf89 -8473,Sony PlayStation Portable,Valhalla Knights,,Games,USA,ULUS-10230,1.01,660963328,bdd74671,8dc3a2e9a588d81e9e316d9dc34ca49e,afa75c5a4c88b0a4a2032602b10210b6ab0dae10 -8577,Sony PlayStation Portable,Armored Core: Formula Front Extreme Battle,,Games,USA,ULUS-10034,1.02,814874624,8862ba8d,ad297308548d44be9216f2128ddc12c1,11c8d1df77cf98864e99eaf36f4ff5c3842106ca -8745,Sony PlayStation Portable,Bleach: Heat the Soul 3,ブリーチ: ヒート・ザ・ソウル 3,Games,Japan,UCJS 10042,1.00,799080448,720fec0a,c0717a02b624e0b6ef7abe514a0ca84f,4da0cd89c7f81d07a47c658e796e59b7326fc019 -9126,Sony PlayStation Portable,Secret Agent Clank,,Games,Europe,UCES-00942,1.01,1580498944,b6b8bad8,39b6d502058854ea68ba0a9383864169,65a6311763c2df53801c7ca92c91e3c3db3da2b8 -9127,Sony PlayStation Portable,Manhunt 2,,Games,Europe,ULES-00756,1.02,1305051136,a11ed0b4,1000295c4f83d4de528aedd36522c040,7a3c19e10c47ec171a854eadbcac3ab448dcce4c -9128,Sony PlayStation Portable,Every Extend Extra,,Games,Europe,ULES-00468,1.00,458162176,aa4b4080,b2f59cbaa507cf7a680b693314586cfa,bfd44a706e4c7a91791a7372989d0c1d918421d9 -9129,Sony PlayStation Portable,Football Manager Handheld 2008,,Games,Europe,ULES-00934,1.01,122454016,59cf419c,5c14dc010dd2ec240ba237fc6ce3696b,a3b9ffa55709d31e1e6e6c746a59a9493fac2a9f -9130,Sony PlayStation Portable,PES 2008: Pro Evolution Soccer,,Games,Europe,ULES-00880,1.02,1520238592,708e4aa0,51c51e67ff5502e7d047249242fb08e2,dc58224f4e4c5873e6f284ccd532ad084a33f9d9 -9134,Sony PlayStation Portable,Football Manager Handheld,,Games,Europe,ULES-00248,1.02,591036416,b279ad22,1698a3c9daed34c6be4c9a17a7a738b1,1f27437b13011906f417a20c34ae2bb1ee007180 -9136,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,,Games,Europe,ULES-01044,1.00,1737654272,4f6de18c,49c3bfe256e2a22169824b41bcf181c8,2a24d2ae3057e9fa6e8f9710e0a50dc306029e14 -9348,Sony PlayStation Portable,Dissidia Final Fantasy,,Games,USA,ULUS-10437,1.00,1646657536,b415ca59,6166fb999e7a0c34044fa7e865d0e270,c0a3ca29f9ea76d64ad0a8ee485ded4e3364a53c -9406,Sony PlayStation Portable,Prince of Persia: Rival Swords,,Games,Europe,ULES-00579,1.06,1008893952,5f6b7645,c4ea4f8e7ba63a69b7f0b5421eff6bf9,f71f9e92e631e6390891efab2aa3897dd91b9d68 -9407,Sony PlayStation Portable,Burnout Legends,,Games,"Europe, Australia","ULES-00125, ULES-00125/ANZ",1.01,500301824,94eff17d,5d7b7ed3eac932754fa51a4ab23338a1,a0401cfa12ce00109dd6759bbaa2aa7bea908458 -9408,Sony PlayStation Portable,Tiger Woods PGA Tour 07,,Games,Europe,ULES-00455,1.00,1256390656,8240f1aa,90c0e728d7d4e685a045564d066addbc,8ea71eeee01262e906de0e9a3a1ed1933df5ec2e -9464,Sony PlayStation Portable,Rock Band Unplugged,,Games,USA,ULUS-10418,1.00,1342275584,fc17daff,31a09b144d841da40e1d10e86ca77bc7,cfe7808c9e29d2dcd09ff2df9738cfb29d560b87 -9472,Sony PlayStation Portable,Jackass: The Game,,Games,USA,ULUS 10303,1.02,1812496384,4b1bc8bf,dbb4611899037caff977f3c64b4a3511,2ddbda1ca4edd7e384a416f88eac4ac7eb931526 -9473,Sony PlayStation Portable,Crash of the Titans,,Games,USA,ULUS-10304,1.01,817135616,b78b7824,d1c3841ee6abe66246793cff8451d7c1,f59adf7a6c6f6a55bff35ebd032ce95bcc3d9387 -9475,Sony PlayStation Portable,Daxter,,Games,USA,"UCUS 98618, UCUS 98764",1.00,1405845504,0af9efdc,6d045a4de025925356d692da1b1e29ff,6a54c86d201ad5adaec109b84ffa3798c06282cb -9547,Sony PlayStation Portable,Killzone: Liberation,,Preproduction,USA,UCUS-98646,0.20,553943040,f820bd84,ee048f3bc7049c99b67c0662675439a4,eb76ed937a369f6cc319487a345692aef8eae7f8 -9584,Sony PlayStation Portable,Shadow of Memories,,Games,Japan,ULJM-05512,1.02,1098383360,0c66710e,a1a31f3ed864fc79a489ff9d01cc6737,f8dd52f7e33e81b17dfc169a1475f77d7ec0fb20 -9585,Sony PlayStation Portable,LocoRoco,,Preproduction,USA,UCUS-98662,0.10,589758464,2cb7c40e,7ec87142364893bcc346dd01a2cf1232,e4200cca381617493e6500a6ec1c4dc30e9a4854 -9671,Sony PlayStation Portable,Astonishia Story,,Games,USA,ULUS-10083,1.02,115539968,3b9b8bfa,d4c00fae1fbc9dd2cd2a6bceabe82543,5c3e701a66210057ba162545ff6833161b72e6f4 -9672,Sony PlayStation Portable,Archer Maclean's Mercury,,Games,USA,ULUS 10017,1.00,289275904,62ab3cd6,18e4e96f2f7d4f16905f4d52fb0cfba7,1af11b5b74131f3e64f12fcb8029b8344ae93eb0 -9673,Sony PlayStation Portable,ATV Offroad Fury: Blazin' Trails,,Games,USA,UCUS-98603,1.01,903446528,59d9414c,7441dfe8bcea3de232b4ec635c996b66,941fdf8b0a8b391d608e7ad12a25cdd868436cde -9723,Sony PlayStation Portable,Soulcalibur: Broken Destiny,ソウルキャリバー ブロークンデスティニー,Games,"Japan, Asia","UCAS 40275, UCKS 45126, ULJS 00202",1.01,900923392,0cc637a9,6953a4efbb3d74dc5d66ac52c1540b3d,439f2844b32751ff102c305d10cee0380e0c758e -9851,Sony PlayStation Portable,MotorStorm: Arctic Edge,,Games,USA,UCUS-98743,1.00,870809600,8edf9ada,775b5e28669a961973435dbd37acf0f8,43c7eec83806a1e92c0fac34d5fa459e357d18d7 -9925,Sony PlayStation Portable,Brave Story: New Traveler,,Games,USA,ULUS-10279,1.01,193331200,66088a80,0b69495ad8303f51dba079cfc9b97cc8,ff88192207d897c8f4f24c81743e6c7c1be86953 -9955,Sony PlayStation Portable,Final Fantasy II,ファイナルファンタジーII,Games,"Japan, Asia","UCAS-40152, ULJM-05245, ULJM-05515",1.02,287342592,ace011cd,27758d84776e568789650d7dd8583944,7d1fa79cc5c84451c83858c01a2bfdf00c654d07 -9956,Sony PlayStation Portable,Exit,,Games,USA,ULUS-10074,1.00,135593984,c21af580,051b16a23d8b2afe2c00359f23e355ba,cf66549fc1f0f41f404f854161c2643574796840 -9972,Sony PlayStation Portable,Every Extend Extra,,Games,USA,ULUS-10147,1.00,374702080,19db17bd,6996895f507c796c1915f9be1f44accd,2cf3c1a232692b237787d456b24ea3fb14935968 -9973,Sony PlayStation Portable,Phantasy Star Portable,,Games,USA,ULUS-10410,1.00,1099399168,d3e5e6ad,1746028b246ffdbf00fb426815d9627d,bb0309b9fe1d1d66a64c2ea4d677475b69dd1371 -9995,Sony PlayStation Portable,Gitaroo Man Lives!,,Games,USA,ULUS-10207,1.00,1700626432,e54022ca,69c938b822191e58b58c0bbe81f51962,e0f981a79a9bef6b7fe5b51ceb5ea7e15cdcaf3d -9996,Sony PlayStation Portable,Frantix,,Games,USA,ULUS-10039,1.01,401244160,a5248ada,8b457d0ac5730155a023f9f0396d0209,9fcb07148d5a965e1af7c994f7fb741a14fa938e -10236,Sony PlayStation Portable,WWE SmackDown vs. Raw 2006,,Games,USA,ULUS-10050,1.02,1704394752,89e70eca,3314a852b7f248c5607edaf593e36485,da973f29f6c748688b52ac12c6dd26d48124cfc9 -10408,Sony PlayStation Portable,WipEout Pulse,,Preproduction,USA,UCUS-98712,0.10,456949760,a68017af,d29ffcbf37a6df4b0867f9c2c125959b,0db2b49c523a312797d0856af560da556012b5b8 -10409,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,,Games,Europe,UCET-00794,0.02,1672609792,9fe75df7,743c52a2f52124d039e163c39ed9b08c,0b5047b59ba0c7376fad9711b8db2d434e48fd83 -10410,Sony PlayStation Portable,Hot Shots Golf: Open Tee 2,,Preproduction,USA,UCUS-98693,0.01,941457408,2c6b5c52,bd2b147a3f7b512841d2f19804d5c4b8,f53b60d5d77fa9c31bc24a7d582e9da0ae1ecb7d -10411,Sony PlayStation Portable,Soulcalibur: Broken Destiny,,Games,USA,ULUS-10457,1.00,900923392,b8d41d25,ea00bd30a408486bac14fdeea4d013ab,77273152a9b3b63e9255e478c796b852b1b0a5f7 -10413,Sony PlayStation Portable,FIFA Street 2,,Games,Europe,ULES-00264,1.01,903053312,c5b5c3e9,2bf33bf85f2a683ee685601a1c9266f5,5893231b19c65adeaf45f83672a30b7f221132e1 -10414,Sony PlayStation Portable,Dissidia Final Fantasy: Universal Tuning,ディシディアファイナルファンタジー: ユニバーサルチューニング,Games,Japan,"ULJM 05550, ULJM 05761",1.00,1670381568,b7d59b9e,f05540a4425d09cd2031a1555ce39b73,abc9e9be6e6a3cc413a583a335ce04bbee2656d3 -10417,Sony PlayStation Portable,Dissidia Final Fantasy,太空戰士: 紛爭,Games,Asia,UCAS-40274,1.00,1646657536,1e7ef9c3,e6d42cdacf259f6f98134b5e8ea8970d,d2b0b03c8eb22ed4e6d1e02e05144fedd7332425 -10418,Sony PlayStation Portable,Gendai Daisenryaku: Isshoku Sokuhatsu Gunji Balance Houkai,現代大戦略: 一触即発軍事バランス崩壊,Games,Japan,ULJS-00213,1.02,529367040,87f0fcb5,6a08d9566ed7d3c8495eaecd41c9a2b0,ab3a1840c74aa43890dfe79da808f90699d60a9d -10419,Sony PlayStation Portable,Shin Sangoku Musou 5 Special,真・三國無双5 Special,Games,Japan,ULJM 05524,1.02,1808793600,a7ae8145,21aab12b043ae0fbc7c97f94a8b4f2de,c9d3e0c7c9868b4e40a7bb7cdc8babffdc8d4eec -10473,Sony PlayStation Portable,FIFA Soccer 08,,Games,USA,ULUS-10293,1.00,1622999040,87175b40,52cbb0d163d58ab07db729ab7c0ee7c7,1e1149f0462dada842e48af063a7e41df8649287 -10627,Sony PlayStation Portable,Ghost in the Shell: Stand Alone Complex,,Games,Europe,ULES-00135,1.00,793280512,a7190995,e52a046153932917584007e415405dc2,7aed3fa5538c53b79a38ef21aac9d01cd506c557 -10628,Sony PlayStation Portable,Impossible Mission,,Games,Europe,ULES-00764,1.01,148209664,e271bf75,6b7b69bcd67a6b67a4fa95e79e64c804,7f2653ebaa5525058a817aa98206899c202c9f35 -10905,Sony PlayStation Portable,Major League Baseball 2K8,,Games,USA,ULUS-10342,1.02,1646362624,aca3ce37,cf226c352f3e1a97d6f733e14cc86710,0b91ccd5bff12d3055477d49318ec0adfbe146cd -10906,Sony PlayStation Portable,Puzzle Guzzle,,Games,USA,ULUS-10334,1.02,123240448,0d7339ca,502900b49b8649f67e8dbe64b932859b,171aee6e8235942d47989fb9c57887e1534524dd -10907,Sony PlayStation Portable,Army of Two: The 40th Day,,Games,USA,ULUS-10472,1.00,900333568,ecf74464,1cdb5df119034270761a6fa177b6bd58,35b4f08ff9b9f7c5ed9845006d2584ea57c1ff09 -10908,Sony PlayStation Portable,Assassin's Creed: Bloodlines,,Games,USA,ULUS-10455,1.00,809566208,86715fe8,ce598c0b22d34b98a80ab346f5758a7b,9afc341b3e953198938aafc332a2622513e544dc -10909,Sony PlayStation Portable,Secret Agent Clank,,Games,USA,"UCUS 98697, UCUS 98764",1.01,1516077056,6c9417ab,7fd6d6c3d7508975db273d95db64c7d2,575c6d2439c13163042e05589ef4de2093747a85 -10916,Sony PlayStation Portable,UEFA Champions League 2006-2007,,Games,USA,ULUS-10221,1.01,1258094592,4cef7e1f,a61e786b370e671d448410feea04d0cf,dd4b9d8e4f5da19b6a90d51411f71341be8aed7c -10917,Sony PlayStation Portable,Grand Theft Auto: Chinatown Wars,,Games,USA,ULUS-10490,1.01,904298496,b9858e32,e5ba4924e399d31ef28d18b52034636a,ecde1e6d47f099a4d3cd2e3ad8f86af028ef0736 -10918,Sony PlayStation Portable,NBA Live 09,,Games,USA,ULUS-10370,1.01,1635155968,804cafd7,86c9bc760624d2b22f7f2189e59a7c64,a1de57fbc53b02c8b8ec18f79505b33004673c4a -10919,Sony PlayStation Portable,Tom Clancy's EndWar,,Games,USA,ULUS-10358,1.01,221085696,096dd581,88fd1f0ca712414e905d1aa1062b3b61,97ba1053b42d459c193a77f8f56bf44f5616f02b -10920,Sony PlayStation Portable,Metal Gear Solid: Digital Graphic Novel,,Games,USA,ULUS-10108,1.01,978124800,fb7e8c1c,37b2012c3c1393ff986de8240cd048c2,bccfadb8cc58b3d53f9bac9de481b4227a9f4ef2 -10921,Sony PlayStation Portable,Ben 10: Alien Force,,Games,USA,ULUS-10387,1.01,1305280512,191b0afd,f6dab2481788b097c297bceade6793dc,4e96cc91e50502c95d427ea56c31f7d5d309f770 -10922,Sony PlayStation Portable,Midnight Club: L.A. Remix,,Games,USA,ULUS-10383,1.03,938213376,ac5ccbeb,25e6e4daaf71fdc693284d38cdd5d250,5a543fbb7b335f1486a9ec5007b484d227e7d614 -10923,Sony PlayStation Portable,Marvel Trading Card Game,,Games,USA,ULUS-10196,1.02,934379520,0a19186a,c71298b9a4186493b0e709824b94fddc,24b9d3f6240d7d061bd1dd1f2017b40929c0b9c9 -11037,Sony PlayStation Portable,OutRun 2006: Coast 2 Coast,,Games,Europe,ULES-00262,1.01,632815616,b20a8595,a6d24b7418267fb300ec340da0a9390e,0a1cfe401b55c49bdd653b39942b87e8a9719a89 -11238,Sony PlayStation Portable,NBA Live 10,,Games,Asia,ULAS-42187,1.01,1683587072,4bc1ba82,c596a93ed9653a3c0795aee70d645bfc,903463906b4c0fb18088b7758a40805c139a7db0 -11239,Sony PlayStation Portable,Need for Speed: Shift,,Games,Asia,ULAS-42176,1.00,1798471680,71b67ec4,28dfa61d6bc220bf54d29efb7aed3e08,d698661eeab1501457c994813b9953906b907dac -11275,Sony PlayStation Portable,SSX on Tour,,Games,USA,ULUS-10042,1.00,1414037504,c0cb34f2,933547f53f0e65707495a3f544af4ef9,25d20af42c4a9b89458440ea489efa8a265b9ad6 -11276,Sony PlayStation Portable,Gundam Battle Universe,ガンダムバトルユニバース,Games,"Japan, Asia","ULAS 42137, ULJS 00145",1.03,784564224,68110e44,cb59633b5fdd037d566c0a1b358ef060,1dff0d5f2fe4967ef33a6807444183fe7c7d1eee -11277,Sony PlayStation Portable,Metal Gear Solid: Portable Ops Plus,,Games,USA,ULUS-10290,1.01,1248067584,9bbb497d,7936c851b5c74545f113416938592921,229fd1f0ec1b568657a8d65c2289280eed63ab2f -11278,Sony PlayStation Portable,Ridge Racer 2,,Games,Asia,"UCAS 40119, UCAS 40273",1.00,1523023872,03886bd1,8704e8df49fd9df11181ec464bb3ef8e,9ee57fc509b43f8f575bfab1056e39b686918801 -11279,Sony PlayStation Portable,Macross Ultimate Frontier,マクロス アルティメット フロンティア,Games,Japan,"ULJS 00223, ULJS 00231",1.02,1237843968,68543dc2,54230be229d383b802ba5b1f4381703a,64a00d4ed0aa5b71425b3f9897c9ce97ef5ae76a -11280,Sony PlayStation Portable,Simple 2500 Series Portable!! Vol. 10: The IQ Cube: Moyatto Atama o Puzzle de Sukkiri!,SIMPLE2500シリーズポータブル!! Vol.10 THE IQ CUBE ~モヤっと頭をパズルでスッキリ!~,Games,Japan,ULJS 00108,1.03,372899840,ca6c6754,7216ef48e1085d8419d0cbc64852d28b,34ff05ed417fa3de6b39265ab9339421f32fa196 -11281,Sony PlayStation Portable,Daxter,,Demos,USA,UCUS 98654,1.01,186580992,87f5c8dc,9d8c127fd918b9f02a3db0698330b97c,8c9817da13718ca64f96cf3ed1fee30c2cb6e60a -11353,Sony PlayStation Portable,Need for Speed: Most Wanted: 5-1-0,,Games,USA,"ULUS 10036, ULUS 10036GH",1.00,926580736,bde283c6,f918068f4e336a66d81a41dfaeb8928e,38fdb2143333de22af42b2eea0b9044fdb49106c -11435,Sony PlayStation Portable,WWE SmackDown vs. Raw 2008,,Games,Europe,ULES-00931,1.01,1785888768,11870f56,add2e3090a9f6fe4d1b6de5889fffcc6,f75a2091aa7548eb3ce457fa527e62e626539718 -11540,Sony PlayStation Portable,TalkMan,,Educational,"Europe, Australia","UCES-00254, UCES-00254/ANZ",1.01,1803059200,ffc0e4a0,cb0b3e11eccee85196b2428c917026ff,65e146d3ed556b8c0e667dd37bbd812e7608a484 -11976,Sony PlayStation Portable,Namco Museum Battle Collection,,Games,USA,ULUS-10035,1.01,174358528,f66e9638,bfd8a64e39474c6c96b3dd6dba9e45e0,6248df464e33102c2bda89f6ed089b8b0ca24674 -12071,Sony PlayStation Portable,Burnout Legends,,Games,USA,ULUS-10025,1.00,500301824,8292a2ce,bb248d1d68ffee3c57299faea3387fa7,a8a00e2c6590896735e007102eefba39ba887161 -12072,Sony PlayStation Portable,Patapon 2,,Games,USA,UCUS-98732,1.00,586711040,9a8a39af,0f50a8305d521faf28dbe623063b1b1b,261c12a600fb878cbcb2ea61f2f4c585d47249c4 -12186,Sony PlayStation Portable,Sega Rally,,Games,Europe,ULES-00910,1.00,197394432,01b39cb4,7532c4d45e38b2df11500b8d788c82f3,280ae7edd468c9bff55eb4661a98fcd3f40f7919 -12321,Sony PlayStation Portable,Dissidia Final Fantasy,,Games,Europe,"ULES-01270, ULES-01270/E",1.00,1689354240,418408c2,ae97fa63ad32844cbd27f7efecd639ab,da4482a8977c15113e29cb0bc97d1f8169d84a25 -13366,Sony PlayStation Portable,Monster Hunter Freedom 2,,Games,USA,"ULUS-10266, ULUS-17008",1.01,837156864,b5780e66,077c39a46fb25c15805184e8a1199c19,35192767ca9d0a0c8f800806ae18d6c793cc2df2 -13367,Sony PlayStation Portable,Monster Hunter Freedom,,Games,USA,ULUS-10084,1.00,741277696,1a08520a,7c29d81c4fc05002527ffe7dc95b2ba0,5fcea1da9475f590472294bf97df2efb311b6e15 -13738,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,,Games,Germany,"ULES-01046, ULES-01046/P",1.00,1738342400,1d800575,9faa600be2dff89340c4cf1dd9199b7e,95e8bf5b9299be0340a09e26dcc3ae3659a3ea30 -13901,Sony PlayStation Portable,"Warhammer 40,000: Squad Command",,Games,USA,ULUS-10313,1.01,498892800,ee37d42b,29b0fd9a0e43d955f463e6aec3916f43,1977284420942172a223db9d3764256d7b760e09 -14013,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,Europe,ULES-01072,1.00,628097024,34f25dcb,62425e60ece3b9c3611b8f8b4f6d8df0,92bfd7d7755a0f51297e57b3fbe539075cd12661 -14014,Sony PlayStation Portable,FIFA 09,,Games,Europe,ULES-01135,1.01,1349353472,a2c10bf6,4a365cc62caf0ab7b635b4d37eb39b40,63d603910b03e9d91906f74876ea6b4b56711253 -14015,Sony PlayStation Portable,Phantasy Star Portable,,Games,Europe,ULES-01218,1.00,1099399168,1e621766,bd1d97dddb9b2f1a608be9abd40c8272,45fcb8647bbba5468aba9b491f5c9e0af898283c -14016,Sony PlayStation Portable,Tom Clancy's Rainbow Six: Vegas,,Games,Europe,ULES-00584,1.02,993034240,0ae396da,8840f32945ee5d1d51c159d65754cace,47302573e7f4b93c16f1ae8ee9c05f1dba1d75ea -14054,Sony PlayStation Portable,DJ Max Emotional Sense P: Clazziquai Edition,,Games,Korea,ULKS 46190,1.04,1729855488,473fcc60,7eac37d6d62556e88f5fa87423fc1239,faeb19cb9ad49861a3ed424134bc7ec5db6e7f66 -14151,Sony PlayStation Portable,Dante's Inferno,,Games,USA,ULUS-10469,1.01,1812725760,db54d4a0,ae91c5d0dcd933329b81efb5a194a227,579df44399a0ecb16ffe4bd195e6afdf4b49b900 -14152,Sony PlayStation Portable,Lunar: Silver Star Harmony,,Games,USA,ULUS-10482,1.00,978845696,9136cf84,8060253a45b50acc5bc088eba69b86d7,8541c68a918e370d2d375c6c6b7ae03f1322bf8e -14153,Sony PlayStation Portable,Power Stone Collection,,Games,USA,ULUS-10171,1.00,517341184,1ac42c36,d894984240f73b14da09285ed0dad83c,5f19975540a1aea31d31742109ed3af19fa6f066 -14258,Sony PlayStation Portable,Fat Princess: Fistful of Cake,,Games,USA,UCUS-98740,1.00,311197696,0035fbe4,e41b33aafd096bacdfd826c6420acc76,8076e844870ba4169f07c5844a249b497bde2bc3 -14259,Sony PlayStation Portable,Prince of Persia: The Forgotten Sands,,Games,USA,ULUS 10480,1.01,691437568,1ac3e681,8fca59b232a79b9ca795f51fd5ec6f86,ef88fa4d4167d6c94b1ce875d2d0a535aa8a4ac5 -14260,Sony PlayStation Portable,Disgaea 2: Dark Hero Days,,Games,USA,ULUS-10461,1.02,793870336,9d51be14,a4a1f22584e9ff6ffb3904f00afd71bc,8f90b9d34a76aa8faf475299382d1a358efef8e3 -14289,Sony PlayStation Portable,Midway Arcade Treasures: Extended Play,,Games,USA,ULUS-10059,1.02,648249344,47b907a1,f75305796ac583bbcb20cb091ccbf2f1,120b280a77db52e2870bbdf894d3e2781d44cae5 -14290,Sony PlayStation Portable,LittleBigPlanet,,Games,USA,UCUS-98744,1.00,1506869248,5abf828d,26f04a771ecb24ee4efe134068884c08,a6441f6137b665f0fffdac5f486816c3734b76e6 -14291,Sony PlayStation Portable,Lemmings,,Games,USA,UCUS-98647,1.01,471498752,1fca769a,367eb49c91b37c32ab7b30e10c327480,fb50074e30a582ee913d108a4024dac702ea5b91 -14292,Sony PlayStation Portable,Smart Bomb,,Games,USA,ULUS-10016,1.03,119406592,a2d3fb41,2c2a2f0caac9c823c8a27a98497624a9,7e48741e1ba9f058af09448f08b265130e2f5878 -14293,Sony PlayStation Portable,Rush,,Games,USA,ULUS-10174,1.01,1395163136,f2b44dc5,cdeb5f61fc8db4ada7c99c0eaf0f13ef,579d3fb6b1600945a9fee8e969ff709e0d196917 -14294,Sony PlayStation Portable,Virtua Tennis: World Tour,,Games,USA,ULUS 10037,1.02,429654016,f47b8046,7ec87be05dd65a5d1b1ffd81788d9d56,e3c8c9416d1590432c5b3a6e48ecb48b1fcfce44 -14295,Sony PlayStation Portable,Pinball Hall of Fame: The Gottlieb Collection,,Games,USA,ULUS 10052,1.00,264142848,82fdb0e1,0b42d2919fb0812d7fb794b692e31771,2a8b669096de9c765f3f4afefc0097b0d8a45f64 -14300,Sony PlayStation Portable,Tekken 6,,Games,USA,ULUS-10466,1.00,855638016,ae9abfb0,740f4fb82775d4e8c1843fa9777f5389,ba1c98d3b30f296c4fe03a68bb7ce51738e069d6 -14303,Sony PlayStation Portable,Tom Clancy's Ghost Recon: Advanced Warfighter 2,,Games,USA,"ULUS-10237, ULUS-10237GH",1.01,759758848,5240df58,b47ba438f55ffdf952a1dab867de30e7,4647aa560e9f01578407ba6d32bf7ad6f866f89f -14305,Sony PlayStation Portable,Street Fighter Alpha 3 Max,,Games,USA,ULUS-10062,1.00,246808576,e68c5f62,204e3ac4c2678c4746e7f237bb93e58e,321ff2143b4c3e8aa24efcf52ffe577c9739f57b -14307,Sony PlayStation Portable,Syphon Filter: Logan's Shadow,,Games,USA,UCUS-98606,1.00,1293877248,2730cabb,ac7f63f53c43d6cfd330f0bf7ee30f8f,dd27a1e30367c9d79da40762bdcaf19bd39cc62f -14308,Sony PlayStation Portable,Gran Turismo,,Games,USA,UCUS 98632,1.00,1097826304,9613ac93,e83fa3aecae465c1f3f01d19fb9f4512,37b7ccb3d702cced12bd8e0c51fe2e94f09aa3b4 -14316,Sony PlayStation Portable,Marvel Nemesis: Rise of the Imperfects,,Games,USA,ULUS-10033,1.00,906330112,f6499e71,a9aafdaebb598feba95198a5404fadb0,a056298062348ab5460f8fce7b139fdfc487fc7e -14317,Sony PlayStation Portable,Crazy Taxi: Fare Wars,,Games,USA,ULUS-10273,2.01,555909120,d5077aae,b41e4e22edc69b9b4dd09133c0a1a947,de3d5ab533341a56db2f097506441a2f0b8d0d71 -14318,Sony PlayStation Portable,Need for Speed: Shift,,Games,USA,"UCUS-98765, ULUS-10462",1.00,1798471680,f73ef83c,bc4706e0c24b41be842eccfef8344088,0f77580f7a812860d7a9a1d37c263bc8f7aeabc5 -14319,Sony PlayStation Portable,MX vs. ATV Reflex,,Games,USA,ULUS-10429,1.02,906330112,3da9a661,480bb696ec8116c5ac4cb05ec25a5832,aa735a45134bd281d40c27711fb99e1fa8694f36 -14320,Sony PlayStation Portable,FIFA Soccer,,Games,USA,ULUS-10011,1.02,1235451904,87c66e03,77b9c69d3fdbd35d02dcffb5c140c433,fa3de1a5efbdd3a5cf2e8342f0289f1701579014 -14321,Sony PlayStation Portable,Hot Shots Golf: Open Tee,,Games,USA,UCUS-98614,1.00,459702272,141dd4a7,b4a9d4036c84e3998c75af927de4238d,06691f00e1252809a52838a04557683936cba11b -14322,Sony PlayStation Portable,Gripshift,,Games,USA,ULUS-10040,1.00,827523072,50ae27b9,c454b612e81934db339cd025235cac9c,16e7e30d5c567b75a89090e0ea9896e6b05a643b -14323,Sony PlayStation Portable,MLB 06: The Show,,Games,USA,UCUS-98624,1.01,1476657152,00f2f807,d086155099c4571ebb4d7530bdd2ca98,35532528b1e9b5c1f30f3332b7c4e5c394c23f0f -14324,Sony PlayStation Portable,Ultimate Block Party,,Games,USA,ULUS-10043,1.02,142737408,40d7f2c3,fd80bdb6b121e4982c3aa564ea0e0f04,53406c67cf350170913e3acf3b87dfbfe4402554 -14353,Sony PlayStation Portable,Hexyz Force,,Games,USA,ULUS-10506,1.00,708640768,07aec822,437ca3366263ebc0dc8ba5ab8c06bca0,4af8f9550f1e224ac98f1245b198a5e56edcb4f0 -14355,Sony PlayStation Portable,Resistance: Retribution,,Games,USA,UCUS-98668,1.00,1669726208,45a3bb4b,0a6c4fc815b8f77ba5d75382dab0eec0,5ea217aeedb537cf944581029796515737c270de -14394,Sony PlayStation Portable,Activision Hits Remixed,,Games,USA,ULUS-10186,1.01,277708800,4e326563,06ba19acff7810cb1a669d72edeff374,92e215b04d510a916c0c96b178ada1b0c1d75205 -14395,Sony PlayStation Portable,Gun Showdown,,Games,USA,ULUS-10158,1.01,795738112,a4c71611,5410775abf591c23fe20a9e8a1dfd578,952ac5bdaed96333e7b46e4dd7e0c0d3795c726b -14396,Sony PlayStation Portable,Mercury Meltdown,,Games,USA,ULUS-10133,1.01,360611840,68941149,e83007cab31616e605530ee85781ce7e,fd059fa1b317c1ffc71f8839ff59a5f4890e70f9 -14397,Sony PlayStation Portable,WTF: Work Time Fun,,Games,USA,ULUS-10172,1.01,439615488,062ef3ce,bc5f0700700a8fc219c87034a26e2fed,f018fa4a354dd7f82f843358a77df67e0cc91f50 -14417,Sony PlayStation Portable,Mega Man: Powered Up,,Games,USA,ULUS 10091,1.00,311721984,4c24e683,2cf4a43e8f01505645dcc2d3c60a03cb,d3ca688ecdd05c6d664f7d84e404882d2733477c -14418,Sony PlayStation Portable,Pursuit Force,,Games,USA,UCUS-98640,1.00,1465024512,e176649c,d73ed26a871f433a98a2b627a8cd3625,ce950da5a564b97e110cb19bb0bab23c9c1f0897 -14431,Sony PlayStation Portable,Need for Speed: Carbon: Own the City,,Games,Europe,ULES-00577,1.00,1464893440,ab807263,9d361b2881bc993fcac903fdf8160692,fb7e411350907c53c81beefde5b1542e51eb86cf -14434,Sony PlayStation Portable,Iron Man 2,,Games,USA,ULUS-10497,1.00,869072896,c85702fc,5b295a0f4ac841da93cfd81ad55dd91d,689c1c62e8e59166827abf9eb3894f22da859c9a -14468,Sony PlayStation Portable,Bleach: Heat the Soul 5,ブリーチ: ヒート・ザ・ソウル 5,Games,Japan,UCJS-10082,1.01,579502080,8c99104f,c5cab4aea2b60a55b0515b8f10d30a85,c54653a7c416ac8874a475ffbc2e093a398e809e -14505,Sony PlayStation Portable,Undead Knights,,Games,USA,ULUS-10453,1.04,507510784,ebb163cf,c4e3d6fb769d49d42df0ee1ba207402e,02b172a16e931c9311aca90ef5e4fa4ed231ddfa -14511,Sony PlayStation Portable,Half-Minute Hero,,Games,USA,ULUS 10491,1.00,222101504,47ebd66e,575f2b21856dd0877a31d3320627b864,d9c53bbb52e1954a2da7f39d018cae6f4221e3df -14515,Sony PlayStation Portable,Mimana: IYAR Chronicle,,Games,USA,ULUS-10492,1.01,662831104,39ac9e83,9dac99d969157324cb8e11c67271e804,e059da6d512d7e808f74fea2b810a3569625804a -14522,Sony PlayStation Portable,Metal Gear Solid: Peace Walker,,Games,USA,"UCUS-98919, ULUS-10509, ULUS-10509GH",1.01,1646002176,1a2c5ca5,b8fe04e4fbeaefd67af2ac2622ed983a,957d88fea235b9da5716155b2445f06df50aec67 -14532,Sony PlayStation Portable,Innocent Life: A Futuristic Harvest Moon,,Games,Europe,ULES-00658,1.02,344850432,b93ea8a0,e74208f584550b37be75a14ab61f0acf,603e99b7dbd1c3ee08a70ac4cb7cbf86976d9af7 -14537,Sony PlayStation Portable,300: March to Glory,,Games,USA,ULUS-10241,1.01,953974784,f86538f1,0b38a83ea52c0f6300638e2f2cd9b588,7da7fab6288a4af463ed1d1dd28d1d200d474323 -14560,Sony PlayStation Portable,Star Ocean: Second Evolution,,Games,Europe,ULES-01187,1.00,1439825920,9f5b9e8a,68a87021c29c72065d8e7b5532a3b595,bb8a6085b93947c5af04c2178ea7ac1d90cdfa86 -14564,Sony PlayStation Portable,Major League Baseball 2K10,,Games,USA,ULUS-10503,1.01,1648689152,54db0d6d,9898bc27f87cbe4fe7c10c2f2840ab9f,c4fe25f0f2e24aec53310bd63ab4bf6828ac3b1e -14593,Sony PlayStation Portable,DreamWorks Shrek: Smash n' Crash Racing,,Games,Europe,ULES-00618,1.01,906362880,f5646308,9d181b7780abf5b5fa0b68f0590834ec,00cf27fdefcd15a0525f9f7cba03a7a7c1858cf0 -14594,Sony PlayStation Portable,After Burner: Black Falcon,,Games,USA,ULUS-10244,1.00,427360256,b0c2d6a2,c419bd2610e2c2044fd669e11f48088c,d0cef4378316b4d27c4ac5b0e7969f358e79a926 -14603,Sony PlayStation Portable,Class of Heroes,,Games,USA,ULUS-10396,1.01,340721664,af0b5a26,fa4ce106ac3843837ecb8e3872220fd5,3b53cb916daea71eab533359afbb956e483ad0a4 -14607,Sony PlayStation Portable,Marvel: Ultimate Alliance 2,,Games,USA,ULUS-10421,1.02,1788575744,a8d2b3f4,c07b9f4995c02b74980a71502c9d7aa4,bf663c108bedf57d56e435b8fde724e1ddb8eec2 -14608,Sony PlayStation Portable,Shin Megami Tensei: Persona,,Games,USA,ULUS-10432,1.00,820740096,7756a333,c75f75b0f1e92d7cca77d75585bebd82,ec190259efdac60801e25c9f7d1ce51cda8f94aa -14631,Sony PlayStation Portable,Astro Boy: The Video Game,,Games,USA,ULUS-10454,1.00,1147731968,11979e2d,8dc1aa2c19c04997859b712dd25c4153,6693ae4bdc6aa799d736fd9f89243209064ca8e5 -14647,Sony PlayStation Portable,Hatsune Miku: Project Diva 2nd,初音ミク -Project DIVA- 2nd,Games,Japan,ULJM 05681,1.00,1612283904,242e921c,2f5d32d9f77f926492b8cc07d88b18b0,af3929cf33e6f92cf3b991245df1ee8e2b576a17 -14648,Sony PlayStation Portable,Hatsune Miku: Project Diva,初音ミク -Project DIVA-,Games,"Japan, Asia","ULAS 42163, ULJM 05472, ULJM 05682",1.01,1402929152,1ad74675,e4886b42939a47e39486414388061042,098758b6d50c584b874e032b15e5b68aa97e5a16 -14711,Sony PlayStation Portable,Transformers: The Game,,Games,USA,"ULUS 10274, ULUS 10274GH",1.02,816676864,7ec72ea5,26f0f257a5a06098d46727a19d07e400,c4f5d72cf962a15f7c91bc82f9e9a5600adf3d85 -14712,Sony PlayStation Portable,Kenka Bancho: Badass Rumble,,Games,USA,ULUS-10442,1.00,524222464,cd74299d,a9f2095cd6120c5cd4f1964732773b80,ef7fb4b5b0365dfce126e8b18c300fe51cb499b9 -14734,Sony PlayStation Portable,Harvest Moon: Hero of Leaf Valley,,Games,USA,ULUS-10458,1.00,421429248,6e3abe6d,807aaf9519e2cc4040d230883c3cdbf8,d25227defc1d11beb9e634981e96cad8cf19315c -14848,Sony PlayStation Portable,Ultimate Ghosts'n Goblins,,Games,USA,ULUS-10105,1.00,431947776,fbfc3e27,75dbb58afe0497092f3cac294dd8762c,0b569d1b415abb328fa2bf0bdaea7832b075feac -14849,Sony PlayStation Portable,Dynasty Warriors,,Games,USA,ULUS-10004,1.00,160497664,e4cb00d9,84354446b52bead0c7760628ac1769b3,f1ab9fabeee1103c67192a090e4421952b75cc75 -14850,Sony PlayStation Portable,NBA Live 06,,Games,USA,ULUS-10030,1.00,1302200320,59e5e15e,df6cf1f26fd83473ba2e33a7893f2e28,635f8178b8a997f9a7fef941b8afd0e6606b15ac -14851,Sony PlayStation Portable,Street Supremacy,,Games,USA,ULUS-10069,1.00,489291776,86d1e42f,96223da5b15f0f27a618f6688666e0b1,311057dfcc0a19b34882b461ff208765dcb9bbda -14853,Sony PlayStation Portable,Adventures to Go!,,Games,USA,ULUS-10417,1.02,176128000,777abc6a,901941eafe53fd78ad09dcc56ccabd91,ad4d8d6bf3aa08fa6c219832d4546b89addeb532 -14854,Sony PlayStation Portable,Madden NFL 08,,Games,USA,ULUS-10275,1.00,1596588032,9bd76345,3ea4552721df5c302d9f501147207428,d0f85a70450afe320e365ec8a070398cd8c92eec -14855,Sony PlayStation Portable,Dynasty Warriors Vol. 2,,Games,USA,ULUS-10170,1.00,279117824,af6e022f,754e92229fac743d42f0e07ba21a0e08,1997835dc2f3e534a147721f262e1db2911e5432 -14856,Sony PlayStation Portable,NCAA Football 07,,Games,USA,ULUS-10116,2.00,1638432768,068bd18f,2d3975052703c7e36363cd86e3f1090a,bff593ace86c5a6dc816e14bf71edf2f8bade9eb -14857,Sony PlayStation Portable,Guilty Gear Judgment,,Games,USA,ULUS-10104,1.01,600637440,712813b6,ae653f90899451c64484e1e2e1242df7,51778e88c1c4283f1c090055e20359ac94faf8df -14863,Sony PlayStation Portable,Capcom Classics Collection Remixed,,Games,USA,ULUS-10097,1.00,571965440,55860969,1cc687a0b91ae38a0ac0ef3eb6d72729,33e834f23fdf7b5bd90be9221a2dfe7bb3f9e30e -14944,Sony PlayStation Portable,Transformers: Revenge of the Fallen,,Games,USA,ULUS-10433,1.00,1752793088,2447fc26,5a72246406ebb70504bf8a4a4706efa6,7f977d6168c6eaeff4d994f5a3e4164f2c9c15d1 -14946,Sony PlayStation Portable,BattleZone,,Games,USA,ULUS-10156,1.02,906362880,cdf81c75,1d2705ad877a8974defedfc1c2ce8c02,28c537f54fbe5d6be6cd41e862305bb7084040dc -14948,Sony PlayStation Portable,Atari Classics Evolved,,Games,USA,ULUS-10325,1.02,83984384,11ec5e01,72d40565d5cce8937454235207b7087a,06dbcb842b52a7d885df41de167a9ae0163df584 -14987,Sony PlayStation Portable,Disgaea Infinite,,Games,USA,ULUS-10522,1.01,280297472,063925a1,6c87f93322cb5222aaef2d6afe7b0283,be30687be921d4574f7ccd4ecc2fe50df0b14075 -14988,Sony PlayStation Portable,Bomberman Land,,Games,USA,ULUS-10319,1.02,357171200,1b29821a,d75dee28a93b2354a61f130363ebc7df,784a2d794da75145d2d236b803cce522aeef9eaa -14989,Sony PlayStation Portable,World Tour Soccer 06,,Games,USA,UCUS-98631,1.00,906362880,16e8e6a0,970524054c8967a2adf278130bfd75ff,d9447157c17f2366fe24785bc5eca281b043348e -14990,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,USA,ULUS-10141,1.00,1447002112,250e420d,cbed092c262a527ccecaf5ef424e20ee,4f09c1b92094f7884bf54c957b950b0be573b9f3 -14991,Sony PlayStation Portable,Madden NFL 07,,Games,USA,ULUS-10117,1.00,1596391424,6e043702,791cca28eb826365dae9508be11e5a16,4a2c8f0ad27c453132cf1526ae3ad39696618308 -14992,Sony PlayStation Portable,The Sims 2,,Games,USA,ULUS-10031,1.00,1115553792,4d0baded,abe440da2101b7ff384b3711a937360f,758d7e69667f15194b81f7c5dd7b900b53562a21 -15028,Sony PlayStation Portable,Passport to... Amsterdam,,Applications,Europe,UCES-00243,1.00,811499520,439e96ee,368d77b6fe7f4a9ed0f40a67e880d1b3,7f27dfbb8f18c5c15e80a18781a5a2f678b41dba -15030,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,,Games,Italy,"ULES-01047, ULES-01047/P",1.00,1737785344,ecb4df96,a73d7ccc5e5596067d649df992454ff3,17698b6116248fa9d5d95d72478cc30c2d90d287 -15273,Sony PlayStation Portable,MLB,,Games,USA,UCUS-98605,1.00,1128792064,8a3c0154,f66c951191cafb0208da1f477696937e,e31292ac2b161878a0043a6e3cab4e5d2dfcb912 -15274,Sony PlayStation Portable,Ys Seven,,Games,USA,ULUS-10551,1.00,763756544,45feb104,ac09902a991c02ac6e538463d3f015fb,fa2fa0727a46786845f4ae80161796e51b9bf724 -15275,Sony PlayStation Portable,Dungeon Siege: Throne of Agony,,Games,USA,ULUS 10177,1.02,663781376,e274043b,4a6a7319de8c32996678acb885d55477,7af9db6fb4734f1999205500bbc70d1cc588234e -15390,Sony PlayStation Portable,Tales of the World: Radiant Mythology,,Games,Europe,ULES-00837,1.00,439648256,0837248f,ba38d4905163bd0717b8ddfeaaba1383,c30433aa65068c998f20321410ebb5944e66e467 -15410,Sony PlayStation Portable,Darkstalkers Chronicle: The Chaos Tower,,Games,USA,ULUS-10005,1.00,692551680,20069383,9ac3d4c642af29a9d70b20decdf1db72,bbf780671da3c0c51245b2b8f8217ebb569f10d7 -15455,Sony PlayStation Portable,Valkyria Chronicles II,,Games,USA,ULUS-10515,1.00,1081737216,ece8d4f5,471b3117bace212cc57b9b6089a24b1d,c20d26b251bd716b95067b91c4d19c0c3311cf7f -15456,Sony PlayStation Portable,Ace Combat: Joint Assault,,Games,USA,ULUS 10511,1.00,1768357888,062dffce,41ed76ee6999b205dd3585f95a80d0fe,eb5295e9295e02ecb3f121e3f5b940a4bd7bf30c -15457,Sony PlayStation Portable,Ape Escape Academy,,Games,USA,UCUS-98619,1.01,388890624,129fff01,ef3fb0c8e8a18cf1e31051a0ff01aa5e,7ad2ac91921d9744391610db8fe5180f2853f287 -15458,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Tactical Strike,,Games,USA,UCUS-98649,1.00,1381367808,9263533e,dbec03d2a0bf6f918443d0425ea0ae40,93ed41e584f3de093bcb23b3451b0400b6ec6aac -15465,Sony PlayStation Portable,Tiger Woods PGA Tour 07,,Games,USA,ULUS-10115,1.00,1256390656,c25b87b8,7b03b947b8a78018c047189699c0c155,86a845331f3774a8ddb0abcf88559c8da377d5cb -15466,Sony PlayStation Portable,Major League Baseball 2K6,,Games,USA,ULUS-10099,1.01,1618640896,67a0b56f,8d1c3067a35bc66c2805b552ec3be1a9,eae024315d555d58be728c7f41f52b6ceec5e543 -15633,Sony PlayStation Portable,Spider-Man 3,,Games,Europe,"ULES-00938, ULES-00938/E",1.01,1683259392,a9d63483,46d474577e99079b8682677a97d67eba,6ed126a2a81a477a102cb244e3dd768cb0a868bd -15640,Sony PlayStation Portable,Crash of the Titans,Крэш: Битва титанов,Games,Europe,ULES-00917,1.01,1116438528,2f8c8632,f8dec4a587a92a0fc55469e00c6892d4,5ffc378168f69f351c8c919d85049949c0352393 -15703,Sony PlayStation Portable,Onore no Shinzuru Michi o Yuke,己の信ずる道を征け,Games,Japan,ULJM 05465,1.01,276922368,dc9222fb,8e2489da27090c871d85dca13952098e,a4c58103fb56166f604acd0581269bba79cb287f -15864,Sony PlayStation Portable,Capcom Classics Collection Reloaded,,Games,USA,ULUS-10134,1.00,633110528,d6a9f173,94bb108b4281a2e7780f026a6985485d,7c089eca0ba8079a17bdb3b02de69f3e7bee6457 -15865,Sony PlayStation Portable,Air Conflicts: Aces of World War II,,Games,USA,ULUS-10404,1.02,900825088,1a36c729,6d4e5e80182e438ded1f10eec6265644,39a3f9f1bc6b1faa69f4d7b1fd086baab7c5d711 -15868,Sony PlayStation Portable,Aliens vs. Predator: Requiem,,Games,USA,ULUS-10327,1.00,396492800,7ed436f6,9568c2c27f0c9701f6f27a418b41d05a,f6802ce9225b132cf8b6514e369046c719c98283 -15870,Sony PlayStation Portable,Capcom Puzzle World,,Games,USA,ULUS-10217,1.02,513081344,c64ce4a9,ec9a39a3c3623754b9d2f0f5f9ca4284,606f010bfa21b8dc075c74480e8d20ef4b5caa79 -17185,Sony PlayStation Portable,Assassin's Creed: Bloodlines,,Games,Europe,"ULES-01367, ULES-01367/E",1.00,850362368,a79c68ca,33edd3e0b51213813351242c6cf44e2a,2b75158ad15b4fecf6d58ce183cd4906f0f661a5 -17187,Sony PlayStation Portable,G.I. Joe: The Rise of Cobra,,Games,Europe,ULES-01277,1.01,1164476416,2477f41c,87c550b14f40a7f36bcd1616ad79169a,5df1e166988ce8650188dfb8671d4f751390db8d -17188,Sony PlayStation Portable,Grand Theft Auto: Chinatown Wars,,Games,Europe,ULES-01347,1.01,904232960,3ea726f3,490c44636d467525c59c3be33e9efacb,391b8c81b42f65af718feca06b8a3d6e741be5c2 -17189,Sony PlayStation Portable,LocoRoco 2,,Games,Europe,"UCES-01059, UCES-01059/E",1.00,1805746176,c4db076a,576f03867aa980534e0c396107f97e75,bb6bc76adc30a93203232305bd469c032150cee0 -17190,Sony PlayStation Portable,Resistance: Retribution,,Games,Europe,UCES-01184,1.00,1737981952,983e40dd,de2b84429ced4e924846772047d270be,cc2a810ca16ef4f4920a5166c86de5fbf4cbb985 -17583,Sony PlayStation Portable,Crush,,Games,Europe,ULES-00765,1.00,832077824,dc9ff010,68bcc8e8020f20c51becdbcaa960a393,391b3a843f4041110394f0fe7ee7ffdf820216c1 -17736,Sony PlayStation Portable,Tiger Woods PGA Tour 09,,Games,Europe,ULES-01120,1.00,1616379904,6a5f4e31,759bad6b6dbe5fb3d9cb2ab1fafe5235,1bfa51c4a1e526cc87182537cbcbcd24508f7ab8 -17758,Sony PlayStation Portable,Fat Princess: Fistful of Cake,,Games,"Europe, Australia",UCES-01312,1.00,439549952,780afe99,0c1935671050b78340ff6128a6f52565,8aaa9aa1e0e0d3a35113d9eec22a07ec21db7393 -17759,Sony PlayStation Portable,Kidou Senshi Gundam: Senjou no Kizuna Portable,,Games,Korea,ULKS-46204,1.02,224985088,cb5ccdfc,868465bc8570e16e7ebac0b36be0441a,0357ad99552f3a40c95705af3a27843ae2bb840a -17820,Sony PlayStation Portable,Buzz! Quiz World,,Games,Europe,UCES-01290,1.00,1776091136,ca063b5f,633ae00e7c0450a48513cc116c0ab08e,483d834385db9885f5e23b93cccb5f41ba08934f -17837,Sony PlayStation Portable,Beaterator,,Games,"Europe, Australia",ULES-01023,1.02,1083506688,436adad9,b5d46071795b9049f2efa33ddabccaf8,3baeda4dd7543f976ffe02dcee1fbdfb1225f6ed -17865,Sony PlayStation Portable,Sony Computer Science Kenkyuusho Mogi Kenichirou Hakushi Kanshuu: Nou ni Kaikan Aha Taiken,ソニーコンピュータサイエンス研究所 茂木健一郎博士監修 脳に快感 アハ体験!,Games,Japan,ULJM-05135,1.00,303792128,4594574d,2cbb8f7b45640063a861f6ec526ae368,3615154870ee14e7b8ba90316f40b2edc0a8f436 -17866,Sony PlayStation Portable,Sony Computer Science Kenkyuusho Mogi Kenichirou Hakushi Kanshuu: Nou ni Kaikan Minna de Aha Taiken,ソニーコンピュータサイエンス研究所 茂木健一郎博士監修 脳に快感 みんなでアハ体験!,Games,Japan,ULJM-05189,1.01,366673920,bbda0573,bd7f844e908ee444b63108eaf13b01c8,4210d568911f8ef81db1cc746396967cfaa7c86c -17867,Sony PlayStation Portable,Need for Speed: Carbon: Own the City,,Games,USA,ULUS-10114,1.00,894173184,38b3320e,ea289f9fcc47e2a4dc1997dbb4eed9d1,9bfbd25806c6730c85ae22e1efde75d633fa725b -17874,Sony PlayStation Portable,Ratchet & Clank: Size Matters,,Games,USA,UCUS-98633,1.01,961282048,c711ede4,95214d990dc3188563071ada7a30eff8,1d659b7966edb910066ed4e2bb9e0a8e9a0faa32 -17875,Sony PlayStation Portable,Warriors Orochi,,Games,USA,ULUS-10341,1.00,906297344,5f18f569,27f3e2df3c97b744643916a18e4d84a3,2048497613f2eca9b2b5e53410ee82af9edff177 -17876,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo,,Games,USA,UCUS-98615,1.01,560168960,90ff627e,1f015944a964d7114eaf64f317f6f9e2,b31ff7db5e73d04c68c10d6a8cd38d6a278b55b3 -17877,Sony PlayStation Portable,NBA,,Games,USA,UCUS 98607,1.00,194641920,2b56946d,ed73e04358f0698e608001c1c8b97e8c,4e0932f8b7b06c92d1988a48c969dd9c14851ccb -17878,Sony PlayStation Portable,Surf's Up,,Games,USA,ULUS-10262,1.01,906362880,e69db4db,13b1c7ea0cb737f6d851fe28b31e3c87,6b166ae87539da705e4b797c51c96016959f072b -17879,Sony PlayStation Portable,Virtua Tennis 3,,Games,USA,ULUS-10246,1.02,582156288,08656c8a,0bb80bd2c3539a20a94bd56487194e47,d391480dcc8a91beb76d0d73d0b8370b8f975156 -17887,Sony PlayStation Portable,Worms: Open Warfare 2,,Games,USA,ULUS-10260,1.02,196214784,d8a2adcb,77dfac1b5273de68245b0dbb31ca05fa,11f8ae555a4212d8e2f95e4b9212016305644094 -17888,Sony PlayStation Portable,Tom Clancy's Rainbow Six: Vegas,,Games,USA,ULUS 10206,1.02,852328448,dadf6ada,425acf8643f7aa3dba02bb7b6937f75e,fa9476bd21fdf6f894f40b2f0e8ad9dbde7846c7 -17889,Sony PlayStation Portable,Go! Sudoku,,Games,USA,ULUS-10095,1.00,311918592,8613516a,566095b1c171306f849fc1022998ebef,353611fa9124d97fe1bb491b89efd756d0588b7a -17890,Sony PlayStation Portable,Frogger: Helmet Chaos,,Games,USA,ULUS-10026,1.00,452526080,6e1fb930,deed14a20b206387a491ce5ab5b1c0ca,6cdcc646f55a4093853b286589350d3e438687ee -17891,Sony PlayStation Portable,Wild Arms XF,,Games,USA,ULUS-10339,1.00,1681260544,2711a9b1,70f1a43e9f6a6e9461d781ee3161a3de,3a4f3361a63474672b067cd9faee7bc1c50051c4 -17920,Sony PlayStation Portable,LEGO Star Wars II: The Original Trilogy,,Games,USA,"ULUS 10155, ULUS 10155GH",1.01,1225359360,ab24aaf4,16e1d0b9aef892b5794996b36d2a7b1b,42c5cf87e1e59a42fcd5fa7f095248d12312fe3e -17921,Sony PlayStation Portable,Dead Head Fred,,Games,USA,ULUS-10288,1.02,1407123456,352c845d,fd83bb0b7c73856ef6df68674406a5cd,88df65584dcc965ccdf1e7d98d687b7f037b7e23 -17922,Sony PlayStation Portable,Open Season,,Games,USA,ULUS-10152,1.01,1105362944,51833e00,e326843b2fdd03feba2469b73832de1c,79fc6aed86d652905164ab088b496f292c6004d3 -17923,Sony PlayStation Portable,Brothers in Arms: D-Day,,Games,USA,ULUS-10193,1.01,1454997504,056b2555,99380be5936ac646ccc78ec024c9ee6d,71d6ca8a4f5588e97542134ab69026d36329c159 -17924,Sony PlayStation Portable,The Hustle: Detroit Streets,,Games,USA,ULUS-10048,1.01,988413952,31b6c0f4,ca9b75e3bb01bdc597df18530ee51962,ed88815cc8230497236920bab5fdf0d324d4cc7d -17925,Sony PlayStation Portable,Prince of Persia: Rival Swords,,Games,USA,ULUS 10240,1.01,1269956608,1616169f,c724a53cb3d1b9ac2039723b48167511,1b8dd86dd62701c46a9dfaa0477990f0b189c91b -17926,Sony PlayStation Portable,Tom Clancy's Splinter Cell: Essentials,,Games,USA,ULUS-10070,1.02,1812267008,55d69fe3,71c9b8177b7262ffa76aa8247ec2f9aa,c52ff496ae8af59292f11dde35bf9de1b29abbda -17933,Sony PlayStation Portable,Dead or Alive: Paradise,,Games,Europe,ULES-01416,1.02,870121472,10e8be9e,50fc2121a3a89fdbfb16e218b6f6c46f,0c018072fde95d9ae5878a6b8c1bf5fb6766271d -17934,Sony PlayStation Portable,Harvest Moon: Hero of Leaf Valley,,Games,Europe,ULES-01489,1.00,422150144,be7e8f00,98e586abaeb22bc4590dbb6ae1aaed65,bea192f424645858562d6a9e3509d0e4414de000 -17976,Sony PlayStation Portable,Jeanne d'Arc,,Demos,USA,UCUS 98706,1.00,334004224,df86df44,c1c113257c6aee9efcbcf9b4166ef67d,105f31c05c69e9e508298dfa1e5b8144f1eb955f -17977,Sony PlayStation Portable,Syphon Filter: Logan's Shadow,,Demos,USA,UCUS 98704,1.00,472285184,d295ca4c,f087da417cfe8e8559e6c43fdb7a3667,16aa60dbdb6b473f4dcea42737d51d5cf76cddd1 -17978,Sony PlayStation Portable,MLB 07: The Show,,Demos,USA,UCUS 98680,1.00,1399914496,c35aadad,5b24e12d7d689eb64da039f1f15df33f,f9bde2ddf8d47634d2de87e7adfc66573020e0b3 -18013,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,Europe,"ULES-00557, ULES-00557/E, ULES-00557/P",1.00,1447002112,11bc8da6,2baadc390167545b1b567a8ac2f29601,cb3b84eadd2373a311ea314e4b6b4a27af0af6d5 -18014,Sony PlayStation Portable,Tekken: Dark Resurrection,,Demos,Europe,UCED-00448,1.00,1181089792,275bc912,1b178879ebdb285d1047cb21dafd4cbc,25cd04872d63a0e6712ae76e5e770a10f577b7d1 -18015,Sony PlayStation Portable,Football Manager Handheld 2010,,Games,Europe,ULES-01338,1.04,221904896,f5c71c2c,e9cc577a510029c79a242356977b37b8,07d9169589f180afc636a965e4665dca002156ff -18016,Sony PlayStation Portable,Ben 10: Alien Force: Vilgax Attacks,,Games,Europe,ULES-01358,1.00,1568997376,a3052297,7fdd2e1e7590b86cca26fffd833cfce5,048b7f6899296e5cb92504ecf61867471319a788 -18017,Sony PlayStation Portable,Vampire Chronicle: The Chaos Tower,ヴァンパイア クロニクル ザ カオス タワー,Games,Japan,"ULJM 05005, ULJM 08018",1.01,697466880,291cc7aa,68106571b52ebb72c56ccb849fe50b33,62e7e00b23d4bc4bbde279c6412ecc0b088416a2 -18018,Sony PlayStation Portable,Star Ocean: First Departure,スターオーシャン: ファーストディパーチャー,Games,Japan,ULJM-05290,1.01,1162182656,20043e3b,a7b86fa9e5dfa394488e373e4872beb4,3f90c504b35fc686148104a2c6295a428878253c -18055,Sony PlayStation Portable,MotorStorm: Arctic Edge,,Games,Europe,UCES-01250,1.01,870809600,1ee9dcf0,6d751b52b00dc0e8b84726b3f28003de,628261971367a334c95456d0c2a3cf665e459dfa -18107,Sony PlayStation Portable,Gurumin: A Monstrous Adventure,,Games,Europe,ULES-00627,1.00,1064173568,90e26d57,66ed3b50aa9458acf2803290516816f3,68e5b322f3485503a9b8a6379eccc1ff8db79394 -18114,Sony PlayStation Portable,Lord of Arcana,,Games,USA,ULUS-10479,1.00,805011456,ec43acfc,289d6bd98e6b10a90b1d0340aca657f1,0a4a92923e5f23d7d3b6d9b3cacd29314550b7c9 -18290,Sony PlayStation Portable,World Poker Tour,,Games,USA,ULUS-10079,1.06,607846400,4a736deb,e32f611e20d3c887fc8379a2f4827c3a,72f75bce02cb20e721249a91707f82499e2f0ec0 -18291,Sony PlayStation Portable,Gretzky NHL,,Games,USA,UCUS-98604,1.00,153223168,fcfa1d96,a00c9704dac12681b45756e83a3e9a8a,20eaa2e257c7ec131ee277608bd09c65eff4b690 -18292,Sony PlayStation Portable,PaRappa the Rapper,,Games,USA,UCUS-98702,1.00,377290752,9d677dff,38fbdcbc90e976716782dc89c4dfcc95,bf19177775a2b24cd15d7d2292b603973fbfb6e3 -18293,Sony PlayStation Portable,Riviera: The Promised Land,,Games,USA,ULUS-10286,1.00,1093140480,83cf9317,20e162087ab26ec3ccfad0eac76018b8,151e29a5657d8be9dbb728e39207955b1b6638c3 -18294,Sony PlayStation Portable,Pocket Pool,,Games,USA,ULUS-10151,1.01,705003520,27bd093a,2a597d57362fedbf89666b4e67aaaae8,524b1644ce1d4e3fd26c5aaa9fc38ca31fa75a63 -18295,Sony PlayStation Portable,Neverland Card Battles,,Games,USA,ULUS-10382,1.00,419168256,09ee225c,57d3ff905c1711594e80ffb78630e61d,b87e0d9b9e868c6bae8b7dd8f708bbcb8a3a23f9 -18296,Sony PlayStation Portable,Pangya: Fantasy Golf,,Games,USA,ULUS-10438,1.00,1505656832,6ad4b603,8de32e1a0685a9e708badc3e69831ecc,48d5bfd7073eb60f766dda222fbc7dcb1f690fa8 -18297,Sony PlayStation Portable,Stacked with Daniel Negreanu,,Games,USA,ULUS-10101,1.02,906231808,d74639fa,f1417d0d46ef04bd9df50c7aae075e39,28f3993ba6a7d8e4850134a5dbd5a1df47038825 -18298,Sony PlayStation Portable,Ratchet & Clank: Size Matters,,Demos,USA,UCUS 98684,0.10,122748928,1fb728ef,dc129f9c42b687324bd039951bff76c0,c966ec5a661f548b610f0bf0bcfda9bcf445097d -18299,Sony PlayStation Portable,EA Replay,,Games,USA,ULUS-10140,1.01,891748352,5078793c,cf1601de850b4632c7511f5a9271f870,2f1bf8431c6502e6e43d387a22abf5bc08b3986c -18300,Sony PlayStation Portable,Mind Quiz: Exercise Your Brain,,Games,USA,ULUS-10178,1.00,83525632,c77e5671,3ca2588ee9bf4ebca9be0d3c0bc628b8,f91796152e9d833bcd331827bd1c03f1b2cabe86 -18301,Sony PlayStation Portable,God of War: Chains of Olympus: Special Edition: Battle of Attica,,Demos,USA,UCUS 98705,1.01,371490816,7afd2f24,81fad960ce5ddb9a68911a7596665039,ac9f9487f4c3a54dacb29f3abd9125543e13b0fd -18302,Sony PlayStation Portable,World Series of Poker: Tournament of Champions: 2007 Edition,,Games,USA,ULUS-10162,1.00,757792768,90868020,3a2fca13c782897c999c291830f91406,1403c5c1231f618dfcb751eaa3d6f6c9541be41f -18321,Sony PlayStation Portable,LittleBigPlanet,,Games,Europe,UCES-01264,1.01,1506934784,b77301e8,33ce16bc053d2a9934b3975911af04b4,2612f179e99449f66b86987508678bbce211485a -18329,Sony PlayStation Portable,Monster Hunter Freedom Unite,,Demos,USA,ULUS 90003,1.00,300613632,998a1c1b,f8ac326e2743d0cac6323b3d2e1231a1,aab45708b61852778038e8539aaa5af547bf3776 -18339,Sony PlayStation Portable,NBA 07,,Demos,USA,UCUS 98694,1.00,623804416,251ec2d5,44551143d88db8041b7b30ec8825210d,503e090cff2bff0a3ab02b58ceffb7e385b6ad24 -18353,Sony PlayStation Portable,Final Fantasy Tactics: Shishi Sensou,ファイナルファンタジータクティクス: 獅子戦争,Games,"Japan, Korea","UCKS 45058, ULJM 05194, ULJM 05516",1.00,459669504,87b69e31,7adcd1ee81464e0333754e131083d690,fc348abdb7852c6622aa3a56807c80edc6fb4fd2 -18362,Sony PlayStation Portable,Tenchi no Mon,天地の門,Demos,Japan,UCJM 95402,1.03,385482752,6eeecef7,3683d90d9914abdca13a7952c9e4c034,657fcac89a988653ac70c8a5ff3ab99058593321 -18370,Sony PlayStation Portable,Umihara Kawase Portable,海腹川背Portable,Games,Japan,ULJS 00137,1.02,288063488,a0883dcc,b349e6f305bb40f8c5a9cb95fc315ebb,e8838bb66f8c5558115f57fc59ea6bf13f4f39ff -18371,Sony PlayStation Portable,Tenchi no Mon,天地の門,Games,Japan,UCJS 10010,1.01,1064402944,dcda08da,f5c61fdc17ceeccd983cf30c09d4122a,1e774c0f546d35153f34b244bf7f6b4906084631 -18372,Sony PlayStation Portable,World Soccer Winning Eleven 9: Ubiquitous Evolution,ワールドサッカーウイニングイレブン9 ユビキタスエヴォリューション,Games,"Japan, Asia","ULAS 42018, ULJM 05033, ULJM 08009",1.03,982581248,9bc7757d,80b4504235c6f2b516528e96a5ec3d9b,70b92fa3ddc6a5568a82ef90d6ecd43d953f7ab7 -18373,Sony PlayStation Portable,Soukyuu no Fafner,蒼穹のファフナー ,Games,Japan,ULJS-00006,1.00,421134336,7b90bcec,e96fef08b55a79aa62e31de1af80fedf,546d3b14fc76ef8535483919b5f353bb355fe732 -18384,Sony PlayStation Portable,Def Jam: Fight for NY: The Takeover,,Games,Europe,ULES-00390,1.00,1576894464,6f52d7cb,9dc1ebc1d5825d11a5075e630c5fa519,7db2a5395bf9e5b249bcf2da211a1b25c3e752c5 -18385,Sony PlayStation Portable,Valkyrie Profile: Lenneth,ヴァルキリープロファイル: レナス,Games,Japan,"ULJM 05101, ULJM 05320",1.04,716275712,e96e0f29,1bbede995efecc91ad76a3adf09b1637,b9109e99a2537249212713aedf505b37ff5352ca -18387,Sony PlayStation Portable,R-Type Tactics,,Games,Europe,ULES-01121,1.01,871071744,a0fda493,5a12d79a672c7436b771c89dffa465c5,d30a270b967e0a198e9b2c34ca04f3744f1d59d6 -18388,Sony PlayStation Portable,SBK 09: Superbike World Championship,,Games,Europe,ULES-01247,1.02,590970880,3f0ca267,94a08651ba53170b4fcdbcef7a8206a7,d1537c1e4ae993ee0aa1d487d16fbc104975ea9b -18389,Sony PlayStation Portable,The Hustle: Detroit Streets,,Games,Europe,ULES-00603,1.02,1216839680,4b4e76e7,0c8fce2289a85b31f925f962eb9be70e,8b1de81c9a229dae714d62566fc689239a9a8e5e -18552,Sony PlayStation Portable,Taishou Yakyuu Musume.: Otome-tachi no Seishun Nikki,大正野球娘。~乙女達乃青春日記~,Games,Japan,ULJM 05528,1.01,944570368,5b327c19,b24d9fe06fab7bab363a3099390d9522,60394e03706a24c83f895a6f7fcaff4f9fceb65c -18608,Sony PlayStation Portable,WWE SmackDown vs. Raw 2009,,Games,Europe,"ULES-01165, ULES-01165#",1.00,1563066368,ba69073e,e1e670dea4c8bc84605923eaa05e82e0,183b558ba7917effc5a15839173edc5af177066e -18618,Sony PlayStation Portable,Tekken 6,,Games,Europe,ULES-01376,1.00,855638016,1712a669,d6b3214a00438f5442807eec3dc24944,b21cbcd1b803a0e50a4681de1de03f51a88d8803 -18651,Sony PlayStation Portable,Iron Man 2: The Video Game,,Games,Europe,ULES-01422,1.00,869072896,66988768,997dea48c8b599f92abc96f0b6da8ff1,fd8a73d9ea138bc4afe805e4e1341da1a0a21f67 -18652,Sony PlayStation Portable,Transformers: Revenge of the Fallen,,Games,Europe,ULES-01286,1.00,1752793088,21e48d2b,560dec5bfb47c1350adb87d0311f8e5f,2ed8e294be961b1a617fa9545ae5ef6f27b61569 -18782,Sony PlayStation Portable,Luxor: Pharaoh's Challenge,,Games,Europe,ULES-01028,1.00,134873088,cf252f5d,8f0dd52f7f887fb4567290aea2e51211,b7fc204749c28dc24303442beb81c2a142f9684a -18783,Sony PlayStation Portable,FIFA 10,,Games,Russia,ULES-01329,1.00,1361215488,1513d85b,64b8b29df29fa7f7b4e686b13b93dffa,8e0f09fd771d834c08b4874047c9032fd4440afc -18802,Sony PlayStation Portable,Naruto Shippuden: Ultimate Ninja Heroes 3,,Games,Europe,ULES-01407,1.00,1360363520,6b6fe824,cd9ae4049f4adf61951c73816a1c9290,212879306fe1fc1306406153efa9ca5b12ddd060 -18803,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,,Games,Europe,UCES-00543,1.01,1672609792,430b91a2,6e596d2f70a4e930b17ccad24a547dd7,002a6914578ff62ed8dfd9cb85ac19b4d775970d -18804,Sony PlayStation Portable,Smash Court Tennis 3,,Games,Europe,UCES-00758,1.00,1464860672,fc1d57c2,b9e9f47ab7be86aff2391c9696051c57,8c7c0f54ebec6ac7ead73c208d1ca41eb2784472 -18805,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 3,,Games,Europe,"UCES-01242, ULES-01242",1.00,1791393792,71b97a7a,5812b52eb96562d014d99ccd477b9017,3c048abb1f6006af73ec4355cf96a5299141e318 -18806,Sony PlayStation Portable,Echoshift,,Games,Europe,UCES-01313,1.00,309854208,5727504d,68ede9b7094f78e54b249f0efe29ad8f,e5ac5eef6cb500d7b7d3bd4e51a55f912013e62d -18807,Sony PlayStation Portable,Patapon,,Games,Europe,"UCES-00995, UCES-00995/1.00",1.00,354844672,70688b01,12832f3403e9e7f4087a351fab3551ed,340d870db9b2464b3d4e4c16653ca5ab9f94ac16 -18808,Sony PlayStation Portable,The Eye of Judgment: Legends,,Games,Europe,UCES-01334,1.01,894926848,24177342,34fdd992b7d26ac264cef668717235f2,80868b16e57a4bb798424bfcda8e9390192322d7 -18826,Sony PlayStation Portable,Rock Band Unplugged,,Games,Europe,ULES-01243,1.00,1342275584,181be626,6947063213c5ff3fbda8163bf25d600e,232227a50962e1942234501b9c023be7a772e204 -18835,Sony PlayStation Portable,Ys: The Oath in Felghana,,Games,USA,ULUS-10558,1.00,1105985536,3f236ec6,ff39ebefa69ec9c8529d54dd261d7465,a177ac5df3fbd3608427f6ea9657bc273df3876d -18907,Sony PlayStation Portable,Bakugan: Defenders of the Core,,Games,USA,ULUS-10536,1.00,887324672,a4b4eb27,b1730f2f87e44dfebfc64261992a0734,0273a50db02b3ec81fa9d7a9edf7a9d5d3b09363 -18908,Sony PlayStation Portable,Dissidia Final Fantasy,ディシディア・ファイナル・ファンタジー,Games,Japan,"ULJM 05262, ULJM 05405",1.03,1622802432,53557621,c4a17142565aa07c8bc091398e0cc152,074e90624ccc14359a2e4f1e1da5974855107d64 -18910,Sony PlayStation Portable,NBA Live 06,NBA 라이브 06,Games,Korea,ULKS-46032,1.00,1302200320,4eeba324,926aadd43510658503edda676a978f30,6c185a4cb8106bf176e6279e75be99be2cf3fb2e -18911,Sony PlayStation Portable,The Godfather,,Games,Europe,"ULES-00394, ULES-00394#",1.00,1442742272,a4e9c258,27e31ce887ddcbe18a95b85360461cb2,deaf7667bbe40c6f0448bbec8b37473a58d28af8 -18960,Sony PlayStation Portable,The Warriors,,Games,Europe,ULES-00483,1.02,1797423104,04783709,47665a2e0ee455bc444874a8d6c35371,6a140a4198e2618ef3d9bbb384a1231907274421 -18961,Sony PlayStation Portable,FIFA 09,,Games,Asia,ULAS-42141,1.00,1708359680,38a53861,91c45e0462c1d5978948c7aacdabce46,cf9caa0f2f3d0dc0c980eb91c15a8c5b6f631f1b -18963,Sony PlayStation Portable,Der Pate,,Games,Germany,ULES-00398,1.00,1357578240,c30cf450,2e87e2fc81d1bf1c5318155adca5d530,b67f1fd1edc943a1f6351638f04ff095298479d7 -18964,Sony PlayStation Portable,NBA Live 09,,Games,France,ULES-01148,1.00,1200291840,239bcd98,a0f057cac6482a7112ae6be8f77293e7,1236ec6d13a80b6ea0aac3588ea942e193a1f544 -18965,Sony PlayStation Portable,Scarface: Money. Power. Respect.,,Games,Europe,ULES-00546,1.02,887324672,a43a314b,d9a7271c75dcc5ab53aeb765a16ca6e1,017e85156cfeef43ed4dd362a1b0c913c946a503 -18966,Sony PlayStation Portable,Tiandi Zhi Men,天地之門,Games,Asia,UCAS 40089,1.00,1029275648,b4d3b39c,a8d0cedf27d58dd387fc791cfb7f363e,764df2754c890cf26bcb95f935e27453e2a7c720 -18974,Sony PlayStation Portable,Die Simpsons: Das Spiel,,Games,Germany,"ULES-00978, ULES-00978#",1.00,776798208,bf9151ef,076705a156df98c34127c47e78ccf70f,86bb2cb492b0911716b634a5f8dc3cfa5ec6d965 -18978,Sony PlayStation Portable,Transformers: Revenge of the Fallen,트랜스포머: 패자의 역습,Games,Korea,"ULKS-46207, ULUS-10433",1.00,1752793088,685c03b1,e68a3758183f79388dad81b3ab4252e0,716ce46670072648c16754de836f1e72f3f7d7aa -18979,Sony PlayStation Portable,Rockman Rockman,,Games,Asia,"UCAS-40208, ULAS-42050",1.00,331284480,1baef7dd,35e092503e53d5173175d2e545ae981a,48282e0aaf7ea1497d28f1d5ef40715254e9cd2f -18980,Sony PlayStation Portable,Wild Arms: Crossfire,ワイルドアームズ: クロスファイア,Games,Asia,UCAS-40161,1.00,1377468416,8fdcfaa5,9a9c18f3619b8684e3c21e29a04db0eb,b0ecea8a8d80ec421681d50a2ca157463c8ef303 -18981,Sony PlayStation Portable,ModNation Racers,摩登大賽車,Games,Asia,"UCAS 40305, UCKS 45154",1.00,1651048448,30edfaf0,aa43743de9a57398c44947f9ed30e92e,4103dddeac390d0dcb994da63937b01a69b2995f -18984,Sony PlayStation Portable,Knights in the Nightmare,,Games,USA,ULUS-10539,1.00,509116416,0046bb36,253dd8d3e9006f421bc36b674e86d1dc,c016594e5be0a848ba11c69e4425c1f527e91df8 -18990,Sony PlayStation Portable,Dead or Alive: Paradise,,Games,USA,ULUS-10521,1.01,869990400,5b7ffe0a,7ad8a8996f7fbf4ccdbab066a91d662b,2cb921f971f58b07133831c57577172ecd19025f -18991,Sony PlayStation Portable,Ys I & II Chronicles,,Games,USA,ULUS-10547,1.00,1125711872,30ee3f75,2dbd209fb74823bc4c8a7a1b901539c0,9fde4e47e834e37e78b5de0e6e680e2b85a1d650 -18992,Sony PlayStation Portable,Silent Hill: Shattered Memories,,Games,USA,ULUS-10450,1.00,1014005760,bd9f01a5,58e3a18ded3abeb01d8c2486b4dd06ac,0ba73f491df6e88539e1f2623c6a43bde957900d -18993,Sony PlayStation Portable,Hot Shots Tennis: Get a Grip,,Games,USA,UCUS-98701,1.01,1279328256,6749889c,ce105d010fa0c4483a823146850e5e45,52194d91b539164b0be9acba68e7da9e5368e821 -18994,Sony PlayStation Portable,Ghostbusters: The Video Game,,Games,USA,ULUS-10486,1.00,1175552000,49e69374,b29b349e00363cb27a5444df069a7b19,4fd54692549061707d2a78bbf8d4abf93b326fa4 -19010,Sony PlayStation Portable,Hot Shots Golf: Open Tee,,Games,USA,"UCUS-98614, UCUS-98614GH",2.00,459702272,122c8697,5bcbe48b621d0ff34d89a3721efc92b0,e47f36bbacab9a2fa0052d806378ca829eb2d91c -19056,Sony PlayStation Portable,Ben 10: Ultimate Alien: Cosmic Destruction,,Games,USA,ULUS 10542,1.00,1340997632,12aaba48,a2a10f24af486fca27359f90295a9791,75819985c2498c011cda62bf0b24a236040e6701 -19063,Sony PlayStation Portable,Hot Pixel,,Games,USA,ULUS-10298,1.02,336625664,85cdfb17,77b2f75c916fb4fc654e10321040285b,47306a6cbd0661c64c072b7ed63788e8b232fd70 -19111,Sony PlayStation Portable,Code Lyoko: Quest for Infinity,,Games,USA,ULUS-10351,1.03,895877120,a421645e,9af119140bcc35c2e562210a391284e2,7202e32f892a225f093f30c5a9f0733ed135a1b4 -19127,Sony PlayStation Portable,Tiger Woods PGA Tour 06,,Games,USA,ULUS-10028,1.01,1301381120,f4520c6c,4071d7242aa7d4eaf1b4530e1c7106a2,b1a4698746b51667532cacc0b4f3d7d6877d47cd -19129,Sony PlayStation Portable,Pipe Mania,,Games,USA,ULUS-10359,1.00,321847296,85322bc9,21d4b49a7f0a237c6450dce3faa95546,c6c3951a03073d6d8763ef3e8aecb0469a8a4dd1 -19130,Sony PlayStation Portable,Crush,,Games,USA,ULUS-10238,1.00,612139008,e2967d94,6d89aecab61f1f1515d7875c23d0865c,a51f8808e8d0b20bcd1bd6ae4662b8aab937d6c4 -19131,Sony PlayStation Portable,Hot Brain,,Games,USA,ULUS-10268,1.00,547782656,4ca96457,818ffec182ba9ee5fd81d81ffbb8fbb8,2601a931c63c7f4eb02a0df45e397c1df101c791 -19132,Sony PlayStation Portable,R-Type Command,,Games,USA,ULUS-10343,1.00,333578240,701b96c7,d3f3e34c07f25fdbc7dd083352bf33b6,f9ef390bed8600e75e1163042ac09cc373f0d852 -19133,Sony PlayStation Portable,Blokus Portable: Steambot Championship,,Games,USA,ULUS-10332,1.00,66158592,55703bdd,f507374982b33de986c5a59c4b592ce0,a3b2193f83a7cfa545e9bed9b2c01567838adb26 -19134,Sony PlayStation Portable,Gunpey,,Games,USA,ULUS-10182,1.00,731447296,9844edd9,6cfa4b622b5005ba1e275065a0dcc67d,8778af4e71d4c2b8743a81b68a5ce46e981c9991 -19135,Sony PlayStation Portable,Pursuit Force: Extreme Justice,,Demos,USA,UCUS 98718,1.00,283312128,6073d6a2,a73a9c539254f1cf80b0b2ed9a555c04,f4d2f25b87a31b42134e32d5d619406775585081 -19136,Sony PlayStation Portable,God of War: Chains of Olympus: Battle of Attica,,Demos,USA,"UCUS 98713, UCUS 98713BB",1.00,256999424,80593953,be8190fcd84f60b724cf1c8ccf54938a,cdb993e248ae6861c57e074d6a7de0cbe582a611 -19137,Sony PlayStation Portable,Death Jr. II: Root of Evil,Death Jr. 2: Root of Evil,Games,USA,ULUS-10157,1.01,731676672,e8f6892e,ab90d37f0c76f328bdfaf9c4be1e94ba,9f7ee6e785aae05edc7a31071720efb783c526e2 -19138,Sony PlayStation Portable,World Championship Poker 2 featuring Howard Lederer,,Games,USA,ULUS-10060,1.01,207126528,602639d7,e03ef30e19484377544be54c372c7048,f89bee940fc70f6e22ed5ca1551a14bd997dd0c7 -19139,Sony PlayStation Portable,DJ Max Emotional Sense: Fever,,Games,USA,ULUS-10403,1.03,1713602560,3dc62f19,9d31b047b28b686d3e19fa90620b1f9e,de59ad4fb0ac7ffe0446299dc5dc9c841f234995 -19149,Sony PlayStation Portable,Eragon,,Games,Europe,ULES-00474,1.00,253100032,6c4b546d,53f7049a5f78cb2bd00b4f6b8006ea78,f50a615ee7d4da9936851bcb707402f8383f25ef -19152,Sony PlayStation Portable,Bliss Island,,Games,Europe,ULES-00616,1.01,192905216,462413d1,407c4cf6525fbbb10dcab065b7ea0e42,2660b0294722b576489443b4fe487b048b5fcb0e -19153,Sony PlayStation Portable,Imagine: Champion Rider,Abenteuer auf dem Reiterhof: Die Pferdeflüsterin,Games,Europe,"ULES-01161, ULES-01161/E",1.00,1424588800,e87429f3,6bf9e5b9be1f367dfac4a53bc3e908c3,9ca90c7b21108316d977efc19cc40fd84e3c43fa -19174,Sony PlayStation Portable,Ridge Racer,,Games,Asia,"UCAS 40015, UCAS 40093",1.00,906362880,600c55e2,e22244a989684123e4142c99b016d7b0,35c6bc37c1b050b901c432f09b74c73d87647028 -19175,Sony PlayStation Portable,Hannah Montana: Rock Out the Show,,Games,USA,ULUS-10431,1.00,906362880,8b30a3d3,3eb857509a79c58c688bc503b5a04b0d,59c7a4178952483da263fca0a6a6667b8d99305c -19176,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,クライシスコア ~ファイナルファンタジーⅦ~,Games,"Japan, Asia","UCAS-40167, UCAS-40272, ULJM 05275, ULJM 05517",1.01,1787723776,c62f7203,a838139a3b5982de651d4104f7aa0bcb,96ba56dd9456a8e5876c7c7c78c7c1d3965521ad -19185,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,Germany,"ULES-00182, ULES-00182/P",2.00,1255243776,d0a1c0f5,cf7947456ea763ecf8e330ad428a7f3d,f3ff2dc3e07cf9b377b432e03bc880079d268808 -19186,Sony PlayStation Portable,Riviera: The Promised Land,,Games,Europe,ULES-00818,1.00,393052160,9542b27f,de9c442dc2d477b65c6feed59d66b4ce,83463cc23d981d730f909c6e275603a98595fd69 -19187,Sony PlayStation Portable,Half-Minute Hero,,Games,Europe,ULES-01359,1.01,222461952,5c5712a0,e0478ece37f3e30959bc214dbe834a42,3fb77fcf097b6047d829657301e719520ae3a3d4 -19188,Sony PlayStation Portable,Metal Gear Solid: Peace Walker,,Games,"Europe, Australia",ULES-01372,1.01,1646002176,7d211ac4,ac5b490b17b7e60124e15612a1b54b00,76031e8df71b208d13101dd82c03ea2740036668 -19189,Sony PlayStation Portable,Valkyria Chronicles II,,Games,Europe,ULES-01417,1.00,1081737216,e92e563e,a9187c02e28c7e1638139087dc129604,3dce5f23091f1c0727bfadc63b182b080364a179 -19190,Sony PlayStation Portable,Kingdom Hearts: Birth by Sleep,,Games,Europe,ULES-01441,1.00,1767473152,bb96c50c,a3930d230ce2598761ead2c67fe8f2da,2a7fd906a8869e15817fc1eac9b3b2d267cc032f -19191,Sony PlayStation Portable,Yggdra Union,,Games,USA,ULUS-10368,1.00,768671744,b7d94bf5,a091606fb7a7c3b79b56e86a70bd559e,d516f576687a46199e9b698ad4477ddbab8bb863 -19192,Sony PlayStation Portable,The Legend of Heroes: Trails in the Sky,,Games,USA,ULUS-10540,1.00,1421639680,1f8c6bea,716f86d6631d0702829b97b0aef2f937,37ed4e7f374f4fcdaf400223d7aefa870343e950 -19193,Sony PlayStation Portable,Phantom Brave: The Hermuda Triangle,,Games,USA,ULUS-10572,1.00,797442048,7f4dc345,a7724b3c6292da99bc9ffd7f40741e4d,8739e80f62dc5c34851646a36b48ee5656b5abb5 -19203,Sony PlayStation Portable,Pipe Mania,파이프 매니아,Games,Asia,"UCAS-40215, UCKS-45095",1.00,321847296,be94c9ae,ee0e46303f422d31674187fcf4ee3120,292b87d6abeed1a7209344dc822c4d7fc9b7858f -19214,Sony PlayStation Portable,Guilty Gear XX Accent Core Plus,,Games,USA,ULUS-10409,1.00,902397952,1834c23d,a4b2be6e79435087a8442014900545a2,7173648a945d5dd88a70c1f92f99314f3bae779d -19215,Sony PlayStation Portable,Yuusha 30,勇者30,Games,"Japan, Asia","UCAS-40259, ULJS-00195, ULJS-19040",1.02,219611136,e5e924b0,dee6c178a576a5771c387dd65cebf445,ca0a8f7160869b64b310bce2bc3c8524e86a59aa -19228,Sony PlayStation Portable,Archer Maclean's Mercury,,Games,"Europe, Australia",ULES-00011,1.00,289931264,62913909,87a1c2d2e58cd6f6e15a99cfe5f889bb,d4823c89a81b3d6a7d166366eb7bbf0684103418 -19229,Sony PlayStation Portable,Nickelodeon Avatar: The Legend of Aang,,Games,Europe,"ULES-00633, ULES-00633/E",1.00,179240960,0ff5517e,2a88d596ba4d0a1dbc5a79c3bcd61241,5e0d62fa99d582d32bb5e48f9a98ee87d58a5a3c -19230,Sony PlayStation Portable,Burnout Dominator,,Games,Europe,ULES-00703,1.01,777748480,3d0ca5b6,62a9eda0d9e729a1ab2da95cc0d4f588,26ca8b86b3306e095deaf64615da13caa4ee0541 -19231,Sony PlayStation Portable,Colin McRae Rally 2005 Plus,,Games,Europe,ULES-00111,1.02,1705213952,b3a8c4b1,d61ab4550fabb7d745544eedfb61d6df,8b805d9e2520f3a2d816c965e5a4b77d93dc41df -19232,Sony PlayStation Portable,Dungeon Siege: Throne of Agony,,Games,Europe,ULES-00569,1.02,902266880,43684492,f1a8bdeeef9ce1b43c02d426bbb5a63a,35b697b66d5237a13901b2a00cdd7b77ee16c459 -19247,Sony PlayStation Portable,F1 Grand Prix,,Games,Europe,"UCES-00004, UCES-00004/1.00",1.00,689569792,70e64019,2d77b3c671c8d2a012a5a29bc5c70bc6,46bdb0b7745b5bc620bffbec2643d4bad2e9a9ab -19248,Sony PlayStation Portable,FIFA 06,,Games,Germany,ULES-00163,1.00,1192787968,fea7c337,5b67b7eb00fdf836bfa76707f29cf156,621d03b115fb2a04034e2adcf88e838ebf4cd09d -19249,Sony PlayStation Portable,Fading Shadows,,Games,Europe,ULES-00858,1.02,302448640,fc53a0fb,1057fa9bf4a57ccbf2adefe58376296c,d72bbc7b834cd0df132c7e74ce7156d436226c25 -19295,Sony PlayStation Portable,FIFA 08,,Games,Germany,ULES-00894,1.00,1335328768,0db72bbe,8d4724c4bbf2450a9970e2ffaad0439f,e7c8890faed4f824a0723559076c323fec3fd200 -19296,Sony PlayStation Portable,FIFA 09,,Games,Germany,ULES-01137/P,1.00,1437597696,2de86d3a,40cdf7a7dd137b99ff8e272853d7623c,bdf5e94c3e709902352588244f493a4b43f9532c -19297,Sony PlayStation Portable,Gran Turismo,,Games,Europe,"UCES-01245#, UCES-01245/E, UCES-01245/P",2.00,1177026560,da79c7c1,4dc1b4d42e5081616d46538c629f42cb,c84473375e3cd000d8f14c5905e6514389fd6a40 -19298,Sony PlayStation Portable,FIFA 07,,Games,Germany,ULES-00443,1.02,1315995648,801e04ad,e526efac48a2aed1f2c2829712a93c00,129dc7b965c52d9ee3e52eba9268995fe7ccb66c -19300,Sony PlayStation Portable,FIFA Fussball-Weltmeisterschaft Deutschland 2006,FIFA World Cup Germany 2006,Games,Germany,ULES-00342,1.02,1293418496,b79aef66,8bf1b1a817929b587fc024998ddf6ec5,c1bc29f92edaa50caf125abc71abd84a1f3b7de9 -19301,Sony PlayStation Portable,Der Herr der Ringe: Taktiken,,Games,Germany,ULES-00200,1.00,542212096,a8625ce6,3472925ef29b99a731489d42d4bdbb3f,afd4b71662081a8d9fea37038177a8fa72b0d79d -19302,Sony PlayStation Portable,The Lord of the Rings: Aragorn's Quest,,Games,Europe,ULES-01395,1.02,605519872,7ee31090,2f5d162ce3a84772806593fd5f851553,4a9776416637cce4f978c5b53ee1b9987325b730 -19303,Sony PlayStation Portable,Monster Hunter Freedom Unite,,Games,Europe,"ULES-01213, ULES-01213 / 0991398, ULES-01213/E",1.01,886702080,32627baa,7b86d726aebdb6fc8b57e2d6678ca3ac,b67f57e2ea0d5a31d3c58eb0c7e54c4ef47ea838 -19304,Sony PlayStation Portable,Hot Pixel,,Games,Europe,ULES-00642,1.00,349437952,5eb5cc4c,f7de052976c53e4d85e998d538c58054,41b66c6fd102536e821b2d66d1344b0c97950415 -19305,Sony PlayStation Portable,MX vs. ATV Untamed,,Games,"Europe, Australia","ULES-00993, ULES-00993/E",1.00,300679168,acd31192,28d48c36d02b80b6a14c356bca803000,193a414438ff7f5858688a3899e8ecdcdce6d88b -19306,Sony PlayStation Portable,Indiana Jones and the Staff of Kings,,Games,Europe,ULES-00939,1.00,842530816,3f5c7ef8,d399fed74f6d61f87d1d676d826d93ac,39469818a40f1a92bfe6d1272c9876f8ccdb396a -19378,Sony PlayStation Portable,NBA Live 08,,Games,Europe,ULES-00920,1.01,1616052224,34b2ee5a,b63c712991fe0a2cd93e41473c7d928d,5ee8bb3e3e826b25da19e969cfdfc3b4a05e01fc -19379,Sony PlayStation Portable,Mytran Wars,,Games,Europe,ULES-01098,1.01,1266221056,bc910b23,ba47ce9dad4b019c221c863160d7bd29,5cf142ff9541e92787226bf2a7e710bbf41bd5a1 -19422,Sony PlayStation Portable,WWE SmackDown vs. Raw 2006,,Games,Europe,"ULES-00227, ULES-00227/P",1.00,1704394752,1a425906,cc5e2303df48c83994ee1ca533905f85,da26132b79054e114fa3fab0140439ea5c8d5609 -19423,Sony PlayStation Portable,Grand Theft Auto: Vice City Stories,,Games,Germany,ULES-00503,1.02,1696006144,bcd5e190,ac8e2753bf955be62eb6338780b8367b,ee8ab9ad8bd510d224c59c742ebce9594d0827b1 -19424,Sony PlayStation Portable,Metal Gear Solid: Portable Ops Plus,,Games,Europe,ULES-01003,1.00,1264222208,42c3ba9d,0630085014f7a30bd04ae36ce3fc101d,716c6d8039e767e3c10f64fb051dcaf7bf04c3e9 -19425,Sony PlayStation Portable,SBK-07: Superbike World Championship,,Games,Europe,ULES-00800,1.02,285573120,11b16864,5a83c1a3dc7358c5dd4aa0cc68ad89de,2f4288eb66eee541e7d1dbc6a407744b5199e0b7 -19445,Sony PlayStation Portable,FlatOut: Head On,,Games,USA,ULUS-10328,1.01,450592768,d0619458,d6d6a1cdbf413f5477d2b277cfe595c0,8e049f41269a606acd63a51defd4dfeca7e55ad0 -19446,Sony PlayStation Portable,Crash: Mind over Mutant,,Games,USA,ULUS-10377,1.01,1576468480,3cd38795,6e87a1d2f74feaac5e793502eb7427ed,15a6293fd5e0fa9d1a7bdcbf8d3b1c0659731a59 -19447,Sony PlayStation Portable,BlazBlue: Calamity Trigger,,Games,USA,ULUS-10519,1.00,1699250176,6e40530e,b6edee92e3d03ff1bb8a160b2f9bfef6,02cea88d7702a22b237b86f2671b3e6dc5d2ccd4 -19448,Sony PlayStation Portable,WWE SmackDown vs. Raw 2007,,Games,Europe,ULES-00631,1.02,1642987520,bbe6a22f,9bf4f088afd07d9a0c3cb04eb4adec25,cb04c5c55e91cf5508a573d363a6240d23d25745 -19449,Sony PlayStation Portable,Harry Potter and the Order of the Phoenix,,Games,Europe,ULES-00830,1.00,830373888,4fd563aa,e86d458408b8f7aa2f6a5e6aa1fbbb4a,b4c7404e22fd43a596a2bbd9aba2b3e22db77f2a -19471,Sony PlayStation Portable,2 Games in 1! Archer Maclean's Mercury & Mercury Meltdown,,Games,USA,ULUS 10568,1.00,717488128,1cc02ab8,2681f04af930d616da48058773e4545d,0bb641a9c13d0daf2c1a5e5d2b902838d5ece177 -19536,Sony PlayStation Portable,DreamWorks Over the Hedge: Hammy Goes Nuts!,,Games,Europe,ULES-00665,1.03,467435520,1a5d5ff6,52baa88deced48456bb28535fd3a6449,3d88829efd710aea12818284a3d3a44f4217600b -19537,Sony PlayStation Portable,FIFA 10,,Games,Germany,ULES-01330,1.00,1458864128,5e94bd8e,a256b5a4df1d63d202cb4fadf0a5324d,412934ff2549d7042475d5ede4456abb98cc8155 -19540,Sony PlayStation Portable,Marvel Trading Card Game,,Games,Europe,ULES-00683,1.01,934379520,47c65206,47c3d2a85720e43d1b9e1fe2daf5c88c,1ad6f56c0f6f371e9cd8dc6b5b9da5263cfad57f -19551,Sony PlayStation Portable,Z.H.P.: Unlosing Ranger vs. Darkdeath Evilman,,Games,USA,ULUS-10559,1.00,863272960,a84cb032,d5fae087fc290ab46d54279898b1bbd7,0aa15236676c0591990b035d98f806d4faf5c890 -19585,Sony PlayStation Portable,God of War: Ghost of Sparta,,Games,"Europe, Australia",UCES-01401,1.00,1787232256,5a86346f,7db381d0d3f3548b162025495494fe83,a51afa52ac9ceaf494dc5ce1bd3f5e6c882036d2 -19609,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,Germany,ULES-00182,1.00,1255243776,7ee89c69,6ac9ad3b95e5ef96068d101c1b991bd7,50f3464253f40c01a87bcd6a8dbf10bae7cd6836 -19623,Sony PlayStation Portable,Monster Hunter Freedom,,Games,"Europe, Australia",ULES-00318,1.01,749699072,bbfac2bc,03bb24c5b91ce6ca815b33c8d464beed,4a5d3ab167e911b67685e862b48ee539db8a5bd4 -19624,Sony PlayStation Portable,Pocket Racers,,Games,Europe,ULES-00275,1.02,269254656,47d65099,b7056b1129c2f1856f20993b2bfee7de,475c43eeba4ba5ce709bcf9a959d7c918b439a41 -19625,Sony PlayStation Portable,PlayStation Network Collection: Power Pack,,Games,Europe,UCES-01160,1.02,550699008,2f6800f6,75252b8651fb16c6309be945c998eb61,3ecee0bb3e11d6bd05f37989d4c71315307630dd -19626,Sony PlayStation Portable,Patapon 2,,Games,Europe,"UCES-01177, UCES-01177/9142447, UCES-01177/E",1.00,593199104,1f8ac3d3,cd7f2436e2b20003866685cf8fb69bfa,3374c8eb983a418ef01e27636e7f1053348e6981 -19627,Sony PlayStation Portable,MotoGP,,Games,Europe,"UCES-00373, UCES-00373 / 9686477",1.00,422313984,66c6078f,0de254fc1a18cb38e0acefb343305ef1,b5c1777ce7276b806a71b4dd673fe4bc99aff9bc -19628,Sony PlayStation Portable,Passport to... Rome,,Applications,Europe,UCES-00246,1.00,848953344,a26cdb7b,c4ec4fe91271b2117c45d64f50026810,a8e10e7ba90c3ebe29e83c24b639a243133f3ce5 -19629,Sony PlayStation Portable,Micro Machines V4,,Games,Europe,ULES-00368,1.01,601456640,e4662682,bbe642f88220479b46e5388304c83e51,b9815b2def8a09e98a6dba4f56efc210d63daeb0 -19630,Sony PlayStation Portable,Untold Legends: The Warrior's Code,,Games,Europe,ULES-00301,1.01,1697710080,27d247b7,fd4c9739ec6fda5463b1b7956fc9a161,4e3d788e4515ac02c21413a1d6ef2a5596b989dc -19642,Sony PlayStation Portable,The Sims 2: Pets,,Games,Europe,ULES-00596,1.00,1517813760,245fd11d,769da6ce3f9eca4ce5d81e620b6980f6,e9742a808c71615911653b03f0d9050cae2ae452 -19657,Sony PlayStation Portable,Pirates of the Caribbean: Dead Man's Chest,,Games,Europe,"ULES-00366, ULES-00366/E",1.01,471597056,5d6314f7,14ef83b1a5413ea21ef9b992ca56046b,3dc39561907ad13d4e870b47d3fb04c7668aa59b -19658,Sony PlayStation Portable,Pilot Academy,,Games,Europe,ULES-00374,1.01,328302592,27d26be0,28d51fc8a8744427e4ee3ed98ff9b52e,5ebb1a1ec0da339b4c257dd335adb19489bf027d -19671,Sony PlayStation Portable,Final Fantasy IV: The Complete Collection,,Games,USA,ULUS-10560,1.00,880771072,44d6551b,cd44c4f02eb71ce4c1dc74efb0fb9570,e5147d5fcc300e4480120ccd0ea5dc4bc042cc51 -19705,Sony PlayStation Portable,Go! Sudoku,,Games,Europe,UCES-00152,1.00,286294016,9600a95d,e623006f0d529d6dfca0dacf48da1b65,0a002e46156bb9b402b599b24b92fa228f955d90 -19712,Sony PlayStation Portable,Ore no Imouto Maker EX: Imouto to Koishiyo Portable,俺の妹めいかあEX いもうとと恋しよっ ぽ~たぶる,Games,Japan,ULJS 00357,1.01,485687296,9c5f95f7,45631e2082803fd145e19da04780799a,c79d0843ef48f52a4352453818af5a9f2359c16e -19729,Sony PlayStation Portable,Space Invaders Extreme,,Games,"Europe, Australia",ULES-01078,1.00,153780224,6658d19a,d5967d2bd015a4895453c2e28ba0cc91,90878ff0d3a1e25b3028a25a11b971f0fcba2b3a -19738,Sony PlayStation Portable,Need for Speed: ProStreet,,Games,Europe,ULES-01020,1.00,1545437184,7d2e4fe8,60cec05748c5280b18fa8e3e51880a1b,56eb1bc0f98ab5a2f64c995c4b0eef73d5a19339 -19744,Sony PlayStation Portable,Pipe Mania,,Games,Europe,ULES-01094,1.01,321847296,be217228,4d4cb2fef816e76d90818d17cf69cbb0,e010fab80ab91ced7946ed0990ef90c76663fdde -19745,Sony PlayStation Portable,ObsCure: The Aftermath,,Games,Europe,ULES-01340,1.01,987725824,92668ff9,7c246a05710a2e33c0d73928c90c0455,29ac4a3054b33bd1693c15a6daf79237f6d871ab -19746,Sony PlayStation Portable,Petz: My Baby Hamster,,Games,Europe,ULES-01266,1.00,199032832,82dfd27c,105f5a01d30341b23cd062a5a4068fee,91f9b605efeaee71d1c8335a8cf40499958b59db -19748,Sony PlayStation Portable,Petz: My Puppy Family,,Games,Europe,ULES-01267,1.00,194936832,0178313a,8d3db9d000725f9d86824d4e2760a647,779059aa22992efdc9979448958182d38d0e4a09 -19749,Sony PlayStation Portable,Madden NFL 06,,Games,USA,ULUS-10024,V1.00,1693646848,18120583,e01f4ac60d13e7a3d6047be1ceb9f075,0310a151ea6a594e75757bd0bebbb28b467a756d -19750,Sony PlayStation Portable,MVP Baseball,,Games,USA,ULUS-10012,1.02,1421705216,47a5a82d,28f9fcff3fa37886e76f4f198d8b9a8f,6be44fdaed38e88db5f609cf50230b4edd08e516 -19751,Sony PlayStation Portable,MediEvil: Resurrection,,Games,USA,UCUS-98620,1.00,1189937152,adc64af9,e6014369dc873fbe088ffe7168875ce1,e4a9730b1599952e4d6c4cceeb30edeb7ca0f551 -19752,Sony PlayStation Portable,Tiger Woods PGA Tour,,Games,USA,ULUS-10009,1.00,1812692992,dfd726ef,84084baaaaf35a01c64d6617eda4045c,b19f47cef2fecc53a783fb07e38facea3fbd40ee -19759,Sony PlayStation Portable,Pirates of the Caribbean: Dead Man's Chest,,Games,USA,ULUS 10111,1.01,471597056,37f23db5,7935cf16d00933a04b6122687c751e7c,676e4a1fe4488c630a3b2086540e4750a62f92de -19760,Sony PlayStation Portable,Harry Potter and the Goblet of Fire,,Games,USA,ULUS-10032,1.00,410320896,531a9653,b5fc5cca17de2713f60e83803d40b7b5,298a649417678ab64ae8f6bee9233d9e68ff1bf9 -19761,Sony PlayStation Portable,Buzz! Master Quiz,,Games,USA,UCUS-98729,1.00,906362880,b302e4e5,e4c634c1d54550c92d207456145eccdc,e6b49cdbe572817907769ca5757dc6907bb0c1c9 -19762,Sony PlayStation Portable,Patapon,,Games,USA,UCUS-98711,1.00,341016576,9962189a,ec744df36a51de776962e97df8135d7c,c961221ea6983872dbc434e9c09cc064acbcc556 -19763,Sony PlayStation Portable,Neopets: Petpet Adventures: The Wand of Wishing,,Games,USA,UCUS-98622,1.00,863305728,35f68ad2,f8d4b6cd12ba755d991048a33d2a32fa,cbd9e9139a67bc0fb21c84c66e2e10d290b93418 -19764,Sony PlayStation Portable,ObsCure: The Aftermath,,Games,USA,ULUS-10484,1.00,987725824,84f143e2,3ea984b068cfccbd241b90ce2ab5d3c5,e55fb86a02452a6053cdf926f51fc8469b19acb2 -19765,Sony PlayStation Portable,Beaterator,,Games,USA,ULUS-10405,1.01,1083506688,d69dd83d,fb54536ed0947fadc325c5476fbe3be5,d48c2ab869751be3ef600574c45aa10d3a9ba574 -19767,Sony PlayStation Portable,The Golden Compass,,Games,USA,ULUS-10315,1.00,1265860608,2850732b,f678b064c6dd3cc3143a8f9c2b7f5d1f,9733be2b519426fc59f2c2f1ed0dfda30620b870 -19768,Sony PlayStation Portable,Warriors of the Lost Empire,,Games,USA,ULUS-10309,1.03,1787199488,c1854222,4ea6c2ac8f0bcaead16e7118f598b54e,9d50ac88ba7d7ef8db4505246d4120e86bacd11c -19769,Sony PlayStation Portable,Smash Court Tennis 3,,Games,USA,ULUS-10269,1.00,1496055808,130a6246,223e4add43b951aa4a7079878d909747,7d5fc5d00c374dec993d2dabdfdbd7e9451996e6 -19774,Sony PlayStation Portable,"Traxxpad: ""Portable Studio""",,Games,USA,ULUS-10272,1.02,420216832,c66150e8,8fc52fa92e0938d43731aea5b364f54e,9ef7c8890c54464387a6f4c0049551c38c105a70 -19775,Sony PlayStation Portable,OutRun 2006: Coast 2 Coast,,Games,USA,ULUS-10064,1.03,634781696,c7927da2,e71ea37d9284e57331634b5be1785934,65e64106cf5c56a6953de6df565d0827d160aefd -19776,Sony PlayStation Portable,007: From Russia with Love,,Games,USA,ULUS-10080,1.00,732495872,ec14a394,7ac15312ca3d6dea887d6c537bdc3acc,baae2c81123a73e0ad87165de698c493d2436250 -19777,Sony PlayStation Portable,Sid Meier's Pirates!,,Games,USA,ULUS-10224,1.02,333479936,7f2f78ff,37c34c21a94936f7da3c343b42e405d1,33efd8281655b1785684a09ed777f117af3d8534 -19802,Sony PlayStation Portable,Dynasty Warriors: Strikeforce,,Games,USA,ULUS-10416,1.00,1397325824,c1c0ca98,e21035371f732111a83350a59338769b,20d033b5daf1b6907866a5a7965bd2a21bf116dd -19803,Sony PlayStation Portable,Dungeon Explorer: Warriors of Ancient Arts,,Games,USA,ULUS-10289,1.01,565444608,9b7c6c81,687fc8a1a6c8321c1e33b62fd929d0d4,eb4e870c81da9e5fc6ca1f98bab9ae791b7e8401 -19804,Sony PlayStation Portable,Disney/Pixar Cars,,Games,Germany,ULES-00323,1.00,906362880,31419f99,eed0743a00973aa267c72701ceb66af5,97fa34ae1b7606ec38a0585c0da4ee79d602ebb5 -19807,Sony PlayStation Portable,Naruto: Ultimate Ninja Heroes,,Games,Europe,ULES-00865,1.00,576225280,ccb56460,eac709e533f52db9d2f5926969ee5284,8b18ba5bda46a72c085c00da5849f5b34669c2ae -19808,Sony PlayStation Portable,Namco Museum Battle Collection,,Games,Europe,"UCES-00116, UCES-00116/9181712, UCES-00116/E",1.02,559251456,1488b184,83708f5fbcd3987293caf92da9fa3800,671b595578c525d87a41ec031ad29fe04bddb6e7 -19852,Sony PlayStation Portable,MX vs. ATV: On the Edge,,Games,Europe,ULES-00274,1.00,837910528,534babbc,154498439d4c1e380aad070b2c809561,9b8318510a6190600793ea380fa170939d98f132 -19877,Sony PlayStation Portable,Tom Clancy's EndWar,,Games,Europe,ULES-01068/E,2.00,221085696,fff7ada9,d857daf8202f3ce68b880ffd05052090,81d75f501fb3ab68dc3203d22f9583888fd9d412 -19886,Sony PlayStation Portable,Star Wars: The Clone Wars: Republic Heroes,,Games,Europe,"ULES-01285#, ULES-01285/E",1.01,1478393856,9df2a346,0b365dd3f1d60de2ade074a01072e09d,6930a34020e02734a8271dcbb2cd2f16e97ed079 -19949,Sony PlayStation Portable,Dragon Ball Z: Tenkaichi Tag Team,,Games,USA,ULUS-10537,1.00,1372225536,6a035b1c,5299e6c567a1c652b10777705806b03f,2bc42c418ac321739ec1480170ec53e5de536116 -19950,Sony PlayStation Portable,Test Drive Unlimited,,Games,Europe,"ULES-00637, ULES-00637#",1.01,1537015808,f5a053d3,2870f1ea032e6590d02c3b20103670f1,5c9fee602918cb0392a927e5a60d484ab65843a9 -19996,Sony PlayStation Portable,Harry Potter and the Half-Blood Prince,,Games,Europe,ULES-01180,1.00,408027136,b7fdf185,a61caca753a2e985a6da35f459fc041f,158c2b3eb736d246ea992b6627006370dbd9f6c1 -20017,Sony PlayStation Portable,Star Wars Battlefront: Elite Squadron,,Games,USA,ULUS 10390,1.00,1473740800,8c02055c,d199202cfcf8072b440abe05f163237e,9f491705c1b322b08d2e1e003c7e5c6d34f0e4ca -20018,Sony PlayStation Portable,Sonic Rivals,,Games,Europe,"ULES-00622, ULES-00622/E",1.01,246349824,dcbc235d,7dfe83392b4a3cbdfeaa974bb97c2eb1,b46d1b2456129ed25ce66ca93d295c4f505e0283 -20020,Sony PlayStation Portable,MTX Mototrax,,Games,Europe,ULES-00581,1.01,1062338560,d05fed87,388ac5c923e8246d248ef12041ae03d3,3bcfb692fcc56b2f9be61b2e580fc56aebf28880 -20034,Sony PlayStation Portable,Kingdom Hearts: Birth by Sleep,,Games,USA,"UCUS-98173, ULUS-10505",1.00,1767473152,40430710,962cce6f637464af8fc144c7eda97df0,0a61928fc0eaa78f169b4a172ba6165ecf8564a0 -20035,Sony PlayStation Portable,Phantasy Star Portable 2,,Games,USA,ULUS-10529,1.00,1341882368,2b77f008,10ab4d3da714349004fefdfd7bf0d0d7,29121b08e8c6e5055c4400f2ae43011d0cde0994 -20036,Sony PlayStation Portable,Warhammer: Battle for Atluma,,Games,USA,ULUS-10123,1.03,240648192,5f6f9d94,6d98f7ad9ae91578258a47326f0b9af0,5bf27b184717d9b63ed7fea975a69c0569bb0a43 -20037,Sony PlayStation Portable,Spider-Man: Web of Shadows: Amazing Allies Edition,,Games,USA,ULUS 10389,1.01,436830208,08960e40,2524150f964f688d10f8198ba8ecb0fd,637083f49562dd9f0382f19596388e4e6a493d2e -20038,Sony PlayStation Portable,G.I. Joe: The Rise of Cobra,,Games,USA,ULUS-10435,1.01,1164476416,eb35e3d6,0ef66b95e9df87d2311097d8d6814bac,10416e411e78784be076ced2c86f6e7f3e86e258 -20154,Sony PlayStation Portable,Harvest Moon: Boy & Girl,,Games,USA,ULUS-10142,1.00,341508096,77683451,dcc7ff404251f779fdfe7fd01130ed28,c3c966e14356421f52f32476499dab45f8581d38 -20207,Sony PlayStation Portable,Miami Vice: The Game,,Games,Europe,ULES-00375,1.01,427065344,048ce819,67f4a72aa13438d5aa6d0ca09d62cdce,f8ac5c5fc7a18b2b3367c508ff83594e2cd5024b -20211,Sony PlayStation Portable,Disney/Pixar Toy Story 3,,Games,Europe,ULES-01405,1.00,905838592,2d5a6303,ff0c2f9581af5de5e7f245b4720abec6,7fb456ccecba3228bfc860d150d9cd14776f2c88 -20212,Sony PlayStation Portable,Crash: Mind over Mutant,Крэш Повелитель Мутантов,Games,Europe,ULES-01171,1.03,1616805888,8b09aff8,ab5c34933d3e4ab6fe89b469e39afbb4,b90930b25e706b3758c52d917d91d6dcae26e14f -20265,Sony PlayStation Portable,Gran Turismo,,Games,Europe,UCES-01245,1.01,1177026560,f11efe3f,b4852a0706055a01364d138ebd0c0c75,3caff200892abb53f02f2c2a0e90ee8f2d30df31 -20297,Sony PlayStation Portable,FIFA World Cup Deutsch Taikai 2006,FIFA ワールドカップドイツ大会 2006,Games,Japan,ULJM-05133,1.02,1291124736,8911a765,86089f702d67dbe1c65dd091e9cecba6,691e51141ca7250de46d4747f2d9dbf6ee49f05b -20300,Sony PlayStation Portable,Need for Speed: Shift,,Games,Europe,ULES-01275,1.00,1798471680,84c2b2dd,96563fee9041b59bc0470b6be1226b1c,f8216be4002db4c2958c960644165931a4d29193 -20302,Sony PlayStation Portable,Monster Hunter Portable 3rd,モンスターハンターポータブル3rd,Games,"Japan, Asia","ULAS 42260, ULJM 05800, ULJM 08058, ULKS 46264",1.02,1207140352,d875535a,8e19a966356a83b8b395957671494bd8,0680394e5bd35f428711d55cf674f42e780d00b6 -20312,Sony PlayStation Portable,Star Wars Battlefront: Renegade Squadron,,Games,Europe,ULES-00861,1.01,1393688576,5396c553,299e2e71ccce78bc38256431ae902fec,b32f6bac109f899bed895c731ed71f137da7c570 -20313,Sony PlayStation Portable,Justice League Heroes,,Games,Europe,ULES-00609,1.00,1442086912,948605f3,881585863110dafb3c01a7792f3b80cb,7ca8cefc886cb8e6c26bc602b8d160bb2ace44cd -20431,Sony PlayStation Portable,James Cameron's Avatar: The Game,,Games,Europe,"ULES-01357#, ULES-01357/E",1.00,726597632,9255238e,73f6d93fcf106f92ac5ef744e97dd108,5a178ec5169a9c66e4d7b9c37dba394c69f8ac71 -20448,Sony PlayStation Portable,Thrillville: Off the Rails,,Games,Europe,ULES-00887,1.00,894271488,27b167e5,aa41f6c91ecd233e65ed983f68b55e76,6e7ac596ab73d83c91616e4e01b231c2103c9e10 -20485,Sony PlayStation Portable,Tom Clancy's Ghost Recon: Predator,,Games,USA,ULUS-10445,1.00,906362880,2ffc79ce,a503b22a02a0fea3232493a14529b579,6b05b038f0ac10dddfc3ee9b6c194945c1fffe5e -20501,Sony PlayStation Portable,Mana Khemia: Student Alliance,,Games,USA,ULUS-10408,1.01,1085833216,67b02322,0ba7fd9d96681e17bb6c6d51b28abfd9,5e3489f094513761a12a893e268834dd36d2b980 -20502,Sony PlayStation Portable,Crash of the Titans,,Games,Europe,"ULES-00915, ULES-00915/E",1.01,1078001664,ca09cb05,e90834233afce27886a2a4fa52eb0ebb,a534507b407a1a7b656e45de16e970d8177117f4 -20503,Sony PlayStation Portable,UEFA Euro 2008: Austria-Switzerland,,Games,Europe,ULES-01025,1.00,1458077696,d6e63f3d,318f54cf13720ce3c163b92c7220a891,5e18d82d87f9568d086c8cbf3629c1e17a357ea4 -20504,Sony PlayStation Portable,Tiger Woods PGA Tour 06,,Games,Europe,ULES-00154,1.00,1301381120,763cb2a8,7d9e19a7e07a9a93517ef523d5eb87c5,3126f2163c6b484210b4a420127916002d1acce7 -20505,Sony PlayStation Portable,Transformers: The Game,,Games,Europe,ULES-00824,1.02,1560117248,838568fa,d10346d5dce34b4e8226586a996b17f6,84c5c9a0457d073b918846af430c918b7ca1b98d -20506,Sony PlayStation Portable,Fullmetal Alchemist: Brotherhood,,Games,Europe,ULES-01432,1.00,497876992,e40da593,c1421e770c38adb8ed09aa2b4387ed57,b3c28d705bb887107ed27a1ded6cde7428d03bcb -20507,Sony PlayStation Portable,Carol Vorderman's Sudoku,,Games,Europe,ULES-00388,1.01,1125580800,11e7fef3,08e36592ad3152ee37dbc1325e9842c5,8875bdf7c818660705f89cde53f237df6eb46cf4 -20508,Sony PlayStation Portable,Pro Evolution Soccer 5,,Games,Europe,ULES-00160,1.01,1029013504,3c550810,52280230dace893089ff5281e2140a4d,ca8afd3537190c3cd01b5b1584723c2959eab2f3 -20509,Sony PlayStation Portable,Shaun White Snowboarding,,Games,Europe,ULES-01185/E,1.01,491454464,5c9cc776,f9f48fb095061f03b75a89d4bbe942fa,ba97b8903bce7f0688c27ca45f6dbd268f8aedfa -20510,Sony PlayStation Portable,Nickelodeon SpongeBob SquarePants: The Yellow Avenger,,Games,Europe,ULES-00280,1.01,174260224,c44c2bd2,ff08fe1a61c6ffaa04ce600b16948a1e,4087bab3ab00cdcb39b60112c4fa923b74de421f -20585,Sony PlayStation Portable,God of War: Ghost of Sparta,,Games,USA,UCUS 98737,2.00,1747714048,b82d36cb,558241ad68feda59c7537b8a7b04588c,3238b23f3f99e6d7b598d7703b53a4f5437d0b6c -20587,Sony PlayStation Portable,ModNation Racers,,Games,USA,"UCUS 98741, ULUS-98741",1.00,1652162560,b8d04288,caaff72a984aa0e21831a26c0102feb9,b8e56db4f13e4ca6e5cf5bbb0ecaf9649ba2cd2c -20589,Sony PlayStation Portable,LEGO Indiana Jones 2: The Adventure Continues,,Games,USA,ULUS-10487,1.01,677511168,7902099b,87b75aa969b533a2e5f941e37cb94f65,def9e75e0baee3c075e4d61842491a00ed6c604d -20590,Sony PlayStation Portable,Metal Slug XX,,Games,USA,ULUS-10495,1.01,463732736,6d18bed8,ac04e33e048d26f2cbb3350a80d5c06a,ef933b8ea01b0f06214b9a6767387f2c0842c501 -20592,Sony PlayStation Portable,LEGO Indiana Jones: The Original Adventures,,Games,USA,"ULUS 10365, ULUS 10365GH",1.01,1241153536,c4059a1e,7eb2b573710e2064b06c605e14bb7c4d,4d5bced4a4fc783a0f70d1087a3e9978605ff740 -20701,Sony PlayStation Portable,Tiger Woods PGA Tour,,Games,Asia,ULAS-42002,1.00,1812692992,47355097,21bff37420b825dd428c72543297444e,9b0a25d8bdfbf2a4a189d5f62340c4a5a1d8ad2c -20702,Sony PlayStation Portable,Tom Clancy's Splinter Cell: Essentials,,Games,Europe,ULES-00281#,2.00,1811709952,b15b7542,a2ec692c445add804108f687b757a737,09527a31dffbb09c3e19a984ea5e601a328a06d6 -20703,Sony PlayStation Portable,Monster Hunter Portable 2nd,モンスターハンターポータブル2nd,Games,"Japan, Korea","UCKS 45045, ULJM 05156",1.03,836304896,ff200cdb,e6e1596e31edd9181f0499a33fbab625,8c27382291d3e2a98b592e87478d8072ef0da87a -20704,Sony PlayStation Portable,Patapon 2: Don-Chaka,"파타퐁 2: 동챠카, 戰鼓啪打碰2: 咚鏘",Games,Korea,UCKS 45135,1.00,583794688,6e0aed7d,33a7a573ed46a229920df88ed4fff791,a24ed728e5af3212f48cf12dcf54b862058691ff -20705,Sony PlayStation Portable,Fantasy Golf Pangya Portable,판타지 골프 팡야 포터블,Games,Korea,ULKS-46164,1.03,1510834176,35466df2,8761bbe83568a28eeb5706d156b50e31,af725498154abf81bb9ce6ef87977839fc588ab4 -20706,Sony PlayStation Portable,Piposarugetchu P,삐뽀사루 겟츄 P,Games,Korea,UCKS-45009,1.00,811728896,e147c421,47fa9309e622120e0122e9acce26f9e8,d1841f22792f7981ac9478e9c50066ec61a4b07a -20708,Sony PlayStation Portable,Sid Meier's Pirates!,,Games,Europe,ULES-00688,1.01,333512704,01bee310,c236b42b88966c50660b233bbdef38ae,4450d1c4e970f5290475f1eb00681ce85ee653d9 -20771,Sony PlayStation Portable,World Poker Tour,,Games,Europe,ULES-00296,1.01,525107200,9af5d5c8,0ed863da3876ecdd4807e465fddea0c3,45e89ea8f99639c6ac85b3560b53a205823af85a -20831,Sony PlayStation Portable,PC Engine Best Collection: Ginga Ojousama Densetsu Collection,PC Engine Best Collection: 銀河お嬢様伝説コレクション,Games,Japan,ULJM-05358,1.02,650805248,82b3b10d,a8127ef72f313256f36aff63f1324aa3,a8bb05b934650ca6798146f8ae9b91be5327a3a2 -20835,Sony PlayStation Portable,Ginsei Shougi Portable: Fuun Ryuuko Raiden,銀星将棋 PORTABLE 風雲龍虎雷伝,Games,Japan,ULJS-00405,1.00,215121920,537219d7,3c9b38be783a9538ee8e43abcea6c0f3,77f90cc9f880736b0fc231f58fe82952899333eb -20836,Sony PlayStation Portable,Xyanide: Resurrection,,Games,Europe,ULES-00634,1.01,1567227904,ae0db564,931b2a98e2af48b96ae4f38b0d1b329f,c6ba11e1e8e4a54a983853db2370e71e2417deb2 -20837,Sony PlayStation Portable,WWE SmackDown vs. Raw 2008,,Games,Europe,ULES-00932,1.01,1785757696,3c4c2ae0,9ec9dd6f8d728b2134332e9a8ab29e9a,0b059de2bbdd2e1fefcb6eebc82ea010e74f4ce6 -20838,Sony PlayStation Portable,Phantasy Star Portable 2 Infinity,ファンタシースターポータブル2 インフィニティ: スペシャル 体験版,Demos,Japan,ULJM-91022,1.00,1467252736,4c4204fd,17d4dcdb4b84c2f7efcefd2f34d7fd33,8336051a3c3300f2fc5318da413b8002113c235b -20839,Sony PlayStation Portable,WWE SmackDown vs. Raw 2010,,Games,Europe,ULES-01339,1.01,1577025536,de31e5fa,4f7d38c020a1722914e450f21a188fc9,42ba4a78c983d17076bbb3e6bb8bf5f6a4f9499b -20843,Sony PlayStation Portable,Silent Hill: Shattered Memories,,Games,Europe,ULES-01352,1.00,1014005760,6c244393,73ea096d1ae8bc676d508f4fd8aa7b0c,2d94ea4921f8d081bd797bcb180235cb65676290 -20860,Sony PlayStation Portable,Prince of Persia: The Forgotten Sands,,Games,Europe,ULES-01409,1.00,735543296,886b7b6e,57c9bef2e6e6574c87705e621792979f,3dfdb3fd270c458cdd0df818735b5de1d8657604 -20861,Sony PlayStation Portable,Yu-Gi-Oh! GX: Tag Force,,Games,Europe,ULES-00600,1.01,834895872,170954c5,719c99478032a4210ae877832061e9fd,6e46f4327050623035dcb5bc8da78985f02ab961 -20862,Sony PlayStation Portable,Yu-Gi-Oh! GX: Tag Force 3,,Games,Europe,ULES-01183,1.02,1792999424,5d2dff66,c28c8b13078919255d7623c921f8d82e,379601a07d73374fa4a03272488fd195133d7c0d -20863,Sony PlayStation Portable,Yu-Gi-Oh! 5D's: Tag Force 5,,Games,Europe,ULES-01474,1.01,1660289024,8469b6c9,c6aaf66680852a02e509c488c159eb30,9ead602eb1fcba906cfc07d39c63ad60ab55ce48 -20874,Sony PlayStation Portable,Naruto Shippuden: Legends: Akatsuki Rising,,Games,Europe,ULES-01306,1.00,770768896,3cbd38fc,1c30804352fee163d0933c01e82f4e2d,474c2306a7e7999ae5c80d956a36e4a7fd52fece -20875,Sony PlayStation Portable,Arthur and the Minimoys,Arthur and the Invisibles,Games,Europe,ULES-00669,1.00,1496154112,14bade5c,501e05e86c526672f357413555a09925,723ac0ed53040c66ff7b0f43a9926920acab4996 -20877,Sony PlayStation Portable,Dead or Alive: Paradise,,Games,Europe,ULES-01431,1.01,870121472,f5cd3d32,26ec0ebaa5edb50152522022d6cd7efb,6f9afc06f8cd4d6428b38c1bc648a3da2d212e79 -20879,Sony PlayStation Portable,Asphalt: Urban GT 2,,Games,Europe,ULES-00719,1.01,884146176,f867eb93,543a84ee3434e8ae3479b3359eac1593,ae1f4eec2f36dda37b71e052f802ebeb622d0295 -20881,Sony PlayStation Portable,Ben 10: Protector of Earth,,Games,Europe,ULES-00906,1.00,673775616,a5cdbaab,5101de621f945681e9e46bf40f5e8c61,13616ca813878d0c04582a30c5d83c4891177061 -20945,Sony PlayStation Portable,Jikandia: The Timeless Land,,Games,USA,ULUS-10562,1.00,169148416,24ac39d2,262a6b5e3945723a5a72db6e2c393998,90608135171019e44ce80ebc02c2033fd9529187 -20946,Sony PlayStation Portable,PQ2: Practical Intelligence Quotient 2,,Games,USA,ULUS-10258,1.01,672825344,57f56ef0,b2c08d5c600cba5873c43ac465d0ae23,ed945228a02d21cd67ee30d3383436b6fb2dc9d3 -20947,Sony PlayStation Portable,Taito Legends Power-Up,,Games,USA,ULUS-10208,1.01,316407808,8238b5c4,0f58f00ccde4bd201bff112fc46cdfd9,6b79e4929a7dbea9075c27a50a6d53107b5b8ec2 -20948,Sony PlayStation Portable,Dave Mirra BMX Challenge,,Games,USA,ULUS-10204,1.00,729841664,371222a6,81181dbd2a2481ea36f859ca0d76187e,6f2394de7a3cc59407883e74f816a9b898ffa274 -20949,Sony PlayStation Portable,Thrillville,,Games,USA,ULUS-10191,1.01,723189760,c9f7ef55,de3c705f368647aaf090b004e6dcfa88,f2684044a8771aafc6de417b1581a034e1e0fd0d -20951,Sony PlayStation Portable,Tekken: Dark Resurrection,,Games,USA,"ULUS 10139, ULUS 10139GH",1.00,1750237184,3ffd7a9d,3236024a1c151f9d5a3b23ede2fd63f6,8193a65dee49685db49284408c89bdb35324bc32 -20952,Sony PlayStation Portable,FIFA World Cup Germany 2006,,Games,USA,ULUS-10082,1.01,1291124736,34c83f3f,714797a7557affd08e583bff7a8d8bbd,aeeb37936d99ec586093432c30fa029ab641e40b -20953,Sony PlayStation Portable,PixelJunk Monsters: Deluxe,,Games,USA,UCUS-98739,1.00,220626944,c5aa5ad1,573c2a9617c725f5856a216990e4b61a,43ea26ae87af675a819977caf08a26f81393a107 -20958,Sony PlayStation Portable,Marvel Super Hero Squad,,Games,Europe,ULES-01368,1.00,1778450432,b4613e69,6a731a6d4c69fe19e2f2a7e7015dad3b,e1f6cf7d9d405553ddb1aadaa629e6020269956d -20959,Sony PlayStation Portable,Michael Jackson: The Experience,,Games,Europe,ULES-01512,1.00,339443712,3cb53284,23df5b659887c159b614d11ef9cf19c5,717c24165a391f45c52b0c6d5d807cca7e1732fa -20960,Sony PlayStation Portable,LEGO Batman: The Videogame,,Games,Europe,ULES-01151,1.00,1136689152,b531dfcd,ba30758b133663f0dc983d9e741f790e,96f870b6badfae0c168bdd19eaf9ed90680bce08 -20962,Sony PlayStation Portable,Open Season,,Games,Europe,ULES-00508/E,1.00,1507590144,b76d1ede,17120b498e4fb1d356a10c4900f00e96,10005b2b79dd2a08686479db5741209f470308ef -20963,Sony PlayStation Portable,Invizimals: Shadow Zone,,Games,Europe,"UCES-01411, UCES-01411/GER",1.00,1777958912,898d8ab6,0d8bc79e8307d68ea537102c27bc6d9e,c65921d90f6e89ff7c0cbf39cb5777521baaf764 -21004,Sony PlayStation Portable,Sonic Rivals 2,,Games,Europe,"ULES-00940, ULES-00940/E",1.01,516259840,a994a3f0,0e69ac256f4b86d6f2a3ac7eae5e34ca,8bf9fad2131e3f4d244239842853cb0cf2345b9a -21005,Sony PlayStation Portable,Buzz! Das große Länderquiz,,Games,Europe,UCES-01209,1.00,1614512128,93613241,83ed67df9bdbc6d9f1bca385c3d6b119,0c22b1be853738541d4a12b041d3d3e03a91896f -21006,Sony PlayStation Portable,Shin Megami Tensei: Persona 3 Portable,,Games,USA,ULUS-10512,1.00,1321861120,fa047515,72c194c04fbd2657acb418413c0de873,06b7ace9bc5293df7bf8609e652185543ab7d062 -21007,Sony PlayStation Portable,LEGO Star Wars III: The Clone Wars,,Games,USA,ULUS 10531,1.00,1746796544,c10b0f2a,ab902cf811e3cf1b2c1c1092285fe295,9fd6ca369b67d069ef269e1ae656c5fbac162db9 -21008,Sony PlayStation Portable,UFC Undisputed 2010,,Games,USA,ULUS-10508,1.00,1762328576,6c01eae5,e4af8cb45b065060d61b7b1cb050d994,693da8047dcb9437afbd76b8e9bb3c1eb0293cff -21009,Sony PlayStation Portable,Yu-Gi-Oh! 5D's: Tag Force 4,,Games,USA,ULUS-10481,1.01,1759838208,e5bf9bcd,d68e0d325ca365ae340d5f3ef083dc22,acf4fd9c1071cef9bc355e62dd08d98e1961791b -21010,Sony PlayStation Portable,Puzzle Chronicles,,Games,USA,ULUS-10468,1.00,402948096,c9787b2d,249fbd482a7bf3310814cb837ea0d00d,01ed50b2f1ceb70c81d6263494d56e7123f19783 -21011,Sony PlayStation Portable,Silverfall,,Games,Europe,ULES-00808,1.02,872710144,72274648,729fce16b8817e257ab5fdfe55a3550a,5d9e7519a7a0de662d8ee8582284b07b4fa4eebf -21012,Sony PlayStation Portable,Spider-Man 2,,Games,Europe,ULES-00023,1.00,950140928,90574a4a,d25a570de2143337fd5b24a6343fad4a,ea2360207a942f75aefe31c0fb61732aa9cf73aa -21013,Sony PlayStation Portable,Spider-Man: Freund oder Feind,,Games,Germany,ULES-00901,1.01,577142784,cd0fd04f,4d4b05a6d872c37672b10fb418ae55a4,76581522c2e684d1da056e1bb6a89e0439670b8c -21033,Sony PlayStation Portable,Hot Shots Golf: Open Tee 2,,Games,USA,UCUS-98693,1.00,942899200,90cab222,da3ef46acb08ccbbdb307a67ed5bfcaa,a2ddbd0fc243f6f8bc73a4b2864e8dae0cb4f569 -21034,Sony PlayStation Portable,Hot Shots Golf: Open Tee 2,,Games,USA,UCUS-98693,1.00,942899200,34cb921b,05b30707f85a5d5364f4f37eccbe973a,38c5aa36b51652656a7a62b715b548aa7e64fc46 -21081,Sony PlayStation Portable,Kao Challengers,,Games,Europe,ULES-00146,1.00,616562688,920ccbca,345e566984283fce2193745cbd899647,26780c0a34986eca204e1c93a884a3627593b0b3 -21082,Sony PlayStation Portable,Street Riders,,Games,Europe,ULES-00276,1.01,734003200,1630b59b,790ca89c507f47b58c8f4c0a48a6ab3c,0cf44ad2646929169a752e848ce642d8419bb2f3 -21083,Sony PlayStation Portable,Split/Second: Velocity,,Games,Europe,ULES-01402,1.00,1616379904,105b6722,27981ebeb7238f54e05b7e614c7e50b4,cac5fd587b39efa700bcdd66f22c74c81d963da8 -21205,Sony PlayStation Portable,World Snooker Challenge 2007,,Games,Europe,ULES-00453,1.01,900104192,2368a18a,b6a55e8c0dc39bdb16dcec3bf6cf5e2b,b896a4bcae432a0288260cd730af61c3b3250afe -21206,Sony PlayStation Portable,World Series of Poker 2008: Battle for the Bracelets,,Games,Europe,ULES-00991,1.00,900202496,4add31fd,7327613ea845ff22658df484a5239a2c,9fec8050246243e76a5ada58a649a467ce465af5 -21211,Sony PlayStation Portable,Tactics Ogre: Let Us Cling Together,,Games,Europe,ULES-01500,1.00,1614610432,c8abfddd,117128cc924f8f42a88d775ce2b809e8,8fc32e524776d92bb7d5e3219a8aad2ddebeaff9 -21212,Sony PlayStation Portable,Tiger Woods PGA Tour 08,,Games,Europe,ULES-00845,1.02,1350696960,8d37137d,cdaf33a1073ba6c702b8f77e8e9f82d6,16ec3b9d3571a17c5c804322686ef4544b36d2be -21214,Sony PlayStation Portable,Twisted Metal: Head-On,,Games,Europe,UCES-00018,1.00,1765048320,f6a68ff2,c9db389a2a4f9540c27125a9dbb4a14d,181914f4ad8a5164a3253798368c5c9ccd125204 -21215,Sony PlayStation Portable,World Series of Poker,,Games,Europe,ULES-00224,1.00,345276416,9aaf49a4,c3cd146c0a0009e116523dfb01939801,3062be239e11b4ad0aac21d8dab28d1c45a4e6cb -21242,Sony PlayStation Portable,ATV Offroad Fury Pro,,Games,Europe,UCES-00786/E,1.00,678821888,a0d325c6,17ecbab55d47210a22a38698faa0ea19,00a85a5034c1a364819f7fce0d759500470c02bf -21274,Sony PlayStation Portable,Diner Dash,,Games,Europe,ULES-00755,1.01,137265152,1df25513,543439e1ecee139143e931ef89f95464,973071b380e390cc0f67cd1440a041ba25bc606b -21276,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,Germany,ULES-00736,1.01,906362880,5da0ab5d,2fcf47ee77917edf4170ea3221670a21,da2bbadab0cd0dd0d814b27e4222e68676f53b37 -21277,Sony PlayStation Portable,The Lord of the Rings: Tactics,,Games,Europe,ULES-00198,1.00,554008576,ba5abaf8,2e2efe92f3d03c316ea70eeab5225427,d6b8c62010a783f15c0882ee41af702a6c928cd4 -21278,Sony PlayStation Portable,Mega Minis Volume 1,,Games,Europe,UCES-01502,1.00,308248576,c618b735,96e15923e93ad8f93dde7437859e8051,5c78d435fbf4d8451a63bd3e1bf7f3c173e609b2 -21279,Sony PlayStation Portable,Mega minis Volume 3,,Games,Europe,UCES-01504,1.02,363069440,16d1a099,8d262161f1044474e6d99c441e4a2417,bdd4c36ea79a8504be006f13d09a2eaac73ea560 -21280,Sony PlayStation Portable,Thrillville: Off the Rails,,Games,USA,ULUS-10306,1.01,778698752,e4e8b714,1251907f5d284c4243f27ea16195a390,9e1567716c1ddbf2a3cf5cf316196ef5767f8980 -21281,Sony PlayStation Portable,International Athletics,,Games,Europe,ULES-01090,1.01,138510336,d0a8d96e,a118d303a23fdc8b051b6ceb0f92d1ed,b265ae0b698fa4c545df9e96164ea36571877a5b -21282,Sony PlayStation Portable,DreamWorks Megamind: The Blue Defender,,Games,Europe,ULES-01415,1.00,906330112,c2da7338,092f6c681de4ca9d68fc8907f556fd6d,28e197c8766f1def0165eecfc894cd63ced3cf17 -21283,Sony PlayStation Portable,Bakugan: Defenders of the Core,,Games,Europe,ULES-01466,1.00,887357440,2b949580,580e9134479a4a3ef43f025b060786d6,8a0ce8c12ea52dcc9337f7564bb2e15518623aa5 -21322,Sony PlayStation Portable,ModNation Racers,,Games,Europe,UCES-01327,1.01,1794572288,8284a099,75c2e1f27f9018f681c4faacefa3455b,d87eecb1abcf279a8912a81f97e9f6cef25e08b4 -21325,Sony PlayStation Portable,Patapon 3,,Games,Europe,UCES-01421,1.01,582418432,39150910,c781bb038321b0eb52fbb2beb9b8b9a9,022dfdc6cbe071a8e5ec0dfd47a77f5c8fa377f4 -21342,Sony PlayStation Portable,World Tour Soccer 2,,Games,Europe,UCES-00206,1.01,906362880,b81fd96d,49d35fbac2d08142903a41471b914103,8d5044e294123141310f5b2a5dcaddce847e2b4e -21343,Sony PlayStation Portable,Pursuit Force,,Demos,USA,UCUS 98655,1.00,136052736,56f93b5f,bc676c7e5b3e79f8093ed64cce613aec,8cc6d52ca5ba34fc8b6df1210734925034cba08b -21344,Sony PlayStation Portable,Madden NFL 12,,Games,USA,"UCUS 90678, ULUS-10581",1.00,1205600256,2673bafb,751de3e25dd60d0f9449219da69d0fc0,c2a44bd34d2950c69b7df71dbd33e87df0b23f21 -21345,Sony PlayStation Portable,Hellboy: The Science of Evil,,Games,USA,ULUS-10301,1.00,906330112,80e4efc6,b28130358a6533b7ce7970f34be08a06,fdeb1fbec02656deaeb3687718dfe8729c6f6bee -21347,Sony PlayStation Portable,Cabela's Legendary Adventures,,Games,USA,ULUS-10385,1.00,489783296,72e226c3,4dfd53dfedad54a9a7ecd763e9a6fcec,5c1b521438910212cffcdaf1d201ed6b9934c98a -21348,Sony PlayStation Portable,Naruto Shippuden: Ultimate Ninja Heroes 3,,Games,USA,ULUS-10518,1.00,1360363520,2617678e,ff0c5acaa68cd9ede1970c511e9a54bd,6c909c770564adbc0966ea6c75a317d9174f4a8c -21352,Sony PlayStation Portable,Shin Megami Tensei: Persona 2: Innocent Sin,,Games,USA,ULUS-10584,1.00,1130889216,58ae311a,f7015d746b5b14b9194c29df5eeda845,d970d2cca78e46639f5191ac51b29a89f8e4edfc -21353,Sony PlayStation Portable,Star Wars: The Force Unleashed,,Games,USA,"ULUS 10345, ULUS 10345GH",1.01,1111490560,8f1ef50e,ba8158a2d320be4460b5317f06131f69,a0f7ae66d0145dcbfa1b1d2363c39941858f4b8d -21354,Sony PlayStation Portable,FIFA Soccer 07,,Games,USA,ULUS-10112,1.00,1616478208,b36ee6cc,378a4fd2f99b42ab0631e8484b2abfe1,76ba7944feebe5e728432daa4c4328b196c4ff28 -21355,Sony PlayStation Portable,NBA 09: The Inside,,Games,USA,UCUS-98715,1.00,1079508992,2316dcb2,cd25402627284bedee2281934da09421,4239a53630beb6357d69480f3ce21064113141af -21356,Sony PlayStation Portable,Rengoku II: The Stairway to H.E.A.V.E.N.,,Games,USA,ULUS-10127,1.02,502333440,71111d56,76ca76c3b46552e3022e249122be4142,634131fc127abbb5e12273a4ad5d7b60223764aa -21357,Sony PlayStation Portable,Viewtiful Joe: Red Hot Rumble,,Games,USA,ULUS-10087,1.00,656637952,9a22dcf7,0b95c4baa78e3e55cf77525dda8cb7b2,ec9b486c2f6d65428a444cbd59810ba4dd8cde8f -21358,Sony PlayStation Portable,Bust-A-Move: Deluxe,,Games,USA,ULUS-10057,1.00,70221824,f2a45263,e02cb90b1ec569fd648cc900f47cb06c,30c2407cfa1833956eefbe2f991ccce88232caf7 -21359,Sony PlayStation Portable,Infected,,Games,USA,ULUS-10054,1.02,590053376,d9a46244,0c3c21ed13514b3478bc2f6d4a58f266,27f4f53ef2fdde945c1d6348c2ebfe63d6556b26 -21360,Sony PlayStation Portable,NFL Street 2: Unleashed,,Games,USA,ULUS-10008,1.02,695861248,a5a8635d,bd6a315f011dc729b9b9a966b07f1e41,2a418e2507b6b81b7bc37a017bfa963f32c6455d -21361,Sony PlayStation Portable,NBA 06,,Games,USA,UCUS-98626,1.00,310542336,9b1a4236,eecf464112720dbe632e11d8a3609aad,809673f5e2d2000b2329868446049f85480c4e2a -21508,Sony PlayStation Portable,Nickelodeon SpongeBob's Truth or Square,,Games,USA,ULUS-10478,1.00,1417248768,8b7befa2,2439756edf7a007dbfa2dfa4021384c3,a0948ee2e609a110f0eaaa8f9091cc430b5ed3ba -21527,Sony PlayStation Portable,MX vs. ATV Untamed,,Games,USA,ULUS-10330,1.00,304349184,b2b06cb5,2951762af22e1a20a729bec03b09ae3c,e42408cdb533610daa807f578dcb08b42858e592 -21547,Sony PlayStation Portable,Peter Jackson's King Kong: The Official Game of the Movie,,Games,USA,ULUS-10072,1.02,495190016,af99fddd,905c4e946ed1a8b401eac915e9e13087,d2640cdc3b588c787be5e0a7ade6e16dcbb0293a -21548,Sony PlayStation Portable,Star Wars: Battlefront II,,Games,USA,"ULUS 10053, ULUS 10053GH",1.01,738656256,65017578,f527fc2ce844d77f49f0c9f1155d9635,14ff9c85e824865e9cbfcff1182114d3aff3237d -21549,Sony PlayStation Portable,MX vs. ATV: On the Edge,,Games,USA,ULUS-10071,1.01,837910528,c2fa1968,cc8380e5b53b5987ec0a10bec87cca6c,db6b26e79896f390d28c75a8839de706bb97bb06 -21550,Sony PlayStation Portable,FIFA Soccer 06,,Games,USA,ULUS-10029,1.00,1190461440,7f9758c7,3ea67c5c622ce02875dd3da2ee6da3a1,1a47bd2fdeb73746c813e1fb0e30a56e4049b9e7 -21551,Sony PlayStation Portable,NBA Street Showdown,,Games,USA,ULUS-10010,1.00,1181679616,dc5eadea,0a98bcd5993abc4282e3d4635e69590c,74b222ab2e594658029960cd70e34f67bf63f603 -21552,Sony PlayStation Portable,Steambot Chronicles: Battle Tournament,,Games,USA,ULUS-10470,1.00,268828672,bcdc31d0,41575a853ff73bdcdfeec2f8a35abad0,046f5f9483a1ab8564eafeced0354f775ab199f7 -21553,Sony PlayStation Portable,World Tour Soccer 06,,Demos,USA,UCUS 98676,1.00,906362880,0009a9ff,05730187cfae26a8617a402f7b6e0f4a,74fab22adbd813a51456c3042ee39e404bf8232d -21598,Sony PlayStation Portable,Alien Syndrome,,Games,Europe,ULES-00772,1.00,499089408,0c294bd3,6b8f7d2424d21d5fdbac769a95010a09,908a9145926e35d2f03c963cdd573b3d870e1a72 -21599,Sony PlayStation Portable,NBA Street Showdown,,Games,Europe,ULES-00037,1.00,1181679616,04af5867,a6b14161dcf8140d76683a675133b580,5aa20d7a3cfbf23aab2b311e5fc629c215275c60 -21600,Sony PlayStation Portable,Pro Cycling Season 2008: Le Tour de France,,Games,Europe,ULES-01100,1.01,564297728,ca82457b,d473903b3421ec0e4bd114f707633876,bca60079f5f1bbf0b8f34d5c0bf5902e48553340 -21601,Sony PlayStation Portable,FIFA 09,,Games,Russia,ULES-01140,1.00,1335394304,63ed7c27,70a05e59a20587d92779492c757d87bb,77b77b0c52abfed16552427935adeceec5283fb2 -21602,Sony PlayStation Portable,Rainbow Islands Evolution,,Games,Europe,ULES-00594,1.01,857440256,9afb522c,9831a59c5dfca7c3d4ca2f517d47914d,bf5569ab37cd4ff5354cf2146f43a29a2df1fade -21603,Sony PlayStation Portable,Spider-Man 2,,Games,USA,ULUS-10015,1.01,583532544,a4fd656b,ebe869d1e0c29ab06c3d8bd97490a8f4,d9246ee4d9a2dc14a017397ea49b28a9bbdf22f1 -21663,Sony PlayStation Portable,PES 2009: Pro Evolution Soccer,,Games,Europe,"ULES-01176, ULES-01176/P",1.01,1482817536,ea4892b8,1992c86d2ac72b6e0f1ad03a1ef66092,748f94f40b48ed1f451012c05105c09f32af51e2 -21666,Sony PlayStation Portable,Naruto: Ultimate Ninja Heroes 2: The Phantom Fortress,,Games,USA,ULUS-10349,1.00,1209073664,75e58e1b,cca172f3325d2f2a5e625aef50a83eda,4b89a64924e4a198f8ce7d327efd6d8256311f30 -21667,Sony PlayStation Portable,James Cameron's Avatar: The Game,,Games,USA,ULUS-10451,1.00,695107584,4ed1bff6,123b73a1f686fff7ae7719304bad30bd,2286ee61b26230da02dd72306b6c0d596dc184a0 -21668,Sony PlayStation Portable,WWE SmackDown vs. Raw 2011,,Games,USA,ULUS 10543,1.00,1746534400,159ba0c6,a2a0beeb64bbb3b52137abc9325c05f8,0fdcbe81d60986833e6075ce7e8cf7998e4ee206 -21669,Sony PlayStation Portable,Yu-Gi-Oh! 5D's: Tag Force 5,,Games,USA,ULUS-10555,1.00,1713799168,07131d12,167ad0db3169f67ee2af99ce91ce7f9d,1a6da2603cf71847f937b25a16b263525e75c0da -21670,Sony PlayStation Portable,Gods Eater Burst,,Games,USA,ULUS-10563,1.00,1466204160,cf0af15e,8f72ac9dedbb1dd700fc694db44c2c0a,c3b09d013e33253eb855661a475d98555f6fb914 -21672,Sony PlayStation Portable,Blazing Souls Accelate,,Games,USA,ULUS-10527,1.00,1102905344,5953b3fe,498767111b92398b2514a37df1e942ea,68888d934c700647779d062398188cfb956c96bd -21673,Sony PlayStation Portable,Cabela's North American Adventures,,Games,USA,ULUS-10533,1.00,857178112,31764c53,125013f3f27070a14836bdb1495f53c5,35102722dc6dc57a11f00420c80c21fe1cca0468 -21766,Sony PlayStation Portable,Juiced 2: Hot Import Nights,,Games,USA,ULUS-10312,1.02,1134362624,daf1533b,5a1f0d00fac406296d644a5973dd7ad7,57561d3eed417db71f33ee9837ccf34ef47d410b -21875,Sony PlayStation Portable,Monster Jam: Urban Assault,,Games,USA,ULUS-10379,1.00,906362880,9e200787,0a883a1ced24fcdb161eb8befff1247d,b580e046bef3f7135bf7a1696f664299c4b2bd34 -21876,Sony PlayStation Portable,The Lord of the Rings: Aragorn's Quest,,Games,USA,ULUS-10475,1.00,605323264,40cd6479,8450817a2c14e6c5c8898e92b2300b60,396d1dacbb7f00b464eba123b8e82818d11a07a4 -21877,Sony PlayStation Portable,Luxor: Pharaoh's Challenge,,Games,USA,ULUS-10333,1.01,133857280,bbbe6fe8,c27c40db1e7f0811ca737910a597b022,1842d7610152ea139b53a93cf4c9213fed08d6d4 -21888,Sony PlayStation Portable,Chessmaster: The Art of Learning,,Games,USA,ULUS-10335,1.00,213450752,a043e57a,0b3d3f21a08ad300c694fc772d1cadcb,9037754acd91128ffd56a499a511f06cceec1f14 -21889,Sony PlayStation Portable,Michael Jackson: The Experience,,Games,USA,ULUS-10564,1.00,339443712,0f8df933,52a8741d2d271257891ab5b76d655eae,2c6fb21d4ba52f15d5c54f592036932342e3af4c -21891,Sony PlayStation Portable,Monster Jam: Path of Destruction,,Games,USA,ULUS-10530,1.00,306937856,794d835b,8a45683c8da0a1880f931690655dd521,97878b434e399a8bbb621697ad45d4ae8963d447 -21899,Sony PlayStation Portable,Dungeons & Dragons: Tactics,,Games,USA,ULUS-10232,1.01,484900864,1ba3a196,ad58b1c1aead61b3cbf50d481a67e80f,4e3779d2c69c48fc79851d41a4333f3539136d50 -21900,Sony PlayStation Portable,TNA Impact! Cross the Line,,Games,USA,ULUS-10436,1.00,1140359168,6f74367a,85332c809b44defa4bfbc83110da7dc0,7e3d123b3d814f68d6d1e6b4dfa2e3e29497d52a -21901,Sony PlayStation Portable,MLB 08: The Show,,Games,USA,UCUS-98696,1.00,1452965888,b1495247,43d4f4749c59e35fe83957ef9820bab6,2390f4552a2ca744eaf6221229a19321f410065a -21902,Sony PlayStation Portable,Gangs of London,,Games,USA,UCUS-98617,1.01,1078558720,ee433040,f075c06a38d901da37e02b8d24d6e03b,f3f68a6748c089ea490957d6198b3f9c4a73fa81 -21912,Sony PlayStation Portable,LocoRoco 2,"樂克樂克2, 로코로코 2",Games,Asia,"UCAS-40222, UCKS-45103",1.02,1805713408,ca559d18,d2c714a454b74d9a110531c4c9a7bf4f,70abefd272955ef4faac5adbdc2e7f15aea95334 -22219,Sony PlayStation Portable,Petz: Dogz Family,,Games,USA,ULUS-10463,1.00,189399040,11708fef,3d3c04d63ca210a45d6b72eb73bfeb53,00019e4db2e531229d3f5957ded561ea57af8f26 -22220,Sony PlayStation Portable,Petz: Hamsterz Bunch,,Games,USA,ULUS-10446,1.00,199032832,140cad64,4355029bdee3551b4eeeab8b612656bc,f86d26280ad177b0c6805e41a583f3305c280989 -22221,Sony PlayStation Portable,DreamWorks Megamind: The Blue Defender,,Games,USA,ULUS 10520,1.00,906330112,1e2a4933,f05dedc37779e739431c17162b82fbbc,4a08e494a2ba014eeb380f6c6dce764084a50ec7 -22222,Sony PlayStation Portable,Tactics Ogre: Let Us Cling Together,,Games,USA,ULUS-10565,1.00,1614610432,ab639eb5,ee004e917225339ee8daff476ab74557,92c5f69400a12e150e8389751c5bfd3a844640ac -22479,Sony PlayStation Portable,World Championship Cards,,Games,USA,ULUS-10226,1.05,657915904,6fa3d3e5,6b2278a127b924a691919dd3571e9ec8,c9db67ad1cf24078bef0a977ec6f67ee07b3af66 -22480,Sony PlayStation Portable,Shepherd's Crossing,,Games,USA,ULUS-10499,1.00,265125888,479d3b9c,ba529d4f5d9a69361181c14fc9a7a852,8b70ee5ffacdb28afb67853afb8e7969016d2de1 -22481,Sony PlayStation Portable,NBA 2K11,,Games,USA,ULUS-10552,1.00,1461551104,d16d906c,60f7cd02b8afea1b10938f0cb165cb8d,3e9c0d7378d9ee4177e11037c0667c47d7b9e37e -22679,Sony PlayStation Portable,MLB 11: The Show,,Games,USA,UCUS 98758,1.00,1420623872,21e31513,7a65b1d702384ff4ebfb67be50ac278f,ec1775bac7d8b38e475c3c3e58625290c0df20fc -22680,Sony PlayStation Portable,Despicable Me: The Game,,Games,USA,ULUS-10534,1.00,519274496,00be9a2a,ded02d7c12de0cd393de4ece5209f9eb,fb266ee2cf987552d91f322e943404b570118912 -22681,Sony PlayStation Portable,DT Carnage,,Games,USA,ULUS-10406,1.01,567934976,f3290a3e,ebd028ed2ea9114073cd4cae00cae9db,0abcbe4f0833c9466f45fe408e4945edc7f5fb3c -22746,Sony PlayStation Portable,Bleach: Heat the Soul 2,ブリーチ: ヒート・ザ・ソウル 2,Games,Japan,UCJS 10017,1.01,667189248,1a9ea875,e8958958d4c364c1d86b28375cec78bc,5acfca57ccf07f6124479d40712427528fe04f8e -22747,Sony PlayStation Portable,BlazBlue: Continuum Shift II,ブレイブルー コンティニュアムシフト II,Games,Asia,UCAS-40337,1.01,1651834880,b27fe30f,7ac8c8bff3408a0b61e2cad92bd6b6b5,ac0bba46a1283f92bc3441f9dbb9f757b6006540 -22835,Sony PlayStation Portable,DJ Max Portable 3,,Games,USA,ULUS-10538,1.01,1774223360,ff14bcc6,4aa9ea958f5d1c3ffd4f5c9c3f610476,c5920fea4c340d443b20260d01257a222ced861f -22840,Sony PlayStation Portable,Miami Vice: The Game,,Games,USA,ULUS-10109,1.01,346619904,932f9840,df6b90f34b30d4e3da525e139dfc14ab,a1fa7108368f5d8ee58c57749ad806df829068d6 -22908,Sony PlayStation Portable,WipEout Pure,,Games,Korea,UCKS-45008,1.01,305102848,cc68b2ee,6b3da555861ae94f9b17f69727813631,6251b2cf7fba7f577a7fccd42e7d13d009af4b95 -22909,Sony PlayStation Portable,Steel Horizon,,Games,USA,ULUS-10215,1.03,130187264,30f74e70,00f94ca1100089cdbe1d88965842f21f,e53f918d8fe563116a7f96ec696478ccb2423ce2 -22910,Sony PlayStation Portable,Legend of the Dragon,,Games,USA,ULUS-10250,1.03,827195392,ba3a36fd,3e274f57a8e8cd657b4f5afc02cf9059,ba9bccd1e64d4ff75981f6e853be82820f188964 -22911,Sony PlayStation Portable,Dissidia 012: Duodecim Final Fantasy,Dissidia 012: [duodecim] Final Fantasy,Games,USA,ULUS 10566,1.00,1754529792,54d57cc3,64d7b19cd3c627bd81e60a2e6fb46549,ec23f5beac89312a2a25654e202ae1c997999c9e -22912,Sony PlayStation Portable,Invizimals,inviZimals,Games,USA,UCUS 98746,1.02,1615003648,74ca9f50,e941ab09d1f6b679787ca6e5ca8f27cd,836f5df73c145b58bc02bfb24a8340d86f7bcb93 -22913,Sony PlayStation Portable,The 3rd Birthday,,Games,USA,ULUS-10567,1.00,1467547648,0c98cd59,47a7cb8e9e73d8aabef8139db7ee522b,36918618e23ca87c2fa5a4d921f0517735355f26 -22934,Sony PlayStation Portable,NBA Live 08,,Games,USA,ULUS-10294,1.00,1616052224,9b0e1445,b26371053ae1adbffd7d48ac52534219,0d6ff37c5cbcad06ed94790a2b32cca8beebe2c0 -22935,Sony PlayStation Portable,Major League Baseball 2K11,,Games,USA,ULUS-10573,1.00,1787166720,d5ffa971,1f16588bde8a4fc0a8c52d6137cb13c1,a7ecabacac324f57079aa5dd578dccf16624bb11 -22936,Sony PlayStation Portable,Dungeon Maker II: The Hidden War,,Games,USA,ULUS-10393,1.01,173309952,e8b65886,6679613b054f61f796c60805704bfacc,7c24dc9ab34f9af1c13ac7fb174fc7ce90c5440c -22937,Sony PlayStation Portable,Test Drive Unlimited,,Games,USA,ULUS-10249,1.00,1535901696,27e28d03,54fa0706df786d4379ae96e034cac52b,5d3f0798404bc047f13d4d5aff6f96d7ddeea62c -22938,Sony PlayStation Portable,Coded Arms,,Games,Europe,ULES-00124,1.00,193855488,988830e1,7ba77364feed5efbb381660541c95b93,fabc93b30962f9e4df25c9ecbc7f7098ebe31c4f -22939,Sony PlayStation Portable,Pursuit Force,,Demos,Europe,UCED-00150,1.0,183107584,382939b8,7862e0cf4df0b99f5e7c6a0535a49811,6431a66725c554c3cf561b6b2737b3a894348f53 -22950,Sony PlayStation Portable,PlayChapas Football Edition,,Games,Spain,UCES-01134,1.02,168984576,51531605,88402d64cd0ba491270828fa164589d1,017b67b4afb2537ae21552daae29312962b910f9 -23054,Sony PlayStation Portable,Invizimals: The Lost Tribes,,Games,Europe,UCES-01525,1.01,1439760384,191417e1,8b0b3e818a511a534f10b95c2287042b,d74721f9deb8d52223fa8125c3e54a9bdd7c3fdb -23055,Sony PlayStation Portable,NBA Live 10,,Games,Europe,ULES-01308,1.06,1452113920,a75515b5,c76e417171de180c00d8f3609b4b0c0d,23f9111cc3d4e03be3be093ea488d8e61d82b815 -23056,Sony PlayStation Portable,FIFA 07,,Games,Europe,ULES-00440,1.02,1357611008,87fa882a,1eb973909649a167e5961926135193d4,3416ec01c94a3e536047bf9f9f454b0d2e919d86 -23057,Sony PlayStation Portable,FIFA 09,,Games,Spain,ULES-01139,1.00,1300758528,3041b63e,1345bbd61e4eb297b94d240135316456,07ab4cca4bfe0aee81de33008c59ce153725882f -23059,Sony PlayStation Portable,FIFA 06,,Games,Spain,ULES-00165,1.00,1216970752,da13795e,42e81260685ebb3dc856d300c7ebe679,dd86ea1ac48cb7b5d4675748a0118ce63e7d4ee2 -23060,Sony PlayStation Portable,NBA Live 09,,Games,Spain,ULES-01149,1.00,1181155328,cd8db5cc,3741b7ade7ea287df2bc89f94d29ce24,4f18261c82740c19918bf2bc764ce5dd8b600429 -23061,Sony PlayStation Portable,Ape Escape,Ape Escape P,Games,Europe,UCES-00045,1.00,801603584,51aa48c5,8e3ca8a5162a3374f83527d4071e579f,de4aac9bce0481c92fe3e46fece27740f6f02247 -23062,Sony PlayStation Portable,Ape Academy,,Games,Europe,UCES-00010,1.00,382566400,252899ec,fa308cc4205a61cb5839f6f3f1b59619,94878a4db5e488aec886b91236437f166d5cbb0a -23063,Sony PlayStation Portable,Football Manager Handheld 2009,,Games,Europe,ULES-01152,1.02,227540992,b8755750,0262e2bd189a090940e0237fd33e0f30,15db83b1e193d5c0e31f8131404520fe9e7b290c -23064,Sony PlayStation Portable,NBA Live 07,,Games,Spain,ULES-00464,1.00,1532690432,484cb603,8c84d47e9e0f5897ccc57ce59a580ff7,c337b066ae8706ca08cf0167eb1f20a7d439ce92 -23075,Sony PlayStation Portable,Patito Feo,,Games,Europe,ULES-01493,1.02,860160000,add39f82,320d6a9c144e916c3354654c2e55feef,18d4b26ad14f023999ddaae413b36fa1f2f44395 -23076,Sony PlayStation Portable,WWE SmackDown vs. Raw 2009,,Games,Europe,ULES-01166,1.00,1563066368,c86cb0ed,a080f6fa1476cf5914b997551e9bf190,01c765985631f3e368bfa305daefa0893ff7e8ce -23083,Sony PlayStation Portable,Naruto Shippuden: Kizuna Drive,,Games,USA,ULUS-10571,1.00,1177255936,cf227bfd,83db6c84870d0276202a81158e68866c,366d0aff300c47a419f59eaa3643c8ec1f687741 -23084,Sony PlayStation Portable,MLB 10: The Show,,Games,USA,"UCUS 98742, UCUS-98742",1.00,1451032576,fb165cae,429af9e0bfd61dce6b9b3ee0a04035d6,b8cace100318ec55eb0abd04a25b0d7229c298d6 -23085,Sony PlayStation Portable,Petz: Saddle Club,,Games,USA,ULUS-10402,1.00,1424392192,d35da397,717fb9aa95793dc49aef33cfd63fb7d6,ae9750a35d0debf02e81847224b5aa693fc2b581 -23086,Sony PlayStation Portable,UEFA Euro 2008: Austria-Switzerland,,Games,USA,ULUS-10337,1.01,1458077696,8545ddef,dc094a58a5bf2740dd749cd4ede95f37,904a9fc6c83623d9466bc6837c477229a2f2102d -23089,Sony PlayStation Portable,Maplus: Portable Navi,MAPLUS ポータブルナビ GPSレシーバー同梱版,Games,Japan,ULJS-00091,1.03,1692532736,c70ce2b7,7f0b3bea1f0888760a693e69e3ab3a5f,4d5727553291fdc15edac54237a889bf72fa75b4 -23164,Sony PlayStation Portable,Lord of Arcana,,Games,Europe,ULES-01507,1.00,812908544,63f4fa48,93e64b6b3235afce40ae84e7095603ef,c228b2d2d906d98d183fc033d750d7260bb10647 -23165,Sony PlayStation Portable,Adventures to Go!,,Games,Europe,ULES-01383,1.02,184385536,a6285e69,5e976936610ff0e61efb475cb3e1b3c8,5deaab9ecb0ed725c7d8832865d9965e1a6eeabe -23166,Sony PlayStation Portable,Cover Girl,,Games,Europe,ULES-01302,1.00,827490304,9604893a,78351f7ef4f9d686dc7bf7b4b2be584e,7953a411723d283c8f5f8a28b7ee0ff95e5067cb -23167,Sony PlayStation Portable,Cube,Cube: 3D Puzzle Mayhem,Games,Europe,ULES-00722,1.01,543522816,d7296537,bc308d0ea2f0b2244aaf0f4d637fa4af,791837917dd305f794b0237c2b61207b9fab562e -23169,Sony PlayStation Portable,Disney Pirates of the Caribbean: At World's End,,Games,Europe,ULES-00727/E,1.01,1796833280,fe6352d9,10dace063eb4e314668a3692a5fa97ba,949146ae6b8467655a4943463b2f3f9fe261ee00 -23183,Sony PlayStation Portable,Blood Bowl,,Games,Europe,ULES-01230,1.01,234782720,53a90c37,1505342956328875b0f8382660008a31,2b00df05d67580b0a5c70b60adeb929efe382bb0 -23185,Sony PlayStation Portable,Championship Manager 2007,,Games,Europe,ULES-00636,1.00,213417984,3ee78f33,4ac3ebc94efcd9b2b460079a51447391,d4f728f824e6f0854fc8d6d16c87ae37838cbe17 -23186,Sony PlayStation Portable,M.A.C.H.: Modified Air Combat Heroes,,Games,Europe,ULES-00565,1.02,362283008,d7196eed,861ec7601302644845d4487bc0cfb6c5,fecbff15e658339bfd636c99f54c09dbed2414e3 -23187,Sony PlayStation Portable,Warriors of the Lost Empire,,Games,Europe,ULES-00924,1.01,1754169344,306c9625,77b62b21edcb6c9e2f5f564e9c9b0566,78e42e6ddf1e9664abf25d2f59341b821b8d01f0 -23188,Sony PlayStation Portable,The 3rd Birthday,,Games,Europe,"ULES-01513, ULES-01513/E",1.00,1467547648,80ba851c,d7c2309da1fb349b8dfce11f1b6c90a7,6112aa5d52c018c894a0d29be70018e2af1d63eb -23223,Sony PlayStation Portable,Armored Core: Formula Front Extreme Battle,,Games,Europe,ULES-00219,1.02,823984128,2bd4af69,52ba30372569e9c6945694082ffb8bbd,9357db5e670b5ebcd871e10c3bcc53b5c6eef816 -23393,Sony PlayStation Portable,Madden NFL 11,,Games,USA,ULUS-10541,1.01,1219592192,9c481368,e8e2da8eb97ed89bb08c152b7b1f671f,e3ac79e97ed8870701770dbcea99b3ebbf5468f9 -23398,Sony PlayStation Portable,Echoshift,,Games,Europe,UCES-01313#,2.00,309854208,15806bca,80cd889c419f96b3fe3b1b3eb51c0e1a,b56e3da00a648ba100b83c0275c092639162dd10 -23403,Sony PlayStation Portable,Juiced: Eliminator,,Games,Europe,ULES-00379,1.01,1265565696,34311488,a51830c7d5e4b06b269001c1983721fa,310a7b0475f95c74469e708f9e8c7b184142b2ec -23404,Sony PlayStation Portable,Gun Showdown,,Games,Europe,ULES-00484,1.00,797507584,5661d521,38c6030f4cdb7b40c01f1cd26343ffaa,d2f41e80ca97e5312967af5ceab6ced2f679da6c -23405,Sony PlayStation Portable,Ghostbusters: The Video Game,,Games,Europe,UCES-01321,1.02,1182040064,b2785bb8,85eaafac9315128cd7dc502bf6359029,bc2d877b3cd4753995109d8e3864b3b0e42cfebf -23406,Sony PlayStation Portable,Frantix,,Games,Europe,ULES-00175,1.01,403636224,44dc6615,fddffc7efb0d495f0a9beb157d7e4fcb,9b1c3c606bff7f772b59996c45e775bc4a1f6b42 -23407,Sony PlayStation Portable,FlatOut: Head On,,Games,Europe,ULES-00968,1.00,450592768,57d831f3,cc10cade16319672fdeab8470edcfd02,263a8d1542bb24f726d06a08adf3448d7f78c57c -23408,Sony PlayStation Portable,NBA 2K12,,Games,USA,ULUS-10585,1.00,1506607104,63a701d9,88e15239084f39e9a96e11d63b55dd8c,a0d2acbff5a57d16a0b9a1cb2ced5d8734cdb4a6 -23509,Sony PlayStation Portable,Major League Baseball 2K9,,Games,USA,ULUS-10413,1.02,1714978816,9bc05576,bf8ffe3c03694d56b32d3056ba36bb55,cffe99d7eae289cf37c5d4e47d524745bc292e40 -23510,Sony PlayStation Portable,NBA Live 06,,Games,Europe,ULES-00156,1.00,1302200320,2ea2ae15,2e637b02fdce08f65d7a15bb1dc26805,3e63ba4969667c2278b27a607b641a69bbddd9b1 -23511,Sony PlayStation Portable,Off Road,,Games,"Europe, Australia",ULES-00963,1.01,734003200,b2a29dd3,077eccbb81850df8d38ea7c515ac82e4,f8a197c544021bff59286516e041673088d7f487 -23541,Sony PlayStation Portable,Ratchet & Clank: Size Matters,,Games,"Europe, Australia","UCES-00420, UCES-00420/E",1.00,993394688,8981e31f,e38e81601aca2fbc5bdc030d9f2b9dfb,48799b08d0219d13aa86c6388da5e910fd30ca92 -23542,Sony PlayStation Portable,El Padrino,,Games,Spain,ULES-00400,1.00,1390739456,8da604fb,d1ad88bf8ae2ff780a78dc26b13264ff,d2bae8c5013066efca093e8ccb7066e5813c0faf -23544,Sony PlayStation Portable,Scarface: Money. Power. Respect.,,Games,Europe,ULES-00545,1.02,578519040,ac4a3654,9de9f96dd82d5d6edd8d59f0077e0b77,7c1871652301ebd93ac67e5739fc3a6f90a4f554 -23548,Sony PlayStation Portable,The Legend of Heroes: Trails in the Sky,,Games,Europe,ULES-01556,1.00,1422524416,3421f610,6b28dc78f449334939933175a4723efa,fe6b6567b5da3c410ef77b22c1bdae65702c4969 -23549,Sony PlayStation Portable,UEFA Champions League 2006-2007,,Games,Europe,ULES-00699,1.00,1258094592,c598df01,88c7b04d89506d5773a7fbb268f5fe3b,a943be934cd8343ab43935b0d7965ebe9362f6b5 -23552,Sony PlayStation Portable,Street Supremacy,,Games,Europe,ULES-00239,1.02,591134720,0d140bb3,48bf5e707c5215e398eaeffb90c1467d,5a084da2674fa7e4c50dea048b83328764c35ced -23553,Sony PlayStation Portable,TMNT,TMNT: Teenage Mutant Ninja Turtles,Games,Europe,"ULES-00759, ULES-00759/E",1.00,1151270912,a7afdf46,1addc24a0a0775363c31efd549b0704b,e8e5a68080b7d06cf8bc10c29a57207ae3e780ca -23648,Sony PlayStation Portable,Pro Cycling Season 2009: Le Tour de France,,Games,Europe,ULES-01274,1.03,597819392,18ba62f9,4fa1f472acae8d09eabd8d1d7eb78e82,fafc4cce9e3988a9f84d026934e016800c8ee71b -23649,Sony PlayStation Portable,Naruto: Ultimate Ninja Heroes 2: The Phantom Fortress,,Games,Europe,ULES-01088,1.00,1601110016,eb545f4f,0807cdba90d78927ec7254cb22e2e4e4,82200b9c6921e1e12901f60fb8df313d571af0be -23650,Sony PlayStation Portable,Yu-Gi-Oh! 5D's: Tag Force 4,,Games,Europe,ULES-01362,1.01,1759838208,e7cb786a,d30b160def21885bf3bea67bf532a516,2e9f85036ba42b30069eb79e48f843d242dea155 -23651,Sony PlayStation Portable,Rengoku: The Tower of Purgatory,,Games,Europe,ULES-00123,1.02,381779968,8051da90,8f5475b0851829ff9856d852259301d7,a21240b261263e9103a49b158f5ee89cbd85de6c -23653,Sony PlayStation Portable,White Knight Chronicles: Origins,,Games,Europe,UCES-01511,1.00,1131315200,ac64718f,08581cf78e03f15998f746728cc2cf7f,48e5dcbfda9b5ab970b46b717b016068c5872ddc -23654,Sony PlayStation Portable,Spinout,,Games,Europe,ULES-00693/E,1.02,128778240,7ee80eb8,dc0e9d0a0bef6a9b71af42d4b3a7488d,011b704dfe47710840c38ab2f3a1d20a8a3d9901 -23655,Sony PlayStation Portable,Tom Clancy's Ghost Recon: Advanced Warfighter 2,,Games,Europe,ULES-00770,1.01,759758848,dcc828bb,83f4c4995f2754029d910232df2b6dc9,703cc9884002aa1092adcb3f7a909c57128e15df -23656,Sony PlayStation Portable,Spectral vs. Generation,,Games,Europe,ULES-00757,1.02,196050944,0ee4fdc9,9afa081ea934ca6e57c29f3314e0e087,b646c9a9653f0e49aeeba02b5e05fdb36c6ffcf9 -23698,Sony PlayStation Portable,Phantasy Star Portable 2,,Games,Europe,ULES-01439,1.00,1341882368,958b00bd,210bc50d7aff22b95155b12aa8a3eca6,8bbd6ebab39f016929c98fa73d768c6879a1e68b -23699,Sony PlayStation Portable,Final Fantasy IV: The Complete Collection,,Games,Europe,ULES-01521,1.00,880771072,2bbff0d5,4fb5669f50ed9f17126d7613224f804c,01fff7e72868c0a0f6e816ff8d1926517ba62582 -23703,Sony PlayStation Portable,King of Clubs,,Games,Europe,ULES-00914,1.02,460226560,5aa58881,60f10de5184dbe084d750d9d6723be16,2b22df5b7ae00be5a4be507a57d4fff45303432b -23704,Sony PlayStation Portable,Heatseeker,,Games,Europe,ULES-00760,1.01,404520960,219c7762,b6789f8cc4a92ae96552f26a58f51567,472d25dfa2b3d21e27a32f57298aac2446187d05 -23746,Sony PlayStation Portable,NHRA Drag Racing: Countdown to the Championship,,Games,USA,ULUS-10278,1.01,805371904,d554132a,a92ed47b1effb8e51035f6174fe8853c,4aa43f2bf0e18f22cf032674dbd30a8503216dfc -23747,Sony PlayStation Portable,LEGO Harry Potter: Years 5-7,,Games,USA,ULUS-10580,1.00,1513422848,936a625e,75c1dd70af18740ac40c5ff1dc47f0a9,9f5472c767c042628a2a16878abe0346c66e0b14 -23748,Sony PlayStation Portable,Xiaolin Showdown,,Games,Europe,ULES-00711,1.03,906362880,f381c90f,282094a1d98bfd0b892b49c7e101b73c,19f7277544ddefe365db28fd9969b954b94f93cd -23749,Sony PlayStation Portable,Undead Knights,,Games,Europe,ULES-01390,1.00,412680192,fbafbadc,dc225cb9300dd7ebd73588beb709ff5b,b690e594a16b7431daf8ae51609a78083e543cfc -23756,Sony PlayStation Portable,Army of Two: The 40th Day,,Games,Europe,ULES-01381,1.01,900333568,b6ff0d2b,0221b8b7cd684ba18b058a9f6ad2f355,0b9a7db05bce9d43fcb3a2a9a8bec5eebb32f686 -23757,Sony PlayStation Portable,Brian Lara 2007: Pressure Play,,Games,Europe,ULES-00814,1.01,385875968,ffbe8b6c,47f9666d648255ad25e8e8036de7a8e6,afc2bb9172b26a5b5445a906dcbb43098bf18f8c -23758,Sony PlayStation Portable,Championship Manager,,Games,Europe,ULES-00174,1.02,195362816,4e0fcb99,108298d969845e99579dc87d9c9e911a,b65018f03356f01b46abf38925be4d6ef8434448 -23759,Sony PlayStation Portable,Championship Manager 2006,,Games,Europe,ULES-00330,1.00,206012416,201cc54b,ef7db3e6695debadcb42e56e1cbea214,5cd36441a31157ee1245eaed24b976a2048aded7 -23760,Sony PlayStation Portable,Gripshift,,Games,Europe,ULES-00177,1.00,894861312,c8d1a498,65717378d68ac81a6a3f6f89eb6635d7,a5d71a29b76898f0ed9c2cdae49c710fa85ad3b6 -23761,Sony PlayStation Portable,Iron Man,,Games,Europe,ULES-01070,1.00,906362880,53dfbd74,0e0ecc54b9a426205fb5be919d9ace3b,de61792302447507b61ac1cc32d27828d8585f1c -23766,Sony PlayStation Portable,The Fast and the Furious,,Games,Europe,ULES-00973,1.00,905216000,2fbac7f2,17155e83c95cf2931ffe992213182708,857760ff96bb064af523de49988958ecb0302a9d -23767,Sony PlayStation Portable,Steel Horizon,,Games,Europe,"ULES-00739, ULES-00739/7062159",1.02,462880768,7d3514d2,88563a583948a6141bc55ddd3e16f1d4,6df628e7de0964b5e4c3029c00509108042cfcc8 -23768,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Tactical Strike,,Games,Europe,UCES-00855,1.00,1382252544,581353cb,34ef360eab82f7830f3ec844afb59278,f6547453bbd3e8f2095cdf80d3e93c4e74e02f16 -23769,Sony PlayStation Portable,After Burner: Black Falcon,,Games,Europe,ULES-00753,1.00,427851776,3f3f6a57,2c6da8d3b81d6ac5c9df1b2dac23eb5f,c3a9430b75dc1dc42d9a87d1ad6b6fe9db918280 -23770,Sony PlayStation Portable,Colin McRae: DiRT 2,,Games,Europe,ULES-01301,1.02,365625344,a3128372,6e237376ab6ec5d4aea143d769923fa5,1ab7debc6e03914c246bde5a95d611e55830c777 -23771,Sony PlayStation Portable,Dungeons & Dragons: Tactics,,Games,Europe,ULES-00721,1.00,484900864,0c19b333,436dbf1e4c869d0e320b1ba7e4b2270c,f23a7ba960a7353ee0024f5343e39e18c69a3cd5 -23772,Sony PlayStation Portable,Everybody's Tennis,,Games,Europe,UCES-01420,1.01,1399980032,7b58103d,ce984ef290934b751ea7931629babdbf,ef45d880e7ae968399ac71c1d0b9ab04ef969904 -23852,Sony PlayStation Portable,Rapala Pro Bass Fishing,,Games,USA,ULUS-10532,1.01,731873280,72a1ba31,aae12793bf556fe2c5c3fe9ebeb32b71,481821f8ae28fae414badb69040c0dd3b755102a -23853,Sony PlayStation Portable,Major League Baseball 2K12,,Games,USA,ULUS-10591,1.00,1739587584,e561b26d,68043cb0101bb6d85699680a9aa8229e,56b76c4304a39ba9c34a5200372cb9cf5dda4c37 -23854,Sony PlayStation Portable,IL-2 Sturmovik: Birds of Prey,,Games,USA,ULUS-10476,1.02,670138368,ff01278a,0572997ce957a0ef220cadaa50a38949,c84622d1c737c4ea712083997e3fcabb0f09ce41 -23855,Sony PlayStation Portable,Sunday vs. Magazine Shuuketsu! Choujou Daikessen,サンデーVSマガジン 集結!頂上大決戦,Games,Japan,ULJM-05450,1.05,456720384,1feaeba6,c398e72b684d7041e6e8e69228f5343d,ebf4cb90ae6d1b3adb4589d7cb6c8c3061479877 -24047,Sony PlayStation Portable,Jeanne d'Arc,ジャンヌ・ダルク,Games,Japan,UCJS 10048,1.00,1245249536,22f8ff00,bed277a5e3ebf94894f7edeecc2ec251,d8f9518140d6f21d3885f2c723cebe81d707f429 -24049,Sony PlayStation Portable,Phantasy Star Portable 2 Infinity,ファンタシースターポータブル2 インフィニティ,Games,Japan,"HSN-0019, ULJM 05732",1.02,1727201280,af5d2bc9,46de8510a37e5866a4f60ab6af6d7479,2961727668beadde6002c1fd311cc47e9ecfd139 -24050,Sony PlayStation Portable,SD Gundam: GGeneration Portable,SDガンダム ジージェネレーション・ポータブル,Games,Japan,"ULJS 00065, ULJS 19022",1.02,1449033728,4a21cb5a,e02671452319434402fad058268eb6b8,d7a424e0fc9b09fd61401dfcf2649802e751984b -24051,Sony PlayStation Portable,Free Running,,Games,Europe,ULES-00704,1.01,453378048,5653aafa,0d7561fda57c0e0c4e0adf7d1b019d65,054d28f41a51ecdb1c953c15d170d2160457e5a5 -24052,Sony PlayStation Portable,Tony Hawk's Underground 2 Remix,,Games,Germany,ULES-00035/E,1.03,1257537536,563abe0b,95a83f064dd75ba427281e863dec7ee9,0fc5c14df243be7cf96bc6c1fa5af469fc45d404 -24053,Sony PlayStation Portable,Yu-Gi-Oh! GX: Tag Force 2,,Games,Europe,ULES-00925,2.00,1812725760,64daca94,7b1cb36dbf2b96b38b14b3fa44b2faa7,77faf0fc53e6a83998bf29f554299ec895bbd29c -24054,Sony PlayStation Portable,Final Fantasy Reishiki (Disc 1),ファイナルファンタジー 零式,Games,Japan,"ULJM 05900, ULJM 06217",1.01,1797029888,025d4d96,4abce3927a057fb397ab688478598658,e5212540445a9e86217172887df1673b8ee5d689 -24055,Sony PlayStation Portable,Final Fantasy Reishiki (Disc 2),ファイナルファンタジー 零式,Games,Japan,"ULJM 05901, ULJM 06218",1.01,1732083712,7bff2bcf,4068f532ded259fef304fdc9c05e592a,02b3abe76fc236ae0fa8ba0917d03f654d66ed34 -24057,Sony PlayStation Portable,Metal Gear Solid: Peace Walker,メタルギアソリッド ピースウォーカー,Games,"Japan, Asia","ULAS 42218, ULJM 05630, ULJM 08038, ULKS 46239",1.02,1583874048,06033d6c,c73a3e925acd2f3e37beb582e7445c56,2cd7b1b406ecee2b8e362d3f3b2183a03383c4c0 -24058,Sony PlayStation Portable,Ragnarok: Hikari to Yami no Koujo,ラグナロク ~光と闇の皇女~,Games,Japan,"GOEC 0001, ULJM-05880",1.02,667385856,6846944f,fa0f7c65c5190f5ed2dad6594a3bd974,979551f4e9ff8796f79a9474b251bb555ec093f3 -24059,Sony PlayStation Portable,Super Robot Taisen OG Saga: Masoukishin II: Revelation of Evil God,スーパーロボット大戦OGサーガ 魔装機神Ⅱ REVELATION OF EVIL GOD,Games,"Japan, Korea","ULJS 00444, ULJS 00446, ULKS 46282",1.02,1808957440,5bfab75b,d98164de4f2ff1debf00a002235b938f,485e02c7923ef44830a6602835fb39c8c83945d5 -24062,Sony PlayStation Portable,Manhunt 2,,Games,"USA, Canada","ULUS 10280, ULUS 10280F",1.03,1299513344,6ac42daa,674d20ee7b4b5640eec0bd8cdf31d3e1,cc48d55f8a936d121bddc6c04e1256ae5e9ecf57 -24063,Sony PlayStation Portable,Samurai Dou Portable,侍道ポータブル,Games,Japan,ULJS-00155,1.02,323092480,57cfd7b3,fdc0dcb7ff1edcdf5cc0c9b6e65d7a5a,9836f2fd364a4277c40252b15f8d531164ba8285 -24064,Sony PlayStation Portable,Shin Sangoku Musou 6 Special (Disc 1),真・三國無双6 Special,Games,Japan,"ULJM 05938, ULJM 08061",1.02,1765441536,334cb0f8,0b33eba6ddb10dca08eff2c133489fe6,53a0ad80c973cde39c62f250e6bf8adf37b8a3a4 -24065,Sony PlayStation Portable,Shin Sangoku Musou 6 Special (Disc 2),真・三國無双6 Special,Games,Japan,"ULJM 05939, ULJM 08062",1.02,1800798208,a13c17d5,bf912e1236c59a7e089e8b50e788c4ae,381adc30a6c69a72e302be3e068109b13a6ad6b3 -24066,Sony PlayStation Portable,Eiyuu Densetsu: Ao no Kiseki,英雄伝説 碧の軌跡,Games,Japan,ULJM 05899,1.01,1519321088,efdd7e79,df3df715fb2a0366bfa65c926ab40b48,a0010fb19ed6ca941ebff2e251efb0773673e59c -24069,Sony PlayStation Portable,Dai-2-Ji Super Robot Taisen Z Hakai-hen,第2次スーパーロボット大戦Z 破界篇,Games,Japan,"ULJS 00379, ULJS-00352",1.01,1217986560,c02ba2af,d85d9cb5b39f2393f83aa0447891fd15,cf7a93805fa79b158a060512a7d80f38a97cf7cd -24070,Sony PlayStation Portable,Tenchu: Shinobi Taizen,天誅 忍大全,Games,Japan,"ULJS 00018, ULJS 19007",1.02,421822464,8a591272,a6c703527a970e41746b3b364a71989d,86ed2d6efb3b211ba322974bc218c0c5787eb687 -24123,Sony PlayStation Portable,The Con,,Games,USA,UCUS-98621,1.00,858292224,e5f3a27a,21de240ed31defa685c0c0ec1de0d85a,aa4031f871e32691d9c6355c4b2603807e09ba8f -24124,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo,,Demos,USA,UCUS 98638,1.00,155549696,45e89c0e,69f2e986b3f0d66e37c52cf49eff86bd,c196ea37c0c1089831f7a60dd9eb801284c3ea92 -24125,Sony PlayStation Portable,ATV Offroad Fury Pro,,Games,USA,UCUS-98648,1.00,885850112,5ac09974,28dec59ee4a4697490ee192f4903550e,4ef203fbb494fd75e691cd2f7d7270f9153af2ea -24126,Sony PlayStation Portable,Patapon 3,,Games,USA,UCUS-98751,1.00,556007424,7fd2399b,c1a080008d4b0386b909ec1f65a4b42e,31f24a630f5f26a367d8fd232c62705392d69ecd -24127,Sony PlayStation Portable,Worms: Open Warfare,,Games,USA,ULUS-10065,1.02,236650496,235f8986,47580d85acff915ee668ff7021f016fd,7ecef96abf319af9d2f9c3ff73f89e4214d7d1a9 -24128,Sony PlayStation Portable,Hatsune Miku: Project Diva Extend,初音ミク -Project DIVA- Extend,Games,"Japan, Asia","ULAS 42298, ULJM 05933",1.01,1799192576,463d7382,4560397fde6f5c6d468278b1eefe4457,02de8c0e2f637fdf155a8bd2ac657013ac49d486 -24129,Sony PlayStation Portable,NBA Ballers: Rebound,,Games,USA,ULUS-10078,1.05,888012800,b337b86b,5cc7c99878e5d6212f48aa54a536de34,0fe1a4ab7de933cd9647bf67f216aeb784b7ee66 -24130,Sony PlayStation Portable,Samurai Warriors: State of War,,Games,USA,ULUS-10089,1.01,327614464,c33e699c,3129ff001d3aea46c070f7b531d07d44,28ccabb39a5d5f56ec79050895cf9947bfbea3dc -24131,Sony PlayStation Portable,Ultimate Board Game Collection,,Games,USA,ULUS-10254,1.02,127074304,86cb11ae,540b6582e3b8cf170161a47f8a333609,24c4676bbbad5c8eba156e91fcb296922577f740 -24132,Sony PlayStation Portable,World Series of Poker 2008: Battle for the Bracelets,World Series of Poker 2008: The Official Video Game: Battle for the Bracelets,Games,USA,ULUS-10321,1.00,900169728,f83a6e8a,8c95dcc9c32e982007171b1f790a452c,0dc471d5abc7688bcd85120aef3ad8ccb0a00325 -24133,Sony PlayStation Portable,Space Invaders Extreme,,Games,USA,ULUS-10346,1.00,153780224,444437e3,90a103ff3250af0c1727eb3faea79773,894eb0dd456fc96e25f6fecf4b58515d5b4e52e0 -24134,Sony PlayStation Portable,Gladiator Begins,,Games,USA,ULUS-10528,1.00,474644480,bf9a514f,e450263a3da577a3639dbe72fd97c21c,5976b4ef5b003d5839dcdda51645424ef7a60d88 -24135,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,,Games,USA,UCUS-98645,1.00,924844032,86d81558,7917ffb4452f037d1ca3b572f189530a,20e0caffb5dd43d13a8ad64e4a116623f3d70d5a -24136,Sony PlayStation Portable,MLB 07: The Show,,Games,USA,UCUS-98667,1.01,1430978560,31223c35,d1bab6c052493faceec73affe85f7eea,c46273c66f2991cb3763f3699af67ee989eec516 -24137,Sony PlayStation Portable,Pursuit Force: Extreme Justice,,Games,USA,UCUS-98703,1.00,1453457408,e1225178,89a1fa2a1f2299eec1f1ca4a338d50ab,88e63161736e903df5e90cc207d47b6ee02d1dfd -24138,Sony PlayStation Portable,MLB 09: The Show,,Games,USA,UCUS-98730,1.01,1454997504,4d0b2022,9e4dbb867efdb07e092e099360441d94,46a1a06fefa7d424b59b7cc83be1061f38355bdc -24139,Sony PlayStation Portable,Crash Tag Team Racing,,Games,USA,ULUS-10044,1.01,1536065536,bb59c0ba,ede188ffa147e024cb0d9a495080dacb,73b4c3d91a6c2d5450c998f9c81229cb9c1d6156 -24140,Sony PlayStation Portable,X-Men Legends II: Rise of Apocalypse,X-Men Legends 2: Rise of Apocalypse,Games,USA,ULUS-10045,1.01,1326907392,df294ab9,b20a513d3978175db41e7ebf16221a9c,a92875d1eac5e31d6293a71af8184567e22e1d4d -24141,Sony PlayStation Portable,World Tour Soccer: Winning Eleven 9,,Games,USA,ULUS-10056,1.02,976093184,ed5825c2,dcdf6849acec21c755402ba558f9b8a5,ebd9343a0181eff2cf5453db0ae3cda3b6f282b9 -24142,Sony PlayStation Portable,Juiced: Eliminator,,Games,USA,ULUS-10090,1.00,1262059520,39aa5900,0c1b6da1e92ccfb67a7b9c0d590b943a,4eb6b38be2482227746bd66c172b7b25c2c74c28 -24143,Sony PlayStation Portable,Race Driver 2006,,Games,USA,ULUS-10096,1.01,1717370880,266a4bf2,7c0d0d788ec4ab148570bade3746adf1,27d7b713af9a2048d7160e54cdcb308c8f221092 -24144,Sony PlayStation Portable,The Godfather: Mob Wars,,Games,USA,ULUS-10098,1.00,1377665024,97460e77,10c7e7a747452f5398e262e69939d8de,c0a1f28beff52c76076aea01b00446aa9b2fc4eb -24145,Sony PlayStation Portable,NBA Live 07,,Games,USA,ULUS-10113,1.01,1551433728,da489b5a,a76d65739aa94efab84cd2885e53d21c,de8672de0681d89373ccc0f0eba4fbe58c7f4f56 -24146,Sony PlayStation Portable,Justice League Heroes,,Games,USA,ULUS-10214,1.01,1442086912,48dd8597,a95b14db7497c6a55c9468c95f91cdee,87055c512472e8fd160361a84c2fb5444bba422d -24149,Sony PlayStation Portable,Marvel Super Hero Squad,,Games,USA,ULUS-10485,1.00,1576009728,fd689692,3d401aab8e894835a77c8dd4ba04d278,b11f5e3ee304c4d68ad671fffd231036dd8c813a -24150,Sony PlayStation Portable,LEGO Pirates of the Caribbean: The Video Game,,Games,USA,ULUS-10575,1.00,1478459392,77d8183f,deae88f7be4bdf44c613f5a37b6aaf5b,1c58cade1bb1d3131f3403ed1a6d9235f1f064ee -24151,Sony PlayStation Portable,Fate/Extra,,Games,USA,ULUS-10576,1.00,1284079616,064591e2,c9a968f80d5e91b2472925c8895be08f,37fdaf91a80552df995ce99a930b88f14f954f1f -24183,Sony PlayStation Portable,Naruto Shippuden: Ultimate Ninja Impact,,Games,USA,ULUS-10582,1.00,1062928384,d8f7797c,721cbd32b7ca5066d7a511b55b738ee1,41c2a5e8078088d3f6f29415d00379cb19e13bd3 -24343,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Tactical Strike,,Demos,USA,UCUS 98714,1.00,337215488,3e8df5a7,8f3141467135775c5d8ba950d72be626,a1080dc22e56797f7074501537ffc651f9a1dcd0 -24344,Sony PlayStation Portable,ATV Offroad Fury Pro,,Demos,USA,UCUS 98681,1.00,259325952,21f6e917,74cc27b5cf74e69d174508391c8c9de3,d219991e71a96a47ef0aac0caf28005334de72f5 -24345,Sony PlayStation Portable,Syphon Filter: Dark Mirror,,Demos,USA,UCUS 98656,1.00,339214336,c21f817f,54a56971e7dcd4bbe20598bffaaf3717,1fd89d449d3c246dd912c91be9d98e9de5b13120 -24346,Sony PlayStation Portable,LocoRoco,,Demos,USA,UCUS 98685,1.00,57278464,a6b5e853,7fe08090c4e9af11a903d420c2c5b1c4,d4c23fbac2d69c5f02555dc48343ae6a0a426e45 -24347,Sony PlayStation Portable,Ro-Kyu-Bu!,ロウきゅーぶ!,Games,Japan,"ULJS 00401, ULJS 00573",1.01,1135804416,4b69a7fe,0af9f1495c9f83928c0e0c4a26bda298,99c07b2c915240bd5db508a63a3a745f64551282 -24348,Sony PlayStation Portable,Yu-Gi-Oh! 5D's: Tag Force 6,遊☆戯☆王ファイブディーズ タッグフォース6,Games,Japan,ULJM-05940,1.01,1717600256,94033ba9,0b601b66f9a5d86fa2dc7045a1ebef1d,a2e9e13ce7b1801333c50aabdb73809b0752c533 -24349,Sony PlayStation Portable,Patapon,,Demos,USA,UCUS 98721,1.00,125435904,38ccff7b,e74d0fd7500f3047d54cf8eb768d27cd,afab1f7027f853989a48859dfd7c4acabfc44baa -24373,Sony PlayStation Portable,Geki Sengoku Musou,"激・戦国無双, 激・戰國無雙",Games,"Japan, Asia","ULAS 42219, ULJM 05071, ULJM 08012",1.01,329842688,7f348852,dc595434b5a71ca95738589d06309c45,132e8f70d0bd83db7d12c48c9597f72d86ce14f8 -24396,Sony PlayStation Portable,Magna Carta Portable,マグナカルタ ポータブル,Games,Japan,"ULJS 00042, ULJS 19012",1.03,1611497472,6f522326,91f4baca1f78eaf01e88d92a0437bc07,0f785df517a9ac4a9fd48cec7a8d829eeed2707e -24419,Sony PlayStation Portable,7 Wonders of the Ancient World,,Games,Europe,ULES-01037,1.00,211288064,f562a4b6,6ac39080c5fa1d0481e4fdec0bd35368,bb5109b18cf124ff4aa00250993bb153b0d292e8 -24420,Sony PlayStation Portable,Activision Hits Remixed,,Games,Europe,ULES-00640,1.01,277643264,13dabc01,8f639ab00e1e6a8622b32a5e9769d4a8,37590770a50c770d5f9a00a08476d66c632d85c4 -24421,Sony PlayStation Portable,50 Cent: Bulletproof: G-Unit Edition,,Games,Europe,ULES-00451,1.03,1686175744,87855ca8,d577d1ceac344ecbe66eaf0ec03779ed,5bf37498559f58844fd2dd47964f8cb4410070f1 -24422,Sony PlayStation Portable,Ace Combat: Joint Assault,,Games,Europe,ULES-01408,1.01,1768357888,f693ddfc,08b52190032ab3cf803b28203b78f46f,59602300f796986ae1b1f2ba9c5d1446ab85388c -24423,Sony PlayStation Portable,Astérix & Obélix XXL 2,Astérix & Obélix XXL 2: Mission: Wifix,Games,Europe,ULES-00527,1.00,1110769664,558437e5,98e8755626be09d63b31986d5cc0467e,ce8ba850280f0c450061d83f0d4650201d2f0c25 -24430,Sony PlayStation Portable,Fairy Tail: Zerefu Kakusei,フェアリーテイル ゼレフ覚醒,Games,Japan,ULJM-05955,1.01,1003782144,38888433,d829cc578ea22e4fe96eb1c42d174691,77d400ed20495a0f70b1c625c24e4fe08cc01e94 -24462,Sony PlayStation Portable,2010 FIFA World Cup South Africa,,Games,Europe,ULES-01413,1.01,1671331840,cff60cd6,0a53538c5a02d0c2f910e258eb30a9a3,11038706a8f5aa2f361049dae772a9aa7e68da86 -24463,Sony PlayStation Portable,Ben 10: Alien Force,,Games,Europe,ULES-01189,1.01,1306394624,938b4b76,e62f6ebc383fd855bee5ce0084f53895,4510aa9504d2376bba62af9f67ad86c8b38c4217 -24464,Sony PlayStation Portable,FIFA 11,,Games,Germany,ULES-01478,1.00,1458405376,36073b2e,798c6a3657dcd558ebdc03a78d973969,7a8ba9b9bf94e8887ec6a8fb18c7300968e9a97f -24465,Sony PlayStation Portable,Buzz! Brain Bender,,Games,Europe,"UCES-01157, UCES-01157/POR",1.01,804782080,00e748a7,e4aa5ebd6e49ebdf46a89a1929e10c35,990b9dcfe2a716360560ac754ebd65b287251158 -24466,Sony PlayStation Portable,UEFA Champions League 2006-2007,,Games,Germany,ULES-00708,1.00,1258487808,0e6a17b9,3e4d6321595fac51f4b3065e5c566237,6d1c5ef27e117b4ca4b52d43161e5e3baf27508f -24473,Sony PlayStation Portable,PES 2010: Pro Evolution Soccer,,Games,Europe,ULES-01354,1.01,1033043968,a2441eec,75a4554d0795e6ecd8283baa9c0c8746,31ba17c104ee587abbde10bf039f56c2c31f4112 -24506,Sony PlayStation Portable,BattleZone,,Games,Europe,ULES-00522,1.00,906362880,5a8b4b9b,fe618cf28aae0a54724fd402adbb6d75,95750fa7d821d87db99df45446f6e4303a26edfa -24507,Sony PlayStation Portable,Blokus Portable: Steambot Championship,,Games,Europe,ULES-01016,1.01,94470144,3c058228,b20d11e4f45eeec6179a8c1b484f806a,2b1855c9b922336ea3e1a86dd6519bb74e2be88e -24508,Sony PlayStation Portable,Bomberman Land,,Games,Europe,ULES-00959,1.02,510689280,6e3c154b,1f4c5389ba15dac2b66ed2e58fbbda14,a9b944e35a60f418f27462858b9a9002419bca3a -24509,Sony PlayStation Portable,Buzz! Deutschlands Superquiz,,Games,Germany,UCES-01199,1.01,776503296,292e743c,536abc1f93bcf15b91069433015e8427,82803a3d89fe4cc5653e8e423c5d5dfa0a63c682 -24510,Sony PlayStation Portable,Military History: Commander: Europe at War,,Games,Europe,ULES-01179,1.01,182288384,ee9e57f8,f721cbb82f7f7bdd995ca60e8fe0e13b,1ea9e9ee81479ebbbbe5395821b05296d0cd19c9 -24511,Sony PlayStation Portable,Crash Tag Team Racing,,Games,Germany,ULES-00170,1.00,1530200064,09970486,ec9dc7abef088eeb64b3b670c4d2da74,582de68d57d4de87e497910d6ae4bb7b350cee1a -24512,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,,Games,Europe,UCES-01449,1.02,1021378560,f962fbf8,6439d82c5dee4960bd04a27ed9f4dfc4,f26c2affde9ce661c0bff998eaaa712a4e738bbe -24513,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,UCES-01031,1.00,1517420544,ee44c337,22e5f94dc718303c56b34f6720d8198b,7a94e35faaad5f566ad228764cdd243d77a18bab -24514,Sony PlayStation Portable,Blade Dancer: Lineage of Light,,Games,Europe,ULES-00541,1.02,1425965056,42b32e1a,0ed220f8673d5c8e660276ce5f23eb05,4c0e54e90bc66f577840186a93644b13fb5f210b -24528,Sony PlayStation Portable,Goku Makaimura Kai,極魔界村 改,Games,Japan,"ULJM 05265, ULJM 05366",1.00,978485248,de3c4590,7e8b15544d205838b92cb5217c1a414f,574ce2a6b04ac99a8e246051767b1f8ef8dc2efc -24529,Sony PlayStation Portable,Queen's Gate: Spiral Chaos,クイーンズゲイト スパイラルカオス,Games,Japan,"ULJS 00376, ULJS-00377",1.01,1388871680,2e8adf55,4dbebf5c40bc830af72e14eace361998,b6ce86a2ee2b0ee852738d8ebd65ca2551e00770 -24530,Sony PlayStation Portable,Minna no Golf Portable,みんなのゴルフ ポータブル,Games,Japan,"UCJS 10001, UCJS 18001",1.04,402620416,4a6386de,020c88b8b054c6827fe4a78fa75945c9,83ec2378795ff3dcb5c1a7484447666f67065272 -24531,Sony PlayStation Portable,Super Fruit Fall,,Games,Europe,ULES-00639,1.01,61308928,fd6eac25,656ba8e885cf9a2c521f931e423e4d80,16393de8b303a39fb1c823a6e04f426479c6bbe4 -24532,Sony PlayStation Portable,Super Monkey Ball Adventure,,Games,Europe,ULES-00364,1.01,422707200,dc0c483b,6a9d46727a8714dacfe41fedf45ba017,25768616906a9435815efad6cd744854160f6ad9 -24533,Sony PlayStation Portable,World Championship Poker 2 featuring Howard Lederer,,Games,Europe,ULES-00635,1.03,682262528,618e54ed,2e41edda759cf4c04704ced8507297cf,5ae6d4afb8d488459e8fe5663c35d09777911d1c -24534,Sony PlayStation Portable,World Snooker Challenge 2005,,Games,Europe,ULES-00021,1.01,719552512,05399ca4,1f6ad85d70f72902b70cc4ee05fb8489,a2a39d8b2ccf3a31c2dd682b2dbd5c520e28305c -24535,Sony PlayStation Portable,FIFA 10,,Games,Europe,ULES-01322,1.01,1381236736,81b783cb,c356afd198a860ecee7c5a99c052626f,cea3b4f57d774dd63f6220ec3d64dabe04102b88 -24536,Sony PlayStation Portable,Football Manager Handheld 2007,,Games,Europe,ULES-00549,1.01,122945536,6890f15b,210310ca3663487aad97e2bcb598dc03,e6b725391312a6f3ffc56e7598512862adf76069 -24537,Sony PlayStation Portable,Ridge Racers,リッジレーサーズ,Games,Japan,"ULJS 00001, ULJS 19002",1.01,906297344,37dc8144,739ba19e712185bbbf1cd6ce4bbd859b,bfc7fc540711721e76ec5124f0986caea23caf60 -24565,Sony PlayStation Portable,Capcom Puzzle World,,Games,Europe,ULES-00647,1.04,513376256,bd0e24dd,b17556a961fb8421430e7bced4f66c4e,0cc0e778c7ab36063a9ae037c90c06017ea05781 -24566,Sony PlayStation Portable,Disney/Pixar Cars 2,,Games,Europe,"UCES-01534, UCES-01534/9271918, UCES-01534/POR",1.00,731217920,00a91af8,6d2e6cac628ff4d38e4b8baf2d52276b,860cbcbeed3c624f850173e693aaf1e2a1693b5c -24567,Sony PlayStation Portable,Disney/Pixar Cars: Race-O-Rama,,Games,Europe,ULES-01333,1.00,906330112,c0ab8ea1,7a28f0550c243e5a9bf3435994c626f0,1e85b43287d21175681afd38f24899874c504605 -24568,Sony PlayStation Portable,Disney G-Force,,Games,Europe,ULES-01239,1.00,1189183488,eff248e2,25d8bef1474d1ece935df9e8810ab87f,2efbde8ac93bd4b9318bf22ea0b6d09ce9853f5d -24569,Sony PlayStation Portable,Dante's Inferno,,Games,Germany,ULES-01387,1.00,1812725760,d62ce2a3,11ff3d5894e3307c1b85bbcaf5c09c21,820d53a67d24eefe59f59c12386c263c44b20f3e -24570,Sony PlayStation Portable,Dragon Ball Z: Tenkaichi Tag Team,,Games,Europe,ULES-01456,1.00,1373667328,60dcc003,f9d0a2b5cd28177dd1858c9ebfd02717,99b9075c67e17a2f99716f5d0b356e34623bd385 -24571,Sony PlayStation Portable,Fight Night Round 3,,Games,Europe,"ULES-00270, ULES-00270/E",1.00,1326252032,ccc44215,96affefdd0a078ad8d8559021c3324a5,c8c3044059cfe9370f03daf872d484779e28d6b3 -24572,Sony PlayStation Portable,Ben 10: Ultimate Alien: Cosmic Destruction,,Games,Europe,ULES-01471,1.01,1340997632,e35dd48e,72d440e12af4b6cbedd8d245a295d333,ccf66c814f408684c91cadba88e508a84e85da82 -24689,Sony PlayStation Portable,Cabela's Dangerous Hunts: Ultimate Challenge,,Games,Europe,ULES-00550,1.00,784203776,71336eb7,890b99306a0f3ccbde9df178f00ffaaf,3980b0c1a4b762d348e451e50163bc784f867d0e -24690,Sony PlayStation Portable,CID the Dummy,,Games,Europe,ULES-01024,1.01,527499264,030f27d1,e6f8ec74837bcdc05b57e7ff4d52a191,9692a530ca73b08d81a703d29b6f07f8f65e0f49 -24691,Sony PlayStation Portable,Coded Arms: Contagion,,Games,Europe,ULES-00718,1.06,604241920,37a93e82,b0a5541dea88fbb0a0b0b059b25ebdf2,08bbeec07d16d7c284be5d6dde30dc0dd485d7aa -24692,Sony PlayStation Portable,Crazy Taxi: Fare Wars,,Games,Europe,ULES-00811,1.00,906330112,0e8bc7e8,f572e2d7f536145af3392ffbb98638e3,520570a858e0fee9ca60616ef8a7dc86e1c0abea -24693,Sony PlayStation Portable,Dave Mirra BMX Challenge,,Games,Europe,ULES-00773,1.01,721125376,2250faa5,f5dd3feb480239f470356b7ab5fb1723,a20c8e513e93e9ad496dfdb7a84a3c4e1fb83e8a -24694,Sony PlayStation Portable,Death Jr.,,Games,Europe,ULES-00144,1.03,774373376,7dcfdfc9,47b23a33b1b4a7c46622dffbca771c78,072c4b82dffb183a59f1f9b2baffea9d6039d7e1 -24695,Sony PlayStation Portable,Death Jr. II: Root of Evil,Death Jr. 2: Root of Evil,Games,Europe,ULES-00582,1.00,1290633216,06077388,9700c187ee7a3c4222c07a13265c0033,b86d2c1298c0538c57252c3b34660527d6942a60 -24696,Sony PlayStation Portable,FIFA 12,,Games,Germany,ULES-01547,1.00,1458405376,d921e028,1625641dbacafc4ffe470a7251a4e510,6876875c2b672ca5a5b7116db53bbfead12bce69 -24697,Sony PlayStation Portable,Der Goldene Kompass,,Games,Germany,ULES-00952,1.00,1275592704,9dbc19e3,1887a5ab2cb3af30cb09488ce95b2577,cfb871a8e73da2bc950b8f22fd2788bfb0fbe5f9 -24698,Sony PlayStation Portable,The Mystery Team,,Games,Europe,"UCES-01536, UCES-01536/POR",1.00,1145405440,210078b1,7d3811432b19a87504a14727e2313343,3668fab314125fee68c8d824bb44a484a9d3910e -24734,Sony PlayStation Portable,Bleach: Heat the Soul,,Games,Japan,UCJS-10008,1.00,308150272,0baa63a2,ffe92cf051b810c9e8afa050f4ed24ad,c680990e52f0df0ba870529d0ba5007eeebce5ed -24735,Sony PlayStation Portable,Toaru Majutsu no Index,とある魔術の禁書目録,Games,Japan,ULJS 00328,1.02,601456640,9da98dfb,786ef722be44f8e558736131990a0dd1,33f2b7dabb6b585a100e6ccbe21384a75e371c9a -24765,Sony PlayStation Portable,Akumajou Dracula X: Chronicle,悪魔城ドラキュラ Xクロニクル,Games,Japan,"ULJM 05287, ULJM-05548",1.03,1108770816,1439373d,3c7645c0d1a303024bb65edbbac079fa,1cd3ebedc0c1ececcb636bced86a4ef578226101 -24766,Sony PlayStation Portable,Ys Seven,イース7,Games,Japan,"NW10107630, ULJM 05475",1.01,762773504,af7c1bb2,70c7c7fd6aa820b50ff30ba990c94f45,6ad97796e626df08510507b0648408988d0a0b99 -24767,Sony PlayStation Portable,Metal Gear Solid: Portable Ops,メタルギアソリッドポータブルオプス,Games,"Japan, Asia","ULAS 42087, ULJM 05193, ULJM 05573, ULJM 08016",1.02,1396736000,32bdcc8c,7f217c33b09ccbd0b4564177a1b3533a,4b04dfc2bebe8f87c4ebd33629b58a09a33ffb2b -24768,Sony PlayStation Portable,Kamen no Maid Guy: Boyoyon Battle Royale,仮面のメイドガイ ボヨヨンバトルロワイヤル,Games,"Japan, Asia","UCAS-40248, ULJM-05418",1.00,258113536,959ea52b,9fa8fad23907bcce2c6a4de72d4be329,b6860e3e6da71502f53613747b8ec4da5abae99a -24769,Sony PlayStation Portable,Saru! Get You! SaruSaru Daisakusen,サルゲッチュ サルサル大作戦,Games,Japan,"UCJS 10060, UCJS 18029",1.00,457670656,c18a6468,4fd462a517ee59892f5f44e30d3cff70,a001307b4c4118ea150274a060814c758777cc6f -24770,Sony PlayStation Portable,Tales of the World: Radiant Mythology,テイルズ オブ ザ ワールド レディアントマイソロジー,Games,Japan,"ULJS 00093, ULJS 19019",1.01,501481472,3bf10cff,df9c1cc70a0583c7704f3ee1bc727ccd,2851ec3495fb25f25e73048170253dbdbf44e144 -24771,Sony PlayStation Portable,Yu-Gi-Oh! Duel Monsters GX: Tag Force 2,遊☆戯☆王デュエルモンスターズGX タッグフォース2,Games,Japan,ULJM 05260,1.06,1812725760,415ddca0,bc71eea56c1a7597674e3cae50a1a9e5,ee309debf42ea3fe78b59de2988709a038da2119 -24789,Sony PlayStation Portable,Dai-2-Ji Super Robot Taisen Z Saisei-hen,第2次スーパーロボット大戦Z 再世篇,Games,Japan,ULJS-00460,1.01,1690107904,b1d944f1,9ba68735de364aeafb7f0787d7bacbdb,30fe01ffe6f17ab7c72673f99268f0f58093a9bb -24915,Sony PlayStation Portable,Dynasty Warriors,,Games,Europe,ULES-00026,1.00,160497664,190bc386,e2627d61bb4aa145466a642239b07324,40243ad57a039ab36d43f3a9557ac7887ea0364c -24916,Sony PlayStation Portable,Dante's Inferno,,Games,Spain,ULES-01388,1.00,1812725760,9c06d70f,5fa74b03a4acf90bb6a17139017912d5,b166273b43646c91cb04f0657381112bb833138b -24990,Sony PlayStation Portable,Tenchi no Mon 2: Busouden,天地之門2 武雙傳,Games,Asia,UCAS 40156,1.01,1190395904,b890c503,748f98ac6caee54e5721791b1fbdecb1,d0c08a00fe7253449f6bcec9fabca4b61269b9e4 -25028,Sony PlayStation Portable,Chotto Shot Edit,ちょっと ショット エディット,Games,Japan,UCJB-98012,1.01,79691776,392ec42c,b040e7070c36dc960828cfcb1c39ebbf,5d78c7458e40bea4c6e82ab65b5796f1b2c9bac9 -25029,Sony PlayStation Portable,Tenchu 4,天誅4,Games,Japan,ULJM-05425,1.01,826703872,df507d62,39672908f5b21ab46e40127ffcd95a2d,9f1522e5b6f6d185cd6bb8fb4157c034c572de81 -25030,Sony PlayStation Portable,Dungeon Explorer: Meiyaku no Tobira,ダンジョンエクスプローラー 盟約の扉,Games,Japan,ULJM-05164,1.01,768737280,d4f86e75,91b4a12b9baaaf2dffa84c45ac0aa887,3582e155a9ece9a9ce57555b5cf12e2a965ae850 -25031,Sony PlayStation Portable,Queen's Blade: Spiral Chaos,クイーンズブレイド スパイラルカオス,Games,Japan,ULJS-00190,1.00,906362880,c658c199,b0dc6f02ef7bf7790928e531417de918,73c9e8e734fe74cf7f3fa8b07693c1ae29c4de1c -25032,Sony PlayStation Portable,Danball Senki,ダンボール戦機,Games,Japan,ULJS 00361,1.04,1761574912,55dc4cb8,c0a9e1f09ff39ca964f5044aa3c1d627,a18972c898d6479ec1a16d8202631d0afa4774aa -25033,Sony PlayStation Portable,Battle Dodgeball 3,バトルドッジボール3,Games,Japan,ULJS 00468,1.01,901447680,232b91d3,bb343bb527b165d0edeb7f7447164592,4bccac1d1cb4a2d67d41380183f45a97452ba2b1 -25034,Sony PlayStation Portable,Great Battle Fullblast,グレイトバトル フルブラスト,Games,Japan,ULJS 00467,1.02,1321631744,493100da,a465d66d51a46ce9971d986fe857cb6f,71758aecd312ccbdaacc433d68c74105668a61ae -25036,Sony PlayStation Portable,Dissidia 012: Duodecim Final Fantasy,ディシディア デュオデシム ファイナルファンタジー,Games,Japan,"ULJM 05814, ULJM 06121",1.00,1768259584,40020142,23eab344691ef0a86fdc65d738ad51e5,147ff79333f1eb2e98ab4601308d66afc8c1549e -25037,Sony PlayStation Portable,Silent Hill Zero,サイレントヒル ゼロ,Games,Japan,ULJM 05281,1.02,802488320,e1207e2b,dd9673508661f54a8b3991a999bd3b78,98deec8078a8a754aea0774cf51db3d9525460c7 -25386,Sony PlayStation Portable,Rezel Cross,超傑交融,Games,Asia,UCAS-40140,1.00,1543700480,3096e72e,3d4165c1f59d448259a01f4dce6c5d7b,cef74af4c658510ed085906a5c286747134f795b -25387,Sony PlayStation Portable,Everybody's Stress Buster,全民都爽快,Games,Asia,"UCAS 40290, UCKS 45145",1.00,518782976,e169e0dc,727fc6e6c95a775917b826daace26c59,92992c3967c30e3842544c802a6d41e764c56442 -25388,Sony PlayStation Portable,God of War: Chains of Olympus,,Games,Asia,UCAS-40198,1.00,1613168640,02599b61,545ac8236bfbbab321c17a3d517ec595,80a10af59de60978c1de4c883b0ac18dd1b76f5d -25390,Sony PlayStation Portable,Dissidia 012: Duodecim Final Fantasy,디시디아 012 듀오데심 파이널 판타지,Games,Asia,"UCAS 40329, UCKS 45166",1.00,1752170496,1112aa2d,10f1d1523c66b3edc11a2fba1bf9d95e,36b5e435df120f9270323922c2901d7c9b0bab20 -25405,Sony PlayStation Portable,Bleach: Heat the Soul 6,死神 Heat the Soul 6,Games,Asia,UCAS-40258,1.00,645660672,cb8febd8,3cfb7f175f633550308d6749052c9a0b,b9947ad8bf4c5a24b2dd0e3617e837f9cc345686 -25406,Sony PlayStation Portable,Bounty Hounds,星戰傭兵,Games,Asia,UCAS-40037,1.01,1149370368,2cc48952,1332a057682f4cb301f69bac2a9d302c,5b8d819d57492599752bc7a478057a88dc480033 -25407,Sony PlayStation Portable,LittleBigPlanet,小小大星球,Games,Asia,UCAS-40262,1.00,1493499904,24652dd2,2f6973f3ea9359190875be437c8b5270,430b60f0b88ba14500b576329f8438b41e7c4018 -25421,Sony PlayStation Portable,Naruto: Narutimate Portable: Mugenjou no Maki,NARUTO -ナルト- ナルティメットポータブル 無幻城の巻,Games,Japan,ULJS-00055,1.01,634257408,34f72a26,826c06a0c701dd99191ca9e368f38803,2713cc225ff9582a29f8d5af97957e50905f7a6f -25422,Sony PlayStation Portable,Musou Orochi: Maou Sairin Enhanced Version,無雙OROCHI 蛇魔再臨 增值版,Games,Asia,ULAS-42164,1.01,1729396736,a5e174ae,e28b9b9615afd982524b0b7c0ed8386c,9d942e5a37f2e740fd8d19ada122c706d0605835 -25423,Sony PlayStation Portable,Audition Portable,오디션 포터블,Games,Korea,ULKS 46122,1.02,841252864,9054eab7,9a3002b71bdf42b6ef7e44a4eb9ef0d3,b2aa24ddcc801058e524801a4643fb39eea90ee5 -25434,Sony PlayStation Portable,EA Replay,,Games,Europe,ULES-00592,1.02,891682816,97f92764,20a929b7031130e2d8d2e7ac2c29c937,c49e657854eb0ca8db01a52444bb23b2a6f885bd -25435,Sony PlayStation Portable,Surf's Up,,Games,Europe,ULES-00817,1.00,906362880,fc1d31f7,17cde959c9a2a8286b4baf0789f0a635,6e85f282bcdc95dbfb3c457887116c73dc90f142 -25436,Sony PlayStation Portable,Skate Park City,,Games,Europe,ULES-00957,1.02,277839872,7ff72789,80497351cea1349729551f983269c0c8,3eb3834d28dff5ba327374263551a774b979def0 -25437,Sony PlayStation Portable,NFL Street 3,,Games,Europe,ULES-00641,1.00,902103040,a2ec4d0e,729ddc49d710f3742e8563cfe7b897a5,20daea08321832ae899d9e4224bce7e46d9c98b9 -25438,Sony PlayStation Portable,PDC World Championship Darts,PDC World Championship Darts 2008,Games,Europe,ULES-01096#,1.02,341114880,8acd48e8,36919a03d7740b9e88108a4272d3eaba,6e70b2b6c3929e36acbbba686b42e06561629ec5 -25439,Sony PlayStation Portable,ProStroke Golf: World Tour 2007,,Games,Europe,ULES-00472,1.00,809467904,73f4cb8d,9ffe197c2949ba0d7fcc31d37da45dea,4f493a8f40a273928bda578f968ca43a635e70d3 -25440,Sony PlayStation Portable,Rocky Balboa,,Games,Europe,ULES-00670,1.01,906297344,5d922ca1,860cee18f91f6e7aeb10d3a22dd701b4,fb51b6652807134438cd1284021e3da3596893e8 -25441,Sony PlayStation Portable,Reel Fishing: The Great Outdoors,,Games,Europe,ULES-00612,1.01,213057536,d9477cbf,25e19b4ddcabee401f9d811dac05e2d1,11ea7f18475c69fbafae1f930cb72318a3c04c9d -25454,Sony PlayStation Portable,Madden NFL 09,,Games,Europe,ULES-01093,1.00,1353154560,22e035f6,107180b58484a647f1c793b0cd63eaed,5c27250d077f8bd1f6443483fcb631befe8ec71d -25455,Sony PlayStation Portable,Madden NFL 06,,Games,Europe,ULES-00147,V1.01,1693646848,9da03d6b,d4e5a0ae74b066ae2bdda2c6e6116790,10dc5642c6bdd04e4f4db3db14df876a6f962902 -25456,Sony PlayStation Portable,Madden NFL 08,,Games,Europe,ULES-00867,1.01,1596588032,76dde0dc,a4dd5757f504e98e811f4ef5436c9a8c,5cb5eb98eb006de523d292e7e514866e9f0ef64b -25458,Sony PlayStation Portable,NBA 2K10,,Games,Europe,ULES-01342,01.01,1520271360,0093d2f7,0b98373cc07e0218a8abd6bc48448e07,405acdf72d423a6b714449ae6cdeef31663bc769 -25459,Sony PlayStation Portable,NBA 2K11,,Games,Europe,ULES-01488,1.00,1487241216,8019cdc1,5e8e3820242e0f78d623e0b5c38c74aa,66cb7ef6f7ae8ceab5c16263f1a34726fd980005 -25460,Sony PlayStation Portable,NBA 2K12,,Games,Europe,ULES-01554,1.01,1528823808,0f75393a,6f45150ae31a4ad4976e238af663782f,6d5c462648b70698eaeb61c25139f5b23626dd57 -25461,Sony PlayStation Portable,NBA Live 07,,Games,Europe,ULES-00462,1.00,1551433728,554b31fb,4069dfa0cf29df0326766b938c9cefca,5a785538c828e24815ad094be5d5897e444705db -25462,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,Europe,ULES-01468,1.00,1448378368,6385857b,4454a15d4e189f7b81647a59f49f9d64,f1464bf5bed00c6b56412aa56c76716f7c23af74 -25463,Sony PlayStation Portable,PES 2012: Pro Evolution Soccer,,Games,Europe,ULES-01541,1.00,1366654976,f8106862,4fd3482a75951ee69f2edb4909cab0e6,4c89317b66db1f4d185a6fdf16cf9494669532d7 -25466,Sony PlayStation Portable,Tenchi no Mon,天地の門,Games,Asia,UCAS 40018,1.01,1064402944,5e334ec4,6878dfd3dedaf6e5a484b62a90e15e25,08d60762b8bb9c9f607bfc0a43160985e60447fd -25468,Sony PlayStation Portable,Minna no Sukkiri,みんなのスッキリ,Games,Asia,UCAS-40278,1.00,431620096,8ee4ffae,cfab9cc4a326059125fee815fbc0a3b5,6b66d0c023735e12b29234e7e18c66e947c00c5d -25511,Sony PlayStation Portable,Mystereet Portable: Yasogami Kaoru no Chousen!,ミステリート ポータブル ~八十神かおるの挑戦!~,Games,Japan,ULJM 05328,1.01,1674772480,0c5640c8,fb55ff0e783aaa5a1aba9a939f834924,439732af3c8ca552f5ec71d33eb8e508d37d16a9 -25526,Sony PlayStation Portable,Kurohyou: Ryuu ga Gotoku Shinshou,クロヒョウ 龍が如く新章,Games,"Japan, Asia","ULAS 42244, ULJM 05713, ULJM 08047",1.02,1238171648,5da1afc2,7bbaa6d23d31c5554cf5349eba50c7c5,e9af145e16fc25a9223f911844fe05026a2029a8 -25627,Sony PlayStation Portable,Mahou Shoujo Lyrical Nanoha A's Portable: The Gears of Destiny,魔法少女リリカルなのはA's PORTABLE -THE GEARS OF DESTINY-,Games,Japan,"ULJS 00384, ULJS 00385",1.01,874840064,b6373a8f,32e9aa4b791f492b025ff46dbdcd6e7f,52ab81b80323ea183b814b3f38e23eef4ce83b9b -25632,Sony PlayStation Portable,Lord of Arcana,ロード オブ アルカナ,Games,Japan,ULJM 05767,1.00,822050816,2b36c100,cc739a7f58cf0b08514a99563e1dd129,ec567bc0acc427b7bbf5e1019cf7d1b674dd02b1 -25635,Sony PlayStation Portable,Kidou Senshi Gundam: Senjou no Kizuna Portable,機動戦士ガンダム ~戦場の絆ポータブル~,Games,"Japan, Asia","ULAS 42155, ULJS 00181",1.02,224985088,a2af5d53,23af38ca81cb57af53197649dff1a620,4e1ff7e48ca711bc76d0467d92eb5f467bc5dfea -25649,Sony PlayStation Portable,Hagane no Renkinjutsushi: Yakusoku no Hi e,鋼の錬金術師 FULLMETAL ALCHEMIST 約束の日へ,Games,Japan,ULJS-00292,1.00,1528987648,38c73614,90ff8e7765ac60bdc66d3f28ee1c3c86,90bb6519636e8f6cc82d5942fc65de0e70cfba0b -25674,Sony PlayStation Portable,Disney/Pixar Cars,,Games,Europe,"ULES-00319, ULES-00319#, ULES-00319/P",1.01,906362880,b0b30775,9b38032135df563c208f6dd7a6da2f52,b8019eadb6b0cddc8954dfe94589e25d2dd42f37 -25692,Sony PlayStation Portable,Go!Explore,,Applications,UK,UCES-00881,1.01,906362880,c0951132,5ed81b88350ccc15ef61c8d486413821,fe5816981d3874cbc04e5f160bf7359057e6fcf9 -25693,Sony PlayStation Portable,Invizimals,,Games,Europe,UCES-01241,1.00,1613922304,6b58cc40,d09e32a446c10fe273ab7c48fd40501d,5a0a24e2d45db3da573a97ae1a86ce3ea59f6fa7 -25694,Sony PlayStation Portable,Astonishia Story 2,어스토니시아 스토리2,Games,Korea,ULKS-46142,1.08,874119168,2476a6a8,ee6efb090dff252fcb795f791d39d4b6,5d0c2d2f5b2063c223e991035803d354f341526e -25710,Sony PlayStation Portable,Shin Seiki Evangelion: Battle Orchestra Portable,新世紀エヴァンゲリオン バトルオーケストラ PORTABLE,Games,Asia,UCAS-40269,1.03,503939072,20165803,0570ef9c662a79167d87c62324fce38c,023040b7bc1258c946cf14e372e45c8249402594 -25718,Sony PlayStation Portable,Viewtiful Joe: Battle Carnival,ビューティフル ジョー バトル カーニバル,Games,Japan,ULJM-05080,1.01,653983744,be05ed6b,eca08483b23fee9e9f0604e17b653ce6,06548c8fc937424e69649e843bec373cc5f84275 -25770,Sony PlayStation Portable,Monster Hunter Portable 2nd G,モンスターハンター ポータブル 2nd G,Games,"Japan, Asia","ULAS 42149, ULJM 05500, ULJM 08019, ULJM 08025, ULKS 46177",1.01,895582208,be7e39f0,1f76ee9ccbd6d39158f06e6e5354a5bd,951d1a360eec83af294a7a51ec4bba08f8633a6e -25844,Sony PlayStation Portable,Sengoku Basara: Battle Heroes,戦国BASARA ~バトル・ヒーローズ~,Games,Japan,"ULJM 05436, ULJM 08031",1.01,1703411712,48d3e82d,fcd34e193b5d0ce36eb482a9c4a94080,dc73ba2a0b5eb5c19949bbcfb84032961a7ded96 -25845,Sony PlayStation Portable,Crisis Core: Final Fantasy VII,,Games,Spain,ULES-01048,1.00,1737883648,12b20cba,cc65a096614822598ed66d3b871effb5,03355901f9f8cffd2dc66696a08d6ff024481b7f -25867,Sony PlayStation Portable,Evangelion Shin Gekijou-ban: 3nd Impact,ヱヴァンゲリヲン新劇場版 ー3nd インパクトー,Games,"Japan, Asia","ULAS 42293, ULJS 00407, ULJS 00408",1.02,1142915072,d8515c17,d1752ec00c5a9974eb94154eb1bd06fc,1797fefd53e8e993f9f1e0206d1d634462e46701 -25964,Sony PlayStation Portable,MonHun Nikki: Poka Poka Ailu Mura G,モンハン日記 ぽかぽかアイルー村G,Games,"Japan, Asia","ULAS 42285, ULJM 05881",1.01,669417472,bb800e29,bdf5b0fc86cede62b6f3050151afc6d6,f22cfc2fd4cce0754fde0a55e9a674b2d085dac9 -25993,Sony PlayStation Portable,Harry Potter and the Goblet of Fire,,Games,Europe,ULES-00215,1.00,540540928,ad6b19d8,ece4754f9b6c81671282930b81aaee73,d1ffc9d79b1014ed869a881e7677249d362feb7c -25997,Sony PlayStation Portable,Super Pocket Tennis,,Games,Europe,ULES-00619,1.01,108724224,a0e9abb0,f55dd85ef0f4ee3d65ca09883d6dab3e,023f61092dc47f435876754507360edfa69bdaed -25998,Sony PlayStation Portable,X-Men Origins: Wolverine,,Games,Europe,ULES-01226,1.01,731414528,691936b0,a4c2f330b8fea2bbf1a78db591099a43,4cd29cfb788ff272b2738330b7464e00e431f79d -26013,Sony PlayStation Portable,Disney TRON: Evolution,,Games,Europe,ULES-01494,1.00,307232768,aba764d6,1b1316fdfdc5e24580ba218be0ebb067,98348d722841973520a516d4156e77c154f687ad -26014,Sony PlayStation Portable,WWE SmackDown vs. Raw 2011,,Games,Europe,ULES-01472,1.01,1746534400,d2beca39,2459c1bfba396db15cc252c88e612596,2cb8ac43ec4946a0ddac7acff80870c9353676cf -26015,Sony PlayStation Portable,WWE All Stars,,Games,Europe,"ULES-01510, ULES-01510/E",1.00,1601404928,e33f81ba,4274f27d0638ff9c42df9eb33eb51ecd,8d52b911e6ef18a7b2612b8da11314118b7a4caf -26016,Sony PlayStation Portable,Gods Eater Burst,,Games,Europe,ULES-01519,1.00,1466171392,cbd3c3b8,ea5f234b90fb8919359772291d8a7fe7,5356a80510a48b5aae2d7bbaa7508e98a9916968 -26017,Sony PlayStation Portable,UFC Undisputed 2010,,Games,Europe,ULES-01410,1.00,1782579200,e9d27faa,33dd023cf036eb8f4b55dbf6283270e1,2b838e38279099c2a0fd0629563a089338b5bbb7 -26018,Sony PlayStation Portable,Cloudy with a Chance of Meatballs,,Games,Europe,ULES-01318,1.00,963182592,e141ab96,a65ea1e5c437fada0e4eec956669f20c,1306d7dbaa79e0bb65902675fa757994e74ae7e5 -26068,Sony PlayStation Portable,Sega Rally,,Games,Europe,"ULES-00910, ULES-00910/E",2.00,264437760,c6c5c7b0,6be6a3107c40a449259312fb4b331ca0,c01d444f106b2b9acd65c8dbfeb946e77fa8a83d -26073,Sony PlayStation Portable,Mussang Orochi: Mawang Jaerim Plus,무쌍 오로치 마왕재림 Plus,Games,Korea,ULKS 46209,1.01,1729232896,aac43e1f,9ebb407dafa6ad16ee7c9ae44a9bcf8d,f95540521c5c837db02edbe8b4728c7282c0904a -26074,Sony PlayStation Portable,Jin Samguk Mussang 2nd Evolution,진・삼국무쌍 2nd Evolution,Games,Korea,"ULKS 46084, ULKS 46130",1.01,278429696,70311f0e,62f01a63146b39c919dad0d89a68a707,055ad3c3e36d18df0b823d89d4cd9ff7a74e5d80 -26306,Sony PlayStation Portable,Dragonball: Evolution,,Games,Asia,UCAS-40256,1.00,394821632,e63afd04,460b183e9e029e94ce79c5198589f5a2,8f7c4c6a3ade9893c50fb52234429d8823551074 -26488,Sony PlayStation Portable,Jin Samguk Mussang,진・삼국무쌍,Games,Korea,ULKS 46012,1.02,201687040,9376a0bb,a78b8914518999db79c383b8a1365c7c,be91bfe4195d71d503c287b0b8e21fba4f8f91e1 -26489,Sony PlayStation Portable,Sincheon Magye: GOC IV: Another Side,신천마계 ~GOCⅣ 어나더 사이드~,Games,Korea,ULKS 46013,1.00,976125952,087f381f,59a2bb3ddeba7ecba761c710ba692bde,5bd14e8bd79ab88a2cda8ff85da8da327b80b15a -26495,Sony PlayStation Portable,Metal Slug Anthology,,Games,Europe,ULES-00530,1.01,1328873472,6364ec0c,c4c64bc2f0d5d2adbd5dd38216d9b2eb,de2865ca472999e49a547f01f87454475f52aa4a -26516,Sony PlayStation Portable,SSX on Tour,,Games,Korea,ULKS-46038,1.01,1414070272,b49a58ad,14feec62bff50dae14f32965aaaf3b2d,feeaf8c7b7dd89af5a84f2f614a648efbb1e6428 -26517,Sony PlayStation Portable,Virtua Tennis: World Tour,버추어 테니스 월드 투어,Games,Korea,ULKS-46023,1.02,429654016,e018fe2e,51c5c69650bb4581b3b31f1a60bb1af7,02769409d4c0fbdea889d438d677db54ee30327e -26557,Sony PlayStation Portable,MVP Baseball,MVP 베이스볼 2005,Games,Korea,ULKS-46006,1.00,1421705216,2ee1f029,0cb6cad574f84640ccde83da4fb1e316,6139b061d6d1b7d900c9561e9daa2f21a7904035 -26558,Sony PlayStation Portable,Need for Speed: Underground Rivals,니드포스피드 언더그라운드 라이벌,Games,Korea,ULKS-46004,1.00,266403840,52e3219e,c059964afa15baddfd262f1e1f6793b1,56e1bb9b5c32ca6c8e83a02a8ca13e111bb5c73b -26559,Sony PlayStation Portable,Armored Core: Formula Front,아머드 코어 포뮬러 프론트,Games,Korea,ULKS-46003,1.02,811466752,86e39073,7e3a417d023643845efd2cafb81dbf9c,cfd51dddba3fc9554a0a6c4a95d12bc3c4cb2d2e -26560,Sony PlayStation Portable,Kollon,코롱,Games,Korea,ULKS-46001,1.00,40075264,e2e09c00,89adb889247de9993a5b48eba7907b18,0754eddeb9ab71fe058121b56d9fa5fa84b2c254 -26561,Sony PlayStation Portable,World Soccer Winning Eleven 2011,,Games,Asia,ULAS-42256,1.01,1302855680,ba808bfe,40f61683805ce6d34f9246d59c425676,76592d2a155ea74b918be83167e6e22c1f89ce1e -26562,Sony PlayStation Portable,Hot Shots Golf: Open Tee,,Games,Asia,UCAS 40133,1.00,459702272,0b160ad4,5ed0d927e31542473168d75de021c71f,eb1bdde7fc0b0c6e84b4d85000374971b7b37e46 -26563,Sony PlayStation Portable,Need for Speed: Undercover,,Games,Asia,ULAS-42146,1.00,1304690688,ad0afa69,c1b1d74d33cfd9586b039548273c3ab5,47f5e4f1ff6624db46b2b054dd93020e99517ed2 -26564,Sony PlayStation Portable,Need for Speed: ProStreet,,Games,Asia,ULAS-42129,1.00,896237568,6ccd48ea,24d4d412f4682901c81d987717e7d3a6,a1eb589fa353c6455dc09fae3954a00b4e9d96c2 -26577,Sony PlayStation Portable,DTM Race Driver 3: Challenge,,Games,Europe,ULES-00615,1.01,1230929920,76d2f9e0,bd7358b5edcd4d2050307e6947c386ff,03b4df047662e7c62e441e475d495ce9fe0feff0 -26581,Sony PlayStation Portable,Hellboy: The Science of Evil,,Games,Europe,ULES-00827,1.01,906330112,26ab5a8a,3a3be59ca477d1bbea5e09f4cec97a24,c80f6b7a0059b814df60db4957b53b6e3bce54d8 -26583,Sony PlayStation Portable,King of Pool,,Games,Europe,ULES-01164,1.00,108101632,d52c0e21,5423dae4e0ecae8bedd38b47591d9a5e,03d85e503c37f559f9c214e623ee98eea56859fb -26587,Sony PlayStation Portable,Disgaea 2: Dark Hero Days,,Games,Europe,ULES-01392,1.01,793870336,2d05da51,a438d46b26dbb8540ee81e7527334f7e,164d1478034072e2632d8398b768be63bcb0ef73 -26589,Sony PlayStation Portable,Ultimate Board Game Collection,,Games,Europe,ULES-01017,1.00,199229440,ce4baf3a,ab396a2d0415ff52fcea0609076be98e,b58d88900731cc7c5c656d14849983bf62ba2c65 -26594,Sony PlayStation Portable,Dragon Ball Z: Shin Budokai,,Games,Europe,ULES-00309,1.01,811728896,791ad34d,7c8e04b66cb2e4c3473cb1427a614f71,ce5a4dfee4d1782a612d164d31ed3114caaf5a71 -26596,Sony PlayStation Portable,Dragon Ball Z: Shin Budokai 2,,Games,Europe,ULES-00789,1.00,867991552,ccbe9db1,0099a3ccabf5f5f23cea90368ecab54e,eef6ec05a37c0b9cf550b9eb25e5c4e8033c739e -26597,Sony PlayStation Portable,Dragoneer's Aria,,Games,Europe,ULES-01004,1.00,455901184,cb6c4fcb,89773dfb00478d746ae2e806971a5948,e4a396e92cfeb3e83c923fb9e291341dd3cf1768 -26599,Sony PlayStation Portable,Disgaea: Afternoon of Darkness,,Games,Europe,ULES-00999,1.00,969900032,8654bce5,f5101304e60084d4f7708da53ea5d766,bd595ccf1948c6b5cd99270dffc9a0dd2212cf45 -26600,Sony PlayStation Portable,Diabolik: The Original Sin,,Games,Europe,ULES-01248,1.05,1647149056,d8d3abd7,cf4f57f962a16f830af919a7b7140090,b92e277fe084afd969fcde513381bd45179cdea2 -26601,Sony PlayStation Portable,BlazBlue: Calamity Trigger,,Games,Europe,ULES-01497,1.00,1723760640,da3207e5,b16e88c2031c085456d367f9c87231db,1265e1fd7bd952e8b417131127ab50ed22b8e12f -26605,Sony PlayStation Portable,Syphon Filter: Dark Mirror,,Games,USA,UCUS-98641,1.01,1206910976,da9a9d97,b5b58939cd1d4a764b2ae41f20d6e243,aa704f6e8a62b2806636d3cc66e0dcfe78263723 -26619,Sony PlayStation Portable,MotorStorm: Arctic Edge,모터스톰 : 아크틱 엣지,Games,Korea,UCKS-45124,1.00,870842368,8b1996c9,3bd20a4962cbd35c1d1e48deea072b22,b3aba5301559cbcb99f949795bb8630dab7cd27a -26621,Sony PlayStation Portable,R-Type Tactics,,Games,Korea,UCKS-45065,1.00,339640320,e837f66e,13aa89b66f5a0911862152a4b76146f2,8b3d50348b661e00fd52d567e7b16f2d6381a483 -26632,Sony PlayStation Portable,Chase Cop: Pursuit Force,체이스 캅: Pursuit Force,Games,Korea,UCKS-45016,1.00,1441333248,a52d705c,7970ad87750714661f18550a061df838,f509c577b14378847996860e91973e0388a67775 -26633,Sony PlayStation Portable,Talkman Yeongeohoehwa Sudajaeng English,TALKMAN 영어회화 수다쟁이 잉글리쉬,Educational,Korea,UCKS 45044,1.00,458424320,2088a268,2acf97f131dfbd62c45cf812b35e3872,d5dfffb1c802d6d0d6c295974787e1dbffbaf56e -26636,Sony PlayStation Portable,Star Driver: Kagayaki no Takuto: Ginga Bishounen Densetsu,スタードライバー 輝きのタクト 銀河美少年伝説,Games,"Japan, Asia","ULAS-42270, ULJS 00368",1.01,1143734272,8e63b3e5,90eb123a6cde524f0756bf5ac38a2878,97397ae28182f12828927e581d6485676b2a4fe2 -26637,Sony PlayStation Portable,Utawarerumono Portable,うたわれるもの ポータブル,Games,"Japan, Asia","UCAS 40254, ULJM 05457, ULJM 05458",1.01,816906240,5c83c782,9c3f78610ac477cf2e73aa8a76741136,d50d024e6f2e6c6337e055388a28e67ce57c6bc4 -26646,Sony PlayStation Portable,Kenka Banchou 3: Zenkoku Seiha,喧嘩番長3~全国制覇~,Games,"Japan, Asia","UCAS 40231, ULJS 00166",1.01,521109504,3adb607a,00037a2c6b682b6189d0c23062e13930,1203b8194bcba3ca8980c33bf1f37c8f597a96a4 -26647,Sony PlayStation Portable,Kenka Banchou 4: Ichinen Sensou,喧嘩番長4~一年戦争~,Games,"Japan, Asia","UCAS 40300, ULJS 00268, ULJS 19046",1.01,764379136,932a69e3,abdf6c3f1e129dfc471f8940c724afeb,6c9740416f5d693602b89be86b0572fc45de2704 -26648,Sony PlayStation Portable,Samurai Dou 2 Portable,侍道2ポータブル,Games,Asia,UCAS-40277,1.03,567377920,50acd736,ad7d277728a070605d85cd16fd1187ca,a54f95b16297f5251956d44d0185136ec515a302 -26649,Sony PlayStation Portable,Hg Hydrium,[Hg] 하이드리움,Games,Korea,UCKS 45007,1.01,338591744,4345539d,86b4b30aec0df3779b86c8d75bfd7a6e,e1279ba10d66d6b168c61643aab844c637a46b30 -26650,Sony PlayStation Portable,Tenchi no Mon,"天地의門, 천지의 문",Games,Korea,UCKS-45011,1.00,1008074752,002d6d89,a13739f20dd4189b89c8eab9f2423a63,2677dd79d9ce56ba78d8bc890156038d2f6bd376 -26651,Sony PlayStation Portable,Bleach: Heat the Soul 7,ブリーチ ヒート・ザ・ソウル 7,Games,Japan,UCJS-10110,1.01,560496640,b245b08e,b31eeedc05df9c7889ad6fe29726d3f6,d8fc21ac3977f48edc4486f7f216759ee8a4ea77 -26652,Sony PlayStation Portable,Quiz Kidou Senshi Gundam Toi Senshi Deluxe,クイズ機動戦士ガンダム 問戦士DX,Games,Japan,ULJS 00074,1.01,339771392,f13d5236,0fceeaff24928b32fbd9de3960ac1ebf,48e6eb6b73be4ccd20a7d46e67aad77f10023855 -26653,Sony PlayStation Portable,Fate/Extra,フェイト/エクストラ,Games,Japan,"ULJS 00253, ULJS 00254",1.01,1280933888,488fe72d,9818790dbb432cda3cbbfc98a1683c58,6044271f8167bd322ada2e606d4e82e73ab8df45 -26661,Sony PlayStation Portable,Namco Museum,남코 뮤지엄,Games,Korea,UCKS 45005,1.00,240975872,a07555ae,375b59ae7ef16dac55db6eaf603fc7f7,2821d6717a7f65edc7aa7fd238eaad297222f9c2 -26662,Sony PlayStation Portable,Vulcanus: Seek & Destroy,불카누스,Games,Korea,UCKS 45006,1.00,1270743040,94e980a6,5735496cbde46c712784f3d77c2efaff,7ef17b8d02bdc390a0da9389df1a10d4afb7be5a -26663,Sony PlayStation Portable,Everybody's Golf,모두의 골프 포터블,Games,Korea,"UCKS 45004, UCKS 45049",1.02,563478528,f473977a,f768b2ea4036bcec55ebe86dffb94fe4,abbcc56a7c771e9f292e4d8ac0d6d5178532bdd0 -26664,Sony PlayStation Portable,Piposaru Academia: Sagomungchi Neungryeokpyeongga Wanjeonjeongbog,삐뽀사루 아카데미~아 -사고뭉치 능력평가 완전정복-,Games,Korea,UCKS-45003,1.00,391708672,a2e777f8,1dea7b541fed627f26486a90c86a0081,d9abd0146a04cf70a25bf0be047aafb5a15bdf22 -26665,Sony PlayStation Portable,Tekken: Dark Resurrection,철권 다크 레저렉션,Games,Korea,"UCKS 45027, UCKS-45069",1.02,1750171648,07aa4903,356126331b8a71abe0b17796911d259d,469b604c673e2ef1b98b4e08d3b7aea62a35ee33 -26676,Sony PlayStation Portable,Patapon,파타퐁,Games,Korea,"UCKS-45076, UCKS-45099",1.01,341049344,1a3ece29,50cf150aaeb71c3886762a30a7394fc0,c2ef9f05823787a0c03b9ac421814d3d5e17ba04 -26677,Sony PlayStation Portable,P3P: Yeosin Jeonsaeng: Persona 3 Portable,여신전생 페르소나 3 PORTABLE,Games,Korea,"UCKS-45140, UCKS-45175",1.00,1388118016,d88152eb,d4d08ef9c52b864c40530f917a22456f,7021e33bae3ef729bb861be599489c34d7a8fc0a -26678,Sony PlayStation Portable,God of War: Chains of Olympus,,Games,Korea,"UCKS-45084, UCKS-45155",1.00,1612611584,f53ef08b,9ac44f7fd51c4f48815811fa2459bc28,d84357642017ad36e629fc57df4ce9c8843434a6 -26679,Sony PlayStation Portable,Glorace: Phantastic Carnival,글로레이스 : 판타스틱 카니발,Games,Korea,"UCKM 84002, UCKS-45001",1.02,64258048,7fb8ab1b,6b8f77edfc7ada24c052cb9453cb6598,bda37a01ce1742820d2612c82a2f22d2f124f2bd -26680,Sony PlayStation Portable,Dungeon Maker: Hunting Ground,,Games,USA,ULUS-10282,1.01,150437888,91e75e8c,89989dbe26e54a525c8d97606e6e8aed,3c9f7bf3b0268754b4ed0c1d2d958b196f0404ea -26681,Sony PlayStation Portable,Brooktown High,,Games,USA,ULUS-10257,1.00,1292173312,03c8946a,b25b8f7d49c4701f0efbad99ff5d2025,d4c6169c5dd7546370a62e547a9dc1eb3a5c699a -26683,Sony PlayStation Portable,Armored Core 3 Portable,アーマード・コア3 ポータブル,Games,"Japan, Asia","UCAS 40268, ULJM 05492",1.02,875659264,663eff23,3f314bbe02c93370e4dc83566a87d366,b8f94fd2e4987ade18245d80c99740c90253ff3a -26758,Sony PlayStation Portable,Naruto Shippuuden: Kizuna Drive,NARUTO-ナルト- 疾風伝 キズナドライブ,Games,"Japan, Asia","ULAS 42239, ULJS 00291",1.01,1061191680,2512b9a7,5401abaf65326ce2ff4eda5b31fc954f,8c19bcbf8bb026d9c3ad436ad9d88820b67915ca -26773,Sony PlayStation Portable,Medal of Honor: Heroes 2,,Games,Europe,ULES-00956/E,1.00,1226768384,a7c1c1bc,7c472f83140e3af1a2fcdcdbadec850a,261898a262cdc8652e8d2c0e978e72c1c34a26fa -26774,Sony PlayStation Portable,LEGO Indiana Jones 2: The Adventure Continues,,Games,Europe,"ULES-01370, ULES-01370#2",1.01,676691968,605fad80,18b7373a29c12ef8f9c7788af92b5e6e,e773a4c19c5b6c14841897df481ad4aa5fe2870e -26775,Sony PlayStation Portable,Jackass: The Game,,Games,Europe,ULES-00897,1.00,1812496384,a9fd0d7c,bd071194e06c721cbff726a437731cb6,e78ed8427f8ef7e22654b21a67c93eda9169a67f -26788,Sony PlayStation Portable,Frogger: Helmet Chaos,,Games,Europe,ULES-00207,1.00,495747072,fc54cbfa,5d116f4db4e82fdbd1cc1aa33593014f,e4d5af35068f922c3d4022740f416932c865ac95 -26789,Sony PlayStation Portable,Practical IQ: Test Your Intelligence,Practical I.Q.,Games,Europe,ULES-00806,1.01,632258560,40a62adc,0e277689da7638b96248e746978e6c9d,35e890a388b4f2985c7d22c21e1bdbaeba8eb4be -26790,Sony PlayStation Portable,Dynasty Warriors Vol. 2,,Games,Germany,ULES-00606,1.00,279183360,3e4d9696,900e9831ab86959a8746ffc93373e7d2,474079eece25a2e8f36e0bd97a3956054ec322c3 -26791,Sony PlayStation Portable,Ghost Rider,,Games,Europe,ULES-00630,1.00,789479424,1e0453a5,016752f07d9500f9573dd25b6da425c3,7f841becb0420ed25e0225c0b69a8f3d81a84e7b -26792,Sony PlayStation Portable,Final Armada,,Games,Europe,ULES-00661,1.02,541589504,401d8c61,26188c12d7b490d9f957232a095e2a68,6ee6dcd1e51625d380b67fb2839936be6c29f23a -26793,Sony PlayStation Portable,Dissidia 012: Duodecim Final Fantasy,Dissidia 012: [duodecim] Final Fantasy,Games,Europe,ULES-01505,1.00,1754529792,81bfb318,184e0e4b222cfd4b516cd2675be32345,2e6e8b71a1f66a5ba1390fa68ea36188ac4fe2b6 -26794,Sony PlayStation Portable,Family Guy: Video Game!,,Games,Europe,ULES-00601,1.00,1201176576,7ed3cc18,b00f6011bae07060a1885a5d114565ad,6bc83549d9ffbb82f67e5c2561f3ee0f3fa34fe9 -26795,Sony PlayStation Portable,Generation of Chaos,,Games,Europe,ULES-00820,1.01,1133903872,4078c202,be771c1ceea36f3eaef369c8800674af,69c1946b9385689cba62f335c3eeafcac3821081 -26796,Sony PlayStation Portable,Dynasty Warriors: Strikeforce,,Games,Europe,ULES-01221,1.00,1801256960,028b71c9,5f703f844ba19c8a0a3d8a27755ddff2,e78537b273c2c6bd27c7e351ddc9731d2969ddf7 -26797,Sony PlayStation Portable,World Soccer Winning Eleven 2012,,Games,Asia,ULAS-42289,1.00,1210417152,899ff887,b1e1366ef91eb6bec1c7bbfc810e2522,9066a4bc0b88e7716334d02b823de78ab6981ea7 -26865,Sony PlayStation Portable,Hello Kitty: Puzzle Party,,Games,Europe,ULES-01397,1.00,234586112,b0b41203,8f15da851bfd890d386b87a31f7eb315,48e150c3cd1f254c4eaf87f23dc93529684ca4b6 -26866,Sony PlayStation Portable,Mega Minis Volume 2,,Games,Europe,UCES-01503,1.00,281772032,ea79a680,8a60d05d0c879f67ae2923b381a0d09d,aa19eaf43c0e67ba07cea1274677e5cc126747f2 -26867,Sony PlayStation Portable,N Plus,N+,Games,Europe,ULES-01026,1.00,110886912,5278c8bc,cbe8e24742d75b37e0a3cc909195d141,028341c6027a6b8f367a0eb553b6793896418008 -26868,Sony PlayStation Portable,Hannah Montana: Rock Out the Show,,Games,Europe,ULES-01303,1.03,906362880,f0c1084c,6b48887362d3f58f6cdbac56de10248a,e76089db134bd0505c606fa754f3ed6b4acbaf2b -26869,Sony PlayStation Portable,MX vs. ATV Reflex,,Games,Europe,ULES-01375,1.01,906330112,626f4650,8700c4a72235f2556ba0661d67c9a9f2,b175f17b80269ff3599e80b3770822aabd62c0f7 -26870,Sony PlayStation Portable,Jak and Daxter: The Lost Frontier,,Games,Europe,"UCES-01225, UCES-01225/E, UCES-01225/P, UCES-01225/POL",1.00,1784840192,39de4b84,cc58f5849dc22ca4b090f41864876bb8,dcd57ce78d95985d852b1ec9d58dcb1ca2210f11 -26871,Sony PlayStation Portable,Disney/Pixar Oben,,Games,Germany,ULES-01254,1.00,525762560,664fbc8e,1fa8c7cbc8429812581998cd6169a849,dc72239c6159e9c93ad5550578b343fc1a22ead3 -26872,Sony PlayStation Portable,LEGO Pirates of the Caribbean: The Video Game,,Games,Europe,ULES-01528,1.00,1478459392,a8fb3219,46ddc45e4d9bbaeb7795c52773d50f8b,fe4be4a1a881d32e715edab1922d2085ddf239e4 -26914,Sony PlayStation Portable,Naruto Shippuuden: Narutimate Impact,NARUTO ーナルトー 疾風伝 ナルティメットインパクト,Games,"Japan, Asia","ULAS 42297, ULJS 00390, ULJS 19071",1.00,801701888,9150387e,59f720ff052f70f18d62083530b3de8a,59fd05ca2c6cb874e57e1f6adac05d0eafa38c26 -26915,Sony PlayStation Portable,The Idolmaster SP: Wandering Star,アイドルマスターSP ワンダリングスター,Games,"Japan, Asia","UCAS 40242, ULJS 00168",1.01,1415446528,2b45cb84,566f5f68870fbfa7d83eb08839d2335a,ca956323db36690c1d6ee3c68b490088bf01c216 -27014,Sony PlayStation Portable,Medal of Honor: Heroes 2,榮譽勳章:鐵膽英豪2,Games,Asia,ULAS-42120,1.00,1226768384,acd9f375,d1198b63631ea60d21ddfbc5576882b2,120b37dc1f4e664e0f67466dc9cde0de65276f5e -27021,Sony PlayStation Portable,PSP System Kiosk Disc #3: Yellow,PSP Kiosk Disc #3,Demos,USA,UCUS 98664,1.00,1221459968,32b8ef74,c6c6a3002bf8961fe623b02c117b43cd,b5b7328235f78646eef6d45e6f3d2702f1a6137c -27022,Sony PlayStation Portable,PSP System Kiosk Disc #4,PSP Kiosk Disc #4,Demos,USA,UCUS 98665,1.00,911376384,24c7fc67,8e510426a570e4689ac0e0db64ae5db7,c9e7b685d5407192e563cc81d40bc8b4384208a6 -27183,Sony PlayStation Portable,Lanfeust of Troy,Lanfeust de Troy,Games,Europe,ULES-01022,1.00,387645440,b71df121,ffa11874291f3d023dfb09f2235b283e,3f8451787fc39eda3bccc613ca2e250d0aefe6f4 -27184,Sony PlayStation Portable,World Championship Poker featuring Howard Lederer: All In,,Games,Europe,ULES-00681,1.02,905084928,45626cb1,a5503392652d4c6e0c42ef0621ccb394,dc3c7f576f5f616146c230fa32dfbe4a4cffd975 -27338,Sony PlayStation Portable,FIFA 12,,Games,Netherlands,ULES-01544,1.00,1217593344,7a41cef9,f970f5d66cb4b60c733fd2fd71a05a74,4b8e0bbde29b65b32414678b93c157a31c913b5e -27390,Sony PlayStation Portable,Disney Phineas and Ferb: Across the 2nd Dimension,,Games,Europe,"UCES-01564, UCES-01564/E",1.00,1202683904,8d75f60d,5f9c8bc0ebb0d843650907887aebfc6d,34c426ee7fbeaae36310f35efeacab4ad7bb3ba5 -27391,Sony PlayStation Portable,Space Invaders Extreme,スペースインベーダーエクストリーム,Games,"Japan, Asia","UCAS 40194, ULJM 05315",1.01,171245568,a44b9985,025a73e3abc36d530aae94af6a932a77,bc8c5e133a2680ae87199f95fe688a7d00982061 -27452,Sony PlayStation Portable,BlazBlue: Continuum Shift II,,Games,USA,ULUS-10579,1.01,1651834880,ba8ea3c3,dfc7546eb130ffcc907a18c449f21be4,2d7bd9dcdfb73d3801505badf209c497b4142fae -27453,Sony PlayStation Portable,Growlanser: Wayfarer of Time,,Games,USA,ULUS-10593,1.00,1137377280,08d34057,55053b5b4b1d05c6c6c79e4e98621f29,55ffd74929a2193572021eff59317d4cbbc1a227 -27454,Sony PlayStation Portable,Jak and Daxter: The Lost Frontier,,Games,USA,UCUS-98634,1.00,1453916160,c7230e04,1612fbe6e6dcba9a6668010e356853cb,d4e2f8df9636c583594a6f09caeb1d77eaa22518 -27455,Sony PlayStation Portable,"Prinny 2: Dawn of Operation Panties, Dood!",,Games,USA,ULUS-10561,1.00,795115520,5eb56c25,d73d155897ed3f03e5eafc35c79baf83,8babc7c6fe27d7b0ef7a1143b6c533c3e11a8086 -27456,Sony PlayStation Portable,Ragnarok Tactics,,Games,USA,ULUS-10594,1.00,645431296,04edfc63,af17d052e8985207394fac69eb9d6584,9957bbf71d8c55b3d590b063c7ef07174899fe71 -27457,Sony PlayStation Portable,Sonic Rivals,,Games,USA,"ULUS 10195, ULUS-10195GH",1.00,246087680,a7556f70,3f289f6e48aaaa1ad557a123eb818fa2,d5b01c769e4191f8fe5e7ff1d697506e0f78195c -27487,Sony PlayStation Portable,Metal Gear Solid: Peace Walker,,Games,USA,ULUS-10509,2.00,1645936640,a3437f3f,c0d334fa69bacc4041460c242492ddb4,d2586df8ed1508980e500681621c88dd1ffc222b -27897,Sony PlayStation Portable,Rainbow Islands Evolution,,Games,USA,ULUS-10205,1.00,847020032,6c4aeecd,a50b6d4401d0d22c34d4332f01c3eec9,8e9de125fe87a99ff0fb35dd4892fde9b2c40d72 -27898,Sony PlayStation Portable,Kao Challengers,,Games,USA,ULUS-10085,1.01,614301696,adbffd20,857943b7d2383d0fa76529cc092b376e,86472de8aaca6b0739624ed4c87067e9ec3a81d7 -27899,Sony PlayStation Portable,Disney/Pixar Cars,,Games,USA,ULUS-10073,1.02,906362880,eacee7bd,b8097a12709dc23bcab7195ab0f9f1cb,c2a1e59e1e8c219d105e60daa965c7692de40a35 -27900,Sony PlayStation Portable,FIFA Street 2,,Games,USA,ULUS-10067,1.01,902922240,c295373c,e8fa95e847ffac35e537ddbf00b5a600,dc14735ac73d0a57629308faea9220eba0314408 -27901,Sony PlayStation Portable,Pac-Man World 3,,Games,USA,ULUS-10055,1.01,494239744,36975d70,65a83fe7265d4bc6a83a05d96a3f5e75,e29ffc814c6e0b43eed8a73e2b8f9f7433a485dc -27954,Sony PlayStation Portable,Macross: Triangle Frontier,マクロス トライアングル フロンティア,Games,Japan,"ULJS 00321, ULJS 00369",1.01,1676050432,1729ad6c,ec1bcb7393c7c3ca5424e0a6bc3c0e87,84a7a28799fd7fc6c7ebceb1b38c8b0fcbb92c97 -27959,Sony PlayStation Portable,Ys: The Ark of Napishtim,,Games,USA,ULUS-10051,1.00,681607168,7f184dae,6802bc53753c979f979e9cc9f66f6494,49d2cb016a62def1ce1adeaabde13090c320fb7e -27963,Sony PlayStation Portable,The Idolmaster SP: Perfect Sun,アイドルマスターSP パーフェクトサン,Games,"Japan, Asia","UCAS 40241, ULJS 00167, ULJS 19036",1.01,1406959616,d49cf27d,71225f89b5c67c672b9245a8c6d63e9d,7bb1525ee0f9f569bad3fe5fa6e6396644fd1490 -27964,Sony PlayStation Portable,The Idolmaster SP: Missing Moon,アイドルマスターSP ミッシングムーン,Games,"Japan, Asia","UCAS 40243, ULJS 00169",1.01,1453424640,ca4469d0,5998414e19895f144c855353d82c6d2b,fcf118a0fd65e957e5ea1a576994a17212dc6c72 -27971,Sony PlayStation Portable,Puzzle Quest: Challenge of the Warlords,,Demos,USA,ULUS-90001,1.00,90374144,0f566cdd,2bfdadbdfcd31dfb29c3e93e3896538e,aebabf08c93292bf9bc306cf55cdcfc77348cc06 -27972,Sony PlayStation Portable,Chili Con Carnage,,Games,USA,ULUS-10216,1.02,797081600,4711abeb,4d756980b0c67b5bb2faa1d15aa3f3c7,226f82240dd0b00dadb48358aff58609a4cb0f5c -27973,Sony PlayStation Portable,Nickelodeon SpongeBob SquarePants: The Yellow Avenger,,Games,USA,ULUS-10092,1.01,174260224,e28f4c4d,beba45f9755f6f5673f5af3d6de90df4,c61e9fa73a730cc33b97bd41d96b8cd1adef0cca -27974,Sony PlayStation Portable,Tokobot,,Games,USA,ULUS-10061,1.02,328564736,81176a40,446136afa0d1c173d1414513d4770840,25968212cb6ac7dc8857fb2319954d602278ef45 -27975,Sony PlayStation Portable,Beowulf: The Game,,Games,USA,ULUS-10329,1.01,1261305856,6af7e2a0,c8ba98b69ff85074e5c2dcf9b6fbeaaf,3a2d0f479a97f0bc2a3690688b492f86e644e95c -27987,Sony PlayStation Portable,PDC World Championship Darts,,Games,USA,ULUS-10386,1.06,341016576,f645669e,f7563401cf9708996722e8e457eb2b3b,8021b2cb1f7311b7e5dd66d6b36e394545728d3b -27988,Sony PlayStation Portable,F1 2009,Formula 1 2009,Games,Europe,ULES-01355,1.01,684359680,4a7be933,fa3bf469327ebfaa4df61e0ea3fe4524,317c549701767c276264df1d8821da8308f9d70d -27989,Sony PlayStation Portable,EyePet,,Games,USA,UCUS-98759,1.00,691765248,511bace9,a3ef1d191bbf1864b66488e1babf97fe,24c305aaf6189972354b68c2ef69ef6a3acae30f -27990,Sony PlayStation Portable,FIFA Soccer 10,,Games,USA,ULUS-10464,1.00,1754562560,8d7e058b,acb68354b4549679bd58f1211d1d3311,003b278c6ec30adaca8e3257bed4fc6f33cc2d27 -27991,Sony PlayStation Portable,PES 2010: Pro Evolution Soccer,,Games,USA,ULUS-10483,1.00,1020035072,396f1022,7dfd389c75e59a6535f6b974914c24c9,9599863db4f80834ce1ec7a14ad474e8eba24748 -27992,Sony PlayStation Portable,PES 2013: Pro Evolution Soccer,,Games,USA,ULUS-10597,1.00,1675264000,d4396dd2,664ab3d0143d00e11a8581b9c4f35aa1,4df43278bc21061a8e7c031e953b9e90bfa7bc18 -28066,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,USA,ULUS-10554,1.00,1470234624,d9693164,c26ec0135fdef02fa02c9d1482f08f6b,fd9e7f01fc31f707012d44f96c208ae624eecc50 -28067,Sony PlayStation Portable,Disney TRON: Evolution,,Games,USA,ULUS-10548,1.00,292913152,cc5b0fa2,9b48d36457cf5f63b9d35b32c10fb575,0325672724bb7dcbe40a76f79746087b734cbd1f -28084,Sony PlayStation Portable,WRC: FIA World Rally Championship,,Games,USA,ULUS-10093,1.01,1320255488,a8900122,c84b2a046a18128809c01a04de38e652,a3e2df5241dbdc043049f17e88f62c824af495e9 -28210,Sony PlayStation Portable,Network Utility Disc: Chinese Ver. 1.00C,,Applications,Asia,UCAM-80002,1.01,139001856,52218f43,8e05b2666e291215ed7e0cb940da6d2e,b366b24fedb76ba378276076b1a77bababb7c027 -28288,Sony PlayStation Portable,Sengoku Cannon: Sengoku Ace Episode III,戦国キャノン SENGOKU ACE EPISODE III,Games,"Japan, Asia","UCAS-40019, ULJM-05021",1.03,170459136,610fd571,79b61bbf70b7cc62ff3ae1765f08bffe,6d9b95dbf6ce7a2d1d88a1f7cf67ad84f1f4f57f -28589,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,,Games,Europe,UCES-01450,1.02,946241536,2efbba60,27a357f260e0665a9421dfc2e716feb5,39682c8091413efaf6f37f873d32736443b95881 -28590,Sony PlayStation Portable,Cart Kings,,Games,India,UCES-01520,1.01,515768320,9dd2e7e4,bd9584646715f562762420cb48812e20,13eba28da79064db02ccf16e3228dd889d0035e2 -28609,Sony PlayStation Portable,Chandragupta: Warrior Prince,,Games,India,UCES-01559,1.01,334528512,ba273ca2,5f316f8d2f6ff6487076dbb80d0e0fc4,330e781458cb8ebf3e63a0d243a922b21e9ae79d -28614,Sony PlayStation Portable,Buzz! Danske Genier ~ Buzz! Norgesmester,,Games,Europe,UCES-01203,1.00,1507426304,91c1670a,b5d0a74481dc879a385d785edf937307,060b7637200d702c7d8418ffa8eb628b14f38def -29101,Sony PlayStation Portable,World Soccer Winning Eleven 2010,ワールドサッカーウイニングイレブン 2010,Games,"Japan, Korea","ULJM 05513, ULKS 46228",1.01,993951744,9d98127a,48a59f75a8433c68a46de6151f5bd3ff,64c1a17d674f66e718bf23e33045cd86f5685748 -29102,Sony PlayStation Portable,Capcom Classics Collection Remixed,,Games,Asia,UCAS-40199,1.00,571965440,137e6dfd,0864c87cffc27effed9b8b44fa6754bd,32264269bdf18db2c92e406440a85add28c932b8 -29612,Sony PlayStation Portable,Metal Slug Complete,メタルスラッグ コンプリート,Games,"Japan, Korea","ULJS 00090, ULJS 00206, ULKS 46129",1.06,1328939008,4205b399,407704923028b1b35d65f6f937624c30,048e03b0401c2d0dcdcd01048be07329336c4b05 -29681,Sony PlayStation Portable,The Legend of Heroes III: Song of the Ocean,,Games,USA,ULUS-10144,1.01,874971136,f6a8e8a7,02a36b9fbb1b94ec8e43f9bf93219647,7f22c195ce546d204eba756cabad3431bc2ca82d -29734,Sony PlayStation Portable,Gungnir,,Games,USA,ULUS-10592,1.00,262766592,183f3edc,c687b198bffcd459bd8d914fcb7fcfba,7cded8a4cb5ef7a6e018bb73d10c0ad728747adb -29815,Sony PlayStation Portable,Hakuoki: Demon of the Fleeting Blossom,,Games,USA,ULUS-10577,1.00,1198555136,1d84cb8c,2b50bbd2b18d3124efe05b8a02bcfb92,367b177fa3f60e18e40a31baba3a722641e2c41a -29829,Sony PlayStation Portable,WipEout Pure,,Preproduction,Europe,UCET-00001,1.0,252346368,0de6ff07,27da6cf67395b05247a15dfd68cb02fa,166a6906efcffca9de03dbbc2ffaae0f067c8cba -29830,Sony PlayStation Portable,WipEout Pure,,Preproduction,Japan,UTST-99100,0.10,178913280,80b76d20,2e4d9fea44a8e1bb055730e38b500f5c,17625cfce98404dd82c8e001575d68a8613bb8be -29831,Sony PlayStation Portable,Puzzle Quest: Challenge of the Warlords,,Demos,USA,ULUS-80018,1.00,90374144,8b556640,241e38e7476d58e621cebded98689759,73cda64f2d38e037a4c23c1be9700c6c68041243 -29832,Sony PlayStation Portable,Colin McRae Rally 2005 Plus,,Preproduction,Europe,ULET-00122,0.02,1705017344,93cb617e,9dfae75d641ac2ceef26ca8150ab24a0,8f6e1a7ffca1516455e4740417734aac7fc078f2 -29833,Sony PlayStation Portable,My Spanish Coach,,Educational,USA,ULUS-10378,1.01,284360704,7a701c78,61c65cb37f6dd17ca3d53486c8b3c54c,af92eaafe4698fb907d0acee81657e154337a30d -29834,Sony PlayStation Portable,NFL Street 3,,Games,USA,ULUS-10135,1.00,901644288,68f96119,d3a22428174a4bc62b1a8c6f061245e5,2459a3d3205a8ffaef6e5830235cca28c2e9fa31 -29835,Sony PlayStation Portable,DreamWorks Shrek: Smash n' Crash Racing,,Games,USA,ULUS-10194,1.01,906362880,f80e033b,f0f2dd43027cf8df4c5aa84888818456,6586b4d2c9a8d2174779119acf24974fb7632b0d -29836,Sony PlayStation Portable,PSP System Kiosk Disc #1,PSP Kiosk Disc #1,Demos,USA,UCUS 98642,1.00,925597696,5b28344b,8701999bd7da850956d7410500c32e18,6eed20b079b45f76ed6b3a8087d76895ef1c5c5c -29837,Sony PlayStation Portable,The King of Fighters Collection: The Orochi Saga,,Games,USA,ULUS-10360,1.0,1532887040,72ed0926,72b120fe70a83c4a23fcf14a9afeec60,be5c76f2be9257a07ee04fd03441dd911204ee1c -29838,Sony PlayStation Portable,The Bigs,,Games,USA,ULUS-10284,1.01,865370112,fa2bde1c,7e429607b3737390bbe53da70d562982,bcfe9ebb61ba185d6a5df777c90a11443ea0d949 -29839,Sony PlayStation Portable,The Bigs 2,,Games,USA,ULUS-10448,1.00,778960896,38c67405,99e78a102bd472a005fe8faa51b1641e,47ab1ea8c5f786fdac897a81bb4cf057142533b1 -29846,Sony PlayStation Portable,Hakuoki: Warriors of the Shinsengumi,,Games,USA,ULUS-10651,1.00,1514438656,51b32c75,7198f1d849dd308e9a30efe6c722e13e,d28fcceb057f1d19d74e7a54c6f315e0509c534b -29885,Sony PlayStation Portable,Call of Duty: Roads to Victory,,Games,USA,ULUS-10218,1.03,640974848,ea73e047,bf2e8cc0054f611ba734f5e304498fb5,f0282c6e698d5edce1ee1441c8037b1d1fbb8479 -29886,Sony PlayStation Portable,Coded Arms,,Games,Asia,ULAS 42009,1.01,183631872,5b97abb2,e8ddef9c373c36fe8e5535abfafd50b0,34ac6016378ef8a743406d4e266618a1158d8f43 -29887,Sony PlayStation Portable,Dragoneer's Aria: Ryu ga Nemuru Made,ドラグナーズアリア 竜が眠るまで,Games,Asia,UCAS-40162,1.01,388104192,01ef7cd0,e0434a6965e073c3ce28c351ddae0586,9ad93807651a82c96d452ff606e2667880b88840 -29953,Sony PlayStation Portable,NBA 2K13,,Games,USA,ULUS-10598,1.00,1753022464,d9e8fd5c,328299b1f935ec8af35f55faa471b07c,54f26bc7ee0eeeec081935eda2adab5b7f6b0e7f -30010,Sony PlayStation Portable,Bomberman,,Games,USA,ULUS-10121,1.00,110002176,8ff6ab31,ca29f6886726a2d5e8e859cfbd0f41aa,c514eace1667e74c959ec218d7e12f46dc7754b9 -30012,Sony PlayStation Portable,Naruto: Ultimate Ninja Heroes,,Games,USA,ULUS-10299,1.00,254050304,1376ce50,2f23155f9e5075daf9b75eff39885a9f,0ca0e817598921f9dfecea854e7f9ad5e811f322 -30038,Sony PlayStation Portable,Sweet Fuse: At Your Side,,Games,USA,ULUS-10652,1.00,1134100480,ae032f1f,a9a73182358abb088ce73082028eccae,763c729e5fbce90fa4dbb784992c1142ef4dc75a -30102,Sony PlayStation Portable,Spider-Man 3,,Games,USA,"ULUS 10317, ULUS 10317FV",1.02,1683259392,ad00100e,af7598e8d10df18764e9b428bb15a922,1bd561d55558e38440376df8d5bd1f0e7fe44a96 -30209,Sony PlayStation Portable,Bounty Hounds,,Games,USA,ULUS-10161,1.00,1147404288,af98b295,527a5ddb65750e603d10f451862fbdb9,3963ffc8ba1909cb7be0ab527cae1c097ce40aa0 -30221,Sony PlayStation Portable,Monster Kingdom: Jewel Summoner,,Games,USA,ULUS-10211,1.00,531726336,0de75769,88a37060ab3b9452a9d9cda11fb398b0,0ad1c0e049444e744582f22db83571b0f027b33a -30444,Sony PlayStation Portable,Class of Heroes 2,,Games,USA,ULUS-10653,1.01,692060160,681c936f,5f35c6815441eee8c0f44315f7926afc,ad679d255eed2d710e6c95c1053b0b60c7512225 -30582,Sony PlayStation Portable,Crimson Gem Saga,,Games,USA,ULUS-10400,1.00,878641152,fb3ba4ca,bdd923d2f72e8145fb1741c0b3c0ae57,ea69d5862b60df26161816007bf86d69ff1bd900 -30583,Sony PlayStation Portable,Dragon Ball Z: Shin Budokai,,Games,USA,ULUS-10081,1.02,326729728,5f6807d2,0eb2f89470f54c379624e96b35437ae7,33e7cff3f421c77eb771a1e111c9419c672be996 -30584,Sony PlayStation Portable,Marvel: Ultimate Alliance,,Games,USA,ULUS-10167GH,2.00,1773764608,4bec498d,f31dcc0631f63057754ef90b38e288e7,6773c4a831b0d3b46273432381f18362e1d5c7de -30585,Sony PlayStation Portable,Sega Rally Revo,,Games,USA,ULUS-10311,1.00,197263360,3aca7787,329d0fcd6161ab4ba261eb89554220e1,6ed5cec20fec9d11cf6a62dbe80a795a2aadcf50 -30586,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 3,,Games,USA,UCUS-98716,1.01,1442578432,ec37107a,32393bdbf6c0a7592c1c66cd172351a4,1af92ee0c1fab91361727a154a5d7c5b278adfbc -30587,Sony PlayStation Portable,Star Wars: Lethal Alliance,,Games,USA,ULUS 10188,1.02,899547136,6829b361,bb2d9eeb307988bf42775dadfb3cdce5,d62545e21ec1c7e77f5e84e71c4e7df0f1a293cb -30635,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,Italy,ULES-01080,1.00,632553472,a5d370dd,08d3458911c2ef76a75ce4839eeedc86,69cace682df04092e501e16adb139459ddb78cea -30636,Sony PlayStation Portable,PES 2012: Pro Evolution Soccer,,Games,Europe,ULES-01540,1.01,1306951680,9c3fe267,eb034b6a39b314493b4bbc8eacee4e34,d93ac5bbc9cd99e814bf05f37bdca4b634d6b026 -30655,Sony PlayStation Portable,Buzz! De Slimste van Nederland,,Games,Netherlands,UCES-01217,1.00,836403200,2f364eb0,5f2858e0eda00bc01cd0f17c24d300a5,8f4f3905d1f56f5b37c5477aaccd94757fdd914b -30656,Sony PlayStation Portable,FIFA 09,,Games,Netherlands,"ULES-01141, ULES-01141/P",1.00,1200586752,2613a5d9,ef5e1d35fb86051f7b56ac66728b0597,dc8fc9b12c7feffb3ceca1f975e322da3187c1a5 -30674,Sony PlayStation Portable,Tenchu: Shadow Assassins,,Games,USA,ULUS-10419,1.01,813891584,1c32b563,583aeefee87077d8439ebefc5ab9db7e,bc777b1d2570b2353b7cc94845009101c13a41f2 -30675,Sony PlayStation Portable,FIFA World Cup Germany 2006,2006 FIFA World Cup,Games,Europe,ULES-00340,1.02,1291124736,c191129d,321373d7de03ca66fd98e02a6c358d04,2656e5bcb1d941bb9a2ff3cc8bf9add33cf07181 -30676,Sony PlayStation Portable,2010 FIFA World Cup South Africa,,Games,Europe,ULES-01412,1.01,1617526784,53b877c7,4b97a12df6bd6d6e44244c6ab3cf284b,94fd7d5dc8ba15be02fb1a1d6e593879174084c5 -30677,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,Netherlands,ULES-00562,1.00,1447002112,94ec0b0c,73fd1611c55ee07d0b7f208bd37028da,2d8e674f506296502f02d971a487c78336862d84 -30678,Sony PlayStation Portable,Call of Duty: Roads to Victory,,Games,Europe,"ULES-00643, ULES-00643/P",1.02,639926272,e9331bb8,b99b323a1dd53af941b7db66d76094d2,bdc713e37f2f6bbf91af0c3f4adcd1f8d90973b5 -30681,Sony PlayStation Portable,FIFA 07,,Games,Netherlands,"ULES-00459, ULES-00459/P",1.02,1193967616,c2e147e0,d829f2c19526a36fa831cdac0a9d792d,e1ba2a12d721a4ca4a599fda6a2b38aaf7ad28b7 -30682,Sony PlayStation Portable,PES 2010: Pro Evolution Soccer,,Games,Europe,ULES-01353,1.01,1033306112,1c1e2a32,aefb8384799c3abcd4920eae5b3b71cb,c17a2f2729ab74a12ea0eebbdb4682c8f696db60 -30683,Sony PlayStation Portable,FIFA 06,,Games,Europe,"ULES-00161, ULES-00161/P",1.00,1190461440,32021632,723dd7ef2b5f1a34375d6cc918a63efe,0a076abd50dd924a03882e2aed0ddbf41116543e -30691,Sony PlayStation Portable,Street Fighter Alpha 3 Max,,Games,Europe,"ULES-00235, ULES-00235/0990834, ULES-00235/E",1.01,246808576,b7b8d744,5f58de7e83a0270bead43103f6c0136e,6562c25bf07bc81ebcf7375105ec5bcce7daedc3 -30714,Sony PlayStation Portable,LocoRoco,,Games,USA,UCUS-98662,1.00,589758464,c7a025fe,5010f792397bf71a421aef2c2d047491,6871506b0f6b91cfc9c813e872495b5dbae407bc -30741,Sony PlayStation Portable,Gretzky NHL 06,,Games,USA,UCUS-98627,1.02,874840064,26a8df0a,b240eebd79ede69948e33883c60a2cfb,4b68cf4c1b933c0623986787e9aa95f16537bcf5 -30742,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,,Demos,USA,UCUS 98677,1.00,351240192,4b7caf9b,bb0189b142204a7c7ad582c0e81c45a1,d0bfd28d9128054e47f36656bf67d225bc6175f7 -30743,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,,Demos,USA,UCUS 98691,1.00,351240192,6f41296c,f8f9534b455f3e460be7582c01bef0e6,abfaef9a9444571f750c868c8653fdfd7f7e564d -30745,Sony PlayStation Portable,Gran Turismo,,Games,USA,"UCUS-90691, UCUS-98632",2.00,1097826304,1eadb6b4,b03396f1637dfafd4596e392fcb37368,80003ebc446c6b38e8431761984588db2a3c8158 -30759,Sony PlayStation Portable,Tony Hawk's Project 8,,Games,USA,"ULUS-10197, ULUS-10197GH",2.03,1494056960,280dc966,e2b5355332c76ed47f67102546abefbd,3b125f3732c07e75476bb3410292a2d620d1274a -30760,Sony PlayStation Portable,Dragon Ball Z: Shin Budokai: Another Road,,Games,USA,ULUS-10234,1.00,529432576,90444e43,ad070dfec1ed0b4b4d963b3d731ae2ff,bc69cecd8e52bdb69f357dd1105767b536bc5a6f -30761,Sony PlayStation Portable,SWAT: Target Liberty,,Games,USA,ULUS-10314,1.01,878837760,5c222f21,5b57bac2288d6f0d3f696343903d386e,b260103c6bfb667c3d14c462c5fe09c0d6cbe78e -30801,Sony PlayStation Portable,Final Fantasy: 20th Anniversary Edition,,Games,USA,ULUS-10251,1.00,198115328,279ad1f4,86a3476e8f05aefeee90579b69dd9ffc,30c7b61bcb39599b41c19dc28ea69db90c342b9f -30802,Sony PlayStation Portable,Kidou Senshi Gundam: Gundam vs. Gundam,機動戦士ガンダム ガンダムvs.ガンダム,Games,"Japan, Asia","ULAS 42147, ULJS-00165",1.00,896401408,d21e984a,0e7269a7b74c832501d4f4be97a552b7,8204e5dbb55c9b820265df9c6b0511d5194ff326 -30803,Sony PlayStation Portable,NBA 07,,Games,USA,UCUS-98644,1.00,623869952,b9c970a5,80113770a384dc1ba7d0245e491dcb72,9b1b03b9718192949ffbace11b5f8583b21a26c5 -30804,Sony PlayStation Portable,Puzzle Challenge: Crosswords and More!,,Games,USA,ULUS-10120,1.00,88178688,2299f5c3,43dd9dfc4a876a5e4ad538218172d613,c5d514562905b39a53c9cf6be8c787560337710c -30805,Sony PlayStation Portable,Ford Bold Moves Street Racing,,Games,USA,ULUS-10159,1.01,734003200,4221a7d4,75d0c5666fe9864e6d726c1a8073181d,83d9b22aaad10114059faf4268af2e645dd52716 -30806,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,USA,ULUS-10247,1.02,906362880,b000752b,7ba9cde6cc4f4792b444776088f1fb2c,718d96efbdce5a283853cd570e49cbac81528349 -30807,Sony PlayStation Portable,Napoleon Dynamite: The Game,,Games,USA,ULUS-10305,1.03,657883136,b0bec28a,8a912fa3388355fb72314d275486b2de,853dbe779cf39d46de37d54a2d5c140659f343cb -30808,Sony PlayStation Portable,Medal of Honor: Heroes 2,,Games,USA,ULUS-10310,1.00,1226768384,51d20dbd,d194f91fa73d40efce874c1ad3793623,8539eb68cab24694b544c22e436f906ab9e21b86 -30809,Sony PlayStation Portable,Madden NFL 09,,Games,USA,"UCUS 10352, ULUS 10352",1.00,1353154560,9869e698,911db6ba7aa3a4d1451b6193efe186ae,f5a2f5ad8b0675973dd62ebc5e4687463475bcb6 -30810,Sony PlayStation Portable,Split/Second,,Games,USA,ULUS-10513,1.00,1616379904,607ce2c8,b385b2132ce15ba72ee9aa4c474ca08f,9d3990177b330d77b8fc228b1e326d7ad85ad8ad -30863,Sony PlayStation Portable,Lumines II,,Games,USA,ULUS 10183,1.00,1179385856,04e9427b,e66e6bd21e1052e06c2ad7ff483afded,cdef00d92935ee0671c99bf2f587c48a43259f52 -30864,Sony PlayStation Portable,Carol Vorderman's Sudoku,,Games,USA,ULUS-10126,1.01,429654016,340587db,a1d7b1e96afdbb22143681d2eb58fad0,05c70ccc8787e6c5d50dd19611185b7805f29800 -30896,Sony PlayStation Portable,Ratchet & Clank: Size Matters,,Games,Asia,UCAS 40145,1.01,961282048,5e75fb77,b4d81511f7aab490c88463be8f607633,8d8896933a6e00495cc9c258051f66accb8e1ce7 -30897,Sony PlayStation Portable,Power Smash: New Generation,パワー・スマッシュ ~ニュー・ジェネレーション~,Games,"Japan, Asia","ULAS 42038, ULJM 05079",1.01,430276608,b8cd5abc,91e8080ee3793a80d7d9b71ec9b9031b,88e18942dd688e4afab3404e15cefc75c1aa06e2 -30898,Sony PlayStation Portable,Metal Gear Ac!d²,メタルギア アシッド2,Games,"Japan, Asia","ULAS 42035, ULJM 05047",1.05,917667840,e03f2a41,53b437d87bbf5d5dff20c1830963a3ad,1ff6f9870d4467e53ead0db52355867af1b23d2c -30899,Sony PlayStation Portable,PixelJunk Monsters UMD Limited Edition,,Games,Asia,UCAS-40261,1.00,165740544,d2f41849,7683e54764b9224de0483ab984604043,cb3986490e0b683902c60110cff20088495d5456 -30901,Sony PlayStation Portable,Tiger Woods PGA Tour 10,,Games,USA,ULUS-10420,1.00,1474101248,49002737,ca1ba41ee0e101b89873decb2495eedf,d0bdea19f0a099e10ab36e59d85f1a14cef0a578 -30902,Sony PlayStation Portable,Crazy Taxi: Fare Wars,,Games,USA,ULUS-10273,1.01,906330112,383e40df,61a631a2e65b7ee207e009d4682475aa,80339d49f393951d62da523158ea351532aa6be7 -30922,Sony PlayStation Portable,Hannspree Ten Kate Honda: SBK Superbike World Championship,,Games,USA,ULUS-10300,1.01,280264704,bc2e5bec,440298e880da832478f75f2b6d1d6c16,05d9264081794fcecb4daddf3e1127dcb6fe184a -30923,Sony PlayStation Portable,SBK: Superbike World Championship,,Games,USA,ULUS-10395,1.01,513998848,42882126,882fa484edb044b1e8668e9d8d12cf86,8e0389233d6e5e58daa6e41e0363e129cd37a082 -31087,Sony PlayStation Portable,WWE All Stars,,Games,USA,ULUS-10544,1.00,1601404928,ea40281a,bef12ea3cd95c9379f661f10e2268943,10dfccb779dce8449dd6e4333e87ce2e2a763439 -31088,Sony PlayStation Portable,Naruto Shippuden: Legends: Akatsuki Rising,,Games,USA,ULUS-10447,1.00,763756544,432136c3,fd36bc91ab4828ce4d75d11e3ee092dd,02c76d796dc9ef3231d8271f29cb63bb71fc549f -31089,Sony PlayStation Portable,Gurumin: A Monstrous Adventure,,Games,USA,ULUS-10228,1.00,1064009728,ce8381ff,5539e5beb44b2873e13cd541a2d9ba47,ee621dfc2d9b603fea8067611ce137a2988674d7 -31334,Sony PlayStation Portable,Platypus,,Games,USA,ULUS-10203,1.01,76054528,aa3dc13a,b914e5adc3f9c4ade2b611fd142abbaf,252bb338e3453cc30fad943f4f934b7ac8a2ac24 -31956,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,,Games,Australia,UCES-01452,1.02,929890304,ccde4421,e004d555ea2cf2820faea1c9d0f92d6e,1a1289f35ba0707c39c17c81b48317c821c85ccb -31957,Sony PlayStation Portable,Buzz! Brain of the UK,,Games,UK,UCES-01196,1.01,776994816,eea9614e,e5c1544b4fcc5bf15ee04c41dac0fb04,75bb9722c6d1176f286ee7509ac70c6cbad56f34 -31958,Sony PlayStation Portable,MTV Pimp My Ride,,Games,Europe,ULES-00960,1.00,833093632,5b8b6f7a,d7c753de8e4d9a0e0544e4a85a67efe8,2ecef6e880ec471e584e7ae4027527bc35a12f6e -31959,Sony PlayStation Portable,EyePet,,Games,Europe,UCES-01462,1.01,810483712,f0a1c328,a56941d7f55638024a9d7491f08ae104,08ca2c2b2e5bc6eb348cb05f84989cc0efea1618 -32007,Sony PlayStation Portable,PES 2013: Pro Evolution Soccer,,Games,Europe,ULES-01580,1.00,1289027584,7e8bbefc,8add691ca0644ed937d74b77dd278e9b,25b943620df5daa0dc614c0d5ca3e1081fa1fa79 -32009,Sony PlayStation Portable,Battle Royal,,Games,India,UCES-01496,2.01,193429504,0f4c4357,466edb6427ad95d405c33831db12e8b0,ca59c59695096b9b9058aa8105dd4f832a9f9c3b -32010,Sony PlayStation Portable,Ratchet & Clank: Size Matters,,Preproduction,USA,UCUS-98695,1.01,105512960,35dce0a9,ec302ef8bd5994bdb7c5e88449fd91e8,c00299f708409a1509279b711083549e541f560e -32011,Sony PlayStation Portable,Scrabble,,Games,USA,ULUS-10412,1.00,70811648,8e83d1dc,5e4531da53ce4f59ffacea561b10ae55,16ef777afb2cbd4ff7be4b0d908250ba636db523 -32012,Sony PlayStation Portable,Don 2: The Game,,Games,India,UCES-01585,1.00,656769024,9217f6c2,3e1a15a70f5e7adbc0c9bd488339896c,1c49e04b3bdacdbf3a309c06d3243178b0cbb6d6 -32013,Sony PlayStation Portable,Desi Adda: Games of India,,Games,India,UCES-01279,1.00,542441472,7d33a441,a2559c186ff3df6cdc78d5967e635a65,f78beb04da0f0bc433319e08f60dbc86c1c3c303 -32014,Sony PlayStation Portable,Marvel: Ultimate Alliance,,Games,USA,ULUS-10167,1.02,1773764608,a319d3bb,b126e3a6d9da9833ec6cd55fcfc2863a,3ecdd11baa932bc13a68fd7e3cc313ce34ce611c -32057,Sony PlayStation Portable,Def Jam: Fight for NY: The Takeover,,Games,USA,ULUS-10100,1.01,1576894464,a5b5ec8f,3680b5ba48b4eb08be2623eff78f41b3,a77b43a4dc7797e09653b25406a3fcf24d32b96d -32116,Sony PlayStation Portable,Tony Hawk's Project 8,,Games,USA,ULUS-10197,1.00,1506312192,34bcb2c6,80a1482ea254eca0ef50cffe6ffb09f5,ced3f874f56e16ee5c4bcf51a862534a9671d2c1 -32196,Sony PlayStation Portable,Growlanser,グローランサー,Games,Asia,UCAS 40257,1.01,1293516800,7b577e55,dd45504f15d8c7b8e757d9a41f7629fe,db0c5dffe259ccb032e70f401c599d67189eaead -32303,Sony PlayStation Portable,FIFA Soccer 13,,Games,USA,ULUS-10595,1.00,1666908160,e8054f99,72d0f2149f80e31a2fd3be9841d38ed3,bba382cfd96abb8e121d378f999cce3c3e765051 -32304,Sony PlayStation Portable,PES 2012: Pro Evolution Soccer,,Games,USA,ULUS-10586,1.01,1805778944,cdeba00f,0a0d43a152387212125fce633e25361d,ed28b91fdf79a9b48a3b32d44f9adcde254958b6 -32305,Sony PlayStation Portable,FIFA Soccer 12,,Games,USA,ULUS-10583,1.00,1666908160,4e70022f,5a2ad56ab0ad66a561af5dd20469144e,418cceb5e1e266f1526125836964d33988b8d516 -32306,Sony PlayStation Portable,2010 FIFA World Cup South Africa,,Games,USA,ULUS 10504,1.01,1757577216,9e9b7073,e32ef0b6277fe33be328b79087cae0b6,8d958134a3943e14333dd877909df429d79d31bf -32307,Sony PlayStation Portable,LEGO Harry Potter: Years 1-4,,Games,USA,ULUS-10500,1.00,1425866752,2ecef3d9,9576a73d5ddae9a8485305539ebe3e93,5b407ad06cec934931ae501c5cc44024303d7f34 -32308,Sony PlayStation Portable,Ben 10: Alien Force: Vilgax Attacks,,Games,USA,ULUS-10488,1.00,1568047104,db8d0a28,245cdaaa5fc275820a15dc9ca4797d2b,de7476e7d878516840c5e6a9dd4233abdfcd5ffd -32309,Sony PlayStation Portable,NBA 2K10,,Games,USA,ULUS-10474,1.00,1519976448,33827b45,0cecbb92976b56fb262d408f0a4c3ead,e4786bfec0ce7dc174ef6f5a3f36047d5c5cc781 -32310,Sony PlayStation Portable,NBA Live 10,,Games,USA,ULUS-10465,1.01,1683587072,55bce6ae,d8ca378d156b342988f9cfd6923a31d6,ee5e6747cb99c9dcb4a708cafa7277591c91ecfa -32311,Sony PlayStation Portable,Shadow of Destiny,,Games,USA,ULUS-10459,1.00,1098252288,5636637f,3dcadf40a8bcd4ddcfc7c7b51001364e,756058f70d1cffee6a2b075b05e3e8c232acfea4 -32312,Sony PlayStation Portable,WWE SmackDown vs. Raw 2010,,Games,USA,ULUS-10452,1.00,1577025536,ec2222c0,ac1fa71d9c115d3f5b5e8e4de862bc5e,1aa5c90a305476d98fa136bb1c5e55e0b833a0dc -32313,Sony PlayStation Portable,Cloudy with a Chance of Meatballs,,Games,USA,ULUS-10444,1.00,963182592,c5a709e3,fac166d1d51b8da5b822a195ed2c2819,c74dcb27040646ae8e2712f6e373c7f5f78edc98 -32314,Sony PlayStation Portable,Madden NFL 10,,Games,USA,ULUS-10441,1.00,1434812416,f24af217,edf9f58547dd8eced0cca0af21713b17,0f5297a4c44f231d07bc4415946962ff5b969456 -32315,Sony PlayStation Portable,NCAA Football 10,,Games,USA,ULUS-10440,1.00,1805942784,33c31bab,120c9b7370be4ea4d6e9066461c207c9,8980851283575df7cd2e47ce823a0b632c33cbb2 -32316,Sony PlayStation Portable,Disney G-Force,,Games,USA,ULUS-10439,1.00,1230602240,d6784746,b5e9ef52852d5054dba8f8606d65518a,e1c41d1a6b3488c756a30c65ff940425943a4c9d -32317,Sony PlayStation Portable,PES 2008: Pro Evolution Soccer,,Games,USA,ULUS-10320,1.00,1362591744,09747656,c3c258fb99fdf485169b0f8355e9fb4d,125a4bdb09808988b9882979fada22dbe11876dc -32318,Sony PlayStation Portable,Lara Croft Tomb Raider: Legend,,Games,USA,ULUS-10110,1.02,1514995712,4b265d15,dae97bb942b814f8ddb977e92214e8bc,60173093b2bb221a0e21b2bcfdb9759db1c58b0e -32319,Sony PlayStation Portable,PES 2009: Pro Evolution Soccer,,Games,USA,ULUS-10388,1.01,1435500544,a8d52b6a,bca3aafcd636b351f9aaefa4b751381a,e232e73674403d25c35bc3cffc697722e2a191f7 -32320,Sony PlayStation Portable,Star Wars: The Clone Wars: Republic Heroes,,Games,USA,ULUS 10477,1.00,1478393856,fcbb6cac,3b653f92e74fd96b534e2f1616da7fca,d0042c42699c7c18e82f9df789645c602a9f7ddf -32321,Sony PlayStation Portable,NBA 10: The Inside,,Games,USA,UCUS-98738,1.00,1087471616,9f7a72c6,5f8f016f50a6cf9ec36f6436f513b996,c19df1245e40148bd252b45c799208bb93cdf3af -32322,Sony PlayStation Portable,Ape Escape Academy,,Demos,USA,UCUS 98629,1.00,388792320,594abb2a,c57ef7d7b93ad204382a3e74a2b4fd1f,e0059f0c819e4d5e1ec221fbcb493dbb82d70bd6 -32323,Sony PlayStation Portable,Blood Bowl,,Games,USA,ULUS-10516,1.01,233734144,c308a726,ac01677323456caec069850f3a975c7c,976a25f22a789ced44071e079e66d55fbf156a38 -32324,Sony PlayStation Portable,Disney/Pixar Toy Story 3,,Games,USA,ULUS-10507,1.00,905805824,eaa1ef9b,b7e5717435c0581c67a6166a98fc3c2b,6aa38299e61d51ee26cf1a632717ad15f2f66a62 -32325,Sony PlayStation Portable,"What Did I Do to Deserve This, My Lord!? 2",,Games,USA,ULUS-10494,1.01,324993024,d8aae54d,daad34a56f566096543bd8c08aa81406,724606728e2a02a4a704f92fd15d9037bec0126e -32326,Sony PlayStation Portable,DiRT 2,,Games,USA,ULUS-10471,1.02,365035520,11d44644,e488c4f5c5e1af737121d1e622391731,9c9c01c21478e5a6cb2a40516903473dc91184cd -32327,Sony PlayStation Portable,F1 2009,Formula 1 2009,Games,USA,ULUS-10449,1.00,684359680,815baafc,8115a43c47c2cbf41350ddd55867a77e,3809c049d51f2e154e3b6255d323dc5b12a233e9 -32328,Sony PlayStation Portable,FIFA Soccer 11,,Games,USA,ULUS-10550,2.00,1752334336,3ce31dd3,e424fb53f4f682c84422dd440eab45a0,c06b50eafecc37aa5de3500f759276f44bbaf554 -32329,Sony PlayStation Portable,Disney/Pixar Up,,Games,USA,ULUS-10430,1.00,556269568,25ff3599,31d050526b1fe94b8aaeaeaf4d3cefcb,09a635cd33da1c692ad21bf2dc60f8dfc56f9176 -32330,Sony PlayStation Portable,The Secret Saturdays: Beasts of the 5th Sun,,Games,USA,ULUS-10443,1.00,841515008,2ccbcd81,991955562e0583c5ee00c800352cb75b,93563e34f21566c28194da6e71469315c6ed2dcf -32331,Sony PlayStation Portable,Disney/Pixar Cars: Race-O-Rama,,Games,USA,ULUS-10428,1.00,906330112,f8da4ca3,ff1245931d8966ce27ec3bd8d390443e,ae8bd569e1968a817f517b45ece0aab6a2d717eb -32332,Sony PlayStation Portable,Brunswick Pro Bowling,,Games,USA,ULUS-10283,1.01,167641088,cd9ce4d0,9ab14ed36f42d1fdc80d3ba9998f685c,58849d7e4fade0d846df295e25ebe0affd16f269 -32333,Sony PlayStation Portable,NASCAR,,Games,USA,ULUS-10122,1.01,737935360,3be09eb0,091900886c9343f77ef3244c0081ebb2,7822f529fc6ea12a5bbbe16e417af39a764aed80 -32334,Sony PlayStation Portable,Payout: Poker & Casino,,Games,USA,ULUS-10118,1.02,202244096,68cc27f8,ff7380faf46d05e03d23799fd8e995a1,b342f33129e2338204606d5bc4859a18e5c7c9d3 -32335,Sony PlayStation Portable,Cabela's Dangerous Hunts: Ultimate Challenge,,Games,USA,ULUS-10106,1.01,450199552,957e0f34,f4a2496518be162953bedf2ecef28e3a,9e54b3acc31d47c0851abbed2b937b17dfa01bf7 -32336,Sony PlayStation Portable,Disney/Pixar Cars 2,,Games,USA,UCUS-98766,1.00,732397568,7b2ad8d3,253c04055baa19a066a77d134517f8e9,1eeb1e1975d204692078d509a35cf9ad776b8303 -32421,Sony PlayStation Portable,Invizimals: Shadow Zone,,Games,USA,UCUS-98760,1.00,1778810880,b4da0fcb,e25f7070c650e6507b67f07b63416059,66f5ccff04361b87aa93d68fc1d0c647f42135c2 -32478,Sony PlayStation Portable,NBA 08,,Games,Asia,UCAS 40181,1.00,906330112,ae832ca5,0d26a3f37c6e70486b1b28e768eaa8fc,dd93a36353b30ce5a6566b583f3d4b750caec616 -32479,Sony PlayStation Portable,MLB 09: The Show,,Games,Asia,UCAS 40249,1.01,1454997504,c2d9bf27,d0938614840094a9542f0f12bd805c6f,938b76a08e0575eebc92f988f418f71343427f90 -32507,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,Europe,ULES-00741#,2.00,906362880,66a6ca59,0898d90ab8e0fab687f022edebf47a03,c15bcd15e57419e998bbc260f6b66469efd3e4b2 -32609,Sony PlayStation Portable,PQ: Practical Intelligence Quotient,,Games,Europe,ULES-00358,1.01,184025088,e06bb921,5ac7daf5d1fc4f4afe63cf431cf29690,0a43a5e10297037216c0871bf7a0ba27895d5c94 -32610,Sony PlayStation Portable,Ys: The Ark of Napishtim,,Games,Europe,ULES-00267,1.03,733413376,a700ac82,9776ae3f66a5ad5a8a7f85ae394cc6cd,8217cb287e1d49e667a6bf2da3ed4a62a10c6a23 -32611,Sony PlayStation Portable,Valhalla Knights 2,,Games,Europe,ULES-01265,1.00,1069907968,93b0ef2a,a2018700508593f60cabc32244bed6ac,2259f90ae07582337a8d0caa2f13c0f83fa81f53 -32612,Sony PlayStation Portable,Prinny: Can I Really Be the Hero?,,Games,Europe,ULES-01278,1.00,529989632,2bd19cd7,9cad28ff6dd15d817c2e57512acf7886,87a97f595140c284db808b36ce05f106f967ce18 -32615,Sony PlayStation Portable,Soulcalibur: Broken Destiny,,Games,Europe,ULES-01298,1.00,900923392,7089d77a,7677186558f4fa1b0387fddc879a5a3e,02236191a2012f5a8d888c30584a299413456b4d -32616,Sony PlayStation Portable,Mana Khemia: Student Alliance,,Games,Europe,ULES-01215,1.01,1085800448,4a5d98bb,8d5a8bbce60929f329774ca2928bbf8d,ce82425c772097f215551a720521c6fcbac462a5 -32617,Sony PlayStation Portable,Football Manager Handheld 2012,,Games,Europe,ULES-01555,1.00,216793088,10482ed8,5a8d302d5257a3fb656e327db884ff14,7f8874da62692481fd07ff0c3b8352221adabdcb -32660,Sony PlayStation Portable,StateShift,,Games,Europe,ULES-00776,1.03,210534400,45d3d63a,867ba943d72cf65a2cbd971fdc395ca0,7cf470cc579c262ebbdcad67cefbad3c2a749c87 -32693,Sony PlayStation Portable,Valhalla Knights,,Games,Europe,ULES-00657,1.01,697008128,def71c3f,b64f34ef2b64703a261a316a4894ae61,e28f591c0dbb61ed59b3b15923feed19227dd899 -32732,Sony PlayStation Portable,Initial D: Street Stage,頭文字D ~STREET STAGE~,Demos,Japan,ULJM 95001,1.01,1187938304,4a79dca1,e743f16ee023f07cd6fbb62318bf43c9,4cea098c3cbd08d650caf42cce2b2cece6d2428e -32767,Sony PlayStation Portable,FIFA 12,,Games,Europe,"ULES-01543, ULES-01543#",1.00,1293582336,a7dd3062,ba7414e06b807cc2f61f9f792368f102,2f576ba77059b63bfa692310fb90ce2f32c47652 -32792,Sony PlayStation Portable,FIFA 09,,Games,Europe,ULES-01142,1.00,1349713920,26a02bfa,b11be4ab48948ce6e674b2d560fd9600,373817830d2f55e481eb0550a32a84e3dc69bf7a -32793,Sony PlayStation Portable,FIFA 08,,Games,Portugal,ULES-00896,1.00,1264320512,87497a89,04a3c2178bac4f755575a3bac256e9b1,759400a37585557264275b0d396f96daf0d957a9 -32794,Sony PlayStation Portable,FIFA 09,,Games,France,ULES-01136,1.00,1275854848,1a3d79e4,48df09dc921f04ac453ebbf878f610ce,00253335202d9be1e7626198c6b81ae42586334d -32966,Sony PlayStation Portable,Harry Potter et la Coupe de Feu,,Games,France,ULES-00214,1.00,415170560,989e77d1,058c266e2c85550fdbdfb9d012033a0d,a3a152292da6db4d1b3a4f68adc3eef1ffad16cb -32984,Sony PlayStation Portable,Harry Potter and the Order of the Phoenix,,Games,Europe,ULES-00831,1.00,832405504,27c25d0e,788888e9e0dd5078a7cdcf512237d7b4,908ae9f5bc92161927ed6cadb106c3070dc33aeb -32985,Sony PlayStation Portable,Il Padrino,,Games,Italy,ULES-00399,1.00,1373667328,36f01162,dbf1d3e674186734519ecea68c419a62,21632e636d3e107b52093812b736ce0d59461200 -33006,Sony PlayStation Portable,Minna no Golf Portable: Coca-Cola Special Edition,みんなのGOLF ポータブル コカ・コーラ スペシャル・エディション,Games,Japan,UCJM 95401,1.01,450723840,f6159ab0,9964a8b7e347836162674cb70a44b66c,b326e86f77f82af1c4b6633a07d8a2ac80352783 -33007,Sony PlayStation Portable,Need for Speed: Carbon: Own the City,니드포스피드: 카본: 온더시티,Games,Korea,ULKS 46034,1.00,894074880,e5737a40,091bf3dac94456d713193b18b0e29098,4ea8f1ce62a80da7c9e2b4755fca54be85518ef3 -33008,Sony PlayStation Portable,Gitaroo Man Lives!,기타루 맨 Lives!,Games,Korea,ULKS 46071,1.01,1673691136,898f89f1,11e399fcfe4827f85a71ead46d094cfb,d9c3051baaa20bca9522c1db2d7c5c00482127fe -33009,Sony PlayStation Portable,Win-JPT: Ilboneo Chogeub,WIN-JPT 일본어 초급,Educational,Korea,ULKS 46033,1.02,1669300224,bad9ed28,e45c902f056c11edb321d8c46fa821c0,41ea05082b23d7d21fad20d33c561633bb28d96d -33010,Sony PlayStation Portable,Untold Legends: The Warrior's Code,언톨드 레전드: 더 워리어스 코드,Games,Korea,ULKS 46069,1.00,946339840,9ec5fb68,ffd93a89feb4a84eaaf6c39322e78182,eb83b48611930368ae3f54ae99a2016812aa2cb1 -33011,Sony PlayStation Portable,Singi Hwansang: SSII Unlimited Side,신기환상 ~SS II 언리미티드 사이드~,Games,Korea,ULKS-46094,1.00,1168605184,304ab64e,62428a5e80cec7ed6e17ced452c76ea0,b3d0a6ed2df51284fa8e06483f473ea69ab133b8 -33012,Sony PlayStation Portable,Castlevania: The Dracula X Chronicles,캐슬바니아: 더 드라큐라 엑스 클로니클,Games,Korea,ULKS 46155,2.00,1111359488,c64f4b94,4f90c19c30c893eeaddf4948ecd6ab5f,7b2e93c81627568072f31dd1989b4927f484862e -33013,Sony PlayStation Portable,Ridge Racer,릿지 레이서,Games,Korea,UCKS 45002,1.00,906362880,800bf25d,9803b37fee5c7e40e3a42b94c26afe6b,f5ff6a1fde948618ac4bcdd773f4e76e893a38a5 -33015,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo,소콤 U.S.네이비 씰 파이어팀 브라보,Games,Korea,"UCKS 45021, UCKS 45061",1.00,592674816,90ccc603,637ef54d7a35cb355c3c70046ab84adb,83d489ecbd99e1caf08217ccf85514569667e414 -33016,Sony PlayStation Portable,Valhalla Knights,발할라 나이츠,Games,Korea,ULKS 46133,1.00,687964160,f7b031a5,fb1eca38889784b8db56fa110710a193,ae0aa8f3854ec4b8101d20aca05f39d51748c87f -33017,Sony PlayStation Portable,Secret Agent Clank,시크릿 에이전트 클랭크,Games,Korea,UCKS 45096,1.00,1222705152,122311e6,4a8d0953831d1e98e88f55f0d6fed105,aced61866357208f5b678821374f4d280fd72048 -33019,Sony PlayStation Portable,WWE SmackDown vs. Raw 2007,WWE 스맥다운 대 로우 2007,Games,Korea,ULKS 46125,1.01,1673461760,78919e9e,8a7068de184ab57215c09495cae8c49c,0bfe51a65b170e576e38c2831824a5baffdec5eb -33020,Sony PlayStation Portable,SNK Arcade Classics Vol. 1,SNK 아케이드 클래식 Vol.1,Games,Korea,ULKS 46179,1.02,1397620736,d0745dfb,920510bc4e60ee515d89f02c1d06ef52,c5ac2809776c476dd2187a0e918898c6a967eb26 -33029,Sony PlayStation Portable,World Soccer Winning Eleven 10: Ubiquitous Evolution,ワールドサッカー ウイニングイレブン10 ユビキタスエヴォリューション,Games,"Japan, Asia","ULAS 42088, ULJM 05132, ULJM 08015, ULKS 46120",1.03,1155956736,9b9704b5,87b5218adee1474c3b6d138ec6fbb392,2c62c79930ebeb975688eda3738c99356e70a198 -33030,Sony PlayStation Portable,Matching Maker 3 x Tousouchuu,街ingメーカー3 X 逃走中,Games,Japan,ULJS 00242,1.03,146702336,ae4033f6,5ed97920d9458ee78282cb6da7665e92,cddb8a7dfba97462f7526a7c79b41ffba41337ff -33031,Sony PlayStation Portable,Ookami Kakushi,おおかみかくし,Games,Japan,ULJM 05413,1.04,1645674496,d4769a8b,7f1f45896a1883a1ee4ba7b5463778bf,16648dd33c18cc9982e3ab92eddf9ac70870114b -33032,Sony PlayStation Portable,Naruto Shippuuden: Narutimate Accel 3,NARUTO-ナルト- 疾風伝 ナルティメットアクセル3,Games,"Japan, Korea","ULJS 00236, ULKS 46229",1.00,644841472,674025ae,31b74d7933c18b267d6c738bbbd5df60,875540e164878f6d5684d97d5dbd3c98e60d9e20 -33033,Sony PlayStation Portable,Riviera: Yakusoku no Chi,Riviera ~約束の地リヴィエラ~,Games,Japan,ULJM 05188,1.01,619741184,e5c98198,4c10968c6f9b5ed43adc0044d6198fa6,c67ae4c6ccfcd74afac249b09ac7096a8c049399 -33034,Sony PlayStation Portable,Mite Kiite Nou de Kanjite Crossword Tengoku,観て聴いて脳で感じて クロスワード天国,Games,Japan,ULJM 05168,1.01,1054179328,18edc8ae,fc5a585c0b8b976320c174b1e092703c,f59ce3c10f610ab5f495e29da95dd4fd86efd1b7 -33035,Sony PlayStation Portable,Kidou Senshi Gundam: Gihren no Yabou: Axis no Kyoui V,機動戦士ガンダム ギレンの野望 アクシズの脅威V,Games,Japan,ULJS 00178,1.01,1408434176,4059c61f,8a8fbdebf6964b645ebc6bb4bbf7d6a7,f80504bd4217445f83961c1e4402e6e119faecdd -33036,Sony PlayStation Portable,Densetsu no Yuusha no Densetsu: Legendary Saga,伝説の勇者の伝説 レジェンダリーサーガ,Games,Japan,ULJM 05588,1.01,396328960,95044ab6,96ad39e9d1c063e837c6e2b714f8f6b7,de2d373f72bdcc52ea1fd49996f7f83962c56341 -33037,Sony PlayStation Portable,Minna no Golf Portable 2,みんなのGOLFポータブル2,Games,"Japan, Korea","UCJS 10075, UCKS 45074",1.09,922025984,e909ce15,7c94ccb94b3bb336095af3de0fd912cb,9bcb9a4db12974f6307b3a95037ca36f2ca08b87 -33038,Sony PlayStation Portable,Tales of Phantasia: Full Voice Edition,テイルズ オブ ファンタジア フルボイスエディション,Games,Japan,"ULJS 00079, ULJS 19016",1.02,507183104,ffb3c3c1,986193786969438311a41262aead541a,dbdd4bd45dea91511053b805704dd8cf3755b3c5 -33050,Sony PlayStation Portable,FIFA 08,,Games,Italy,ULES-00893,1.00,1179975680,24f04658,d74198088977d574311626fd5abb21d7,579c0b088df2f271a5f8d60e45b0520011342a39 -33051,Sony PlayStation Portable,Pac-Man World 3,,Games,Europe,ULES-00260,1.00,865271808,387977b6,7b8593b3f5f838e2dd1cdf7e55476577,ffe4264307c43fd749e8dc3f5b5de5679a265483 -33055,Sony PlayStation Portable,Yu-Gi-Oh! 5D's: Tag Force 4,遊☆戯☆王ファイブディーズ タッグフォース4,Games,Japan,ULJM 05479,1.01,1572732928,691b075f,015d84f3f0e451324c45ecf1933bdb86,199215a3e06037997ee2a509280cab1fc89f6fd5 -33056,Sony PlayStation Portable,Mahjong Fight Club: Zenkoku Taisenban,麻雀格闘倶楽部 全国対戦版,Games,Japan,"ULJM 05163, ULJM 05333",1.05,280297472,9126d98b,686e3c205344ef760e60d829d975e792,b15aabf3d4bb5dadf5dda975e49b830282e717ec -33057,Sony PlayStation Portable,Daito Giken Koushiki Pachi-Slot Simulator: Ossu! Banchou Portable,大都技研公式パチスロシミュレーター 押忍!番長 ポータブル,Games,Japan,ULJS 00052,1.01,90505216,3f35d98f,2177a7b4c762bb95b81f928483e86920,e6dd7ed5e368ecbd4ee55b6bd86a02dd0702f828 -33058,Sony PlayStation Portable,Nouryoku Trainer Portable,脳力トレーナー ポータブル,Games,Japan,ULJM 05050,1.00,65536000,2451f400,7de6c41e42bbfcb19bb3effcffd4538e,03263c066c66c575048287ee17aa6284f64fc892 -33061,Sony PlayStation Portable,WWE SmackDown vs. Raw 2008,,Games,USA,ULUS-10281GH,1.00,1785724928,3b332f76,7fab7ebe45da4b47b66fc86a75679615,e4bbc6a0372a04eae1a0c3a92d922286f06f3131 -33062,Sony PlayStation Portable,Smash Court Tennis 3,"スマッシュコートテニス3, 스매시 코트 테니스3",Games,Korea,UCKS 45051,1.00,1495662592,be8e7f20,483e1987ab64c65a8ac025d042f13486,c9aa3c38f8f70184c41f3b47944bf51bb69a7a2b -33063,Sony PlayStation Portable,Kidou Senshi Gundam Seed: Rengou vs. Z.A.F.T. Portable,機動戦士ガンダムシード 連合vs.Z.A.F.T.ポータブル,Games,"Japan, Asia","ULAS 42100, ULJM 05238, ULKS 46134",1.01,877199360,4e0f9528,0d4dd06ba223f7ff60e05d9f61483905,110f712faff9e989924276d6ba26a3d8f52b1aa9 -33064,Sony PlayStation Portable,Disgaea Portable,디스가이아 포터블,Games,Korea,UCKS 45157,1.01,1589706752,d719f057,596f29c8ccf25d2304b215af00e4ec84,ec16e02593154f7169f9f0e644528ab477cb0212 -33073,Sony PlayStation Portable,Dante's Inferno,,Games,Italy,ULES-01386,1.00,1812725760,112381b8,9cb7e8a4e87116fd26b924df53c8325a,46988f34609e8bbf0730584d44474dacf017b0cb -33074,Sony PlayStation Portable,Breath of Fire III,ブレス オブ ファイアIII,Games,Japan,ULJM 05029,1.02,403963904,9646db19,c7081c9c0865ecaeb6f4d2a42f865528,c887d7362730b9199c098a8ab8b487710b041c69 -33077,Sony PlayStation Portable,Kingdom Hearts: Birth by Sleep,キングダムハーツ バース バイ スリープ,Games,"Japan, Asia","UCAS 40295, ULJM 05600",1.02,1703510016,746d2c35,2d23c18445b1df33f64c76dd273d62d3,9c5f1ab5c60a037cc3f7481155c58046b72243d0 -33078,Sony PlayStation Portable,LocoRoco,ロコロコ,Games,Japan,"UCJS 10041, UCJS 18011",1.01,569212928,1bb09451,3385c368ab1c3cc38f4c11f7e05267c0,017baba2b8073eff94e7058fff374843f4108a84 -33079,Sony PlayStation Portable,Coded Arms,コーデッド アームズ,Games,Japan,ULJM 05024,1.03,183566336,a2b158ee,e955853939a2eb65da516083d1fead72,780b43fc7701159a4133bf279aabe5888c82b887 -33080,Sony PlayStation Portable,Zhuo Hou La: Hou Zi Ai Zuo Zhan,捉猴啦 猴子愛作戰,Games,Asia,UCAS 40154,1.00,461799424,37baa841,ed58bca4e52ad5470e982b5c5ac7797f,f8a4fd65b941add47bd449fa29826407429fe5b4 -33081,Sony PlayStation Portable,Dragon Ball Z: Shin Budokai,ドラゴン・ボールZ ~真武道会~,Games,Japan,ULJS 00049,1.02,315326464,f646b1e9,145ecd9444c474c4607daea28ee27474,8c0962d4cff4393046ab54e1be78700ea2e2e02c -33114,Sony PlayStation Portable,DJ Max Emotional Sense P Portable,디제이맥스 이모셔널 센스 P 포터블,Games,Korea,ULKS 46050,1.02,1521451008,06164a6a,48319da34ed98f85a91720cb82d6d6f3,80ef0d02e296acf09cba18cee4ac37566b07377c -33115,Sony PlayStation Portable,DJ Max Emotional Sense P 2: Sound Miracle,디제이맥스 이모셔널 센스 P2 사운드미라클,Games,Korea,ULKS 46116,1.09,1778319360,a5c44e0a,526d95c033a2389a722b243a6674859d,9018c4ab491f7314bf2bf125a3dfba2ede19529b -33134,Sony PlayStation Portable,Kingdom Hearts: Birth by Sleep: Final Mix,キングダムハーツ バース バイ スリープ ファイナルミックス,Games,Japan,"ULJM 05775, ULJM 06213",1.00,1790476288,30254453,f03e65561e17231c7510d51a30927ecd,8efcdc92e430885575646a0b279a6270bd7b8592 -33135,Sony PlayStation Portable,Tales of VS,テイルズ オブ バーサス,Games,Japan,ULJS 00209,1.02,790265856,2f6611d3,a6cbe7ce78075b303cf43b7d6126571f,73893622285fd3176c9500ea789b0915b9df5bc7 -33141,Sony PlayStation Portable,AKB1-48+10: Idol to Guam de Koishitara...,AKB1/48+10 アイドルとグアムで恋したら…,Games,Japan,"ULJS 00413, ULJS 00414",1.02,1808400384,e77bee97,ae1ff1773ad24183d6c75874746486e1,10d26042f45020b258c1b1b531ca640cf8cf5ac0 -33142,Sony PlayStation Portable,AKB1-48: Idol to Koishitara...,AKB1/48 アイドルと恋したら…,Games,Japan,"ULJS 00348, ULJS 00480",1.02,1784250368,7c09447d,fbc8c967eef355df0b1e497a6377a857,c40347f06a43d4468ebb7e1c7d46c4e36cdbd5ee -33143,Sony PlayStation Portable,LocoRoco,ロコロコ,Games,Japan,UCJB 98011,1.01,569212928,63de70f2,71150dc8464273302f3ad458a00aef81,b39f22378c95a8c575e4a927aeed07e94024166b -33144,Sony PlayStation Portable,Pro Yakyuu Spirits 2014,プロ野球スピリッツ2014,Games,Japan,ULJM 06348,2.00,1401618432,c1a3e22b,dae23384b4ae587b5cf31f8837be3987,ef56660521b5d792addb522c9d10d60cf2118da8 -33198,Sony PlayStation Portable,MonHun Nikki: Poka Poka Airuu Mura,モンハン日記 ぽかぽかアイルー村,Games,Japan,"ULJM 05710, ULJM 08039",1.02,452886528,c3aa57f7,2e763d736123518accf50bc613aef2e2,4c0840001f9f691f39102308eb6ef6759ac4d7e3 -33199,Sony PlayStation Portable,SD Gundam: GGeneration World,SDガンダム ジージェネレーション ワールド,Games,"Japan, Korea","ULJS 00363, ULKS 46286",1.02,1796210688,12183452,ffb81ccbf50e65059d230162bb1e4a93,a72a13c1a774c78c7f59df8ac5560f142b8f4232 -33200,Sony PlayStation Portable,Ys VI: Napishtim no Hako,イースVI -ナピシュテムの匣-,Games,Japan,ULJM 05009,1.05,866254848,32eba347,7a6065a5e80920d40751db116a64d7a1,16ec13fc368e8266263e0637394d7e0102325292 -33201,Sony PlayStation Portable,God Eater,ゴッドイーター,Games,Japan,ULJS 00237,1.01,1341718528,5590e3e9,a8aa9d68686abd79583c1237dbb288d9,0bf5481641b83700f1f7f6aa6159326f1c4ed160 -33202,Sony PlayStation Portable,Piposaru Academia: Dossari! Saruge Daizenshuu,ピポサルアカデミ~ア -どっさり!サルゲ~大全集-,Games,Japan,UCJS 10003,1.05,379453440,d6527bda,90734a4ce680a0a6bea1cd2010eb3728,4b5187dc1d7cd4186a1e0e1de8a696002229c24b -33203,Sony PlayStation Portable,Need for Speed: Underground Rivals,ニード・フォー・スピード アンダーグラウンド ライバルズ,Games,Japan,"ULJM 05008, ULJM 08003",1.00,884801536,7cf99541,46017d94fa54d064dd24e0f096c98f3c,14c3a3325540c7b31de7115146006ff174c0e5a2 -33204,Sony PlayStation Portable,Capcom Classics Collection,カプコン クラシックス コレクション,Games,Japan,"ULJM 05104, ULJM 05280",1.01,632979456,46db039b,6fbf977c73edbb3e90e9a3dd48230ea7,ebd04007c9e981b5c2f11bd31b5f6483d60aa27b -33205,Sony PlayStation Portable,Hexyz Force,エクシズ・フォルス,Games,Japan,ULJM 05501,1.00,707624960,6dee78a3,6e3c6f5de493c5bced5ce1a8c8493fe7,130eb9673e8e62861f5eac01b4d45ba806cf95a4 -33206,Sony PlayStation Portable,Pro Yakyuu Spirits 2010,プロ野球スピリッツ2010,Games,Japan,ULJM-05631,1.03,1578696704,dc4823c0,fd5c4221a262273b8309ab272f36737a,6e486dad220a650113faece9ac9f3cbb6c4dcf3e -33207,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2011,実況パワフルプロ野球2011,Games,Japan,ULJM 05871,1.01,1591705600,78a642af,f6f555963e7e224931bf1f6f880defad,2a2d32ba08d95f4feabee80513cc03525b364173 -33208,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu Portable,実況パワフルプロ野球 ポータブル,Games,Japan,ULJM 05077,1.02,1745584128,7c6c544e,847844b56188e36cf4b37d957a770d86,f5b3a588ac9ceaaa3fc632a0caaea87d9a2e1157 -33239,Sony PlayStation Portable,Grand Theft Auto: Chinatown Wars,グランド・セフト・オート ~チャイナタウン・ウォーズ~,Games,Japan,"ULJM 05604, ULJM 05804",1.01,883654656,6bfa2786,39369dd4699041a00832aeca8b8ed870,eae841fb5ac4149f13bae25298c634bc41a0b3cc -33240,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu Portable 3,実況パワフルプロ野球 ポータブル3,Games,Japan,ULJM 05300,1.04,1762164736,79ca40ce,db1f16eb8058652462819364eaead78a,4d8e4bf69ddf638bd2cad84da0a23e55e82e9677 -33261,Sony PlayStation Portable,Musou Orochi: Maou Sairin,無双OROCHI ~魔王再臨~,Games,Japan,"ULJM 05402, ULJM 08037",1.02,1648033792,72b485a2,db9f23e189fa1afb6f1892458294e094,2cd6149d9c65afa689046ebd8bc7505d5f638a76 -33297,Sony PlayStation Portable,The 3rd Birthday,ザ・サード・バースデイ,Games,Japan,"ULJM 05798, ULJM 06008",1.01,1466368000,adcd3c0b,688cc34138a19441044bce3d3a4c429b,45610bae21637cfd6f024b28ccc0dc0e41a25f14 -33298,Sony PlayStation Portable,Saigo no Yakusoku no Monogatari,最後の約束の物語,Games,Japan,ULJM 05860,1.01,394330112,09ab0a2b,aa03b6361d836f873e971f45c7e5dd40,b59877c6e9766cb0425f096e78b0d6301d709996 -33301,Sony PlayStation Portable,Grand Knights History,グランナイツヒストリー,Games,Japan,ULJS 00394,1.01,739311616,2e424ad4,3e0de6ac6f623004464b7d77655382b2,ba68904fecc3e0ec2d28c7723f3a70dc123640f2 -33302,Sony PlayStation Portable,Senjou no Valkyria 3: Unrecorded Chronicles,戦場のヴァルキュリア3 ~UNRECORDED ◆ CHRONICLES~,Games,Japan,ULJM 05781,1.01,1408401408,d0c3b8ae,4b1e696dbea91b8e61b02936e553ce96,6c73264f9495182db2614108250eef50fb706c00 -33303,Sony PlayStation Portable,Shining Ark,シャイニング・アーク,Games,Japan,ULJM 06223,1.00,1627127808,dfd7b472,976f8e7916d6488bfb93ca545ffe1e91,5a8b79ac18001567ad5bc604416bfe1b441494bf -33341,Sony PlayStation Portable,God of War: Ghost of Sparta,갓 오브 워: 고스트 오브 스파르타,Games,Asia,"UCAS 40323, UCKS 45161",1.00,1709441024,6b29ee29,6e96f0819820b5108b581703f3d64ebf,a953b27fb0a81d528898eeb7cdc6bdd844a5c6e5 -33346,Sony PlayStation Portable,Kidou Senshi Gundam: Gundam vs. Gundam Next Plus,機動戦士ガンダム ガンダムvs.ガンダム ネクストプラス,Games,"Japan, Asia","ULAS 42207, ULJS 00250, ULJS 19048",1.00,1757806592,f9d9b854,b137ec976cfe73bcd57c91af2e7caa09,ecdd2079222963cb16a43330a1ef8bf008c1c9fb -33360,Sony PlayStation Portable,Baku-No,AI爆弾解除アクション 爆脳,Games,"Japan, Asia","UCAS 40017, ULJS 00017",1.01,161284096,e08ff9a3,81d039101fbf30083b5b754c65d934df,fc47a546fefad9f90f9d4490c30edea382b68328 -33401,Sony PlayStation Portable,F1 06 Portable,,Games,Asia,UCAS 40114,1.00,902004736,6561e206,1ecf0d900abb56910e0d24ff4904eb2f,2e3c794dc7574cb7d83cfc45dfd869936bfe71cd -33568,Sony PlayStation Portable,LEGO Harry Potter: Years 5-7,,Games,Europe,ULES-01532,1.00,1513422848,a41a6e4c,2dfb735b1d1735e51965a6a2e47c6ea9,515d6395bfa4d810c3cdb4f1f44a35e3db150ea5 -33574,Sony PlayStation Portable,Geronimo Stilton in the Kingdom of Fantasy,,Games,Europe,UCES-01535,1.00,897908736,ca31fcf5,7523f78cd9314dc0dc7b49426d9b57c6,8315c718cc22815305883aa32207a35aecef0093 -33687,Sony PlayStation Portable,Densha de Go! Pocket: Osaka Kanjousen-hen,電車でGO!ポケット ~大阪環状線編~,Games,Japan,ULJM 05211,1.00,361594880,c054795f,5624b3b5bfc7b534115293eba4d931eb,4ce66329798ba219b7823600b59bc5fa3a763f07 -33703,Sony PlayStation Portable,Star Wars: Battlefront II,スター・ウォーズ ~バトル・フロントⅡ~,Games,Japan,ULJM 05060,1.02,734494720,7ff6c11a,9977ed6af8d13d61e8ee5a88e801fbb4,14362ecbf3095dbccc1654f6b7e07ff325ae10f9 -33747,Sony PlayStation Portable,Mobile Train Simulator plus Densha de Go! Tokyo Kyuukou-hen,Mobile Train Simulator+電車でGO! 東京急行編,Games,Japan,ULJM 05012,1.04,1776156672,36d4ec0f,8523c3ce9a05c3c22f8e117cb17152c7,1911fc98885ee67fc79ee76af17d8a76e018b5e2 -33795,Sony PlayStation Portable,Buzz! ¿Qué Sabes de tu País?,,Games,Spain,UCES-01200,1.01,900923392,dd041c87,1115e7c6260c9b91a9427b321728b447,03e7b33cf72dc4a61c2207504c5bffd29d5d3e08 -34110,Sony PlayStation Portable,Hajime no Ippo Portable: Victorious Spirits,はじめの一歩 PORTABLE ~VICTORIOUS SPIRITS~,Games,Japan,ULJS 00125,1.03,527597568,1864ecac,1c033cbb42b947f07184adca2fe211a2,6df763c67265b65cabe00ad7cc396aa5109cb03d -34497,Sony PlayStation Portable,Pro Cycling Season 2010: Le Tour de France,,Games,Europe,ULES-01448,1.01,698253312,dce6e25b,63a120ef076d848c41e635cbab98a3e5,6ef98a84e119c23e1c90e9d8d71c75bc6df87014 -34498,Sony PlayStation Portable,Tokobot,,Games,Europe,ULES-00312,1.00,687505408,42f8cb5a,1b694996c1e8220fd5bf844d3d74bf0b,d5194af3f15d39a1c762067e38f202765335bef3 -34685,Sony PlayStation Portable,God of War: Ghost of Sparta,,Games,Europe,UCES-01473,1.01,1634729984,77303ca2,64643c7452fb4d1915b23a96820ee9f7,5653acbca132c82cc9da8682bc6da64d29b70775 -34697,Sony PlayStation Portable,IL-2 Sturmovik: Birds of Prey,,Games,Europe,ULES-01316,1.02,658669568,89db70b1,7c018d229657f927ed9f01ab0153a8ae,942f2ce67ec1b8bd90a4402f633f942b0e1657aa -34698,Sony PlayStation Portable,Tenchu: Shadow Assassins,,Games,Europe,ULES-01237,1.01,828243968,e0316912,b4abd8e9d585a5310d1e7c0be4654d2d,ba729a8cda4a15ebcb7d7cf257b5b2478ab08b46 -34699,Sony PlayStation Portable,Dead Head Fred,,Games,Europe,ULES-00902,1.00,1408303104,c96271cc,dad4edaf3f9cf69f17ffc47acb728738,f17084519b9894e7e9c2ecf0cf1e9b79fc707f8a -34700,Sony PlayStation Portable,Heatseeker,,Games,USA,ULUS-10259,1.01,404520960,e1ede108,1727c236ad320154eff4af1e08d11283,c5e9c4d025e26d5fa4d6fc5fc0b8f9e42789c9bb -34701,Sony PlayStation Portable,SBK 08: Superbike World Championship,,Games,Europe,ULES-01063,1.02,404717568,585e7795,843dd264bd1fd69c46cdd45628114b4e,143fd81a741310b76ee55ad1dd8818b3887c954c -34702,Sony PlayStation Portable,Rengoku II: The Stairway to H.E.A.V.E.N.,,Games,Europe,ULES-00437,1.02,502398976,7bf4fd50,f32063a50fe6e1c17440cc04b4d72e80,37d9366af993858600bbcefea52e27b30e0b5ed8 -34703,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo,,Games,Europe,UCES-00038,1.00,1049034752,5e9c2159,f07050be67cc707e50edd8af5f2480d3,c65186e1ae6f4834e51dd466b9426a9c7ac9ecb7 -35108,Sony PlayStation Portable,FIFA 14,,Games,Poland,ULES-01593,1.00,1293942784,fb158c57,8121cda276b86b96e774eff9b9822bde,2f0e1eba5b3c20c070781e3a6c4c48ad5b43bf0f -35208,Sony PlayStation Portable,FIFA 10,,Games,Europe,ULES-01328,1.00,1381597184,086f7dba,2127e850c3e29bd927c1679ef0ec1842,67329778a8425da84d6f07bd8d97b784dfe89c2f -35689,Sony PlayStation Portable,DJ Max Emotional Sense P: Black Square,,Games,Korea,ULKS 46189,1.13,1710424064,2b74a1ce,573db60c783b623f3cfe35873add2384,7b92f76364103496fe1415e295ad09a2bdb09270 -35876,Sony PlayStation Portable,Kidou Senshi Gundam Seed: Rengou vs. Z.A.F.T. Portable,機動戦士ガンダムシード 連合vs.Z.A.F.T. ポータブル 体験版,Demos,Japan,ULJM 91009,1.01,636485632,9db5b570,4ac5925e729ebec6a388a9949f30fbcf,57f3d517cb7f9392dbfecb751939a3111a6d259e -35877,Sony PlayStation Portable,Patapon 2: Don-Chaka,パタポン2 ドンチャカ♪ 体験版,Demos,Japan,UCJX 90028,1.00,565870592,4c64e8cc,d0e2f891d36667df9f299770d7e2b2f8,c6cd69ff2e7c183eb1d80a8c6046163553a31e04 -36060,Sony PlayStation Portable,Sega Genesis Collection,,Games,USA,ULUS-10192,1.01,856358912,33f35b72,b71f8ae1b96faca67938f4d9f05e1e7c,704f73c40b3ab029a3466adb75f3b42dee8cf87a -36331,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,GTA: 리버티 시티 스토리,Games,Korea,"ULKS 46157, ULUS 10041",3.00,1255243776,1da32381,c2733274c523d33431b1320ef516a1ee,cd801745e674bd1b4da48c6a839c97cf497ed0ae -36332,Sony PlayStation Portable,Grand Theft Auto: Vice City Stories,グランド・セフト・オート:バイスシティ ストーリーズ,Games,Japan,ULJM 05884,1.00,1750794240,11c768bb,b5f6418d0ad7d1646a8cc67c56b805bd,ff13f81325eb427721c049970c9567e0555b50fd -36710,Sony PlayStation Portable,The Eye of Judgment: Shintaku no Wizard,アイ・オブ・ジャッジメント ~神託のウィザード~,Demos,Japan,UCJX 90030,1.00,704053248,ceca5e25,714ce7db59e183ed2ca42fac8c54a7ad,6e739760b0cb0b7ec645305acf13dc4b2d195eac -36711,Sony PlayStation Portable,Metal Gear Solid: Portable Ops,메탈기어 솔리드: 포터블 옵스,Games,Korea,ULKS 46119,1.00,1395916800,1217b4b5,c2e2611023477970fb7d2e8ccd7cc2ff,6c2cc8f8036fc4454b71f4ed7228dcfc0d936cad -36713,Sony PlayStation Portable,Network Utility Disc Ver. 1.00,네트워크 유틸리티 디스크 Ver. 1.00,Applications,Korea,UCKM 84001,1.01,14778368,71d07323,1854c159ca6988822098197643376623,8250b116cd992fe24318088ccb5f8c83ad761c1e -36818,Sony PlayStation Portable,CS Kensa Disc (J1),CS検査ディスク(J1),Games,Japan,UMDT 99872,2.00,911671296,80dbe938,363f046f2e04fbca3b8f1010a0f38e9f,5d3d4a445949d0ace0c60778434439d8448d4905 -37240,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,소콤 U.S.네이비 씰 파이어팀 브라보 2,Games,Korea,UCKS 45043,1.00,930906112,141c5545,c1031dd34bacab290a3f9bcc7d2bc1d9,3dda54d2bbf1c0877e3bfea7dc286f55e5b118d1 -37631,Sony PlayStation Portable,Strike Witches: Hakugin no Tsubasa,ストライクウィッチーズ -白銀の翼-,Games,Japan,ULJM 06086,1.00,526876672,32397667,fec415e6909db524e17a6147beaca438,aac5106c9331da0eb1d0f4686948eaad904049c9 -39654,Sony PlayStation Portable,World Soccer Winning Eleven 2009,ワールドサッカーウイニングイレブン 2009,Games,Japan,ULJM 05414,1.01,1388740608,6c6a3d26,c23e129f5663c768452d5ff5d6d4ef3a,db636c33a342ac18e5737dc1ead10252a0a0d793 -39823,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu Portable 2,実況 パワフルプロ野球 ポータブル 2,Games,Japan,ULJM 05195,1.03,1667891200,691e14dd,bdd9c225e4a1e99103963f683922cbd2,26b4a5eb95101d1cc753f5bc4fc854496cdf7321 -39824,Sony PlayStation Portable,Need for Speed: Shift,ニード・フォー・スピード シフト,Games,Japan,ULJM 05494,1.00,1798471680,23930caa,0922b24b8186d005919ab243026ddf6a,5c54a0afde56c5f36effae0cf1128ebb18ab1b9b -39834,Sony PlayStation Portable,Doko Demo Issho,どこでもいっしょ,Games,Japan,"UCJS 10002, UCJS 18002",1.01,422805504,44b8dce6,a7d8ff8050ac0d1fd6b0d5970eecbd8d,d5561bfb9362a47357aa070d8665ea22fdc83084 -39835,Sony PlayStation Portable,Yuusha no Kuse ni Namaiki da or2,勇者のくせになまいきだ or2,Games,Japan,"UCJS 10086, UCJS 18037",1.00,210370560,2ba6450f,e752b6e89d0b36148e156a7446a89ab0,5129c76d1e5e29affa5699cb2808028df00e09e9 -39836,Sony PlayStation Portable,Tales of the World: Radiant Mythology 2,テイルズ オブ ザ ワールド レディアントマイソロジー2,Games,Japan,"ULJS 00175, ULJS 19044",1.01,1066598400,9b3ed950,d9d7e0b0c0362a365f08e68163265a77,02ca9a344c7e76d080bc110aaad9447248bbf220 -42304,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Carros,Games,Portugal,ULES-00320#,1.01,906362880,d1f2bc99,5f0e1dded297c060fdf53e41baa8d696,72b4f400503567ac14853c1567b5a4d30419783f -42379,Sony PlayStation Portable,Sakura-sou no Pet na Kanojo,さくら荘のペットな彼女,Games,Japan,"ULJS-00566, ULJS-00567",1.01,1508966400,ff0e6f58,081f7b7fc4f763e4358e338e91c8742d,0bd017c548241d2e6786ef7121c75e9adf3dc2b9 -42539,Sony PlayStation Portable,Mytran Wars,,Games,USA,ULUS 10398,1.04,1226276864,8939fc8d,9d6b9ad7a9d2b6045e03c2017f1e9b23,aa01a0822ad38f1f3e48eff6041a5004ce79e74f -43667,Sony PlayStation Portable,FIFA 07,,Games,France,ULES-00441,1.02,1249902592,053f7f09,6406a5c93d50f1c89ef7448b8b6966f3,98826cd8cdb104d37510e9de3f972166ec817790 -43668,Sony PlayStation Portable,FIFA 08,,Games,France,ULES-00892,1.00,1243807744,45679843,dc2026284d2f3b5bac75d56b659458f1,f1560679ac469901c3c989eae4d3916078d7357a -43669,Sony PlayStation Portable,À la croisée des mondes: La Boussole d'or,,Games,France,ULES-00951,1.00,1263042560,79b400ea,6987dbc4c1c557d1624ffbc98989d509,72dcdf6f472a4e4d5123bbeab601a8f5cb5d12cb -43670,Sony PlayStation Portable,NBA Live 07,,Games,France,ULES-00463,1.00,1461125120,94035678,580f7b5ce373510e216bf0d52992383c,cd3e1f02d2747f4199389e8340d5295dc48a0aef -43671,Sony PlayStation Portable,Les Simpson: Le Jeu,,Games,France,ULES-00976,1.00,768376832,5f62c5c0,068bf011cf2604388a318c4e9bd6ac04,8b3cbc60c2fa0f1da97249121a0febc6d6f5a3fb -43672,Sony PlayStation Portable,The Con,,Games,Germany,ULES-00511,1.02,794689536,990d29a2,f0073dfd97a54cef153b929674ebd074,f726c6b1215cd134bbd5bd5d286ed02f5ffc504d -43673,Sony PlayStation Portable,Scarface: Money. Power. Respect.,,Games,Germany,ULES-00547,1.02,449118208,50b6d4be,4543df50e329e971c209da1e68292898,63860bfd75909d4afeda9a59276af9179de223b6 -44559,Sony PlayStation Portable,Disney Pirates of the Caribbean: At World's End,Пираты Карибского моря: На краю света,Games,Russia,ULES-00728,1.00,721256448,970c381e,932f5fed204fa585f5717ece87efb540,1bc65be3969f0e095d2554c3c8f50871a3ce513e -44560,Sony PlayStation Portable,Disney•Pixar Up,Disney•Pixar Вверх,Games,Russia,ULES-01255#,1.01,525762560,8f941aa3,c1fe130148a28c2848d271de6c6cdba4,3ba1a53046dc76f3f93465737dfa5df919973d9a -44740,Sony PlayStation Portable,Disney/Pixar WALL-E,Disney/Pixar ВАЛЛ-И,Games,Russia,"ULES-01081, ULES-01081#",1.00,640811008,ba832579,e8b41c517700cec435f72f7fbd9e7b73,81286bcc983a1674016fbcf1cafafd2627667548 -44741,Sony PlayStation Portable,DreamWorks Megamind: The Blue Defender,Мегамозг: Синий защитник,Games,Russia,ULES-01465,1.00,906330112,ebaf6020,c7629386a881328032e068ac870b1193,651633682b00fbf39ed71d0a6051d31e1af92a7a -44754,Sony PlayStation Portable,PES 2013: Pro Evolution Soccer,,Games,Europe,ULES-01575,1.00,1221951488,a0f7ffbe,d1757a73e3d5a5c7397a5264a424ba3a,0f222f03d53914f9fa6a4f333ad70ea19073ff4e -44755,Sony PlayStation Portable,FIFA 13,,Games,Russia,ULES-01570,1.00,1360789504,187a56cc,8e158b2ad07e88ce11dc2947e3336c1f,788625f1fca7a6ccfcf30a3dc13f81aecf99d0da -49042,Sony PlayStation Portable,FIFA 11,,Games,Portugal,ULES-01481,1.00,1334935552,a26fb604,cee5c6df6c04c91efaabc247380925f7,6e46a19a2722ccdaac6f3fbab47c96a8723ba5d3 -49599,Sony PlayStation Portable,FIFA 11,,Games,Italy,ULES-01477,1.00,1249280000,4153ea6b,dd7f116280eb777c141025314d37de10,edaf7e572dc8e32312c3b53e3b36155f6beaf65b -49976,Sony PlayStation Portable,Tony Hawk's Project 8,,Games,Europe,ULES-00626,1.02,1519124480,3cfe7802,7dc0d056aea52582099a12fc17d8e9db,581b401c6140f422eb6d3f6afa6e17d6a2396189 -49989,Sony PlayStation Portable,PES 2012: Pro Evolution Soccer,,Games,Europe,ULES-01542,1.00,1736572928,ae285b92,a543b564e1b737b4daf161fe8fb5e67e,169d3de585bae2e9538bc27bb12d8b81f7efc11b -49990,Sony PlayStation Portable,FIFA 10,,Games,Italy,ULES-01325,1.00,1249509376,1dea6572,524c0a6df1d5b8ab23e8b27009495515,8e4e2d4aa9c9f95ab7d5b5370bddf0292608767c -50164,Sony PlayStation Portable,NBA Live 09,,Games,Europe,ULES-01147,1.00,1419313152,06feb536,9a1decb3da6386292becca3cbd32e79d,444dc542f0470bc66572beaf9ce898076b8b380d -50165,Sony PlayStation Portable,Thrillville: Off the Rails,,Games,Europe,ULES-00888,1.00,892665856,a238d3a6,63e8489649f4c94c1df3dee4183a32d9,3f93897684d328e696ec1ec6c7c18812f704405f -50166,Sony PlayStation Portable,Disney/Pixar Up,,Games,Italy,"ULES-01257#, ULES-01257/E",1.00,525795328,7ec1db1f,94291fcfb7220037da75c472c7e0dba9,c8092108eadd3e4b85b1a2af5c3a14bb6f5632d4 -50168,Sony PlayStation Portable,La Bussola d'Oro,,Games,Italy,ULES-00953,1.00,1279492096,cef73cf5,89890ad2db4feb541ff53e75572cbacb,35e6e085fa5ce16d73d89207c1a43b8f0672ae03 -50169,Sony PlayStation Portable,Chi Vuol Essere Milionario? Party Edition,,Games,Italy,ULES-00712,1.01,322404352,8a4147a9,18d17b63d5dd17847cc9645fa2f0b5ad,8d7cd4b570f22b721308129f8740a1f58ca02fe6 -50812,Sony PlayStation Portable,Dynasty Warriors,,Games,Germany,ULES-00119,1.01,241139712,434ce28f,cab0621b948498cd2594f1a5f3407139,793de7f633580c4f0a558b475393e408934fb690 -50816,Sony PlayStation Portable,Samurai Warriors: State of War,,Games,Germany,ULES-00299,1.00,328269824,2c6de039,4a720842e7b90f58cb719f930699ba5c,6782899b27d29c95c7e63a1f9cc605166110f5ff -51128,Sony PlayStation Portable,FlatOut: Head On,,Games,Germany,ULES-00969,1.00,450461696,35fea199,3be6bed2551501765db3c63b2dfc5b71,83f63bbac43bb7a2a25b9dd53bad5e09b46d7485 -51129,Sony PlayStation Portable,Call of Duty: Roads to Victory,,Games,Germany,ULES-00644,1.01,630947840,c164a9ce,99dd607ea3ed8dd6e32b00a6fba57927,9833dc334e7cea0c6b07dbd7694f073f0a56e3d3 -51130,Sony PlayStation Portable,Gangs of London,,Games,Germany,UCES-00523,1.01,1078525952,e4d03dad,bb3199c238b306224fc15349d86500ba,c12a10dcb7591e15e15b90f6ffec5c7e7b9b0bbf -51131,Sony PlayStation Portable,Disney/Pixar WALL-E: Der Letzte räumt die Erde auf,,Games,Germany,ULES-01082,1.00,639238144,1c8168d1,dc173abd4953eae65c8ae673c7caf8b2,6d510a863b25f058a22283d78c7baa96af9ec939 -51132,Sony PlayStation Portable,DreamWorks Shrek the Third,,Games,Europe,ULES-00813,1.01,1076527104,eb0212a7,786bd2494e0aa3d61dec05a1d7edd723,cf48aca74022ac4f0e433cbc8f3344f17564f66d -51133,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,Europe,ULES-01469,1.00,1446281216,f992048e,7430f1e53801fb053cf718df0d20e121,2ef87e7a608890b4e25cabddf1dced9d62e0bd98 -51134,Sony PlayStation Portable,Dead Head Fred,,Games,Europe,ULES-00903,1.00,1791688704,ef6e14a1,54cad2d7024e894a2dd7ebb4a5063251,1a9d0ae6b93712155c732502ec3914b3cdb9f8cc -51135,Sony PlayStation Portable,2010 FIFA World Cup South Africa,,Games,Europe,ULES-01414,1.01,1510965248,a4317983,07c9ad9921f9c2e1bb34613655589357,816893203df5ce5b655916e57d2e4e1e3667d95f -51139,Sony PlayStation Portable,Beta Bloc,,Games,Italy,ULES-00792,1.00,89260032,0413858e,da956f48abaf5ea6e62585f29396c35c,803d1dcf6c6a14ff74715516e70d47742d133559 -51140,Sony PlayStation Portable,Dragonball: Evolution,,Games,Europe,ULES-01227,1.00,429359104,b0795cc4,f535acd5d068afd87ecafbaee31e4252,3b070970ff1b5f74f186790c062bc8b89903a908 -51141,Sony PlayStation Portable,Jungle Party,,Games,Europe,UCES-01459,1.01,533299200,ada4e2ab,bbabc94bf5fe07793da459499b114444,42d7f7ed7d08e668ae8b4e6440f10794c486d0da -51142,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,Italy,ULES-00744,1.00,906362880,f491cc28,406f8cb718740f2cc2f1442973fd340a,7e4fc60583ebfcf7421218ae9cef91f358d48cb4 -51143,Sony PlayStation Portable,Viewtiful Joe: Red Hot Rumble,,Games,Europe,ULES-00256,1.00,1033338880,504e0fe5,e010a3a8ccdf5d09fe8be8f1b58027f6,0987e14d5b6d7184546d35289674bcc16ef5b5e1 -51144,Sony PlayStation Portable,Williams Pinball Classics,,Games,Europe,ULES-01014,2.01,434503680,c221ae35,b2089012dcf0b6c4894e46855dd6677b,bdb1988411a2826c6a1f588967d8d8865af820a7 -51145,Sony PlayStation Portable,The Con,,Games,Italy,ULES-00512,1.03,796524544,8bb4b5e8,5dfd6b238c0396d2b4924325c300917f,0dfd9a796011da8326b1455194d6d19f0b8ed93c -51657,Sony PlayStation Portable,X-Men Legends II: Rise of Apocalypse,,Games,Germany,ULES-00190,1.01,1324351488,5176c3e4,4a56c3dc2d95808bc35ab27b83bb8722,2187e604df8d5a10de1a659ed005976785f8965c -51660,Sony PlayStation Portable,Warriors Orochi,,Games,Germany,ULES-01056,1.00,906297344,df2485f8,f7e75453e6dd125d080b6e09a1c7eaf1,d976860dcb1e5a4d82b7feb607cc0a43009a9d95 -51782,Sony PlayStation Portable,Winx Club: Join the Club,,Games,Europe,ULES-00611,1.03,1317634048,533f938e,6c351163c338b78e6ee29d3e3fb7e429,11f6b199172c0fe34d624054f6e3fdc50f5de224 -51791,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,UCES-01032/POR,1.00,1501069312,5d89c901,1af1c4c75408027efbf30f31f558f9bc,7bda74e645c80613c29745a3ee72c893dbf95294 -51795,Sony PlayStation Portable,Disney/Pixar Up: Altamente!,,Games,Portugal,ULES-01258,1.00,531398656,a9c45aea,de07c3e127de8172b57a5bbd80fa583a,3f5d58dd93dd2e9cafeda27da73888435d30654d -51796,Sony PlayStation Portable,Disney/Pixar Up,,Games,Europe,ULES-01253,1.01,555515904,8a7e8dee,fb73536b9e8a02d7d331183dd94a7534,50a71fd9ca246dae796fcc32c9dbe425f7dc3ad6 -51797,Sony PlayStation Portable,Disney/Pixar Ratatui,,Games,Portugal,ULES-00738,1.00,906362880,467fadce,449ce739c37a177beeef96a786b36434,c539050795975bb9934bc289c150b8778d1649f5 -51998,Sony PlayStation Portable,B-Boy,,Games,USA,ULUS 10363,1.01,1653604352,ccb3c6fc,6297f694d21c39c79eebd323f8822efc,dec7b0758f2ebb9d9aa35eb4bb412aa4461b0491 -51999,Sony PlayStation Portable,Cabela's African Safari,,Games,USA,ULUS 10175,1.01,905314304,d5eea28b,2ef8f37260ef366bbad5450efb1fa7d3,213db3c2a672bf24c561610d3bd11ba26783fe26 -52000,Sony PlayStation Portable,Dead Head Fred,,Demos,USA,ULUS 90002,1.00,373096448,bf2f36e3,79d89cc46fdf679642334db3e0c3cf7e,20fd7ddf95a5dc6a234d4da4e6976a272770ae32 -52001,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,USA,ULUS 10350,1.00,767590400,e5e9ab48,9c6e88ff5adec37c801921673122c3af,74804038f55f6b572041f07362b216bc46f651da -52002,Sony PlayStation Portable,Dragonball: Evolution,,Games,USA,ULUS 10415,1.00,394821632,294f3672,bd8251eca9be842c060b879daac7e0dd,1cffeb5186c3577ce929fa97e1fe6fe29e8ba776 -52003,Sony PlayStation Portable,Harry Potter and the Half-Blood Prince,,Games,USA,ULUS 10381,1.00,408027136,af6fb4a9,79a41b9f20c328399a3e41c4f46642c6,43608e032918aa5a8bf450367612c2cf02c8150f -52004,Sony PlayStation Portable,NCAA Football 09,,Games,USA,ULUS 10355,1.00,1640759296,174c9b9f,188a41e402d85bdf2d6d1796c93285cd,a8b415902e6bad6ff19d04512df7ced07cde1e88 -52005,Sony PlayStation Portable,The Sims 2: Pets,,Games,USA,ULUS 10130,1.00,1517813760,6723c47f,517ba9f72784d68fe904092e8c2f5ed1,c1faf10729b05fd709bf85c7811b2ee34bb16d57 -52006,Sony PlayStation Portable,Tiger Woods PGA Tour 09,,Games,USA,ULUS 10367,1.00,1616379904,c788169a,34e925dfc70297bacd6541d900ef23ef,eb8baaba195fce85b086ad25bf4b7feb41d17c75 -52007,Sony PlayStation Portable,Burnout Dominator,,Games,Europe,ULES-00750,1.01,691109888,cb2429a4,99f4d2c56b1bbde524496e72c9ba22ca,c5217b1a84f02069260f76976ed0a56b79e64331 -52008,Sony PlayStation Portable,Disney G-Force,,Games,Europe,ULES-01238,1.00,1310851072,a148bf42,006ae3b06d77a58cf93286425a2ddf97,13e6ada7dfc4d23eea67ea6b24c7696920fc63db -52009,Sony PlayStation Portable,Disney/Pixar Toy Story 3,,Games,Europe,ULES-01406,1.01,905543680,59d6d03f,13f207325f0c2678304d95a84faaeb86,194a6339870455ac0ae758d0b784bf01d5f8599a -52010,Sony PlayStation Portable,Taito Legends Power-Up,,Games,Europe,ULES-00473,1.01,327155712,a4b647ee,382ebcb51c30a49d1d37e0719e6bd957,94144abf194f96b4fc296274fe7c5c0804e92013 -52011,Sony PlayStation Portable,DreamWorks Over the Hedge: Hammy Goes Nuts!,,Games,USA,ULUS 10187,1.01,325320704,73d4227b,79bc0b1ce28533fd7469e2ce15d19b2e,f8f6fc0113e7139de47b7548fd9659fcf87d36ed -52012,Sony PlayStation Portable,DreamWorks Shrek the Third,,Games,USA,ULUS 10248,1.01,509444096,34574272,be9f4e92a15ff08e278a0facd9ccf6b6,e9d99588b5b45aa5f38e48041ece671a1e003f32 -52013,Sony PlayStation Portable,Hard Rock Casino,,Games,USA,ULUS 10181,1.02,614858752,34c9c69d,184ff364915e3efb054a692dcc0a5f78,d5be9b43764160b4d3f13f8d7d14afc2746bf038 -52014,Sony PlayStation Portable,Hot Wheels: Ultimate Racing,,Games,USA,ULUS 10239,1.02,866451456,2401dde5,48228c4b4d499497a7d9ce50cf5f4f82,0a0acfe823a7c7ab1fe10ca5854e130c5acf43dc -52015,Sony PlayStation Portable,Lara Croft Tomb Raider: Anniversary,,Games,USA,ULUS 10253,1.02,1291190272,900933e3,ad1ab0cfc2948fc789d27ca6b6300a37,7b15585ae53e0835b4274ed674588e96a21444f7 -52016,Sony PlayStation Portable,Online Chess Kingdoms,,Games,USA,ULUS 10179,1.02,266928128,f8fea577,f8d50e8dcbce711d784502de18805b50,2bedb229519056bfef3b68a764ed6864bb248009 -52017,Sony PlayStation Portable,Pinball Hall of Fame: The Williams Collection,,Games,USA,ULUS 10265,1.00,392495104,1f54e167,9c2defe34bb55776ecfe86789383aa0c,f50ea7dcb5ce33015e10fab0e842e7f98fe97604 -52018,Sony PlayStation Portable,Reel Fishing: The Great Outdoors,,Games,USA,ULUS 10166,1.01,193593344,8a6a92e6,f592e9a8db221d06f075eb26668177c6,bfe5cc7d021c6e60b73d82e199de17e8bd39b9af -52019,Sony PlayStation Portable,Spelling Challenges and More!,,Games,USA,ULUS 10255,1.00,224034816,fd7e40bc,ed26b4c401dfefb750bd681a74562d5c,a89082e09b5291a9953c078e28182f457e238d21 -52020,Sony PlayStation Portable,Star Trek: Tactical Assault,,Games,USA,ULUS 10150,1.02,255197184,61b47ba3,f730e47629d038d6675dcda4d453a50c,9daa8130636efe51650f0910833d8bafee6a8ac3 -52021,Sony PlayStation Portable,Winning Eleven: Pro Evolution Soccer 2007,,Games,USA,ULUS 10169,1.01,1156186112,071e254c,d754fbda2180a4cc2186a274d5e6b1e1,a4e92430f3a8e0fe0110fc3f7c4dc339e0c964e3 -52022,Sony PlayStation Portable,World Championship Poker featuring Howard Lederer: All In,,Games,USA,ULUS 10145,1.01,1812692992,e2777507,5a664c0b9c019eb8404fd75a6e6b8965,4761725620622536be5527a8e9dc321af6930e80 -52023,Sony PlayStation Portable,WWE SmackDown vs. Raw 2007,,Games,USA,ULUS 10199GH,1.03,1632731136,d7007323,c0c5c3cfa59a372ba721e51b1cb6dd41,bc1e53b91448208edcd0e3f95cb0601fae37f3b4 -52024,Sony PlayStation Portable,Xiaolin Showdown,,Games,USA,ULUS 10164,1.02,906362880,d06f41e1,95ca382095ce2ea4f4111271ae5b7afc,8c4a5c431959f23fa95369a1fa41ef138ad225ff -52119,Sony PlayStation Portable,Demo Disc for PSP Vol. 1,,Demos,Europe,UCJB-98306,1.00,905314304,f52f8c96,9ab0231d59cb632fee110e967338e1c3,24a25ad9a73b044bf580be1721faffed0c604391 -52203,Sony PlayStation Portable,Eragon,,Games,USA,ULUS 10146,1.03,248807424,abb438c2,d63dce5dd3f4eb580716885f62dd45f0,13581031452b89bfce03062da3f21ae64a460eb3 -52204,Sony PlayStation Portable,Iron Man,,Games,USA,ULUS 10347,1.00,906362880,ddbbafcf,4601056f618fef189eb7fba69938dc4b,4fff3d65c4fef5ddf19ba477b7e08589eacaef33 -52205,Sony PlayStation Portable,Need for Speed: Undercover,,Games,USA,ULUS 10376,1.00,1304690688,34d51f1a,8571a1c09089feaf6e692c944389d639,cd7f1398f943b16e6cd15071f1d3897709645f25 -52207,Sony PlayStation Portable,Ghost Rider,,Games,USA,ULUS 10210,1.02,789446656,c4296d41,df5fe5b9690a6fb3cdb221a977bbb488,6e14e5d10678bfc78ff1d6f567a71908befc1cf8 -52209,Sony PlayStation Portable,PES 2014: Pro Evolution Soccer,,Games,USA,ULUS 10654S,1.01,1573683200,056ee4b2,a1f8e0764b384c4775c6fd747d347b29,e777900a8d7b5ac2cfc281131f4e9eef6e3588de -52210,Sony PlayStation Portable,Indiana Jones and the Staff of Kings,,Games,USA,ULUS 10316,1.00,703463424,20eb6447,5104b90a9818bf8f06924e1c559fb669,75fe8bbbf9d9c0987291125c0cb73ba665bad865 -52211,Sony PlayStation Portable,M.A.C.H.: Modified Air Combat Heroes,,Games,USA,ULUS 10180,1.01,830046208,585e0ed3,3b93cb51f342d29528226c35fec13f9a,0ffdb3110a4a4770c70268fee5a6c77f1289f495 -52493,Sony PlayStation Portable,Crash of the Titans,,Games,Europe,"ULES-00918, ULES-00918/E",1.01,813105152,7d1d7255,3fda77c22aa34047f23cd34a5f8ef48d,f9edcee14e6d0ec0ca432b9162256918977bc5d0 -52495,Sony PlayStation Portable,FIFA 09,,Games,Portugal,ULES-01143,1.00,1310588928,d65e2221,4574bdfdd0e360f0354e874103a580f4,e228a67089a0b1e9f8a56ed56eb352e740579003 -52496,Sony PlayStation Portable,Legend of the Dragon,,Games,Europe,ULES-00695,1.01,827195392,3f208429,fb3b450161c4ebe71717fdcde0506652,ab6a217d1c2e120b5c718276e8d81c5193010148 -52775,Sony PlayStation Portable,God of War: Koutan no Kokuin,ゴッド・オブ・ウォー 降誕の刻印,Games,Japan,UCJS 10114,1.00,1596293120,d98c52e6,f5ab60a74ba7d644325e3f7ef6c0e9f7,bf0f1943b3e1a5934835105b446ab87abb2c8200 -52776,Sony PlayStation Portable,God of War: Rakujitsu no Hisoukyoku,ゴッド・オブ・ウォー 落日の悲愴曲,Games,Japan,ULJM 05438,1.01,1558183936,79c5b544,363914a2acb13064e01d746968ec3ed5,4e9798b0b686154c7af44efb0a51fb7d49b2973e -52834,Sony PlayStation Portable,Shirokishi Monogatari Episode Portable: Dogma Wars,白騎士物語 -episode.portable- ドグマ・ウォーズ,Games,Japan,UCJS 10115,1.00,825982976,485e94d5,dc2da25661779ddff3ad877e1a463f3e,a58077b0d200a2d1a3325fbd114da42af175c45b -52835,Sony PlayStation Portable,Sol Trigger,ソールトリガー,Games,Japan,ULJM 06093,1.01,1521942528,cf0239e8,82ef48ea6ae1b444071fea169cadfa66,68a333f874c0bc62d98871d5e4b29cb3fc0ddf08 -52936,Sony PlayStation Portable,Tony Hawk's Project 8,,Games,Europe,ULES-00625,1.02,1506344960,cd070348,32bc37938a3e0ab193b72fe680f9d081,96c47a07e6bb04e1913256bade401d7ccb5baec4 -52968,Sony PlayStation Portable,Disney Pirates of the Caribbean: At World's End,,Games,USA,ULUS 10252,1.01,739409920,85ffc575,54f4d63ac8c70b68a4ca553159c4e7f3,ff5c3b212fa16e6bcb6b61a1f23e71ac7c06ea3b -52969,Sony PlayStation Portable,Star Wars: The Force Unleashed,,Games,Europe,ULES-00982#,1.00,1287684096,eb3881b3,c74ac0c373a0d4af529f51b6becd425e,f8c558f9d52dfcc62c4fce95b3e038fda888fdac -53083,Sony PlayStation Portable,LEGO Star Wars III: The Clone Wars,,Games,Europe,"ULES-01446#, ULES-01446#2",1.01,1746173952,278b8975,6d82da9591103c5645a5a16706b9c723,bbef03ca9dd1ae64934d58f004a9b36ea3786339 -53084,Sony PlayStation Portable,Star Wars: The Clone Wars: Republic Heroes,,Games,Europe,"ULES-01284, ULES-01284#",1.00,1486159872,5f6eeb74,af0ee09341753223e92ba38fe9691d7b,c0b07a65eca759fa95febb0b330ab7584241965d -53085,Sony PlayStation Portable,Star Wars Battlefront: Elite Squadron,,Games,Europe,ULES-01214,1.00,1683685376,730aced9,8fdd023b7780067d8dabed3f282d2dda,80f3652f7a35365ebf0b95a2ed215fb70f79864b -53150,Sony PlayStation Portable,Prince of Persia: Boukyaku no Suna,プリンス・オブ・ペルシャ 忘却の砂,Games,Japan,ULJM 05688,1.00,676823040,0f19f1e9,8aedcc9697f8ecd64b1647ee325b7c46,9cc8e72b2d6a00326af13801d4e0884bad7a9c8b -53200,Sony PlayStation Portable,Bubble Bobble Evolution,,Games,Europe,ULES-00303,1.01,622198784,6cf63243,e616c2549b2f6e909d5c0c0db75dce6f,8834d6a210ed4c2981a2641cd07401c3026741ae -53201,Sony PlayStation Portable,PlayEnglish,,Games,Portugal,ULES-01509,1.00,876216320,1674829f,e18f5b6facde7ba722bee3fa79495403,7f23a134879c68332b9054ad7e83d9cf1ff1b5bc -53372,Sony PlayStation Portable,Mugen Kairou,無限回廊,Games,Japan,"UCJS 10081, UCJS 18028",1.00,183173120,bb5fca23,a259c27c48be499cfa9e525a0b2b7d7b,5ff4f47622c9955ae69cecc785e22f32f0ba044d -53440,Sony PlayStation Portable,Blitz: Overtime,,Games,USA,ULUS 10200,1.01,1379336192,e28b87c1,9da5cc94aafa2b9affa625cffdf261cd,aa45fae86f6b7cb5b037cf5360d1041795a59bf4 -53441,Sony PlayStation Portable,Shaun White Snowboarding,,Games,USA,ULUS 10399,1.01,491454464,43dfe1b5,156586dc9bc05d39b6fcc893498a1e73,21d17adaa978c5a6f4f67bdcfff7cd789e7c7a61 -53442,Sony PlayStation Portable,The Sims 2: Castaway,,Games,USA,ULUS 10296,1.00,1034158080,e6af06ad,f5f6345544d4d8b3d5bb61dfd8d5ca91,dbd7cd82fa03df1334b04e8af6ad4ad13dbb493b -53443,Sony PlayStation Portable,God of War: Chains of Olympus,,Demos,Europe,UCED-00970,1.00,373948416,0ff20ca2,aebb1874c15aa1571e09c6732c096807,978f959a196d40c8963569c6a3145b14e5d0b326 -53464,Sony PlayStation Portable,Stealth + WipEout Pure,,Demos,USA,ULUS-10058,2.00,1795391488,e35de739,f09967725d33c10066a8afd652755a09,bd486ff080c93f1d23f040ba26350e237ec8d1c3 -53465,Sony PlayStation Portable,Stealth + WipEout Pure,,Demos,Europe,"ULES-00229, UMDS 10059",2.00,1806794752,bfd06f63,9fea174c6ac02aba1add55d00a4966a2,c5e940ee2e5f666617c21ff7624bf6ce2f13545d -53813,Sony PlayStation Portable,Tekken: Dark Resurrection,,Preproduction,Europe,UCET-00424/0.02,0.02,1783758848,8d5258e7,767cf429116fb323afbb94264cd9bfcb,76824b57d4cdcbc49f6a5946e28734be198e796f -53814,Sony PlayStation Portable,Jak and Daxter: The Lost Frontier,,Games,Europe,UCES-01378,1.00,1787297792,ec826df6,7e91346cec35ce942c709478d44c75d4,252f7e1f77de0d49bbd39108b329d288efe8aa0e -53815,Sony PlayStation Portable,UEFA Champions League 2006-2007,,Games,France,ULES-00706,1.00,1189150720,77907a50,4354d5e76196ddae11149ddd0845521a,5ab1a802a536e50d8fa3138087d71347c4286326 -54031,Sony PlayStation Portable,Guilty Gear XX #Reload: The Midnight Carnival,ギルティギア イグゼクス シャープリロード,Games,Japan,ULJM 05042,1.01,486277120,5f7eb782,3080520af3cdd0e4de1afe0cfbf84c1e,f2738beacede77bda09a5cd470058a0d7be2aaaa -54032,Sony PlayStation Portable,Wangan Midnight Portable,湾岸ミッドナイト ポータブル,Games,Japan,"ULJM 05264, ULJM 05372",1.02,336494592,33efddf0,85c3abab28df6509911461de9d58b9e9,10cffd2e05fda91fe3a1931acb24ba03bc33e4e5 -54080,Sony PlayStation Portable,Shin Megami Tensei: Persona 3 Portable,,Preproduction,Europe,ULES-01523 1.00,1.00,1321893888,bd322726,673409da4110f8a5a15c87a420420189,4114a2ea28d167e856c0ce0b67fae93658e92d41 -54081,Sony PlayStation Portable,Shin Megami Tensei: Persona 3 Portable,,Games,Europe,"ULES-01523, ULES-01523/1.01",1.01,1321893888,f7efdea8,67bf4cc8beda37c270b5021a5ad324ea,0d0a8cdcec8a43b01379552fffe183bdce12c3cb -54486,Sony PlayStation Portable,428: Fuusa Sareta Shibuya de,428 ~封鎖された渋谷で~,Games,Japan,ULJS 00344,1.01,1659011072,13d7c441,9225a85fb8daa32d50aa5a822261ab05,9e14e2225dc5f879b7e67ec1d3d25419e20f1c03 -54487,Sony PlayStation Portable,Hayarigami 2 Portable: Keishichou Kaii Jiken File,流行り神2PORTABLE 警視庁怪異事件ファイル,Games,Japan,"ULJS 00149, ULJS 00208",1.02,397377536,830148f5,6f5d2dd344d17203f779504bfd4d60cd,b7f3343b5e6daf3d02bbffcbd9b6a7f84c9e3d30 -54488,Sony PlayStation Portable,Hayarigami Portable: Keishichou Kaii Jiken File,流行り神PORTABLE 警視庁怪異事件ファイル,Games,Japan,ULJS 00110,1.01,429522944,3f94385a,800a26224837218e4a2cddc255ab20c5,160ae0366ad8acecc43bef1b31a4366db9148554 -54489,Sony PlayStation Portable,Jigen Kairou,時限回廊,Games,Japan,UCJS 10096,1.00,272498688,9dbface1,20c3f40624f582f2d6c2b59cc0f09d82,ab60ee2164146b2ebbd22f95dc0c0635f9e31469 -54490,Sony PlayStation Portable,Judie no Atelier: Gramnad no Renkinjutsushi: Toraware no Moribito,ユーディーのアトリエ ~グラムナートの錬金術士~ 囚われの守人,Games,Japan,ULJM 05607,1.02,1307148288,e0b0e7f4,abc620edddaf16b0e86ed6929805930d,95af68317787d8154782e0b3c0e835dddcd1dea8 -54492,Sony PlayStation Portable,"Koori no Haka: Ichiyanagi Nagomu, 3-dome no Junan",氷の墓標 一柳和、3度目の受難,Games,Japan,ULJS 00247,1.03,418185216,bb7798a6,ebc5938e50e5e7e0699b2f7e0270c879,bf9f68561ca2a4cac7a0a16c60bd9db91255a7c3 -54493,Sony PlayStation Portable,Machi: Unmei no Kousaten Tokubetsu-hen,街 ~運命の交差点~ 特別篇,Games,Japan,ULJM 05111,1.01,1542422528,5ab112a4,4dcff6f253fcf550c4f92854bea50b69,be294fa78afa377601228c79f2721cc38adf691e -54494,Sony PlayStation Portable,Sorayume Portable,ソラユメ portable,Games,Japan,ULJS 00203,1.02,1028816896,91928e00,13986397a11a19166e2b99bb9506d0af,d95b8937fb2396cebc59b615c2a4e6b1fe5bb8d4 -54495,Sony PlayStation Portable,TalkMan,トークマン,Educational,Japan,"UCJS 10009, UCJS 18017",1.02,1228505088,49a98873,c12d754c2bb7dca50354e32d2d9c42f2,609b038b18a22e709c69e59ea16f13416dceefbf -54496,Sony PlayStation Portable,TalkMan Euro! TalkMan Europa Gengo-ban,TalkMan EURO! トークマン ヨーロッパ言語版,Educational,Japan,UCJS 10033,1.03,1802960896,f0f6f1d2,cc146cb0b9723a38b571037ed278034a,94c54aa0e9f9e2d79665f1dae41726ccb4903627 -54497,Sony PlayStation Portable,TalkMan-shiki Shabelingual Eikaiwa,TalkMan式 しゃべリンガル英会話,Educational,Japan,UCJS 10051,1.00,453640192,f0ab5b0a,9b05cfd0d041714d674908626a440234,c0ceaf66d75f34d1e5f6f86baba47460a4e97133 -54498,Sony PlayStation Portable,TalkMan-shiki Shabelingual Eikaiwa for Kids!,TalkMan式 しゃべリンガル英会話 for Kids!,Educational,Japan,UCJS 10054,1.00,327286784,73ac3a5f,ae35bb5df770474ccbb0f670c145d736,8a54cbed0ae6e9a988652bed297b82d850bea97b -54499,Sony PlayStation Portable,Tantei Jinguuji Saburou: Hai to Diamond,探偵 神宮寺三郎 灰とダイヤモンド,Games,Japan,ULJM 05529,1.01,798162944,4a4b9912,a4b755a9c2a45c21958d400c5ba36fd9,7b91a31b18204df28a9834163125be3ca09d84e7 -54573,Sony PlayStation Portable,Harry Potter and the Order of the Phoenix,,Games,Europe,ULES-00829,1.00,763002880,a9ace2a1,d742e54e45716943cd8ffd3b353d7f42,b118cc40a338b4b71e34d2bd0126a14a501db14f -54574,Sony PlayStation Portable,Ben 10: Protector of Earth,,Games,Europe,ULES-00905,1.00,673284096,4551a1f9,29240bc422185d3c945c9df000967e9a,48db75e14e809fc4b6e0dc024d2bb6aa220e4115 -54575,Sony PlayStation Portable,Crash: Mind over Mutant,,Games,Europe,ULES-01170,1.00,1072037888,e6688dbe,417e16ca75e045456529bb4f241b2447,148641d53727323a08e4fa8d8e87bcbd26717b38 -54576,Sony PlayStation Portable,LEGO Harry Potter: Years 1-4,,Games,Europe,"ULES-01351, ULES-01351/E",2.01,1426784256,bebf03d1,d6d66be3a566efdc060b7b1019fd9f94,9738ba1ca5eae47f5599e37d6f2e16be9354b81a -54577,Sony PlayStation Portable,Dante's Inferno,,Games,Europe,ULES-01384,1.00,1812725760,002d2110,d65a1325e540ac50a04cd3bba2c6ce45,1738562f458ca0a083e45fef3549d16fe4538583 -54578,Sony PlayStation Portable,FIFA 13,,Games,Europe,ULES-01565#,1.00,1293582336,b6ee1f4e,d756c61e8acae658ebe9789e227e1afa,88e7fd10d5402e3aea4ae7822dd15e34d6548b50 -54579,Sony PlayStation Portable,Demo Disc for PSP Vol. 1,,Demos,Europe,UCJB-98302,1.00,905314304,bef67377,907affae3dadf8a9d361f07155342ec6,3f10d6d73c427322bc433a877714f930be5af598 -54709,Sony PlayStation Portable,Simple 2500 Series Portable!! Vol. 3: The Dokodemo Suiri: IT Tantei Zen 68 no Jikenbo,SIMPLE2500シリーズポータブル!! Vol.3 THEどこでも推理 -IT探偵:全68の事件簿ー,Games,Japan,ULJS 00053,1.07,825720832,d74b869b,0d51188ee455656f2aab952f56202617,e9ecbea3298011ed1abbd9e7b55cbce8e6e93f99 -54710,Sony PlayStation Portable,Enkaku Sousa: Shinjitsu e no 23-nichi-kan,遠隔捜査 ー真実への23日間ー,Games,Japan,UCJS 10088,1.00,739835904,e0df5d2a,9f9bb5eec3d2c37f184955b591923e1c,ccfa2fa6f30fa35f248b1acd2990d3bea8591490 -54721,Sony PlayStation Portable,Disney/Pixar Toy Story 3,,Games,Europe,ULES-01406,2.00,905543680,5b4a100c,ac67947409a2ba396a547abfc0cc75ff,97bb8ee0dcdb5f879749ee07b68d198101884d75 -54804,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 1,PlayStation Spot 専用 UMD Vol.1,Demos,Japan,UCJX 90015,1.01,473628672,9d2049cb,b976318fc32577e0c28fbadc247c760c,ad74173551805f704695e943e11ad55eb16965e1 -54805,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 2,PlayStation Spot 専用 UMD Vol.2,Demos,Japan,UCJX 90017,1.01,590774272,48cc709a,d0bc6075261b873315fc3d42fd86eff8,65e24807792d5a116612de1ed748a6017d7fbace -54806,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 3,PlayStation Spot 専用 UMD Vol.3,Demos,Japan,UCJX 90018,1.01,406454272,74150dfc,dd39d4dcf781f081f30731b54a6cb0a6,5686155b9001bd283dec0941b5f88a3b8550e131 -54807,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Vol. 4,PlayStation Spot 専用 UMD Vol.4,Demos,Japan,UCJX 90020,1.00,375128064,4ef92ebf,34b5c9846e77bfb7b52cd2847ddac612,9fd5ded08197e5d2b2c2d576e5673b54c09061a6 -54808,Sony PlayStation Portable,SCEJ PSP Browser,,Preproduction,Japan,UTST-99261,1.00,19955712,a55d954e,744de8364c27a0eb7817acecbd0a5180,d998b217f8827d617e4fbc6efd3e25b086a26071 -54809,Sony PlayStation Portable,SCEJ PSP Browser,,Preproduction,Japan,UTST-99281,1.00,13238272,397f84cb,81b9de6d14723dc591ad2286a16d967e,be6bdc5b916c8322eb5d361a77301c732e514382 -54810,Sony PlayStation Portable,PlayStation Spot Sen'you UMD Version 2.00,PlayStation Spot 専用 UMD Version 2.00,Applications,Japan,"UCJS-90007, UCJX-90007",2.00,48365568,54efa081,6fdf1d3595f11247e3bb29d27f4e93a8,76acad34164c8a9862a4ecd2e9d620191b278532 -54811,Sony PlayStation Portable,PSP System Software Update Disc Ver. 3.11,PSP システムソフトウェア アップデートディスク Ver.3.11,Applications,Japan,UCJX 90025,1.00,42074112,531fbc5b,974bfb7ebb2587a09415953d5887aa8c,e2573f3f8c0f0845205cf6404c669dd6e49ae45e -54815,Sony PlayStation Portable,System Software Update Ver. 3.73,システムソフトウェアアップデート Ver. 3.73,Applications,Japan,"UCJX 90027, UTST-99437",1.00,109314048,9f65d179,e0976780096e4b46c3f80ac0db8ddca9,eb67bde1712791504e1ccb65effee57398c02b34 -54950,Sony PlayStation Portable,Los Simpson: El Videojuego,,Games,Spain,"ULES-00979, ULES-00979/1.00",1.00,760807424,dacea223,712145ff2b5f36f3b1d70dab37a178bc,21fea3d086987047a107744f4b6876f34b47a014 -54952,Sony PlayStation Portable,Hilton Garden Inn: Ultimate Team Play,,Games,USA,UCUS 94341,1.00,114753536,f146e783,e4404d66f290848f146a851a4191dc1d,30403d787bce36968bf2736ddc2f427a14f6abd8 -54996,Sony PlayStation Portable,Monster Kingdom: Jewel Summoner,,Demos,USA,ULUS 80017,1.00,531726336,1fe49334,bca5c7aeb6cb20c892edfe790cb595e8,d957ff8d3722d14612cbb6b4b3c371bf0386da5b -55017,Sony PlayStation Portable,Game Sharing Server Disc,,Preproduction,Europe,UCES-00218/1.00,2.00,48463872,f4dc21f6,f92a916cd8e30868429b472e9c825a28,eed5d991fc0a6aabccf6d8ef756c1598fc2483d7 -55018,Sony PlayStation Portable,Retail Sampler No. 4,,Preproduction,Europe,UCED-00686/1.00,1.00,1561624576,93e41739,f53ec4f6d137ad763e286898c502443e,6d2bc53fa12151f3f4082c687d5977870c5eef64 -55019,Sony PlayStation Portable,Jeanne d'Arc,ジャンヌ・ダルク,Preproduction,Japan,UCJP-00062-1,1.00,828014592,33c5e1e7,49cc30ef723ba8bfd31b0e75d6bfdcbd,c2e16c62b14b0564a864a215e041c0d9d1fb7f9e -55020,Sony PlayStation Portable,PlayStation Spot,,Applications,Japan,UCJP 00018,1.00,42663936,433acb91,2d4d262435949108636a192b21484596,1306262a00ee2447b95e4072b59b3fff31d0348b -55021,Sony PlayStation Portable,Firmware 3.73,,Applications,Europe,UCED-01018,1.00,109314048,8719090b,62e8a6c90ddb0db94a95100931192860,1bcc7158788a8f2149f371438b939d1e5fd8b9db -55022,Sony PlayStation Portable,Updater Test A0304: Game (w) 1.50 + Updater (0304) 9999/9.99,アップデータテストA0304:ゲーム(w)1.50+アップデータ(0304)9999/9.99,Preproduction,Japan,UTST-99332,1.00,226295808,95e05f4a,c4c8857e4338eed413afb8c5bf6be33c,780bffcb392e67f4b24d3cb4252a1d618c04920d -55023,Sony PlayStation Portable,PSP Update Disc 1.00,PSP アップデートディスク 1.00,Preproduction,Japan,UTST-99119,,14712832,397e6867,25bd2ffee63afe4f81f1c7cda020d416,6dc6bcf8caa753a9d69f1159748c499be5d40a53 -55024,Sony PlayStation Portable,Karakuri,カラクリ,Preproduction,Japan,ULJP-00572,0.33,281935872,769b15c3,7524585d75a4eb33fa6fa17cf5ba707d,3702bc41c71fc48ef0b6595d8481709db7de3a59 -55025,Sony PlayStation Portable,PSP Seizou Kensa Disc (1),PSP製造検査DISC(1),Preproduction,Japan,UMDT-99801,1.00,116588544,20d6b5a9,8fda714813ae136c9548b35b34d21edd,74b61c22cbd666fb3b4e67654038a023082d1e15 -55026,Sony PlayStation Portable,Scooby-Doo! Who's Watching Who?,,Games,Europe,ULES-00571,1.00,618496000,b656d028,d562d5fec7df29acc411c56ad6225693,393ab02d317578cde94e16c05b3c38c34b0c6009 -55027,Sony PlayStation Portable,Harry Potter and the Goblet of Fire,,Games,Europe,ULES-00210,1.01,413696000,3fe53151,c89324b997108b50d14e0a80634e35fa,9e6064fb66587c4c2d4de2ba7e15c60b5ae0b825 -55066,Sony PlayStation Portable,Despicable Me,,Games,Europe,ULES-01447,1.00,650969088,5312d8e1,2d75c6ade3a937af34e1e263299180c9,41e26b66c49857d7efc38b0ed523e7bd5109587a -55084,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,Spain,ULES-00561,1.00,1447165952,6181abd4,90d7311f3dd96ce322a64685942a7c5c,64b0c9fa42b22c01ea317674c3789b4655afd6b2 -55085,Sony PlayStation Portable,The Sims 2: Pets,,Games,Europe,ULES-00595,1.00,1517813760,ca4b8967,edf3606872c090bef0cabdef74d83337,e9bcbe447114201f2b0028469167f09e49ccf621 -55086,Sony PlayStation Portable,Spider-Man: Web of Shadows: Amazing Allies Edition,,Games,Europe,ULES-01174,2.00,516456448,e2d49e42,753d6f34f8f1abac4fdb10d1d9dc53a9,2d500aa8efdf99b2b92fbb8eaa28253454510378 -55087,Sony PlayStation Portable,Nickelodeon SpongeBob SquarePants: SpongeBob's Truth or Square,,Games,Europe,ULES-01365,1.01,1417445376,2beae583,a47b17ea0c935da06afda83daa6069c1,55333cda99ec817f28a3552acfd1cbab18778520 -55088,Sony PlayStation Portable,Naruto Shippuden: Kizuna Drive,,Games,Europe,ULES-01516,1.00,1181843456,24703e28,affbc32db639be118e1177dd7bab0211,8c8b3107a0b9e34611d311204251059c24f07ec8 -55089,Sony PlayStation Portable,Medal of Honor: Heroes 2,,Games,Australia,ULES-00988/P,1.00,1226768384,97446e23,1786a97fa96cfa9cbfdcf5916433ed38,4c7551ecf5740cb58dc7909e63ea55b882d8ef56 -55107,Sony PlayStation Portable,Koloomn,,Games,Europe,ULES-00143,1.02,143163392,f4a7589f,5c2c9639645004b285e3fa3fcc46018d,1c9da907cc0c122e60f7bb297b670ba73824dab8 -55108,Sony PlayStation Portable,Il Signore degli Anelli: Tactics,,Games,Italy,ULES-00201,1.00,543817728,c432683f,a224711d4dc15d8268f96f64c6e8b255,8939c390d50e7dafaa0b73e821fbff711e44394d -55109,Sony PlayStation Portable,PlayStation Network Collection: Puzzle Pack,,Games,Europe,UCES-01159,1.02,841187328,08ec66c6,edb148099726727b3c39455dc6ca4e52,17a38ac3379134de182541e058996191f589ca15 -55110,Sony PlayStation Portable,Thrillville,,Games,Europe,ULES-00646,1.00,854720512,dcfbdc75,d598192881ee9a644092158f71a6b39f,7b2844a22fe4364d396ad1708af1b8432ebeaef4 -55111,Sony PlayStation Portable,EyePet Adventures,,Games,Europe,"UCES-01531, UCES-01531/POR",1.00,1027670016,654c4d58,7a5f52de193920d4ab9d3a1a03547dd9,eef5accc88ca20cdd41e5f924af8c5c72246a96b -55112,Sony PlayStation Portable,Professor Sudoku,,Games,Europe,ULES-00389,1.01,1125810176,56ab3ee3,5e0a3707cf9cdb62c04eb92495df13e6,f6bf815b615bc46f69fd79ba2861468b8ee4daa3 -55113,Sony PlayStation Portable,FIFA 06,,Games,Italy,ULES-00164/P,1.00,1198850048,db575fdd,cf46ff55f78a5a111033769fe2b37170,9fe68ec1cd48b2f643e5e4839445fb9cf8adf41d -55114,Sony PlayStation Portable,UEFA Euro 2008: Austria-Switzerland,,Games,Europe,ULES-01038,1.00,1379237888,f4a7d65d,55926e72e20a68a854e574576583b0f8,f5244b862402552a4236a071873161777eccae4d -55115,Sony PlayStation Portable,Transformers: Revenge of the Fallen,Transformers: La Vendetta del Caduto / Transformers: La Venganza de los Caídos,Games,Europe,ULES-01287/E,1.00,1750237184,4f581222,0546ed1f95c7e9b81cf069cbbe74e66e,8f403cb00f718206ca88d67c7a140b03ffd0822f -55116,Sony PlayStation Portable,Me & My Katamari,,Games,Europe,ULES-00339,1.00,1768980480,622629d4,b21ad43b8220a2c11f6d4f2564bbb088,f021d30d2d61b17ca52b49cc6375cd2dda359aa0 -55179,Sony PlayStation Portable,Viorate no Atelier: Gramnad no Renkinjutsushi 2: Gunjou no Omoide,ヴィオラートのアトリエ ~グラムナートの錬金術士2~ 群青の思い出,Games,Japan,ULJM 05835,1.01,1411317760,c92010b3,d279534cf2b9b531fd12377a64740a75,7e2eb40f7fa9c90c9d4509b4c368dc79ab77237e -55180,Sony PlayStation Portable,Hayarigami 3: Keishichou Kaii Jiken File,流行り神3 警視庁怪異事件ファイル,Games,Japan,ULJS 00204,1.01,360153088,9b8a7f2f,765c37dbb7c78e6a20542ef0d85fada0,3af9ab0442d7c4c2b0956eb2b920f66cafedb79d -55181,Sony PlayStation Portable,"Amagoushi no Yakata Portable: Ichiyanagi Nagomu, Saisho no Junan",雨格子の館 PORTABLE 一柳和、最初の受難,Games,Japan,ULJS 00216,1.02,900038656,897f1bb9,fb0d9108f16d63a603f08a11b5a2a0d7,83914c86fd967be62d6aa8ad40622bd8a61aa5c4 -55182,Sony PlayStation Portable,Fushigi no Dungeon: Fuurai no Shiren 3 Portable,不思議のダンジョン 風来のシレン3 ポータブル,Games,Japan,ULJS 00239,1.01,1192886272,4105c2b0,a5a278aaea201bd6d6c5245a2bb8f220,016b0a186d152cca34b110a99c563851e77979cb -55183,Sony PlayStation Portable,Meitantei Conan: Kako kara no Prelude,名探偵コナン 過去からの前奏曲,Games,Japan,ULJS 00488,1.02,716505088,7bbf2ca1,8defe0b0188c134addcea5f686ce9bdc,eb1bc8284ad0a3e106f1a98e5828bc44d895a8da -55299,Sony PlayStation Portable,Scudetto 2006: Championship Manager,,Games,Italy,ULES-00332,1.00,206864384,92619710,f2b039083c37f7c76d9454211e65d7c3,5933154630ee4c6b67b57c7dbe86f0b08639aa2a -55328,Sony PlayStation Portable,Passport to... Rome,,Applications,Europe,UCET-00460/0.01,0.01,838074368,568b8517,0b3da4228acdb97f907e14a8d77de4c4,ea25aa721536ec0c2c613094a765040deb86b187 -55339,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,Europe,ULES-01075,1.00,778698752,7697e767,534521416bfd8790d4e63efbb3705ee9,68714f6a3dabd942d572c9f37cb58af4a7eefdc7 -55340,Sony PlayStation Portable,Surf's Up,,Games,Europe,ULES-00816,1.00,906362880,f789afa3,248afa5e132e38ef0955543fd75a3d3e,9be232920612cda1cb42eb82df1a2aacd8f9dc9d -55341,Sony PlayStation Portable,Buzz! Concurso Universal,Buzz! Quiz World,Games,Europe,UCES-01292/9131366,1.00,1591050240,c00566cd,39b2f0c8a9c5ff3cfdbf935b42568b9a,475b124240d6458fc9eed83ebf06e7781f8a55d2 -55349,Sony PlayStation Portable,Hot Wheels: Ultimate Racing,,Games,Europe,ULES-00828,1.02,866451456,94765d72,c115120bad0dec6956767228728c3524,a0d2ef3edb079c345071882f361126ef2569fd81 -55425,Sony PlayStation Portable,Echochrome,,Preproduction,Europe,"UCED-01060/9991250, UCED-01060/9991656",0.02,195821568,5d2d23ee,75bc959815d5b02f0c40450f5bc58ae1,d2ce5c9e5cd9a32161ddcbbb05eee7609e0e9afe -55426,Sony PlayStation Portable,Greatest Hits Vol. 1,Ceramic White PSP May 2006,Demos,Europe,UCED-00316,1.01,1560117248,5fadd6ee,e4c29d6fdaa5fb0c332fcff4d830e2a2,1d660f0636f4071e51fa9d769a98b15c1feac450 -55697,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Cars: Motori Ruggenti,Games,Italy,ULES-00325,1.00,906362880,de060d79,41c5fedc649dabc763e602ab6cceacc9,6a63c67dc3b50f30ccbc50d3ebd595b85079bcad -55698,Sony PlayStation Portable,Buzz! Il Quizzone Nazionale,,Games,Italy,UCES-01198,1.01,898400256,d691bce7,f74b6bf79af3ad069678f8c18343c63e,5c8ad2a0181a31dcae20c913d7a603e65ff2d77d -55699,Sony PlayStation Portable,I Simpson: Il Videogioco,,Games,Italy,ULES-00977,1.00,774668288,6dd939a3,1c22b53f5a1d5fdab55129bc0d58d49a,855af9807811d00b0e178c2e8af117488a7c0cbd -55700,Sony PlayStation Portable,Scooby-Doo! Who's Watching Who?,Scooby-Doo! Chi sta guardando chi? / Scooby-Doo! ¿Quién está mirando a quién?,Games,Europe,ULES-00573,1.00,618496000,0bc43ad1,084fb8681f4c8b186f7ab6287ab71cfd,232c8b85a25f2a65fb64073805d7b94b942ab88d -55701,Sony PlayStation Portable,Mondiali FIFA 2006,FIFA World Cup Germany 2006,Games,Italy,ULES-00343,1.02,1226211328,1eed5a68,4684ca68df1a761306085d85f12909f5,0dc298e86d1a949e1e883d6f75fa79a703a40556 -55702,Sony PlayStation Portable,FIFA 09,,Games,Italy,ULES-01138,1.00,1229520896,6eaeafb2,b796bc4f667192f2f2f51cfd8527a8f7,bf38f07cbcfcf019d147c0a34fb281ca6b8f828d -55703,Sony PlayStation Portable,FIFA 07,,Games,Italy,ULES-00442,1.02,1245052928,b0a67903,a697324dbdb27798abc3694e1df729e4,462c0216bb8ab331fabc453f183d7a9c66666964 -55709,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,Italy,ULES-00560,1.00,1447165952,02167c39,116a4cc03780d9a0197efc4534e0006c,7b530827bbc2d34208f92d0eaa22c082cfc5dc68 -55710,Sony PlayStation Portable,FIFA 12,,Games,Italy,ULES-01551,1.00,1249050624,d2ac4858,8f91327826b9e9a3a4891f80993626fc,237b03ff7bbea41cdc48b3ccbd4979fd3db30b93 -55711,Sony PlayStation Portable,FIFA 13,,Games,Italy,ULES-01573,1.00,1249083392,aa01457a,9b9a70b1f2a0d1f142fcd810fc3eed25,12a91e5d6f5c9a0b9208328f96a7c953ce14a95c -55712,Sony PlayStation Portable,PES 2013: Pro Evolution Soccer,,Games,Europe,ULES-01577,1.00,1258913792,2a080b07,726cee43dfcd47280c55974e8f7ef4ed,1cfad3de23fc8f5ac93cda76e8bbdd2cf77c3038 -55713,Sony PlayStation Portable,FIFA 14: Legacy Edition,,Games,Italy,ULES-01588,1.00,1249083392,438c07a6,a748c012eb44a93e27d1a3d16e1869ca,3e930015c2585f250040dcfdff376eddb064af01 -55847,Sony PlayStation Portable,UEFA Champions League 2006-2007,,Games,Italy,ULES-00707,1.00,1170505728,fb99ced9,fe924bd27153ece37c8f122e079ea7db,53d0a08062f3f0608f1aa6414b3c73ad10a14fa6 -55871,Sony PlayStation Portable,Football Manager Handheld 2011,,Games,Europe,ULES-01455,1.02,213843968,0365baa0,6281c0b236c267483ef3d388567e386c,9cdb162136ad20e53e1864f8086fa748ef1d5ec4 -55895,Sony PlayStation Portable,Yggdra Union,,Demos,USA,ULUS-80020,1.00,768671744,78af9d97,fee245ba9cb874aa075fe3c6d9bf5889,3c5fc93e68509b0203d8a1cb3b7789e08936605f -55896,Sony PlayStation Portable,Crash: Mind over Mutant,Crash ¡Guerra al Coco-Maniaco! / Crash: Il Dominio Sui Mutanti,Games,Europe,ULES-01172/E,1.00,1576894464,775e8790,e28b3e54e65f20610880be1bf58f7684,d54aaf8d6c63c4ea32f7d83ae1a57105f10b9c7f -55939,Sony PlayStation Portable,PES 2014: Pro Evolution Soccer,,Games,Europe,ULES-01597,1.01,1185316864,c5b4a90d,14012d2767910edf0b6f2e3e73c142fd,6c96aa13c9a8c28ff452b7f2413c025515e34062 -55968,Sony PlayStation Portable,Gottlieb Pinball Classics,,Games,Europe,ULES-00212,1.02,264830976,37a5399d,e71cb3668e8c75d61f899288e3b86a8a,f030097e9d39685b788251464c337af5ecff4130 -56221,Sony PlayStation Portable,DTM Race Driver 2,,Games,Europe,ULES-00041,1.01,1345159168,b4d00d1d,ccd51fdb4adfae0bf27ee116d792c3a1,a35bbf2fe802f4f49e90871cd0e9213eccde7fdb -56222,Sony PlayStation Portable,FIFA 13,,Games,Germany,ULES-01574,1.00,1458438144,49685786,3464581459e696916302b4be1e284019,ca692ea785f9829a36746448935a3341a583af01 -56223,Sony PlayStation Portable,Warriors Orochi 2,,Games,Germany,ULES-01262,1.01,1710522368,c79504a0,756aea2b7e7109af094c8c495c43508a,8b498104d48707545b3823e0767531d60ec9d505 -56232,Sony PlayStation Portable,Secret Agent Clank,,Demos,USA,UCUS 98707,1.00,209158144,6a1985ba,7674b2a4eca95b1b77342262a28c5da5,2029b8bc58ce0b72db36cdd9ce2d953de08a6158 -56277,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,Buzz! O Grande Desafio Musical / Buzz! El Concurso Musical Definitivo,Games,Europe,UCES-01451,1.02,912785408,e7c30d87,7d3b15ac5a71f5cd6f069c0f3aadd7df,8c9f97b32ec5c4e5ea6a2c3f732123ec4768f481 -56278,Sony PlayStation Portable,Crash Tag Team Racing,,Games,Spain,ULES-00171,1.00,1531117568,bb9c22b8,e43420a51a89fb5cf093f3591067904d,5f83886cc5ec12be065f47bee96e33af05d23cbc -56279,Sony PlayStation Portable,Disney/Pixar Cars,,Games,Spain,ULES-00324#,1.01,906362880,a154278e,a4a482e5e8006989ab309dbaedc903b0,92ea4a90ceee3c17ed5c2b1baad8b4037f431d6d -56280,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,Spain,ULES-00737,1.00,906362880,43b89d4a,bbe1c9981ac31f5d50451da2144b8da7,d0122b2d5f90d20b8afe8beb216a4739cc704f96 -56281,Sony PlayStation Portable,FIFA 07,,Games,Spain,ULES-00444,1.02,1305346048,4caebd06,b89ffe15860407aaa889a266ffd229f6,89226ae39d0cdcd183797f835e448e19130b4353 -56282,Sony PlayStation Portable,FIFA 08,,Games,Spain,ULES-00895,1.00,1256390656,17146fa1,be40ba1ceb6b4ac8603776768895ddd2,497e49b27d8e3ed9f87270873da4baef6decf9d4 -56283,Sony PlayStation Portable,FIFA 10,,Games,Spain,ULES-01323,1.00,1327562752,05363593,9eb12fe673056456c5185c21f81307b3,98b0d3448c512aa65e002a32385cddad81a9e483 -56284,Sony PlayStation Portable,Marvel: Ultimate Alliance 2,,Games,Europe,ULES-01343,1.02,1788575744,ff7dd2fd,146f9e2ae5815f1511c09afe780f6b34,debb19ce7ed1faa0d6e9dbfe327a659a6ecb184f -56285,Sony PlayStation Portable,FIFA 11,,Games,Spain,ULES-01479,1.00,1327333376,062cc32d,986e82df5caaefdfed4842c3d6205e5d,0e49d7a6dd1e8aed3ad3acf55d1e7e54699d5995 -56286,Sony PlayStation Portable,FIFA 11,,Games,Spain,ULES-01479#,2.01,1327104000,f8b40a52,4836c665305b9dd7b9e4e77890cb7b81,66007c85591a6648b6345000f1cdd54270457071 -56287,Sony PlayStation Portable,FIFA World Cup Germany 2006,,Games,Spain,ULES-00344,1.02,1237909504,7e6bc7cb,362cbfba7061acbfb4177ac46257080c,94c4fc656659623914db3aadd382997bc3edccb0 -56288,Sony PlayStation Portable,F1 Grand Prix,,Games,Europe,UCES-00004#,2.00,634617856,0a20ce1d,27e2e4452716b0a62a6b174449acff71,f33c349f0fe25cdad67b1993b5414fadb1f22089 -56289,Sony PlayStation Portable,PlayEnglish,Playenglish: Desvela el Misterio,Games,Spain,ULES-01440,1.03,855408640,6fa3e067,7798543802149603c08bb1db6dd36640,911f01a78d06fb59d7bcbab79c4ad9a5b978c039 -56290,Sony PlayStation Portable,Geronimo Stilton: Return to the Kingdom of Fantasy: The Videogame,,Games,Europe,UCES-01563,1.00,1295187968,8dfacabd,4d13e78f9182579e43d0efc67c945476,14bb96b62c14fd359fd6a5afe71409ce70f22a54 -56291,Sony PlayStation Portable,Harry Potter and the Goblet of Fire,Harry Potter y el Cáliz de Fuego / Harry Potter e il Calice di Fuoco,Games,Europe,ULES-00216,1.00,493846528,72fc312d,d551db40901c6c8de4964736dfbf91a0,16a6b215fa0d094fda3d5f77614955dc1033a69a -56292,Sony PlayStation Portable,NBA Live 06,,Games,Spain,ULES-00158,1.00,1233944576,a09dc126,a8dec54062a214526ffa0ba509d552f4,d9b7b6b5a8d389cd12c6e782cebf2ceb3d71366d -56293,Sony PlayStation Portable,NBA Live 10,,Games,Spain,ULES-01310,1.06,1205108736,2ae4cb18,11e456ad36d3d569ef0bffd0cb2d3336,c03c04eaa4d21d8c6ac6594267b134a69c0362a2 -56294,Sony PlayStation Portable,Nickelodeon Bob Esponja: Atrapados en el Congelador,,Games,Spain,ULES-01486,1.00,1407778816,3ddac233,e9ac13600d826d1bbecf8ee5093dcc3d,a54a3a6b62e8869fd7240f45bff8583f3eb68089 -56295,Sony PlayStation Portable,El Señor de los Anillos: Tácticas,,Games,Spain,ULES-00202,1.00,544014336,36dd6bbe,8765af63c679afd822d4688162411cd9,5145bcaaf12d6857b72121d49d0111e898d34ac6 -56296,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,Europe,ULES-01470,1.00,1461321728,d6585fdd,99e593bf100f8862898a93dde50b5035,9d62595916f6033a04c4de14ad504a9d9f1a65c9 -56297,Sony PlayStation Portable,Spider-Man: Friend or Foe,Spider-Man: Allié Ou Ennemi / Spider-Man: Amigo o Enemigo,Games,Europe,ULES-00900,1.01,875036672,7c1e59bb,c42769d4fdd2dfb4337bff7027286fcd,b3300ebb64c4e270241bbef9a0843e2d59935e80 -56298,Sony PlayStation Portable,TOCA Race Driver 3 Challenge,,Games,Europe,ULES-00613,1.01,1230962688,996ae897,072d1247265d497e95bd0195cb0cda3a,5e1bbb3f489606eb046ed559aa681bf4bb8bc301 -56299,Sony PlayStation Portable,UEFA Champions League 2006-2007,,Games,Spain,ULES-00709,1.00,1203699712,74bcc774,a6242a21acb2930fd4211f680925418b,b0d10fef530ca78fd3ead765f3efe8146933b576 -56300,Sony PlayStation Portable,X-Men Legends II: El Ascenso de Apocalipsis,,Games,Spain,ULES-00191,1.01,1324351488,daa90427,8f12b01a19b9c62de2eebef561dbd03e,ee23a5592a53165534b1033b187fdd0b40c52eba -56301,Sony PlayStation Portable,X-treme Party,,Games,Spain,ULES-00393,1.01,882212864,df547d3f,f98754c7580c378bff92250e3455ed6d,a4691125a05e49770b0a3e20a1bd425c91da56e1 -56397,Sony PlayStation Portable,La Brújula Dorada,,Games,Spain,ULES-00954,1.00,1263632384,bcd9d268,4a29194401fb5846e908ab52567c62b6,fb8441c420955c1c18c24dbdec77d87550320eed -56398,Sony PlayStation Portable,FIFA 12,,Games,Spain,ULES-01549,1.00,1327104000,0c97c7cc,7b7c933e5b0fc58b929e9e90ed54bb8d,9232bb251fbb512227331a3e92579a5ded3c5b10 -56399,Sony PlayStation Portable,The Secret Saturdays: Beasts of the 5th Sun,,Games,Europe,ULES-01363,1.01,844103680,c9d873fd,f0ec6a578e462278ca065deb5737d6f2,836874b0d61a12a1870442b7d6573b9afa79dce2 -56400,Sony PlayStation Portable,Tony Hawk's Underground 2 Remix,,Games,Europe,ULES-00033,1.03,1257472000,0b0c750e,224d20d4d69fde6a7d60433a86bfc484,fbc40f676b4c8553876b101e73ee6b3d67b91006 -56431,Sony PlayStation Portable,Disney/Pixar Up,,Games,Spain,ULES-01256,1.00,525926400,9e57ed6a,e01ac45e9b3ad9a31a501103b3d80333,963dd9144c6f1d8078b2116a5f53a6ebcd867b7d -56486,Sony PlayStation Portable,Autoescuela Aprueba Conmigo,,Games,Spain,ULES-01366,1.02,244449280,bc028118,87a37e9e190c947b332dcd47a5a3b9e8,7524a6cfdcff6f119ff4fa794d7a6eac8a07985b -56487,Sony PlayStation Portable,Super Hind,,Games,Europe,ULES-01091,1.01,412483584,a14ed00a,e257f6116257b6f3a64553ae8d1db407,4dc27cff15ad854dcf9eb510bab042988ae2f0d2 -56503,Sony PlayStation Portable,Gun Showdown,,Games,Germany,ULES-00485,1.00,788234240,9810a7ea,541f531b4f985ab1395b18ce99c022c2,dc944018db5a5fabe6306512a69b3a48d8040cca -56504,Sony PlayStation Portable,Freak Out: Extreme Freeride,,Games,Europe,ULES-00783,1.02,653230080,2c1628af,1111655958a6eccfbbf5b2173715b626,a3fcf7093970347932415092c951251fa7624d77 -56522,Sony PlayStation Portable,Real Madrid: The Game,,Games,Europe,ULES-01219,1.01,659619840,04c7b0af,7cfb047b5df01ea7ff87f89808e9fbc7,c4f2d5c39a9ba79fffb010b7d783f55f4d2356c3 -56523,Sony PlayStation Portable,Transformers: The Game,,Games,Europe,ULES-00825,1.02,1566605312,0b814ae9,9504d884957458b18c96666cee27e0bf,fdc70e4dffb2ba53c1bee5d1449e8b4de5312e4f -56546,Sony PlayStation Portable,ATV Offroad Fury: Blazin' Trails,,Games,Europe,ULES-00155,1.02,661782528,746ec423,e67383f6156cb6c1592393fd235aa74f,db40b55d222227e211d32913f486cfe7b5613e69 -56547,Sony PlayStation Portable,Bakumatsu Rock,幕末Rock,Games,Japan,ULJS 00598,1.00,1429602304,5f50d64f,f4c15ba3f5236b893b86952a522ce89c,b8ae5b1b71729f2408bb200aaf89d33f61087df8 -56548,Sony PlayStation Portable,Eiyuu Densetsu: Sora no Kiseki FC,英雄伝説 空の軌跡FC,Games,Japan,"ULJM 05170, ULJM 08033",1.01,1756299264,357cc185,ad33c01ff2d4bb3e8e578e2da3904210,081969fcbedf9f62e9a8a16961255030c7067bb3 -56549,Sony PlayStation Portable,God Eater Burst,ゴッドイーター バースト,Games,Japan,"ULJS 00351, ULJS 19056, ULJS 19081",1.01,1462435840,32b8a5b9,1d6dbc1cd81be6257ce014cac273c275,55764fa796c0185dd9c77900fce1f8df6737c6f9 -56550,Sony PlayStation Portable,Pro Yakyuu Spirits 2011,プロ野球スピリッツ2011,Games,Japan,ULJM 05772,1.02,1581711360,fe66f35b,537b3a802fd0d173972e8e0753698451,1c1f291b8752fdda29b3d68e5c6932648db0222c -56551,Sony PlayStation Portable,Toriko: Gourmet Survival! 2,トリコ グルメサバイバル! 2,Games,Japan,ULJS 00483,1.01,888209408,6173aaa4,f7568baf3e140cf5a9d4d94b857bda27,9666611453adf9f59d7d762a841b6447b3483549 -56552,Sony PlayStation Portable,World Soccer Winning Eleven: Ubiquitous Evolution 2008,ワールドサッカーウイニングイレブン ユビキタスエヴォリューション 2008,Games,Japan,ULJM 05270,1.02,1372618752,fd9bf6b0,b57c1f60cdfc120804865760620bc071,89c37816e8ffe88581fa6c9964c961517c355da8 -56630,Sony PlayStation Portable,Lemmings / Go! Sudoku,,Demos,Europe,UCED-00308,1.01,219054080,24e15754,837c413eaf3ee924dd1d27761bfaef81,08fa23b2b942b733e32e9a6cc4170cb4a1e4bffe -56631,Sony PlayStation Portable,FIFA 13,,Games,Spain,ULES-01572,1.00,1327136768,2367bdfb,9c6a234f64ac45f9903184e77f16cb7b,fa623b7b1f0448fc25f4a1b907d97d33458fffac -56635,Sony PlayStation Portable,Crash Tag Team Racing,,Games,Italy,ULES-00172/E,1.00,1543733248,426982e2,8455e9d0d315b5807af27f19e3004f4a,be0943f48566b24bf0208cda3970876316787ddf -56636,Sony PlayStation Portable,Football Manager Handheld 2013,,Games,Europe,ULES-01582,1.01,216793088,9c185a26,d1974b072ca609fe437ee8fed3eb70e7,8cac167c1b7f0b52ecf70f8048ade4c6ec65a46b -56637,Sony PlayStation Portable,Ford Street Racing: L.A. Duel,,Games,Europe,ULES-00564,1.00,734003200,a79fad01,1e7646d323bf13e80212ae11d7a0c159,806c7886bc86e72a07007927b24f9f8fd1b4ffb2 -56638,Sony PlayStation Portable,Marvel Nemesis: Rise of the Imperfects,Marvel Nemesis: L'Ascesa Degli Esseri Imperfetti,Games,Europe,ULES-00159,1.00,906330112,468e8ef7,50d09c6f43a11bc56e8eb64749bd267a,4d449e21eaf4424b94babb1c1f3833ebed55b072 -56639,Sony PlayStation Portable,Mind Quiz: Exercise Your Brain,,Games,Europe,ULES-00701,1.00,99057664,9ed7503e,8e173e422ee521b0dbfdb4b272684e22,7f6c6b339b48041e749173f71c430cc0c591cff8 -56640,Sony PlayStation Portable,NBA 2K13,,Games,Europe,ULES-01578,1.01,1773928448,3eedb50c,81353ed3d461bfa1f13f9b29ab3011e0,3ca8ef54e79f4308896142440ca7fd1c2e8aaa48 -56641,Sony PlayStation Portable,NBA Live 08,,Games,Europe,ULES-00921,1.01,1754923008,928c8369,0116587f8e018233628aa81416752c7c,f4a932714bb54950574383898e9f92a977c3c8c3 -56642,Sony PlayStation Portable,Pro Cycling Season 2007: Le Tour de France,Pro Cycling Stagione 2007: Le Tour de France,Games,Europe,ULES-00849,1.06,565346304,f72a0c51,2bd58c263ced614e655e48050b41d747,d2d320f7be1ae841fb4433cd52978955e9ee64e1 -56643,Sony PlayStation Portable,Tiger Woods PGA Tour 10,,Games,Europe,ULES-01260,1.00,1474101248,d8ee64ee,c529238502aed7cb35abaf692448ca66,5ab5e29d2d5bc3a89cb579e8f0cb45c2f0c2da58 -56644,Sony PlayStation Portable,TNA Impact! Cross the Line,,Games,Europe,ULES-01305#,1.00,1410498560,a51e2827,7d106d0db8e7d5d45b305d9f1e1f1cb1,ee606ac75a72bb413c08eef97c8a1219e0930f42 -56645,Sony PlayStation Portable,TOCA Race Driver 2,,Games,Europe,ULES-00040,1.01,1345257472,a9da05e6,c577b620ff73ea411806234c3e6b8eda,9ae51f8d929d53fb4d95b48ef9bc49c35d0f62d7 -56646,Sony PlayStation Portable,X-Men Legends II: Rise of Apocalypse,X-Men Legends II: L'Era di Apocalisse,Games,Europe,ULES-00189,1.01,1324351488,99e14578,5d52b283caf580a38ca23e5941b781fa,d302dcff603b2a79a74f427d4e646da33ab41646 -56672,Sony PlayStation Portable,Myst,,Games,Europe,ULES-00412,1.02,1552384000,82b1e6c9,e351970fbc6784216dcde268b16c71a4,967488afb34359af89b2bad2289ef22235631f10 -56673,Sony PlayStation Portable,WRC: FIA World Rally Championship,,Games,Europe,"UCES-00005, UCES-00005/P",1.02,1697415168,56c3e5c2,bb3d862ed7144a5a871f49f593212909,9620d4574b9b6324c9ec279578a08a79f245466c -56686,Sony PlayStation Portable,WipEout Pure,,Preproduction,Europe,UCED-00017/0.1,0.1,201097216,83721422,f5a280361930cbcd21fc9f5d9e997f29,273093f5dc6b6161771fa78508a3fc5ddbf19804 -56713,Sony PlayStation Portable,2010 FIFA World Cup South Africa,,Preproduction,Europe,ULES-01413/1.00,1.00,1671331840,2bcd40b1,4d07097a3b42be32877ea1b2dbc7d257,8c143ca5aeb84fe2c1f5b75e9a33826d47dc1a72 -56714,Sony PlayStation Portable,Buzz! Quiz World,Buzz! Visailun Maailma,Games,Europe,UCES-01295/FIN,1.00,1500413952,70941737,8e87d2509feec6b8c85b87b089e2a4d7,510d8c17a7adee08f6261cf8de28a097c2cfcc09 -56715,Sony PlayStation Portable,Buzz! Svenska Genier ~ Buzz! Suomen Neropatti,,Games,Europe,UCES-01204,1.00,1528004608,474464fe,ef3cbe28a1575108b89f339a5e088a22,70a0c67a190c9fd3fd6e7c02d7479a050150ae12 -56716,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,UCES-01041/9978053,1.00,1442086912,f90c9143,7d80429d0b9481c0497add93684fbc8e,9ab62fd9f4f48a04765111a45294d4ad3fab1603 -56717,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,Buzz! Suuri Musavisa,Games,Europe,UCES-01454/FIN,1.02,917274624,2d9a94a3,b3e96aad70b57a27cc1fc146c7ad4b1e,221e3da6d925b0f5504c879658d44bbf50d6ba7a -56738,Sony PlayStation Portable,Danganronpa: Kibou no Gakuen to Zetsubou no Koukousei,ダンガンロンパ 希望の学園と絶望の高校生,Games,Japan,"ULJS 00438, ULJS 19060",1.00,1801584640,d4ed9d84,e653e69da189d9acd71c598297ff5e31,fdf4875a5e4b631579db18512a12468469fc3b74 -56739,Sony PlayStation Portable,Uta no Prince-sama: Music,うたの☆プリンスさまっ♪MUSIC,Games,Japan,ULJM 05977,1.01,700153856,1596c09d,d6cc7af0d3c6b27f7bd9cc3480288f09,971b1fd139db541249d6a06a6418218bc60a25da -56740,Sony PlayStation Portable,LocoRoco 2,ロコロコ2,Preproduction,Japan,UCJP-00164 #66,0.01,1710489600,da873ab9,18103e66aea925ad28e5325f50b8335f,d86636617a50dd3cf53f3eb3b9688d80e8e83fd7 -56741,Sony PlayStation Portable,Navi-Chu,ニッポンのあそこで,Preproduction,Japan,UCJP-00138-0,1.00,559546368,cf8a7366,43d0a5fe4978403f0385713acee26591,69f7b2e3ff7a9981ed56f8e41747f149cfbf04d9 -56742,Sony PlayStation Portable,Patapon,パタポン,Preproduction,Japan,UCJP-00125-0,1.00,247463936,3aa116ff,ea86a577dc852493fd3eeb99470dd245,ee5a2138caa724f9144ef8d8810a23cf083b2108 -56743,Sony PlayStation Portable,PSP Camera 01,PSPカメラ #01,Preproduction,Japan,UCJP-00060-1,1.00,78512128,061b97d2,946d0e69399ed66b48b4e0262f64a31d,4da31f755c3c6b5fa48029543518ed6de9335493 -56744,Sony PlayStation Portable,PSP Camera 03,PSPカメラ #03,Preproduction,Japan,UCJP-00067-1,1.00,100532224,03674d1c,8dad0f288d147460adc1fcfe4aa25b7c,3a18e2167cf81a6d21e027e8ee5ae811ac2f939c -56745,Sony PlayStation Portable,Ratchet & Clank 5: Gekitotsu! Dodeka Ginga no MiriMiri Gundan,ラチェット&クランク5 激突!ドデカ銀河のミリミリ軍団,Preproduction,Japan,UCJP-00103-0,0.01,658702336,61ff65d2,8f6dab9af7fc14bab08a2e6c3bde9b97,9d7c2865e367f83296f05f91daeba58ede78de54 -56746,Sony PlayStation Portable,Resistance: Houfuku no Toki,レジスタンス ~報復の刻(とき)~,Preproduction,Japan,"UCJP-00174, UCUS-98668",0.10,1654358016,38a2b660,3342050d4aac78f3e27aa0d2a1b90f4e,b9891a8516da066feda7a5b88d060238f4e16f1f -56804,Sony PlayStation Portable,NFL Street 2: Unleashed,,Games,Europe,ULES-00036,1.00,695861248,9d5026fd,a1cfa9f990d958676f8ffcb3e5785cec,929ae5bc960221e1abfba976040e7d14977891aa -56805,Sony PlayStation Portable,World of Pool,,Games,Europe,ULES-00821,1.02,206340096,4ae6943e,cde084c22f753a0e6d90a8190469cfcd,1ff6eea7ee88f30eaa6cfeac8f455740f1d5450d -56822,Sony PlayStation Portable,FIFA 11,,Games,Italy,ULES-01477#,2.01,1249050624,568e2cb9,3902486cf4cfd00c5d5e3bfa18a31205,1c7909610758eaa1c1c7a7267b82dccd64f2ddf3 -56823,Sony PlayStation Portable,Puzzle Chronicles,,Games,Europe,"ULES-01356, ULES-01356#",1.00,402948096,db2e9d23,41f35ab3ce1096952610e0ed593934a1,7ca5bf5e1bb36cb6e3006d89364b605144a58e77 -56844,Sony PlayStation Portable,Donkey Xote,,Games,Europe,ULES-00836,1.02,819429376,587346b9,ec1e52267b12255e8462467a468ffe4e,ac31ad53ae0dbd88b1b13586962f2cf331e3909f -56845,Sony PlayStation Portable,Juusei to Diamond,銃声とダイヤモンド,Games,Japan,UCJS 10092,1.00,737017856,da67f712,e92d7088f7c8ca3442fe211c48796bc3,9a11c6353ecb388400dc8a2347b21ba478cf676f -56846,Sony PlayStation Portable,Trick x Logic: Season 1,TRICK×LOGIC Season1,Games,Japan,UCJS 10097,1.00,718307328,473469f6,4d27b0fccce2eaab86e992d8127c77ac,58e56644f585928fb584c0304767069e827d87a1 -56847,Sony PlayStation Portable,Infinite Loop: Kojou ga Miseta Yume,インフィニットループ ~古城が見せた夢~,Games,Japan,ULJS 00144,1.01,937492480,99f4c6b9,3aaefdaa3b109476d47be5cb5e780e06,765d7204476b95a495f1f0ac8b1a1f23a5269574 -56871,Sony PlayStation Portable,Saru! Get You! P!,サルゲッチュP!,Preproduction,Japan,UCJP-00003,0.16,599687168,99141b3b,75cc84f54ae6d2ea2ae3e34dada26ceb,7c7e44f201e648740f2d0257e7f7012263a214f2 -56872,Sony PlayStation Portable,Mugen Kairou,無限回廊,Preproduction,Japan,UCJP-00139,1.00,163282944,49d004c2,62a829a3c855b62ffdcf955d6b0601f0,d6bd4d81636087e09a052286d71860a8d52be9eb -56873,Sony PlayStation Portable,Clank & Ratchet: Maru Hi Mission * Ignition!,クランク&ラチェット マル秘ミッション☆イグニッション!,Preproduction,Japan,UCJP-00154,0.01,1115258880,e759bf66,41a7e6c68bf6c2012bd36dbeaa61778c,b93c95aa4478b6b6eaa9787ab96566a027624a76 -56874,Sony PlayStation Portable,Twelve: Sengoku Houshinden,トゥエルブ ~戦国封神伝~,Preproduction,Japan,ULJP-00523,0.00,1677656064,6534dab1,793fe1fc258ff75ecad5ed28e89a05be,fd7afb4888393107d6a8d1fef696947954ff309f -56983,Sony PlayStation Portable,Final Fantasy III,ファイナルファンタジーⅢ,Games,Japan,ULJM 06133,1.01,904364032,ca628fe4,119e6f7479e7fce676d6a46821e5eea8,16daca644b74a9c2bd21c70a2d27857ee33e3890 -56984,Sony PlayStation Portable,Anata o Yurusanai,アナタヲユルサナイ,Games,Japan,"ULJM 05279, ULJM 05351",1.01,652541952,112f0f6d,88d9091335e3167eed8449a639089cd4,6ec0b206e40fc063134a20a171b2dd64b0dbe454 -56987,Sony PlayStation Portable,The Idolmaster Shiny Festa: Groovy Tune,アイドルマスター シャイニーフェスタ グルーヴィーチューン,Games,Japan,ULJS 00545,1.02,1614315520,a4f6127b,96a039a5f7ea9348e102dfcf7fefbd3b,a6be75bd722b0d537e740f62c428f1ad436e2342 -57001,Sony PlayStation Portable,PES 2014: Pro Evolution Soccer,,Games,Europe,ULES-01598,1.01,1209335808,95ab79a9,717fca3cc3e533e1c14deb050507a7b8,f7675a41ccae7c791718a3af8521e4c63dce6611 -57023,Sony PlayStation Portable,AFL Challenge,,Games,Australia,ULES-01299,1.03,156762112,ed525d91,e971cdea3a9c426a363837a220f58f20,d7c9ebb55f0490e60f8c9f2ee0c57cc19cabfe24 -57024,Sony PlayStation Portable,Buzz! Brain of Oz ~ Buzz! Brain of New Zealand,,Games,"Australia, New Zealand",UCES-01202,1.01,1560543232,32f7d8fc,70fe232a98b9daf3a3f564761e9d9145,c382f0d53e92d83b190505816984421e96c1dc24 -57025,Sony PlayStation Portable,Buzz! Quiz World,,Games,Australia,UCES-01293,1.00,1658486784,6157eaf3,b952e78012c963681b507aad09523717,5de05630f38c15ca220c30536ea0d82f433b8f88 -57026,Sony PlayStation Portable,Ricky Ponting 2007: Pressure Play,,Games,Australia,ULES-00815,1.01,385908736,4bc9d524,da9bb23145a7f6af82e4804757e82f2d,68c89df38472e70baceb420358005bd622200045 -57027,Sony PlayStation Portable,Sudoku Coach,Carol Vorderman's Sudoku,Games,Australia,ULES-00387,1.03,421789696,70f138c5,1b07c212733b02dc1753441cf69ee363,3df9f169f75dfadc3cde8144ef4de4e076613b36 -57028,Sony PlayStation Portable,Syphon Filter: Logan's Shadow,,Games,Europe,UCES-00710,1.00,1623359488,881832e4,f284140e702390431dc540e82ac1ccc8,c6759967f1ca51cb2bf9ce032cc81bda0533f251 -57029,Sony PlayStation Portable,FIFA 14,,Games,Europe,ULES-01586/E,1.00,1293582336,a8d62c02,29903c43b51c219f54ce5fd43ac7e0b1,42af577da30f4545af2297f631a2761e18514827 -57030,Sony PlayStation Portable,Tom Clancy's Ghost Recon: Predator,,Games,Europe,ULES-01350,1.00,906362880,2f3c200d,da5af2673097183c17e8f3f83170de66,b7dee2471f4091614c31cd1c4151249d5172b002 -57031,Sony PlayStation Portable,X-Men Origins: Wolverine,,Games,USA,ULUS 10411,1.01,657948672,2e3845ab,30864a5e6b4493185f5b7beea20e547f,11da60eed4832a7f2f7f2ef8b91562e20e628b39 -57032,Sony PlayStation Portable,Dead to Rights: Reckoning,,Games,Europe,ULES-00195,1.01,191332352,bfdf323f,78498c4316033ebb4189bf4e855d9e53,06051717047aed04f60ab4c542e7231ef8653887 -57033,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,Europe,ULES-00151,1.05,1255243776,2abcb3a6,17cd20ebfae0c1d992a74f91234c96e6,e3f495ae0091de0370a257b2f1a444f5c653c06d -57041,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 2,,Demos,USA,UCUS 98692,1.00,351240192,ca375e11,16debe09cc5330edc4134855b99b8f75,e52dab2bf4c72902e93e49b3523421a8b7443eb3 -57042,Sony PlayStation Portable,Family Guy: Video Game!,,Games,"Europe, Australia",ULES-00567,1.00,1188986880,f1422b7e,fb8352ef1ab886449b2350413438c1db,33fd3b76cbc9d6b66a6b501cebba5f2a19f29c96 -57043,Sony PlayStation Portable,FIFA 14,,Games,Spain,ULES-01590,1.00,1327136768,b1e6ef6a,e553b41b81c12b91208037dcf1506dc4,b6d4030de0e9233e36d964543909b72284db67df -57047,Sony PlayStation Portable,Hannah Montana: Rock Out the Show,Ханна Монтана: Жизнь на сцене,Games,Europe,ULES-01304,1.00,906362880,97003284,b3466095a47ee3f015b7c2e30d9604a5,ed405d96a13e231682091608094ac873c91e2ccf -57048,Sony PlayStation Portable,Kamaitachi no Yoru 2 Tokubetsu-hen,かまいたちの夜2 特別篇,Games,Japan,"ULJM 05110, ULJM 05268",2.00,906592256,3809e94b,ce24f49bda1bcdc286e5a205feb443b2,b2cc85c03a9c74aa4ceb077e5a6e14bc8193aefe -57049,Sony PlayStation Portable,Musou Tourou,夢想灯籠,Games,Japan,ULJS 00284,1.02,662306816,0cddebcc,5e88e5d4f091c193326caa4e75ee3703,07e52532248beb8b523ab65c3944cdd8a1e134ca -57050,Sony PlayStation Portable,Fushigi no Dungeon: Fuurai no Shiren 4 Plus: Kami no Hitomi to Akuma no Heso,不思議のダンジョン 風来のシレン4 plus 神の眼と悪魔のヘソ,Games,Japan,ULJS 00547,1.01,397082624,a08bca19,dad6db838f13952cf62de7aef42a5984,598ef880c16d5dec971bac84560f18198a00c7a7 -57051,Sony PlayStation Portable,Kuon no Kizuna: Sairinshou Portable,久遠の絆 再臨詔 Portable,Games,Japan,ULJM 05981,1.02,774733824,33f94b65,994e8411d87202116030410df3416bfb,c76eb2761a97e6d680d817a2214165ecd88f8639 -57052,Sony PlayStation Portable,Stealth feat. WipEout Pure Stealth Edition,ステルス feat.「ワイプアウト ピュア STEALTH edition」,Demos,Japan,ULJM 05105,1.00,1789263872,4bbb4bc1,d5f0eddba241a9fed6e73d25cda85b12,cbbacfaf03ce9265e3ce562521999785743ec990 -57110,Sony PlayStation Portable,"Holy Invasion of Privacy, Badman! What Did I Do to Deserve This?",,Games,"Europe, Australia",ULES-01332,1.03,247300096,167b5e7a,2d9d6570c71814d40b1eef42916f512e,09f2d4479ed19ca081465fe87c15319d5d9b22a7 -57111,Sony PlayStation Portable,Wild Arms XF,,Games,Europe,ULES-01085,1.00,1681227776,383ba1cb,4e6dd7c8b248252c639d2862615edaca,18fd16c40dbef0c29a985d2ceb646b379baad562 -57112,Sony PlayStation Portable,Worms: Open Warfare,,Games,Europe,ULES-00268,1.01,225247232,65ba47a6,e3b3ed26f60415b8a0423e5a6d25f675,8b0e2785868edcad0532f89cbb2a1d4db66524f4 -57230,Sony PlayStation Portable,BlazBlue: Calamity Trigger Portable,,Games,Japan,ULJM 05613,1.01,772931584,5e490532,ddaf642f38dabc31f00f2af5449ad082,4dcda54e07d228a031b3cf91e356fe3b0e045924 -57231,Sony PlayStation Portable,Rezel Cross,リゼル クロス,Games,Japan,UCJS 10023,1.0,1543372800,d926e1eb,d48f7ae52821da54015aced22d1a09a5,d3d3d239e50aeeb3f4615146337241518f3460aa -57267,Sony PlayStation Portable,Arthur and the Minimoys,Arthur and the Invisibles,Games,Europe,ULES-00668,1.00,1796014080,a6c67959,8534d2eee8c63c9cf999fcf3e8a961d0,9eb42368f857f5a5dd696ac1eeb0398f56759062 -57268,Sony PlayStation Portable,Code Lyoko: Quest for Infinity,,Games,Europe,ULES-01095,1.01,895877120,dda9eac8,4c4f8fa6776c01f7fc9412e0a96b0c7b,98182bbcf2de270e9799ff566ab89df8a8f88be5 -57269,Sony PlayStation Portable,Gottlieb Pinball Classics,,Games,Europe,ULES-00213,1.03,264798208,a4fc1f56,6841c442cf8d4e76ab055c261dbd15ce,b090022312324bcd9a990702f896356e6855e78c -57518,Sony PlayStation Portable,Naruto Shippuden: Ultimate Ninja Impact,,Games,Europe,"ULES-01537, ULES-01537#",1.01,1073577984,6ddfc31e,0a0f2da550f85d90ec1348cb48fc0485,07558f3d00f424b0dd0e081038f5e1262c61184d -57567,Sony PlayStation Portable,The King of Fighters Collection: The Orochi Saga,,Games,Europe,ULES-01191,1.01,1532887040,c093f221,44cbaa1bab8c041a318827b1ae0ac83f,8e0372b243ace527b3360e901a064c068204d91b -57864,Sony PlayStation Portable,Pac-Man Rally,,Preproduction,Europe,ULES-00705/1.03,1.03,420937728,6849cc0a,35883ebc98dcc28fdc32e88faa9a0053,ccfb29d6a72089cbc4cce87764e06b61e9ae379e -57949,Sony PlayStation Portable,Street Cricket Champions 2,,Games,India,UCES 01579,1.03,404488192,a41dce10,a8264e120e83bc1ef36ece46216a063f,58a1a66923c747dbfbde6d209803d9f20c8ec8a3 -58113,Sony PlayStation Portable,International Cricket Captain III,,Games,Europe,ULES-00835,1.01,126484480,89dd0a82,e10c90022ca091c10b58a98af96f9dd2,785cf8c098415865edded2f24097532d88a4216a -58114,Sony PlayStation Portable,Rugby League Challenge,,Games,Europe,ULES-01283,1.00,181436416,62fd3d3b,f7625952c0bbce5d380e1413921d8b18,54dcfa00a707630b84775a6665ed210abe109e20 -58115,Sony PlayStation Portable,NASCAR,,Games,Europe,ULES-00457,1.01,733446144,c1e91551,6cad49885a224a1e60c2b4fc3a7ae98e,3bc4d3be07f2ba21899feae4888530d07efdf7bc -58159,Sony PlayStation Portable,Astro Boy: The Video Game,,Games,Europe,ULES-01345,1.01,1153073152,d1c45a85,b7c0b582018d11d852668a4b63a989a4,16b376733bf170d3ce225c313ab38d4624995074 -58160,Sony PlayStation Portable,Blazing Souls Accelate,,Games,Europe,ULES-01562,1.02,1103036416,c2eaa7ea,c2b311f39fbaed90bf04ec97664c8eda,7f89b95d977129e4b24562bf88db9a9c6a197f45 -58161,Sony PlayStation Portable,007: From Russia with Love,From Russia with Love,Games,UK,ULES-00290,1.00,792035328,ed656b41,d2d173f5b94f7ce21bbdc8c0af662f10,0bb69019b559d693d73f8e147bc0e11746889172 -58162,Sony PlayStation Portable,The History Channel: Great Battles of Rome,,Games,Europe,ULES-00798,1.03,632782848,d75c8bdf,0bb34155daecf125722893aa0d7c17d7,969014b0ab3281e4fe6d6ecf1a524a432dade78a -58163,Sony PlayStation Portable,Infected,,Games,Europe,ULES-00337,1.01,899514368,44c62045,acbb4800a3c03ad1e7e6dc855130bc85,f90c9fadf6f6d062058a3a2aebd32ddbfe9d3686 -58164,Sony PlayStation Portable,L.A. Rush,,Games,Europe,ULES-00554,1.01,1395163136,a4039632,0f911782c0a575ced3f5985586143583,d8db314047ef659cf97a61f0b55ef7a90733a3ea -58165,Sony PlayStation Portable,The Con,,Games,Europe,ULES-00509,1.02,792985600,03cab074,18bd1ef2c27b72d07eb8ac52d85eec00,10b376de56059e8a1507c8408c7e4910f8d7fc9b -58166,Sony PlayStation Portable,Warriors Orochi,,Games,Europe,ULES-01054,1.00,906297344,76e06584,09e9f02fb145a37fa39f29bb572e9f78,bc77a1bd7fe754f6a70d651d6863208a1ce04de2 -58167,Sony PlayStation Portable,WWII: Battle over the Pacific,,Games,Europe,ULES-00974,1.01,88670208,1188edca,508cce95c0bb64828f5de1d9d82aa76e,88fe0c1a4b86108a0ef307da355891984b389fe5 -58168,Sony PlayStation Portable,"What Did I Do to Deserve This, My Lord!? 2",,Games,Europe,ULES-01418,1.01,379125760,7a6448ad,d380874617be88aa2fcb5c944b606614,08b1e73bf210af85b04a78eeebda284b152d3c6b -58212,Sony PlayStation Portable,Samurai Shodown Anthology,,Games,Europe,ULES-01211,1.01,1331822592,d3844aa2,e26d63dce28fdc778522c4caf0eec151,43f19b5a0ae3ebe3ea41fe9f1ec050a04ffb3e9e -58213,Sony PlayStation Portable,Warriors Orochi 2,,Games,Europe,ULES-01261,1.01,1780973568,08f0a5f1,c497af4eb141549fdedb2bfff9a4b3a9,de0fbd6dd29f3417e1433a11385d6abaa0db219c -58214,Sony PlayStation Portable,FIFA 11,,Games,Europe,ULES-01475,1.01,1379237888,f4df55c7,8d5447f56f609e7e0df2a769c2aa662b,191563ee6a5580890a6c3f06e263d988b20f2a27 -58315,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo,,Preproduction,USA,UCUS 98637,1.00,375652352,f05c080d,ed4b11709aaf1b45c29532c8ad6916c2,120f9db673cb8d6122d9b0060ff965524f8c4ed7 -58490,Sony PlayStation Portable,Brunswick Pro Bowling,,Games,Europe,ULES-00848,1.00,167641088,7913e3a8,6089eab45ef771eca46c62ca8b5cc76b,e2fe4924bb7e17d234b6ba7642b2d14c84265761 -58491,Sony PlayStation Portable,Hot Brain,,Games,Europe,ULES-00834,1.00,535068672,a337f5fb,6ae1bfff00e74676e356b6a77ec779cf,cfc92f750044e54c1265a4f693d7e02cc2b882ee -58572,Sony PlayStation Portable,Mawaskes Puzzle,,Games,Europe,ULES-01104,1.02,332693504,f2aea4d3,63e3884cdc13668bfe2d862fd290224b,e4704166a5eee2dc8428abcb11b4884057dcb255 -58722,Sony PlayStation Portable,Shin Megami Tensei: Persona 2: Innocent Sin,,Games,Europe,ULES-01557,1.00,1131184128,1b2e13ff,28b2b5066260de5c2dd10e1631d18fbe,414021df0270616b6d63226e50b36ea6b02421a7 -58723,Sony PlayStation Portable,Gladiator Begins,,Games,Europe,ULES-01515,1.01,474710016,1c0d084b,75b53f39de5777aa84b679f9598473bf,139457560c1a78d57d37680de8b013271257ee3a -58724,Sony PlayStation Portable,Dynasty Warriors Vol. 2,,Games,Europe,ULES-00604,1.00,279117824,2983f1a1,3bc9fe9c1b0fa851a96518e1f74c3854,78199c772744382f137d05ae7caed8a618390848 -58725,Sony PlayStation Portable,Ghostbusters: The Video Game,,Games,Europe,UCES-01276,1.01,1182040064,2ad74c5a,35d6ce22ef77ec5daa6af0e22a661433,b5fef0cb1d56e3beb2e96e99e4407ab363337894 -58726,Sony PlayStation Portable,Chessmaster: The Art of Learning,,Games,Europe,ULES-01013,1.00,242778112,49783234,a058caa32d3e359d52f7ed7e50f48ad5,cc551ab6bc2c9e05a12ac9862af2ce1669ac4cc6 -58727,Sony PlayStation Portable,Buzz! Quiz World,Buzz! Παγκόσμιο Quiz / Buzz! Světový Kvíz,Games,Europe,UCES-01297,1.00,1619525632,c68b0a75,f829a6893fbe470dac05b8f14ad8d14d,50f85f1bb775520c32c6e30e6de30bfa512184ee -58728,Sony PlayStation Portable,Online Chess Kingdoms,,Games,Europe,ULES-00570,1.02,266928128,fa08c4e6,2e841498d75d0a0bef750ad17d844812,75e9e00574d7c814c4423fabe4a3221c0ac196f2 -58729,Sony PlayStation Portable,Iron Man,Iron Man: Il Videogioco Ufficiale,Games,Europe,ULES-01071,1.00,906362880,0cb390ee,04820de050617a5c6cac30aaadc98724,81ef591247e51f8d7b20897d0c08093d4abf68f9 -58730,Sony PlayStation Portable,Monster Jam: Urban Assault,Monster Jam: Assalto Urbano,Games,Europe,ULES-01169,1.01,906362880,e2045153,01df93872bb652937631d9d3dc9ecca9,9bf807faaf90e75d3fd064eca01f24ab49f32eb5 -58806,Sony PlayStation Portable,Platypus,,Games,Europe,ULES-01029,1.00,77004800,30fc3a6c,85081a37df25e11656f7ebe29b16df8a,83e1176ab5dbf0d7b759ddfadce7301124c6c484 -58968,Sony PlayStation Portable,Guilty Gear XX Accent Core Plus,,Games,Europe,ULES-01394/E,1.01,902266880,a2bee0fb,9a18338422cbea0ca53ee659df41289f,c19c2acba17ba78186f7b61f5b659e8958edf0eb -58969,Sony PlayStation Portable,World Series of Poker: Tournament of Champions: 2007 Edition,,Games,Europe,ULES-00591,1.01,753500160,ad69e19f,003af7069a71e3c497a0c935deb67fa3,167f07b20770bd94f7fc0e28fbb415e622cd8d94 -58970,Sony PlayStation Portable,Dariusburst,ダライアスバースト,Games,Japan,ULJM 05558,1.01,193789952,0ba97c59,8d3f2057fbcd4754da9439b1a4220065,99e3864bf1db9b43b9d163f03e0896b36958b813 -59209,Sony PlayStation Portable,The Con,,Games,Spain,ULES-00513,1.02,800882688,6a43b5b7,facfc10785bfdf4116b725043c59fde0,4b710a93c59f4050b431612742e3bd5c673fce16 -59254,Sony PlayStation Portable,Pac-Man World Rally,,Games,USA,ULUS 10149,1.02,432701440,e675a4fa,fed3d2b49b62abaed10f526d611153ac,003754c1dd955d284542099f270abee6a8e616bb -59324,Sony PlayStation Portable,Puzzle Quest: Challenge of the Warlords,,Games,Europe,ULES-00909,1.00,164626432,34bfd874,87192e9b7d86db33c492fff5fe399292,3cb59ecb46d3ce96b108a907f1b5b298ff28f390 -59325,Sony PlayStation Portable,Gensou Suikoden: Tsumugareshi Hyakunen no Toki,幻想水滸伝 紡がれし百年の時,Games,Japan,ULJM 05886,1.00,1367769088,d746b3ab,d7142d766a2bfbdf9ae27680bd237e7c,0fabef0bd8ad9fa5782f9fc9c25dd61728bc6e2c -59326,Sony PlayStation Portable,Astonishia Story,어스토니시아 스토리,Games,Korea,ULKS-46021,1.02,152272896,03ea988d,8c6aef860291fc3c9b329faad7362128,a262ba135cc658ac8a89877966204f30663a9b6c -59389,Sony PlayStation Portable,Gensan,,Games,Europe,ULES-01360,1.05,442990592,a774929a,ccab7ee05f937c98cf553bdbbad46442,f6ab5fb6955a4349c7e2428c7243b023b83b30ff -59497,Sony PlayStation Portable,Formula One 06,,Preproduction,Europe,UCET-00359/0.04,0.04,1778876416,0e283648,47fe8486e487741895129c2765d66c94,c7ebf8dc7c852ced7300f748c34fc313e14f2f2f -59677,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,,Games,Europe,UCES-01445,1.02,907706368,7027308f,2bbe93bbda0c5fac9405b9dc1867f2f6,515115b7101f580438a1d472171724e90845f0c1 -59678,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,UCES-01130,1.00,1497890816,4d53ba4b,b08bc75dfc8155183aab730ae493b880,ea1a3885240c26ea001cb9c9b703a618995001a6 -59679,Sony PlayStation Portable,Buzz! Polskie Łamigłówki ~ Buzz! Mozak Hrvatske,,Games,Europe,UCES-01206,1.00,1623654400,b18e433d,f715503086df4f64103576a31a020500,f07cfe126f2bb089b9fd2d08d1af4c03d739fdd9 -59680,Sony PlayStation Portable,Buzz! Quiz World,Buzz! Świat Quizów,Games,Europe,UCES-01289,1.00,1699446784,cc29e6b6,8c30990db71d71017f66b137519bf29c,5135a4fdebdadb8c0cd56d9c11551d7975ad7a94 -59733,Sony PlayStation Portable,Street Cricket Champions,,Games,India,UCES-01320,1.00,381714432,fdfdc9d9,3b9c80f5829a696b15183d6085b4ac9e,bc8c28483d064905993aff1932c26295e6902f63 -59893,Sony PlayStation Portable,Pursuit Force: Extreme Justice,,Games,Europe,UCES-00890,1.00,1633353728,10b1ab5c,31f307fac918767d82ea46305f78dd31,f3b54d564a80af79221b2af99f848e89ebd1002c -59895,Sony PlayStation Portable,FIFA 11,,Games,Poland,ULES-01483,1.00,1379368960,821346b8,ac24d64e0b54435141ae4804f3214d6c,0e5fb1d5777aeb666394738668c51885e075c46c -59896,Sony PlayStation Portable,FIFA 11,,Games,Poland,ULES-01483#,2.01,1379368960,f82d9384,ed1f9b306f675609e0b7d28682399c87,384169f2373cce9654c27a2d16029ae2c9d86aa0 -60315,Sony PlayStation Portable,FIFA 12,,Games,Poland,ULES-01545,1.00,1293942784,f9c942f7,2df84776afae463df0cb25902cb58a48,8d1e1e4612265af60456b01ddc712d9bb3b7cadc -60316,Sony PlayStation Portable,FIFA 13,,Games,Poland,ULES-01568,1.00,1293942784,5cbdc1a9,5479794356e02d80d226c013250eb6c0,2540c24e21dc823a212b59c8b562c8de1660347a -60317,Sony PlayStation Portable,LEGO Harry Potter: Years 5-7,,Games,Europe,ULES-01558,1.00,1512112128,05190bb2,f17b6411fec65b66e4b449df426ba269,7fe470dbc93835db7a9531a55b97b815de27ab6b -60435,Sony PlayStation Portable,Trick x Logic: Season 2,TRICK×LOGIC Season2,Games,Japan,UCJS 10105,1.00,843284480,4d563e9b,442ea08324532d3c7cbee06fbe4a8408,a0b84d62365001e28c2bf5a01804b348627a94d3 -60588,Sony PlayStation Portable,Super Collapse! 3,,Games,Europe,ULES-01027,1.00,130285568,f33efe0c,ed84e9376d4963aa0a5099fcd0b3f006,4e7b4a2ba15acf5c6eba66d618edffc2237c3805 -60637,Sony PlayStation Portable,Kao Challengers,,Games,Europe,ULES-00146#,2.01,616562688,8f6179c5,cbda456c2730b1c993dbe04afe871bb5,98a4f4f8fbda1009e3bfdc5bb975cce5ef990741 -60761,Sony PlayStation Portable,V8 Supercars Australia 2,,Games,Australia,ULES-00042,1.01,1345159168,d1d2bf27,e11e905118c96a118139cb29e7ee9406,a888050d6ea4ea619302b3f919064a7985bb1535 -60762,Sony PlayStation Portable,Stealth + WipEout Pure,,Demos,Australia,ULES-00232,2.00,1710292992,1b4b63b9,f6914651b6cd4a9b3a085afbbad23a86,4704257c73b6ef1fc7851e650d5acf98d12fabc6 -60908,Sony PlayStation Portable,Patapon,,Demos,Europe,UCET-01015,0.01,380698624,f3ffb25a,1bd90eb3fd329e57690432d7b19fe728,5a6f435341afc962266675d9361a5fd807136c64 -61169,Sony PlayStation Portable,Furtif + WipEout Pure,,Demos,France,ULES-00231,2.00,1796177920,ad664a9a,ed095825ad8c7fdb7f4b0269991ff8bc,e424ec64c6102a4bda9b73a0d76d45626d191395 -61247,Sony PlayStation Portable,Cloudy with a Chance of Meatballs,,Games,"Europe, Australia",ULES-01319,1.00,966656000,e98bdc43,8b55b5ab026896c908452bbf83b4e1d2,5a9a52b35cc600b5d73b021fa88dba0b44dc3a9e -61248,Sony PlayStation Portable,Demo Disc for PSP Vol. 1,,Demos,Australia,UCJB-98304,1.00,905314304,16597482,0a6f106b6f39898ea26f5d2b42d0872e,6e133f1306d3e004fb945a352631e2f17d473cb8 -61249,Sony PlayStation Portable,50 Cent: Bulletproof: G-Unit Edition,,Games,Australia,ULES-00452,1.01,1686175744,fc7c2da4,3fe493befe08f147298a4b5752ad89fd,19bad0e18e20cb57dfce7a9bbf484d24912694f4 -61250,Sony PlayStation Portable,Valhalla Knights 2,,Games,USA,ULUS 10366,1.00,1579778048,ccf97cdc,decf0fce0c25df331b7af2e86da8bcdd,8f9c83224f4a7088a0aaa78b832a6a06074a71e5 -61350,Sony PlayStation Portable,FIFA 14,,Games,Russia,ULES-01591,1.00,1360789504,84df36cf,dc6e716d41f87a5f6bf23591b9a8f4ac,715dce69d15df2de854426a38fae85492dc0c70b -61351,Sony PlayStation Portable,Lumines,,Games,Japan,ULJS-00005,1.02,234422272,dce275c9,09ccf69e76dd1cbacbdc20452caa514a,aadc790bf6b4af9b73a64716dc02cd36ce665c8b -61353,Sony PlayStation Portable,Namco Museum Battle Collection,,Preproduction,USA,ULUS-10035,1.00,175472640,4f86634b,2412829cb5145e90f01fa1794ee9d235,8d173b443e2022eeed6e683b32cfd06eed86635e -61354,Sony PlayStation Portable,Beit Hell 2000,バイトヘル2000,Games,Japan,UCJS 10022,1.02,464715776,53116bf8,756004aea237688aeba3436fc5916dab,c0f4461daa6de7b897fe320787061db21a29e3d1 -61372,Sony PlayStation Portable,Stealth + WipEout Pure,,Demos,Germany,ULES-00230,2.00,1797095424,b8ae436e,03aea47bce375925a395ab9f9b67ff39,51d2369185136fc0e2aef7e53867dc3939207c9f -61476,Sony PlayStation Portable,NHL 07,,Games,Europe,ULES-00477,1.01,1753579520,e108bb11,ad9779f11bb26a3c57578b3996791cc5,8db08a2cb1bc036288699a230bd8c69a96081631 -61478,Sony PlayStation Portable,Go!Explore,,Applications,Italy,UCES-00884#,1.01,906362880,d2d0a19a,af50e7826da8b285ed4aedafce69e159,6d5691ff9c3fcabbb2bd693cc3aaff2fb42921e6 -61479,Sony PlayStation Portable,Puzzler Collection,,Games,Europe,ULES-01175,1.00,142966784,a7fcf529,093b1720bb440b03601189afcfa40016,a69282e5511701926c3c3753623b0f512b17905f -61480,Sony PlayStation Portable,Aces of War,,Games,Europe,ULES-00590,1.01,488046592,70e4400c,2996b42f417cd5d1545f69b4a5a0a490,1881da3e8e9055bc80e73908d5a386a7b72ef254 -61482,Sony PlayStation Portable,Bust-A-Move Ghost,,Games,Europe,ULES-00233,1.01,70352896,080295bc,2e0981e391fa5c2fc1ace1c36ed22a31,c131f36ee0d030b4cfdad4406beb88562321d099 -61506,Sony PlayStation Portable,Metal Slug XX,,Games,Europe,ULES-01429,1.00,466550784,dee4a34e,a5581c3ca8c774957b1c6cdd8a3883c9,d49df65456540532e1280d468095a08ee3e78e40 -61928,Sony PlayStation Portable,Final Fantasy IV Complete Collection: Final Fantasy IV & The After Years,ファイナルファンタジーⅣ コンプリートコレクション ファイナルファンタジーⅣ&ジ・アフターイヤーズ,Games,Japan,"ULJM 05855, ULJM 06122",1.01,880410624,2c6302f5,20afbff1a454c1e3b89b08d83e7f95e7,c734cba82fde0137f3cc7aa5f9ef90eddb35ca7c -61973,Sony PlayStation Portable,Tiger & Bunny: Hero's Day,タイガー&バニー ~ヒーローズ・デイ~,Games,Japan,"ULJS 00568, ULJS 00569",1.02,863305728,1681da85,0f96af8fa7e23bbdff001bbe449437a8,1a60ec8620bf8957bf3a0dfd757fac7ee759e231 -61974,Sony PlayStation Portable,Enkeltbillet,Enkeltbillet (エンケルトビレット) 限定版,Games,Japan,ULJM-06374,1.01,1469841408,d5a0e58e,7a1e7644f6c244684b242c697f9b537c,db0f48d897131f392e326d6f2cf8b17502a1aacc -61975,Sony PlayStation Portable,Diabolik Lovers: Haunted Dark Bridal,ディアボリック ラヴァーズ ~Haunted dark bridal~,Games,Japan,"ULJM 06162, ULJM 06163",1.02,1196261376,bbedba70,e193fea70a3d0396574e431f0b635936,fcc19cdb094aa7501c66e863e4c4ab9b5b4104d9 -61976,Sony PlayStation Portable,"Diabolik Lovers: More, Blood",,Games,Japan,"ULJM 06310, ULJM 06311",1.01,1802960896,b40a0794,874738380d279f1f38fbe1ec2803b117,09e49397c8cac6dafc6effa7cf7347c839047fed -61977,Sony PlayStation Portable,Are you Alice?,,Games,Japan,ULJM-05848,1.02,1654784000,a66dfb36,980188c7f7952bea15d87204d5f7b20f,324bcaa19ab9a773cb05f6fa458e6ab77d0d9f50 -61978,Sony PlayStation Portable,Gekka Ryouran Romance,月華繚乱ROMANCE,Games,Japan,ULJM-05943,1.01,1756463104,adf4f494,e9a1960b1e92733a6342d432440dae50,6d21bddc496f8b0296b9f227de83f3ecd9565781 -61979,Sony PlayStation Portable,Taishou Mebiusline Portable,大正メビウスライン Portable,Games,Japan,ULJM-06354,1.01,1562771456,003db9c9,5ae31cee212aaa7ab24f1bd3a63fe84b,7bc699678f4955eff6213f30d6a555006ff421c3 -61980,Sony PlayStation Portable,Shiratsuyu no Kai,しらつゆの怪,Games,Japan,ULJM-06289,1.01,1405124608,b33b71e0,610c12961ffd49e3ad515a1a888ae8a6,d70b0f8669c178a14c9aac93b71704566777a369 -61981,Sony PlayStation Portable,Confidential Money: 300-Nichi de 3000-Man Dollar Kasegu Houhou,Confidential Money ~300日で3000万ドル稼ぐ方法~,Games,Japan,"ULJM 06142, ULJM 06143",1.02,1806794752,a1581cac,8024d9e27a3298a5910e752d202807f6,83cfead23aa7270d8fbbc175cf4840aed0670434 -62008,Sony PlayStation Portable,Shin Megami Tensei: Persona 3 Portable,,Demos,USA,ULUS-80022,1.00,1321861120,03bf5d3f,11e1f2d4a89413e58b517a5972945f1f,d75c06fc7d1099faa4fbcd8db6d1d036aabb26e0 -62024,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,"UCES-01033, UCES-01033/E",1.00,1518567424,49c2e83f,cefe955161977b7435449c783231834c,2192dc2dba7a0421e2d90056f92936da1f05f92f -62025,Sony PlayStation Portable,Buzz! De Strafste van België,Buzz! Le Plus Malin des Belges,Games,Belgium,UCES-01205,1.00,1582497792,31d282e5,6981fccd253df4fed71fdfda7b0875fd,b1e014bf8f13d41f45d394729f373005cdaed790 -62026,Sony PlayStation Portable,FIFA 10,,Games,Netherlands,"ULES-01324, ULES-01324/P",1.00,1218052096,cf65efca,32ef1b55f4654e49ea98905dc39bf8c7,7723c17df560578830be2b24fdd172701c867b36 -62027,Sony PlayStation Portable,BlazBlue: Continuum Shift II,,Games,Europe,ULES-01526,1.01,1651834880,b265077a,b8471385a7b3b55f919dc11104ebe35b,87c470219e6a34b0b143d14d624dd1160d204469 -62180,Sony PlayStation Portable,0-ji no Kane to Cinderella: Halloween Wedding,0時の鐘とシンデレラ~Halloween Wedding~,Games,Japan,"ROSE 00025, ULJM 06272",1.01,1173225472,7882038d,2fb7e77a68ecec933ebad380f941ac54,8e086d2365c7a6518492f639e81e6bc688ce7105 -62182,Sony PlayStation Portable,Rapala Trophies,,Games,USA,ULUS 10137,1.00,521371648,353b2d62,b8a3b81f82c5b1810b225c47049db18c,3d5a68c5e75fc937c324ca0c4194cda48e15d2cb -62183,Sony PlayStation Portable,Page Zero,Comic Viewer Prototype Page Zero,Preproduction,Europe,UCET-01058/0.07,0.07,112820224,97dab20a,70e2b2e70aca2cb1dfb76437b6dc0ab3,595125bdea088d65dc3f567bef7666d14eed39c0 -62184,Sony PlayStation Portable,Amnesia,アムネシア,Games,Japan,"ULJM 05930, ULJM 05931",1.01,1143373824,5620dc77,7dcab69be32e9d8ad06d44ad96d9000a,6308d2beb7d5027057bf1606271a95ca2aac8934 -62186,Sony PlayStation Portable,"Asaki, Yumemishi",あさき、ゆめみし,Games,Japan,"ROSE 00004, ULJM 05870",1.01,1519288320,04c887ae,9f77329ece31d3f43cdaef6a1efcbbdf,6f837ffd8dfc1632b48d1b496c10bca9c2cf88ae -62204,Sony PlayStation Portable,Brothers Conflict: Passion Pink,ブラザーズコンフリクト~パッションピンク~,Games,Japan,"ULJM 06065, ULJM 06066",1.02,1755414528,66fcd44a,8b7404fda07c92a252cf0d667ab7dfab,2c0ecab3a0a8a98cc3d689a9e33bfa3dbc8ba3ce -62206,Sony PlayStation Portable,Jewelic Nightmare,,Games,Japan,ULJM 06325,1.01,1476001792,fd7ace36,49c88e91412f91a8846889e3607051ae,5670c924f2b3753dc5680007a7dc958e092ec5a7 -62208,Sony PlayStation Portable,Kaleido-Eve,カレイドイヴ,Games,Japan,"ESGM-0002, ULJM 06397",1.01,1586364416,17c84b3d,98e7cba4daca5a2074bb7686d13c3493,be9db851a4d99512b4b72d86711729515d85b513 -62211,Sony PlayStation Portable,School Wars: Sotsugyou Sensen,スクール・ウォーズ~卒業戦線~,Games,Japan,"ROSE 00027, ULJM 06283",1.02,1281228800,3046ef53,0c0fd5ebfd970460d8fcc864c509d91a,d9a3a0a9e400b7732c3171e990e9bb5c3d1097e2 -62408,Sony PlayStation Portable,Angelique: Maren no Rokukishi,アンジェリーク 魔恋の六騎士,Games,Japan,ULJM 05985,1.01,1562935296,34b1c36a,a8950556d992e5eb70d9a3eb02cd150b,a9593aa6e17b2e8e576bdf7dd5188461bbc83ba3 -62409,Sony PlayStation Portable,Chronostacia,クロノスタシア,Games,Japan,ULJM 06358,1.01,1252425728,4925faab,ff45594de986f2549ff688e538aa1689,731de683501dfb8eb455c88f8535f0db82f5213c -62411,Sony PlayStation Portable,Clock Zero: Shuuen no Ichibyou Portable,CLOCK ZERO ~終焉の一秒~ Portable,Games,Japan,"ULJM 05944, ULJM 05945",1.02,1235779584,a9f0cba0,b899973eca5fe86ef68fdf7c6f7b8e31,282fdef1ecf123b7ccb24950f7e476b1daff1ea7 -62413,Sony PlayStation Portable,Hanaoni: Yume no Tsuzuki,華鬼 ~夢のつづき~,Games,Japan,ULJM 06047,1.01,1773404160,1c155fb1,f81c71d75bfd0ee18a94e8c857ab225f,147b7c4fd10d17595ae0fca8bffb9e643d83b255 -62475,Sony PlayStation Portable,Kimikare: Shin Gakki,キミカレ ~新学期~,Games,Japan,ULJM 06126,1.01,996540416,5dcd2b55,533d90542017f15017487f755a084921,f796973135bf42f213b08baa0b7d7fb1701260b8 -62477,Sony PlayStation Portable,Koibana Days: Pure Flower Garden,恋花デイズ,Games,Japan,ULJM 06285,1.01,1495859200,a1e55362,557b30c4af323cf6c14797086ec270a2,9168cc53e6ffd4d5927e534c4efb3f1d7e63c67a -62479,Sony PlayStation Portable,Snow Bound Land,スノウ バウンド ランド,Games,Japan,ULJM 06327,1.02,1267040256,ff8a0193,96a17bdd7a130490fb85966572da91d2,4ed0e4948c4413c324989e4dc3a664e4b1c8a57f -62481,Sony PlayStation Portable,Who Wants to Be a Millionaire: Party Edition,,Games,Europe,ULES-00540,1.02,329646080,3d73759b,d76a9bcc5d8fd62b8aeaf58da0d706fa,b311f9ed6f40d271e465493ac58a15715253484e -62482,Sony PlayStation Portable,DreamWorks Over the Hedge: Hammy Goes Nuts!,,Games,Europe,ULES-00663,1.00,325320704,2d49885b,7f10992c9a57ae066e19083d71bcde37,5d51de8607012ed5ebd0f8a7680ae04034dab8f5 -62483,Sony PlayStation Portable,Telly Addicts,,Games,Europe,ULES-00983,1.01,490209280,5c5f4536,0d58871daf31e5e43617f29942eaf1f5,48396bedd1ab48d95c78ff6fda5207490185eee0 -62484,Sony PlayStation Portable,Thrillville: Off the Rails,,Games,Europe,ULES-00889,1.01,778993664,018b0cc9,4783932f51613f2aaab81f82dd8768f9,37371cd1afd554eb28ee2dcade5c64d5c84d4a48 -62797,Sony PlayStation Portable,Go!Explore,,Applications,"Spain, Portugal",UCES-00853,1.01,906362880,1efcad87,74f7f787b4fa91a9e534444ad01ac257,7e55f6d1c8ebe6589964c9e6965f83fb18efaea0 -62803,Sony PlayStation Portable,Fate/Extra,,Games,Europe,ULES-01561,1.00,1284046848,a88a9773,c91d7aaf40f0a7ee1b1b66d457c142d2,851177ce9a8c54df07471e91d989618b19d7db4f -62858,Sony PlayStation Portable,Puzzler Collection,,Games,Europe,ULES-01066,1.00,64684032,13ac044f,adc443e01177e323f4c75922e86018c6,2f46815475b11cc91dba007ff8f47fb9c46905f8 -62859,Sony PlayStation Portable,After Burner: Black Falcon,,Games,Europe,ULES-00785,1.00,427851776,d1262dbc,8c55c07db7a2a1be8d761457d4a315cb,79c0d9d6df1ef4ee5bb5d7e3001f173917a89436 -62907,Sony PlayStation Portable,Demo Disc for PSP Vol. 1,,Demos,Europe,UCJB-98303,1.00,905314304,c87ff660,73f03e5d16578cd583aabb204ab10dda,3efbda9c041fa1485fceb3eb4b0e686eb9ba810f -62928,Sony PlayStation Portable,The Golden Compass,,Games,Europe,ULES-00950,1.00,1266941952,a9ee1515,fc95afd019eed0f52e1996de6942bbf2,ef482e0e6ccc4382967396c8750089150feb6477 -62986,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,Europe,ULES-01467,1.01,1393164288,0680f598,5989688f83df0062131d3e33e592500b,70c0079bf4520d99c207ac150445371252f5d55d -63232,Sony PlayStation Portable,Myst,,Games,Australia,ULES-00659,1.00,876707840,d5c31fb9,dcf04cf2865af16a87d2159615c9bdfa,6c6381d4a93ec330f828bdd102ff46ed85c9c010 -63374,Sony PlayStation Portable,Go!Explore,,Applications,"Belgium, Netherlands",UCES-00885,1.01,906362880,3c7535c3,b273a7bf3b295a94578059388581c6c8,2d4e098ac0dbae7a3b6e8af06332cf39b4554142 -63375,Sony PlayStation Portable,PES 2014: Pro Evolution Soccer,,Games,Europe,ULES-01596,1.01,1184432128,eb3211e8,19bbec237eb4e31e1666d6baa25e1383,e246b454ebaee5e79ca4bdf352ea46a21e7c8e61 -63376,Sony PlayStation Portable,FIFA 11,,Games,Netherlands,ULES-01482,1.00,1217593344,97696f93,4cea079bbb46e446090467d2f80ad3d5,0ab05e6bf1d733b72be2129bd9401561e8067d30 -63377,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,Europe,ULES-01076,1.00,776077312,c3be80c0,c4db3eaba421181478313f17bacf06c6,9a318a7606fa0b5c4c44323e7d64b58e42569fc9 -63704,Sony PlayStation Portable,PES 2014: Pro Evolution Soccer,,Games,Europe,ULES-01595,1.01,1144848384,1ba1efb7,adb7d6103f29b7871e07e66518b0c724,3ec82cf03d93b4116a1e59bd4aaa2657f46d1941 -63705,Sony PlayStation Portable,Dot Hack Link,.hack//Link,Games,Japan,"ULJS 00266, ULJS 00279, ULJS 19058",1.01,1065123840,bda73e12,e674d0ea0e266dcd63834c5bb2696200,b40ed3180add9a1f72bdfe51f3bb6c54fb8f65de -63708,Sony PlayStation Portable,O.G.A Onigokko Royal: Hunter wa Field de Koi o Suru,O*G*A 鬼ごっこロワイアル ハンターは孤島(フィールド)で恋をする,Games,Japan,ULJM 06298,1.01,1287061504,fe920faf,7cc3e7f4de821c62c8b1bfb0eca3615e,004cb40c2fb8fa9b5028ba6567ea26bc6ff48953 -63710,Sony PlayStation Portable,Mother Goose no Himitsu no Yakata: Nursery Rhymes for you,マザーグースの秘密の館 -Nursery Rhymes for you-,Games,Japan,"ROSE 00006, ULJM 05892",1.02,883458048,7a4a90ef,4c71addd1e400c2d8673d74c8a7d9252,f47bb0b197077d3207f763156d1199b49cbfc4db -63712,Sony PlayStation Portable,Solomon's Ring: Chi no Shou,Solomon's Ring ~地の章~,Games,Japan,"PP-0004, ULJM 06204",1.01,356909056,ded1639b,42863f7002ec54b6561484589ebcb028,e8ac87f7465fc5e0fc59597edbb888703f31fe05 -64098,Sony PlayStation Portable,Nickelodeon Avatar: The Last Airbender,,Games,USA,ULUS-10165,1.00,178192384,9c8f43ba,c4946436e71507bc52819e01b7927572,6defad29f2ffebf83b375a0e2ce5e9cece1ec154 -64099,Sony PlayStation Portable,Ben 10: Protector of Earth,,Games,USA,ULUS-10307,1.01,685211648,9709e641,9230d967aecdbf51085bef57b071000a,01ebae4ed3105e0e6bbbe3645e54bb766409bb3c -64687,Sony PlayStation Portable,Tanteibu: The Detective Club: Angou to Misshitsu to Kaijin to,たんていぶ THE DETECTIVE CLUB -暗号と密室と怪人と-,Games,Japan,ULJM 05926,1.01,617807872,925ca09a,4d896cfd23b7c606836c2eb20e984340,13ada3a7a85a011c0d708a2caa33469fa353c78a -64688,Sony PlayStation Portable,Kazuo,カズオ,Games,Japan,UCJS 10036,1.00,288980992,7b83c9cc,5f2bb51ef710f9fb6a197e4ef7012442,04c801027ea08694cbf3b8ac80dc07de018b5b2c -64689,Sony PlayStation Portable,Urakata Hakuouki,裏語 薄桜鬼,Games,Japan,ULJM 06280,1.02,1424982016,d4b60e81,4ac9e703b2fab95eda6b1fdc3e26b424,0c4e427b79eec8c52e5a6d7390e3633aef1335f5 -64691,Sony PlayStation Portable,Moujuutsukai to Oujisama Portable,猛獣使いと王子様 ポータブル,Games,Japan,"ULJM 05894, ULJM 05895",1.01,1321893888,d7d0cb91,9c896f231572a9df9156d43bf623011d,a2ff118dd2316d3db250e12d836a00d630b26f29 -64693,Sony PlayStation Portable,Kannou Mukashi-banashi Portable,官能昔話 ポータブル,Games,Japan,ULJM 06014,1.01,1534525440,bff9be38,0d27bd2a2370f1ac96f3ef1f05535ff3,8c437965193cecf2bcdbf6364d3f210cc0688571 -64695,Sony PlayStation Portable,Amnesia Crowd,アムネシア クラウド,Games,Japan,ULJM 06265,1.02,1767899136,a745e87e,2a3fd14404c29fa4bc0e898e5692a8ea,72d105afc2f5a64e9f3d6b8a9df7c52e85ee5d99 -64697,Sony PlayStation Portable,Bubble Bobble Evolution,,Games,USA,ULUS-10143,1.01,624885760,a6e1e2c6,ac537a8a722b8a26c357199dd1f3bf87,50d4d27d1e5ad413892f302caa7c808e63d3bcd6 -64698,Sony PlayStation Portable,Cake Mania: Baker's Challenge,,Games,USA,ULUS-10362,1.02,434503680,77e1fc2f,07ffcbb3e9867035009031d39e8f87d5,5cdc3e24007e669b847c29382ec992ef4bc117fb -64699,Sony PlayStation Portable,CID the Dummy,,Games,USA,ULUS-10356,1.02,524484608,48394edc,c70a83d31070288ffd3aa0da6ec708ad,700d835ad5af12d98736b56a88ec3a62b9f6b4e0 -64700,Sony PlayStation Portable,Driver 76,,Games,USA,ULUS-10235,1.01,1109721088,b15157ea,3b89467361c87a0e2def0615f5f52d76,b51e32a2061afddb93af9fa5befdf09f7be161ff -65097,Sony PlayStation Portable,Innocent Life: A Futuristic Harvest Moon,,Games,USA,ULUS-10219,1.00,351797248,62646480,234515e997e9d0cdc4bf77dcda20dcb3,4a010e8cef956990cf1a17add997d6ebf42a9d6e -65244,Sony PlayStation Portable,Luxor: The Wrath of Set,,Games,USA,ULUS-10201,1.00,906264576,e6375491,983e29d47a34f83bf5f4455250d2048c,4a36e26d2f71afe628451681fe58bcf2d4f3d185 -65245,Sony PlayStation Portable,Space Invaders Extreme,,Preproduction,Europe,ULET-01077,0.01,153780224,109cf656,d12c090db1ef314e174814bbb1fdad8e,0c5821bcbf7d433f84b20fa265e9f5735f4121f6 -65246,Sony PlayStation Portable,Impossible Mission,,Preproduction,Europe,ULET-00749,0.01,148209664,4fdb7bcb,e4aa0d1cfb357100b283c408200903a1,4fa6c318fe4cac9a8d696ba4a783f9597d40932f -65331,Sony PlayStation Portable,Major League Baseball 2K7,,Games,USA,ULUS-10229,1.01,1698168832,e91cdd45,6460660e6331607a08937863ab3f467f,7f0adf35240e09e15a5704313aefa8e3e48e0951 -65422,Sony PlayStation Portable,Need for Speed: ProStreet,,Games,USA,ULUS-10331,1.00,896270336,9c64e94b,15116cd86e3685c9796b4935fdbb1631,e1afdaf7a4832e0c72c96f53dd76c9662c57cd02 -65582,Sony PlayStation Portable,MTV Pimp My Ride,,Games,USA,ULUS 10256,1.00,833650688,37ea9f17,61a0957149dc3eca943953a6e075d12d,6e82508abbb0bb0691e5f4df35d89028e7037464 -65678,Sony PlayStation Portable,Burnout Legends,,Games,Asia,ULAS 42019,1.00,505905152,c03a765f,f6bc3b69b61e76d0e739c99c95cdba15,fc9770498e9ecee1d522c67066cdf9acd4f0996b -65679,Sony PlayStation Portable,Lara Croft Tomb Raider: Anniversary,トゥームレイダー: アニバーサリー,Games,Japan,ULJS 00221,1.00,1105788928,55ee2c4d,b35745dae9ebc639fcfc99f0fd8a6c5b,7e40ac493da98131d54de9ccd7cff7460e7ea325 -65680,Sony PlayStation Portable,Lara Croft Tomb Raider: Legend,トゥームレイダー:レジェンド,Games,Japan,ULJM 05180,1.01,953647104,51aab7d6,e6b531bbd297fe11a7b36a7146ed750e,3a14d8b8bbcd434bca86d38374063cf2c151c7e6 -65719,Sony PlayStation Portable,Ford Racing: Off Road,,Games,USA,ULUS-10326,1.00,734003200,c0d97790,0e959cd50b12057ae324c40c7b9fae8c,d370fa007a6c9e6e186ab040af0d04171b52f8a7 -65720,Sony PlayStation Portable,MTX Mototrax,,Games,USA,ULUS-10138,1.00,1067876352,5f275221,2a3a719f93e5ec6bcb04023f9cd22320,235a99f536b3862683d3df568de8ec3ab3890f19 -65721,Sony PlayStation Portable,Pocket Racers,,Games,USA,ULUS-10163,1.01,268238848,73756129,e6592f603755cd06c8e3c593c466e26f,8b97606318f947f9b5e5585a32645024ce3d0dc2 -65722,Sony PlayStation Portable,Scooby-Doo! Who's Watching Who?,,Games,USA,ULUS-10168,1.01,617873408,bea6bfea,1c18d2b8ebc7882955ddce6d39f4cfc7,bc9c228c076823bf39d0edb532654b8b4b27337c -65723,Sony PlayStation Portable,Spider-Man: Friend or Foe,,Games,USA,ULUS-10318,1.00,578813952,6618b86e,be61d3ceba256c536c3c067b970bcbc4,08e37d42d638a51bf5e46fb66b25b3449c75fa9a -65765,Sony PlayStation Portable,Super Monkey Ball Adventure,,Games,USA,ULUS-10132,1.02,423657472,52ae035b,33f62f5f8c8abc13f49ed70e7e45f370,dbf178459ddffad66c8bf6df3d270a0e70c0a104 -65766,Sony PlayStation Portable,MotoGP,,Games,USA,ULUS 10153,1.02,308346880,313dd577,320075e3c82a82b3ef559fb6526c811f,98199d2a4198c1a597f9314e72eaab8e71287efb -65767,Sony PlayStation Portable,Burnout Dominator,,Games,USA,ULUS-10236,1.00,691109888,73fc1b93,8a05937b37ef37d580dc9f7771c124fd,7a57220683562e1e7f3b3f9629d100f549595775 -65768,Sony PlayStation Portable,Fading Shadows,,Games,USA,ULUS-10344,1.03,736886784,4fdde5e2,6ccbf452c1fe9852876972519ece3279,208a3091e6c3a6308c027fc70f803753691d3ed7 -65769,Sony PlayStation Portable,The Fast and the Furious,,Games,USA,ULUS-10198,1.01,905084928,1a45232e,7310291adfe83052b018a7dae13d6fc0,47debb85e0d9d8127afda5baa5f3faf7bc8c9f44 -65773,Sony PlayStation Portable,Puzzle Scape,,Games,USA,ULUS-10190,1.04,346128384,7849a1c5,f649153bab02065e711fff0497f65ab4,84b41adbd2a9159ddb220ae65caa03cd404dccb2 -65774,Sony PlayStation Portable,Snoopy vs. the Red Baron,,Games,USA,ULUS-10189,1.00,540868608,04f5dd97,864f4b0c4a1dceb8bf4f32edbe317535,c5b4ca0ea9709f246bd5aa1b3cf4951ec2b2895e -65780,Sony PlayStation Portable,Rocky Balboa,,Games,USA,ULUS-10233,1.02,906330112,d145cee2,ff2aed58cc1dc7eda37ef59511eef40a,81a0229a93ef9d2781131bb6cba82838cd0e39d7 -65797,Sony PlayStation Portable,FIFA Soccer 11,,Games,USA,ULUS-10550,1.00,1752432640,4d892f70,e201b73d0f3627914b0d1b42ef74b515,1468667776b9087d6f98a616b60261a6d510c98a -65798,Sony PlayStation Portable,Tiger Woods PGA Tour 08,,Games,USA,ULUS-10276,1.00,1350434816,c0451a77,de62df920f737f1aea7292263344454a,6752792e7dc7547c29d8705aaa2ede99bef3a546 -65799,Sony PlayStation Portable,WWE SmackDown vs. Raw 2009,,Games,USA,ULUS-10384,1.00,1489567744,70c48ec2,0d29bb932f552d6961bc33040b01d65f,e6ed3b5f3a576a9bb69c184129daf86059d96a14 -65812,Sony PlayStation Portable,Midnight Club 3: DUB Edition,,Games,USA,ULUS-10021GH,2.02,1641644032,83ac132a,f8baa2e6eaebc74ec062c5e5c923c3b0,31fc98b061aa8aba152be479368a63dcd14bfc3d -65813,Sony PlayStation Portable,Winx Club: Join the Club,,Games,USA,ULUS-10212,1.05,1317634048,c1740a8f,47e01a4374a63e39de0a6260d4106834,7eb64cef214f1724e7d399e3e76dddaaa3ba1abb -65888,Sony PlayStation Portable,The Warriors,,Games,USA,ULUS-10213,1.02,1797423104,3745b961,add34af0817489af8f266d2158766504,e93c2ccb4e3fbd10c60b4e81ab2e07f58946518c -65889,Sony PlayStation Portable,Summon Night 5,,Games,USA,ULUS-10656,1.01,897253376,421237fa,6d1c75638f31e8aed4447fe6331f1f81,b5154f828f7bec81d25ce1b9b181dff0e098f978 -65890,Sony PlayStation Portable,Puzzle Quest: Challenge of the Warlords,,Games,USA,ULUS-10225,1.00,136151040,37087839,ea5e2215956b6333c4b4dbf793be829a,2f003e3ed9a82727f81dc7d266467fec58d00997 -65891,Sony PlayStation Portable,Cube,,Games,USA,ULUS-10223,1.01,432504832,abd65716,fea19b13768aef99dae843d3abfa132e,aff0fa635b7f158f1df3a38479542a5b6f6865d5 -65969,Sony PlayStation Portable,LocoRoco,,Preproduction,Europe,UCET-00357/1.00,1.00,474513408,b55ce6e0,c0215f6cc7749ba4ba9a1c09a43cde22,7e4000221729c85d64f60ed8d0f448918ea97197 -66080,Sony PlayStation Portable,Super Collapse! 3,,Games,USA,ULUS-10287,1.01,62390272,d5cfe230,2f7feb69f78d000928596b9b628a3da7,c67d0d08daf1a4d51d5d4a5ac558b1435c64f9fe -66081,Sony PlayStation Portable,Warriors Orochi 2,,Games,USA,ULUS-10423,1.02,1808596992,c4863f05,db5b2107b07f4688860d531879e156bc,c8728803e7664dd8513bbbe2ee5b864ec7dafa36 -66082,Sony PlayStation Portable,Family Guy: Video Game!,,Games,USA,ULUS-10185,1.00,1186463744,41283518,9d4a5cfe223b5c0665ce9cc0cfc908f3,8957ef07740224b9720d5ea0ad25aa4b79242348 -66280,Sony PlayStation Portable,NHL 07,,Games,USA,ULUS-10131,1.00,1753579520,4884c8ec,0dcf9328ace64647d0bd6615034cd9aa,ce24840be5d1203e4f88d58cac67fe03666e05df -66541,Sony PlayStation Portable,Assassin's Creed: Bloodlines,アサシン クリード ブラッドライン,Games,Japan,ULJM 05571,1.01,472907776,f4ed0a50,d5b23ed49e8f3a0e8e59e20861f2b46b,386621e2919b4685e0d7e0aa21be55133b93b523 -66868,Sony PlayStation Portable,Black Rock Shooter: The Game,ブラック★ロック シューター THE GAME,Games,Japan,"JRPG 00001, ULJM 05859",1.01,1355972608,151471f9,df98904ec8d1a3d634f32c2f28b8838b,3f3f688b18c92c082d35f2429a0e6e1a4138aae0 -66869,Sony PlayStation Portable,Ys vs. Sora no Kiseki: Alternative Saga,イースvs.空の軌跡 オルタナティブ・サーガ,Games,Japan,"NW10107740, ULJM 05679",1.01,1344208896,4b2fcfce,95751a87bd6e364c2a2503339674526b,01bfc2f1f508d515ba37c76aaf9dd32eacc064f6 -66963,Sony PlayStation Portable,Starry Sky: After Autumn Portable,Starry☆Sky~After Autumn~Portable,Games,Japan,"HONEY-007, ULJM 06209",1.01,1591181312,99bcf7f2,0e122bce0b16258fc453a3f402e5bea3,d57b32b0fae41081105f34c75386a63af7de23e9 -66964,Sony PlayStation Portable,"Starry Sky: After Autumn Portable: Etsuran Shite Please ""Etsu Puritsu 2""",Starry☆Sky~After Autumn~Portable 閲覧してプリーズ"えつぷりっ2",Bonus Discs,Japan,"HONEY-007, ULJM 06287",1.00,516390912,8e6fa95a,dd1d714c972dbcf84dab159bf63358c3,f51418a0262b3929bf590f7bb18f37455d1fc117 -67290,Sony PlayStation Portable,Yu-Gi-Oh! GX: Tag Force 2,,Games,Europe,ULES-00925,1.01,1812725760,9737199b,81cb1dee06d3278b26fe4bf574bc2e36,48d2a184958d799cc1cc3131b678e29d8bfbbba5 -67431,Sony PlayStation Portable,Tales of the Heroes: Twin Brave,テイルズ オブ ザ ヒーローズ ツインブレイヴ,Games,"Japan, Korea","ULJS 00431, ULJS 00432, ULKS 46284",1.02,1285160960,28356530,b13ebc2c2086e3095ada19f29e97cab1,acc3e9e3ac454bba1b9747c9261b3f3d48bebe9d -67504,Sony PlayStation Portable,7th Dragon 2020,セブンスドラゴン2020,Games,Japan,"HSN-0021, ULJM 05923",1.01,1125482496,0bdeea34,507131c25d65a6c0a028deb94b1cff44,e8613897da2d51d67023a4d94d35175cd7292a4e -67505,Sony PlayStation Portable,Comic Party Portable,こみっくパーティー ポータブル,Games,Japan,ULJS 00027,1.08,1333428224,a994277a,a83613e72f54daeba0259ed09ffb35a7,fda4a213d1fb0037d1291131077389b813506f61 -67506,Sony PlayStation Portable,Initial D: Street Stage,頭文字D ~STREET STAGE~,Games,Japan,"ULJM 05093, ULJM 08013, ULJM 08040",1.01,1187938304,23b9e647,225f1f56c37097c7a11ecaddd52abbf1,637150702ac7e0418fe58cfca71c948da2746fa2 -67507,Sony PlayStation Portable,Kamen Rider: Super Climax Heroes,仮面ライダー 超クライマックスヒーローズ,Games,Japan,ULJS 00549,1.00,844136448,eeacbfdf,d8ab3c90ab5cd3907822bc9aaed481ab,062ec4c0c53fd286be7be99d50ed04642854a989 -67508,Sony PlayStation Portable,MagusTale Eternity: Sekaiju to Koi suru Mahoutsukai,マギウステイル エタニティ ~世界樹と恋する魔法使い~,Games,Japan,ULJM 05577,1.02,1700233216,7edc9f71,a7da3454b908608a3e08e13d77c4cad0,4c756020f971f7f7f6a9c6e5455e0305f0158776 -67509,Sony PlayStation Portable,Persona,ペルソナ,Games,Japan,"ULJM 05422, ULJM 05686",1.02,816775168,1e851898,a7abd287cb1a46deef5fdbb3f961aa01,66e76366d412fc4ac3f5c71923fb89a2e594f1c9 -67510,Sony PlayStation Portable,PhotoKano,フォトカノ,Games,Japan,ULJS 00378,1.03,1744863232,a950fb0e,509e9c41a915cb220de249852974f810,af4a5624ef467328866b8998bdc968c50ac2e574 -67511,Sony PlayStation Portable,Senjou no Valkyria 2: Gallia Ouritsu Shikan Gakkou,戦場のヴァルキュリア2 ガリア王立士官学校,Games,Japan,ULJM 05560,1.01,1120927744,8cce5811,ac85092be1397e2d0fb70f2172550b4e,eb4807b28f4e9238768b53a35f9dbc2c79a9c9fc -67628,Sony PlayStation Portable,SNK Arcade Classics Vol. 1,,Games,Japan,ULJS 00193,1.00,1196130304,86eaf515,e2ccd0c68f4a747c2d4e514dd9514cc2,ef83d321555e8384c035d97e9bf272aaec9079bf -67629,Sony PlayStation Portable,Tactics Ogre: Unmei no Wa,タクティクスオウガ 運命の輪,Games,Japan,ULJM 05753,1.02,1616052224,88249e47,3b51e5fc03475e9c2158aea0a97e7437,0cb7a82fe3b7aa6ad596be11270c17339c4c0524 -67630,Sony PlayStation Portable,Vitamin R,,Games,Japan,ULJS 00592,1.02,1738899456,3a33f188,4a1f8386824451111b39810ac7c598ea,ed9db7a52bc616101cc1d00a18106b98d27c1604 -68024,Sony PlayStation Portable,Buzz! Quem é o Génio Português? ~ Buzz! Sokrovishha nacii,Buzz! Quem é o Génio Português? ~ Buzz! Сокровища нации,Games,Europe,UCES-01207/POR,1.00,1580793856,b80f2f26,17db7d4bfd7f7f7c4a2152992a602a49,ec28998d915cd6309c8bb95bd6f0c21fd5c50ca8 -68033,Sony PlayStation Portable,FIFA 10,,Games,Portugal,ULES-01331,1.00,1335558144,bfa118fb,511a056e931956642f60153f2301c589,8fd7f4ffb8df1aa03a0c19151c57079ce3a599a7 -68034,Sony PlayStation Portable,FIFA 12,,Games,Portugal,ULES-01550,1.00,1334706176,f0ee69e2,03869f663db27e27afd0de47321c4f8a,db2f7c5e28032fbc1f3d881926d0b3be60345311 -68035,Sony PlayStation Portable,Toki no Kizuna: Hanamusubi Tsuzuri,十鬼の絆 花結綴り,Games,Japan,ULJM 06300,1.01,1564114944,b9836c1c,e1d8996e996af6d8ee0293488a1a5547,5fad6db757e40d217341494c578e036f91d2e08e -68036,Sony PlayStation Portable,Eiyuu Densetsu: Zero no Kiseki,英雄伝説 零の軌跡,Games,Japan,ULJM 05733,1.01,1386217472,5179b4b0,3002bbf9862d9adbab4226c38eb35f49,e3c526d65adc1ccd11d4f12220ad05832962eb20 -68051,Sony PlayStation Portable,FIFA 14,,Games,Portugal,ULES-01592,1.00,1334738944,f9c3cbf1,dc1ec6cd654850052d67cd9847c9cf33,9355f9ad7c548efd5316e60019ec0d0986b0912c -68452,Sony PlayStation Portable,Metal Fight Beyblade Portable: Chouzetsu Tensei! Vulcan Horuseus,メタルファイト ベイブレード ポータブル 超絶転生!バルカンホルセウス,Games,Japan,ULJM 05731,1.01,296812544,76caa73b,afe9a0c2676713403981f80ff9616700,8c5ce945153b05b42bc501374a85b1cd047864df -68453,Sony PlayStation Portable,Gurumin,ぐるみん,Games,Japan,ULJM 05123,1.01,893845504,31bda796,8369d1901aeb906e6c3fc8c3641ab636,12045a1de5b259bd85bc98f47e07754d63d575e4 -68454,Sony PlayStation Portable,Phantasy Star Portable 2,ファンタシースターポータブル2,Games,Japan,"ULJM 05493, ULJM 08030",2.00,1696366592,f61e590c,87cf3b41780c8fd938e03fb2503d3bc3,dd44172283138d4eab8e1f382d6afd4810bd8576 -68455,Sony PlayStation Portable,Shining Hearts,シャイニング・ハーツ,Games,Japan,"ULJM 05780, ULJM 08049",1.00,1339424768,db5fcea4,d825dd03c3ca883da9f456cf8ef97e9d,8ac3c2d07f99f2592b3c90bb5574e69730923998 -68456,Sony PlayStation Portable,Valhalla Knights 2,ヴァルハラナイツ 2,Games,Japan,ULJS 00138,1.03,1621655552,8a3e811b,2b379c8834eb6f8ea96474422d45974d,19dfe7890f7717954556951da890162d3373089c -69337,Sony PlayStation Portable,Bomberman Land Portable,ボンバーマンランド ポータブル,Games,Japan,"ULJM 05181, ULJM 05319",1.01,413204480,4738e583,fe740f7adcc7399b0f9c3bb98b89a048,978b9b639c09ca8ea2748605b4913b04b578aeeb -69985,Sony PlayStation Portable,Goku Makaimura,極魔界村,Games,Japan,ULJM 05147,1.01,432275456,536042ff,7b19f8b6aac6f1aebb5d32f669d15b08,9c9f25f551947799014583a21be4257fb26a817e -70476,Sony PlayStation Portable,Disney G-Force,Миссия Дарвина,Games,Russia,ULES-01240,1.00,1244856320,2ded897d,581c42230176eb4a485c1c432cb94b4e,c8acdb0e5d7c2a77dee69d03e5e76bb93b2fe9b3 -70595,Sony PlayStation Portable,God of War: Chains of Olympus,,Preproduction,Europe,UCET-00844,0.01,1641086976,d80968f0,5f365435e8744956708c3c717abfa0e9,c02f71e9a7fe2a9846087dee0980c94b91108eb3 -71819,Sony PlayStation Portable,V8 Supercars Australia 3: Shootout,,Games,Australia,ULES-00614,1.01,1230995456,eb28e909,7014c6ecd8e73ec343ca1394992c48fb,3450cf338a18d6b8735eb1dcad7c50b49ef9caea -71824,Sony PlayStation Portable,007: From Russia with Love,From Russia with Love,Games,"Europe, Australia",ULES-00288,1.00,792199168,b4258d77,691a0efef6271887510def5fcba9d74c,9304265be2287ff154c4b4420814596bbc18d8a5 -71825,Sony PlayStation Portable,The Con,,Games,Australia,ULES-00516,1.02,792985600,d4ccf874,c2439566bcf85170d36bb19814979da7,0502d1826edd6915f0bc9ed751e7640bdf6c674e -72443,Sony PlayStation Portable,Dead or Alive: Paradise,デッド オア アライブ パラダイス,Games,Japan,"TCM 30002, ULJM 05640",1.02,877232128,9f610ca1,c29bc2c9c9cd883e3ae25edbb49e65a3,8e952c6c7cde29effd09485e8682c64ca75b0f7f -72444,Sony PlayStation Portable,Shin Sangoku Musou: Multi Raid,真・三國無双 MULTI RAID,Demos,Japan,ULJM 91017,1.01,389349376,6cc4a3f7,530756ad1923f0dab9e4861b4e1955fa,e91dacfed0f2934306aab6e9c99e5a12920a5cf5 -72445,Sony PlayStation Portable,Ooedo Senryoubako,大江戸千両箱,Games,Japan,ULJM 05099,1.01,566919168,4b3e9f76,d14f08dd2c13dfac324215da6eef1915,91b91ed1b34b72b9c76794fea2d57f96e0379257 -72448,Sony PlayStation Portable,DJ Max Portable: Black Square,DJマックスポータブルブラックスクエア,Games,Japan,ULJM 06034,1.01,1723039744,fc48340f,dbec6a2a2a5a352f352281da725f5950,3ca710f08ae5b875f4e7883e3c2ac86816fb88bd -72451,Sony PlayStation Portable,Exit,イグジット,Games,Japan,"ULJM 05062, ULJM 05271",1.00,112852992,05d404f2,b16aa2ac623f7c4e83bb7af1fc3f8aba,028e0ee071182b4e01223b7a32138b35af285b79 -72452,Sony PlayStation Portable,Sword Art Online: Infinity Moment,ソードアート・オンライン -インフィニティ・モーメント-,Games,Japan,"ULJS 00557, ULJS 00558",1.00,1200226304,d97acf65,bcf29f8a7aa234c83fab6ab6aa842261,78da017a5c90e34101608e7ff187db0e02e22177 -72453,Sony PlayStation Portable,Puzzle Bobble Pocket,パズルボブル ポケット,Games,Japan,ULJM 05011,1.01,17793024,7ab34a2d,bfbdcd3ab51de820fceaa13dbd78ee46,3212916db749fb67003c6222179909bda05f2d9f -72476,Sony PlayStation Portable,Ape Academy 2,,Preproduction,Europe,UCET-00445/0.01,0.01,1032388608,12df15c7,6e7ab8aeec149126d2730fb253dd1bd9,51524fbf50dc34ade5309ad822ac06afdfd1e75a -72740,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,Latin America,ULUS-10553,1.01,1514110976,a1a12c16,d1a824e0ba956c84214f8d7b00a3aa38,76c013c164751345f9a3693422bb7180590850d1 -72851,Sony PlayStation Portable,Memories Off #5 Encore,メモリーズオフ#5 encore,Games,Japan,ULJM 05527,1.00,848396288,8893941d,6de1a961003538511dfb9f8cf8cbcd48,76ada96b27944a159f40ff2f823d9b37136380c8 -72852,Sony PlayStation Portable,Street Fighter Zero 3 Double Upper,ストリートファイターZERO3 ダブルアッパー,Games,Japan,ULJM 05225,1.01,271417344,57d9eb3e,d2c5ac0e4398858733c619050e1a6ff9,86b75c0e299400722d5e4e1f7077730da0fbac11 -73155,Sony PlayStation Portable,Sora no Kiseki: Material Collection Portable Mini,空の軌跡 マテリアルコレクションポータブルmini,Demos,Japan,ULJM 91016,1.01,520192000,ace125cb,4ded30dea67685907519ca0bef6a950a,7ddb33d04a295292cc2db794ded045a68df4e948 -73156,Sony PlayStation Portable,Fantasy Golf Pangya Portable,ファンタジーゴルフ パンヤ ポータブル,Games,Japan,ULJM 05440,1.01,1506541568,c78f037f,5c29b57d4176d152924a6986c73678ba,45702494382fca90c1fed30daea97e1719f57907 -73157,Sony PlayStation Portable,ToHeart 2 Portable,トゥハート2ポータブル,Games,Japan,ULJM 05485,1.00,1426685952,b21e1e98,7974d19c4b3f05fec827f5204e77dc8b,77ebbb042e75c5c59c988e088330af34e9c499fb -73158,Sony PlayStation Portable,ToHeart Portable,トゥハートポータブル,Games,Japan,ULJM 05485~6,1.00,603389952,3ebe0f9b,8a15554ee41007ad452f0cf18eb3ab67,5607a209ed3165fdbad4569b33070ffcfd51b00d -74487,Sony PlayStation Portable,DreamWorks Vecinos Invasores: Hammy Enloquece,,Games,Spain,ULES-00664,1.02,325550080,157e685c,c12bab51c3c53b4754bf710c2057b5a5,e098674a2764c4b224fef9de42cde965a4df15bc -75083,Sony PlayStation Portable,Battle vs. Chess,,Preproduction,Europe,ULES-01517,1.02,643039232,2823bf1d,94e3caea8dd7b13c2a8716cea476f972,d42a7f34b10d000f19cd18dacf0f2ab088d3e3b2 -75085,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu Portable 3,実況パワフルプロ野球 ポータブル3,Games,Japan,ULJM 05300,2.00,1762197504,76bac42e,e9b3fdfa704a5454d14477888810ac77,d6b627deb31acc7f96897a5940b9a70cbd671b89 -75264,Sony PlayStation Portable,Arthur and the Minimoys,Arthur and the Invisibles,Preproduction,Europe,ULET-00435,0.04,1796014080,15da5e96,585445e0ddffaea516436ec7c67e5be0,58c3938bae053e1e2bb30546ab01dc6df9f517ff -75266,Sony PlayStation Portable,Juiced: Eliminator,,Preproduction,Europe,ULET-00391,0.03,1262059520,f1f12abc,5f33516cb9c1a750b8ecd0e90b1e6f7d,5be25d6b91dc19bd7caa3c2c2a240644210eebb6 -75267,Sony PlayStation Portable,Key of Heaven,,Preproduction,Europe,UCET-00247,0.01,1141997568,090393fa,b7f22e799b83aee1c6e88f273f163cef,5f0572842a1a450ae464b4a002a74d7861ab02ac -75268,Sony PlayStation Portable,Ratchet & Clank: Size Matters,,Preproduction,Europe,UCET-00751,0.04,993394688,f44c67f3,3705bc50375f1950a8c784812c6eb033,bcfcac002f1133073c3877259f794c756c7bc24f -75277,Sony PlayStation Portable,Blazing Souls Accelate,ブレイジングソウルズ アクセレイト,Games,Japan,ULJM 05490,2.00,1032454144,364a0f48,89e4a36a7fe53d9250c92e9d95554dcb,52664bd428f0da539ee01e05a824245cac642f1f -75278,Sony PlayStation Portable,Code Geass: Hangyaku no Lelouch: Lost Colors,コードギアス 反逆のルルーシュ LOST COLORS,Games,Japan,ULJS 19035,2.00,916750336,df4024e3,8c67fe6a44b5da33094769f638bb64cf,1d1a361830cc860bc50e6691f9a6b73e160ae985 -75279,Sony PlayStation Portable,Field Commander,,Preproduction,USA,ULUX-80153,1.02,846561280,51d78f3a,370a79369768ba6facdd43fe6736ab77,507cd70427e73655c16769cf5323bdb8d6c423f3 -75280,Sony PlayStation Portable,Grisaia no Meikyuu: Le Labyrinthe de la Grisaia,グリザイアの迷宮 -LE LABYRINTHE DE LA GRISAIA-,Games,Japan,ULJM 06382,1.01,1728380928,14f64f4d,3c321ee9d0b02a6d6f371da739d92b9a,d6fcbbcb9a46a53ebed5abdc204cbcd8cb73bba3 -75281,Sony PlayStation Portable,Grisaia no Rakuen: Le Eden de la Grisaia,グリザイアの楽園  -LE EDEN DE LA GRISAIA-,Games,Japan,ULJM 06395,1.00,1789067264,c5c97e1d,2343206d8d35c67353f5df88a919e865,85a5ee8f6269c772791ce3d8ac7397592b43a558 -75282,Sony PlayStation Portable,Midnight Club: L.A. Remix,ミッドナイト クラブ:LA リミックス,Games,Japan,ULJM 05904,1.00,922681344,ca02a0db,33c0fa38f70835c23dde73996f8ead23,280f5fa63ec3af0f956e2d695fb6857953a5c824 -75287,Sony PlayStation Portable,Minna no Golf Portable 2,みんなのGOLFポータブル2,Games,Japan,UCJS 18031,2.01,922025984,c1d4183f,dbf7e2e7053ca717a1303015c10e4873,596c99cecac77d0f41c4d21224f55901d2a444cb -75288,Sony PlayStation Portable,Nise no Chigiri,二世の契り,Games,Japan,ULJM 05703,1.01,1615822848,a0ccd574,7d6ed5b37305bfa78b17b391dd8a2dbc,543a1d023359604fffdf91ab2cb40097051ea941 -75291,Sony PlayStation Portable,Storm Lover,,Games,Japan,ULJS 00299,1.02,1532329984,741d054e,a74e097ffbd6b57f78c408c39977faba,86c87dd80ac4e2c01f75a3fe98a5575552c2463c -75292,Sony PlayStation Portable,Storm Lover,,Games,Japan,ULJS 00300,1.02,1532297216,6b926e9a,a642cecacc44eab72aeed4ab3da14ba3,cf51fb4d16f0de94af831167abb8ad0f366f0f5e -75293,Sony PlayStation Portable,Taikou Risshiden V,太閤立志伝Ⅴ,Games,Japan,ULJM 06158,3.00,304840704,9f2a5bd6,dfce9a0d06256b818f6ce6cd49924b6d,c5471319f253872071bb37678a533bec584d2d1c -75294,Sony PlayStation Portable,Wand of Fortune Portable,ワンドオブフォーチュンポータブル,Games,Japan,ULJM 05689,1.01,1797521408,90e68227,9ec650cfc006df46e46eb22aa047c8f2,52585c2a60f34a87d75e89d13ff0b69099933080 -75441,Sony PlayStation Portable,Sid Meier's Pirates!,,Preproduction,Europe,ULET-00696,0.01,333479936,5196d91f,a70b0e679c98434cc213c64b64efc0a6,f7bd8102c9de442a10edc5691af7d93d57bfdf44 -75453,Sony PlayStation Portable,Artlist Collection: The Dog Happy Life: Shiawase Wanko Seikatsu Dai-1-dan,Artlist Collection THE DOG HAPPY LIFE ~幸せワンコ生活第1弾~,Games,Japan,ULJM 05122,1.02,801046528,d0855f82,98d4cda709f3f598ce4e2b8003e4729e,a767127bc408cb9f97bcdb283c7028df7c7da0d3 -75454,Sony PlayStation Portable,Artlist Collection: The Dog Happy Life: Shiawase Wanko Seikatsu Dai-1-dan: McDonald's Ver.,Artlist Collection THE DOG HAPPY LIFE ~幸せワンコ生活第1弾~ McDonald’s Ver.,Games,Japan,ULJM 95002,1.01,801046528,e293b867,b5408949427dc13bc213cee88feaccc8,7de8116d8226ef680630c7546d62ccb8d411583a -75751,Sony PlayStation Portable,Crash of the Titans,,Preproduction,Europe,ULES-00917/1.00,1.00,1120763904,b5206914,891421579549aab304c0d94759a3bed0,986fd245093b58353726007c7e9c8f482fe4bb5d -76216,Sony PlayStation Portable,FIFA 14: Edición Legado,,Games,Latin America,ULUS-10655,1.00,1666908160,518bd38f,f4a058fe56c5f3024a870c5b51ccf1f4,67bbf542219d5f5c4cfb115325a4ad2298687e23 -76350,Sony PlayStation Portable,Spectral vs. Generation,スペクトラル VS ジェネレーション,Games,Japan,ULJM 05162,1.06,180355072,c0db3855,8c37c701632fc1f75efe1215fce52008,827e481fac3a7f199e127141a0b6b64740e7ada8 -76599,Sony PlayStation Portable,Disney/Pixar Ratatouille,Disney/Pixar Ο Ρατατούης,Games,Greece,ULES 00743,1.01,906362880,80866cc0,ae438154279aecf45887856eb7b46a1e,80609248f58fa4654f373bdc126d59bc97a4914e -76600,Sony PlayStation Portable,Invizimals: Shadow Zone,Invizimals: Στη Ζώνη της Σκιάς,Games,Greece,UCES 01581,1.00,1148551168,ff2e6683,5b22ad16c4a1466b03145e5602918aa3,4031a8171b642dd17afd4d14c4acadc107e7de80 -77232,Sony PlayStation Portable,Rei Chou Aniki,零・超兄貴,Games,Japan,ULJM 05390,1.01,441450496,803b69c8,5c2b53eb9c17480bb7e1d6e145f188b6,0278f9258d5a97620e48f6e73df26925b5bb566f -77634,Sony PlayStation Portable,Ore no Shikabane o Koete Yuke,俺の屍を越えてゆけ,Games,Japan,"UCJS 10116, UCJS 10117",1.01,847937536,349a2aaa,668ff6d3779086f2059dd6a59e5277f8,3b97c51337a3d07724d0fa324dee838e52844cc4 -77635,Sony PlayStation Portable,Guilty Gear Judgment,ギルティギア ジャッジメント,Games,Japan,ULJM 05397,1.04,609484800,f6bfdae6,de21ed0187c3e9be9aab717b4ff8fb18,6bcb351f9f49a0a2e7bc79bb08c33817ad0ead74 -77636,Sony PlayStation Portable,Guilty Gear XX Accent Core Plus,ギルティギア イグゼクス アクセントコア プラス,Games,Japan,ULJM 05355,1.00,902922240,c375c9e2,f326aaeda7b28e0cf18c5a7dcdf92a69,10752b61659970cc996b1951bb6bd9a2fccb68eb -77638,Sony PlayStation Portable,Ore no Imouto ga Konna ni Kawaii Wake ga Nai Portable ga Tsuzuku Wake ga Nai (Disc 1),俺の妹がこんなに可愛いわけがない ポータブル が続くわけがない,Games,Japan,"ULJS 00490, ULJS 00492, ULJS 19086",1.00,1493139456,2758a429,0bf0132e8a5a6efdcffde355a35a3ff8,5a562888b84b5d58e71f6bd7078432cc4ff113dd -77639,Sony PlayStation Portable,Ore no Imouto ga Konna ni Kawaii Wake ga Nai Portable ga Tsuzuku Wake ga Nai (Disc 2),俺の妹がこんなに可愛いわけがない ポータブル が続くわけがない,Games,Japan,"ULJS 00491, ULJS 00493, ULJS 19087",1.00,1498316800,0886e09e,1b774694d0a93cabf79296c0ddf28a91,2e3a9239fcc010eda13153ef40fafff2db64a323 -77751,Sony PlayStation Portable,Brothers Conflict: Brilliant Blue,ブラザーズコンフリクト~ブリリアント ブルー~,Games,Japan,ULJM 06315,1.01,1739259904,ca779d75,c762c16147df33a56fb43fc1d208e843,7606d9b90fe9d9bc2e47f2d0126eb44dd3b4908c -78528,Sony PlayStation Portable,Doko Demo Issho: Let's Gakkou!,どこでもいっしょ レッツ学校!,Games,Japan,"UCJS 10039, UCJS 10039/1.01, UCJS 18012",1.01,295632896,f3983b72,3ec14cc0e1e4eb7ebe0e9d74ea0a39df,290aefa7c1c7d5db46f20af77ef859c2c3b510da -78747,Sony PlayStation Portable,Star Wars Battlefront: Renegade Squadron,스타워즈 배틀프론트 레니게이드 스쿼드런,Games,Korea,ULKS 46017,1.01,939786240,05036ebf,f36231566f12824ab505115769b36eed,48584d6d83ab16a5971783df0a94089770b71f85 -78758,Sony PlayStation Portable,Kisou Ryouhei Gunhound EX,機装猟兵ガンハウンドEX,Games,Japan,ULJM 06225,1.04,734691328,c17fbb5d,f981491ee643fe011770c94ee6f85d9c,bf9f2aea2096947166d039c53efdf0b4e18a8fe4 -79083,Sony PlayStation Portable,Grand Theft Auto: Chinatown Wars,,Preproduction,Europe,ULET-01349/0.01,0.01,809140224,b6fae2dd,bca8e5260e721b7cd8016a078796577c,7d98f7c90e3adcb423a6bda4e8848c967849fe1f -79084,Sony PlayStation Portable,Grand Theft Auto: Chinatown Wars,,Preproduction,Europe,ULET-01349/0.02,0.02,901382144,cf16a71c,0531683e75dfcf0b56d9c689540d8b79,698f7a10fdab36177119679367aaeff72203630e -79097,Sony PlayStation Portable,Accel World: Kasoku no Chouten,アクセル・ワールド ―加速の頂点―,Games,Japan,ULJS 00512,1.00,1508704256,a6e27bce,acbdfd28c9eb2fb36dd9f3a95500f421,928b10d060e969b8e17146c071acec7444ede93a -79119,Sony PlayStation Portable,Shin Sangoku Musou: Multi Raid 2,真・三國無双 MULTI RAID 2,Demos,Japan,ULJM 91020,1.01,753467392,441c2bd6,4071b4b147a4bf1213f58df291491942,65efcb2e3a5510e561130f0f7049cfcfc5609ccf -79120,Sony PlayStation Portable,Accel World: Gin'yoku no Kakusei,アクセル・ワールド ―銀翼の覚醒―,Games,Japan,ULJS 00510,1.01,1632468992,b6e2c9f1,76ce7cfa56fb7bef7d90d02b6b185b18,0a6544a36b129a1060c34791cea1fbe1ba320f3e -79477,Sony PlayStation Portable,Warning: Code de la Route,,Games,France,ULES-01103,1.00,332234752,8150f899,1ba516a606e9861ffc851b19ceed2e4b,5a995c4280301083be9c2ae5103563142d711734 -79478,Sony PlayStation Portable,Dynasty Warriors,,Games,France,ULES-00118,1.01,241106944,25ead8aa,8ba04d7058200c17c9a7bcd906a310c0,9e6a2e11f44c240bc85ef9997cf1b78fe9a975cd -79481,Sony PlayStation Portable,Gun Showdown,,Preproduction,USA,ULUS-10158,1.00,795901952,8f24c1d6,51afd9d864879d6ca199efcb6e67100f,471fc7f10ce3101a5be28c1cd8989199ff21d175 -79482,Sony PlayStation Portable,Lemmings,,Preproduction,Europe,UCET-00179/0.05,0.05,458850304,ab82b3fd,cd1cf8528db6a45ec6aa33174cc2068f,5f995042fe5b6504a2beabc6ac9f947d3d92ed2c -79483,Sony PlayStation Portable,WRC: FIA World Rally Championship,,Preproduction,Europe,UCET-00006/0.01,0.01,1568079872,83adb164,dd60041bfb6d677fdaacd2cf9cb6d84a,88a19042041ff368b9cb887432cb5255c654c33c -80141,Sony PlayStation Portable,Kidou Keisatsu Patlabor: Kamubakku MiniPato,機動警察パトレイバー かむばっく ミニパト,Games,Japan,ULJS 00026,1.00,190873600,2ab745c2,82ee852ad6c1212d2f54f472acad950b,0e97e32240789049866a65de2521a6802d53cef1 -80142,Sony PlayStation Portable,Tales of the World: Radiant Mythology 3,テイルズ オブ ザ ワールド レディアント マイソロジー3,Games,Japan,ULJS 00294,1.00,1807089664,7a5ce0bd,5d63d1652b851e005d27fe42db7d6241,aa1df96ecfa1b53fdda9391dc711c239827bfd91 -80515,Sony PlayStation Portable,Clank & Ratchet: Maruhi Mission Ignition!,クランク&ラチェット ㊙︎ミッション☆イグニッション!,Games,Japan,UCJS 10084,1.00,1115258880,1e5c9a98,a3cd172355b55dd2603eed1318e3c7ce,cd89551f82247618bd2a1e04b45f87eebbf4e953 -80516,Sony PlayStation Portable,Tales of Phantasia: Narikiri Dungeon X,テイルズ オブ ファンタジア なりきりダンジョンX,Games,Japan,ULJS 00293,1.01,1171161088,4841790e,aa49c716783766aa5913e6a5ca8bb822,a8ba8878c6d626806518b8a538d19094e1062ca9 -81607,Sony PlayStation Portable,Starry Sky: After Summer Portable,Starry☆Sky~After Summer~Portable,Games,Japan,"HONEY-006, ULJM 06208",1.01,1706164224,61b5ce15,4e124edca4f92df3c73b3f6f0155695f,d70650b2a3da93d85531355da11153a4a5ae4fbc -81608,Sony PlayStation Portable,"Starry Sky: After Summer Portable: Etsuran Shite Please ""Etsu Puritsu 2""",Starry☆Sky~After Summer~Portable 閲覧してプリーズ"えつぷリっ2",Bonus Discs,Japan,"HONEY-006, ULJM 06255",1.01,641531904,d1422c4b,32d47a41dba7dcab3d43582b1d8792e5,db64a302890471fb535140dc31418bf73d21dd21 -81609,Sony PlayStation Portable,Echochrome: Muhan Hoerang,echochrome 無限回廊 [무한회랑],Games,Korea,UCKS 45082,1.00,290652160,b24455a7,01cd845f04c203dcac57a2d75037e3da,021fffd5ec755116289f7f8f5d7f325c73e95b43 -82346,Sony PlayStation Portable,Metal Gear Ac!d²,메탈 기어 애시드 2,Games,Korea,ULKS 46065,1.02,915341312,0b4ae283,386f9c380eb8a757596c9a8e489f4328,d3131f6dbc5ecdf395a0e057b5b7bc43935899c5 -82824,Sony PlayStation Portable,Hakuouki: Yuugiroku,薄桜鬼 遊戯録,Games,Japan,"UGPP 00501, ULJM 05663",1.02,384204800,a7f14137,a7f6c8166d71cd85b956a2bc05d5dcd4,f7620d25544286007488b24eb5a5ed9a5f2db611 -82825,Sony PlayStation Portable,Pop'n Music Portable 2,ポップンミュージックポータブル2,Games,Japan,ULJM 05959,1.00,1541537792,ee4ffba2,5a6ccc0e3059bdd1e174117d7a23898d,6bec02e9072a04155a735ae542aac0b8ec6b2197 -82826,Sony PlayStation Portable,Shin Sangoku Musou 2nd Evolution,真・三國無双 2nd Evolution,Games,Japan,ULJM 08020,1.00,312213504,3399b126,f0cbf43214210e3946ba3edfd87c572d,795ecbee4f5cbcd35766fbc3a3811f585833d83f -83706,Sony PlayStation Portable,FIFA 13,,Games,France,ULES-01569,1.00,1303740416,8d2b4961,7e0681e34f1e324161b837ba6265ce75,64348943392c0e5efb893fe76baf49e7cd948da4 -83707,Sony PlayStation Portable,WWE SmackDown vs. Raw 2006,WWE 스맥다운 대 로우 2006,Games,Korea,ULKS 46057,1.02,1704525824,c2a4942f,efbfc3f93942fc2b21426fb67c7af3ee,2913b4d4afedc0b1f4fbecb6439954e65e84e5ee -83708,Sony PlayStation Portable,7th Dragon 2020-II,セブンスドラゴン2020-Ⅱ,Games,Japan,ULJM 06229,1.00,1324154880,924402ea,f8b2c5c53191e5c6891371c3ed0a129f,e353a29f66fc76df961bc1eac074259eb05582f4 -83710,Sony PlayStation Portable,Bunmei Kaika: Aoiza Ibunroku,文明開華 葵座異聞録,Games,Japan,ULJM 05824,1.01,1559363584,af7cc5db,47c5b0a148e7af1b17aa7bcf231b5e58,1a1e22ffba27e67d9dd6df9ff96e76bae3cbb74b -83711,Sony PlayStation Portable,Busou Shinki: Battle Masters,武装神姫 バトルマスターズ,Games,Japan,ULJM 05538,1.03,593002496,57009469,acf0c249829b56be445b1e4a387cb862,273a05dd1f4081547159991a252576145cb9469e -83712,Sony PlayStation Portable,Chikyuu Boueigun 2 Portable,地球防衛軍2 PORTABLE,Games,Japan,"ULJS 00374, ULJS 00381",1.02,382828544,84482292,d6af4611f9d06d1d15c2ea7409987e7c,e8a9934da4ed58bd7d65f6855e90d49f5910a090 -83714,Sony PlayStation Portable,Danball Senki Boost,ダンボール戦機 ブースト,Games,Japan,ULJM 05990,1.03,1713307648,5f6502ee,ff23f15692d9f2c998735e816eeb435a,a4b25b7213a2a206b29f2b8e25cdb078ee0ef5ad -83716,Sony PlayStation Portable,Danball Senki W,ダンボール戦機W,Games,Japan,ULJM 06096,1.02,1750728704,598def36,a7c66ad4ef1baa61aadff57e280325db,30df1840a09b6a1f6348b425af67f30e58799fb1 -83717,Sony PlayStation Portable,Digimon World Re:Digitize,デジモンワールド リ:デジタイズ,Games,Japan,ULJS 00496,1.01,1060044800,4f15a275,031400b3febb5c3b7cc5c83776c119f7,8d4b9e8118026ceec38898a6c47c01763ec156bc -83726,Sony PlayStation Portable,Hakuouki: Reimeiroku Portable,薄桜鬼 黎明録 ポータブル,Games,Japan,"ULJM 05916, ULJM 05917",1.02,1653309440,bda131e9,aca74201740ef2772deb85f07aa875ec,0c59c51c400fac33ac80e4f2f0baf7217fc4a7a1 -83727,Sony PlayStation Portable,Harukanaru Toki no Naka de 3 with Izayoiki Aizouban,遙かなる時空の中で3 with 十六夜記 愛蔵版,Games,Japan,ULJM 05441,1.02,1373044736,18521e97,07e9d219637549c7e9ef03f46d1d3126,8ae4efd5664a8ce6e6807500caca156e7d3d6da2 -83728,Sony PlayStation Portable,Hatsune Miku: Project Diva 2nd,初音ミク -Project DIVA- 2nd #,Games,Japan,ULJM 05952,1.00,1618280448,08832d16,1c58ec248d77583803bc6b25c648affb,de0d2e73df4f74743758b1f8c06d78d4e81390ad -83729,Sony PlayStation Portable,J.League Pro Soccer Club o Tsukurou! 6: Pride of J,J.LEAGUE プロサッカークラブをつくろう!6 Pride of J,Games,Japan,ULJM 05518,1.01,1796472832,87c2fced,a083df63ac81ee04fd3787fe7d71e2cd,9d2a50e9d15e072433f925fdefee14b8d8a83f0c -83730,Sony PlayStation Portable,J.League Pro Soccer Club o Tsukurou! 7: Euro Plus,J.LEAGUE プロサッカークラブをつくろう!7 EURO PLUS,Games,Japan,ULJM 05898,1.02,1544814592,233daea8,b554407347beea364d291522bcfe236b,fd942a4ada80f160f9d620e4ae7fad2313fc1cac -83731,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2012,実況パワフルプロ野球2012,Games,Japan,ULJM 06083,1.01,1497464832,8a422cc1,c9d1d239c4dd907eee97d5a53f8c170d,609a8ffd1c5d23befaead4a275117e1aa4cb276d -83732,Sony PlayStation Portable,Kin'iro no Corda,金色のコルダ,Games,Japan,ULJM 05569,1.01,1583153152,558a0826,9b20065401bdccca9e963e7252198f99,410997d46f44886ef1175d34c400dafc1e9d49c5 -83733,Sony PlayStation Portable,Last Ranker,ラストランカー,Games,Japan,ULJM 05676,1.01,950337536,dc47ee2e,22b28ab44e348cd139ed7175cf15f0f6,c3aff148045cda734df96f8240922536dcaf0f98 -83734,Sony PlayStation Portable,Minna no Tennis Portable,みんなのテニス ポータブル,Games,Japan,"UCJS 10101, UCJS 18049",1.02,1235058688,b4f51366,22c7821f3e6e8f44e45deec829006517,f2bbf030f47a6c61dbc1651fec2aa889016e6471 -83735,Sony PlayStation Portable,One Piece: Romance Dawn: Bouken no Yoake,ワンピース ROMANCE DAWN 冒険の夜明け,Games,"Japan, Korea","ULJS 00550, ULKS 46287",1.01,863207424,e47d5472,1d2fa0b652e47128fde453936bd630e0,bdcc96622c9278a79afe296a71f2d91f10f9ba45 -83736,Sony PlayStation Portable,SD Gundam GGeneration Overworld,SDガンダム ジージェネレーション オーバーワールド,Games,Japan,ULJS 00536,1.01,1782448128,688dec81,cef86185f94d76365c850a5ef4efc4df,7ee211e54051ab381b0dff6ae1bf171487c51ef4 -83737,Sony PlayStation Portable,Super Danganronpa 2: Sayonara Zetsubou Gakuen,スーパーダンガンロンパ2 さよなら絶望学園,Games,Japan,ULJS 00522,1.02,1681588224,ddb35dc0,d96b7b06dbf22901408dc6ae49bdd3f2,ef10b5ecf333d52df0174511972ad09603c27114 -83738,Sony PlayStation Portable,Suzumiya Haruhi no Yakusoku,涼宮ハルヒの約束,Games,Japan,"ULJS 00124, ULJS 19023",1.06,1539833856,2d11c835,447f3cb9e5e359fac9878535a9915d9f,2f55a83cc9b6533f9c3c2ba3cf64dd27a3cd95dc -83739,Sony PlayStation Portable,Toukiden,討鬼伝,Games,Japan,ULJM 06290,1.03,1235288064,1fb366cf,72e0f5b7993027bb4d778cbf4afc7107,ffe611cc928e33db54309101de3535694f1ee783 -83740,Sony PlayStation Portable,Uta no Prince-sama: All Star,うたの☆プリンスさまっ♪All Star,Games,Japan,ULJM 06185,1.02,1700626432,12c3a58c,06fe654488ef39b4ec6c5e0530017a36,e051f9d59097a653c6d02a9b454deaf30a84710a -83741,Sony PlayStation Portable,World Soccer Winning Eleven 2011,ワールドサッカーウイニングイレブン 2011,Games,Japan,ULJM 05771,1.01,1539473408,4aea835c,302110b345e42723e995d55623eb7baf,805634f29712c016df8d6d892761522100361415 -83742,Sony PlayStation Portable,Zettai Hero Kaizou Keikaku,絶対ヒーロー改造計画,Games,"Japan, Korea","UCKS 45149, ULJS 00262",1.03,751009792,1b11aea2,fd631ff0395f81ee9ad8ad63decfd3d9,a9190a3292a13dae5c4e54133f41c7b021fa176b -83743,Sony PlayStation Portable,Hiiro no Kakera Portable,緋色の欠片 ポータブル,Games,Japan,"ULJM 05399, ULJM 06067",1.02,1421443072,23fbd141,7f6e5a8adfc853792b53435d59ae0c73,19920230326be7dd3ee05d8a2e96630d2a806439 -83748,Sony PlayStation Portable,R-Type Tactics,アール・タイプ タクティクス,Games,Japan,ULJS 00111,1.02,287080448,6be5b2b3,6f4b0bfc32dabae55e789d49c287fddd,b9509c878326ae5f94c1e24ac66d43d1ef1ae1f7 -83949,Sony PlayStation Portable,Mahou Shoujo Madoka Magica Portable,魔法少女まどか☆マギカ ポータブル,Games,Japan,"ULJS 00429, ULJS 00430",1.03,1564049408,c1824a2c,c62edbc718367597feb3deced5032e4d,71c5af5f9b86f2cc0de176e313d00afa9034b004 -83954,Sony PlayStation Portable,unENDing Bloody Call,アンエンディング ブラッディ コール,Games,Japan,ULJM 06079,1.01,1811972096,016139eb,821ea0382e94142675b4a0184555e201,fc18a716ee7eb8f291ce052d6804547e07590410 -84016,Sony PlayStation Portable,Arcana Famiglia: La Storia della Arcana Famiglia,アルカナ・ファミリア -La storia della Arcana Famiglia-,Games,Japan,ULJM 05956,1.02,1289191424,709f3257,3af168f7557aa6140e869fce1740d67b,f262e51ffca07bc7b5a0d4e7ec4288b17333fff9 -84017,Sony PlayStation Portable,Arcana Famiglia: Vascello Phantasma no Majutsushi,アルカナ・ファミリア 幽霊船(ヴァスチェロ・ファンタズマ)の魔術師,Games,Japan,ULJM 06032,1.02,1115717632,b6a69c71,fae979d82241f70b717c4c0b5ae9f906,8c79263e5d8cf6a060d419caefff9b88dcf2480c -84018,Sony PlayStation Portable,AKB1-149: Ren'ai Sousenkyo (Game Disc),AKB1/149 恋愛総選挙,Games,Japan,ULJS 00532,1.01,1806827520,ba38d5c9,bef4f3245e3eb70f88824cbf939b4004,45417f37c43683ec6dde1760d706db7970ecdd88 -84019,Sony PlayStation Portable,AKB1-149: Ren'ai Sousenkyo (Data Install Senyou Disc),AKB1/149 恋愛総選挙,Games,Japan,ULJS 00533,1.01,1804402688,95b1218b,ad90375529d21a0010e2bc579ef729a7,af472a952f0d5a2923b2ec15a4defdd714c65bbc -84020,Sony PlayStation Portable,Dragon Ball Tag VS,ドラゴンボール タッグバーサス,Games,Japan,"ULJS 00311, ULJS 19067",1.01,1112276992,dca4c3b7,f02cf7a814193f149aa0accc9fd13524,4dcf7340a7e4dc15079b0a118b70f8616c114a18 -84021,Sony PlayStation Portable,Eiyuu Densetsu: Sora no Kiseki SC (Disc 1),英雄伝説 ~空の軌跡SC~,Games,Japan,"ULJM 05277, ULJM 08034",1.01,1316159488,fb3df0b7,c13e551c235ad0d1a7e273744839a949,e1e2bf4ec826e978ef83bd63eb5cf1d61c52d087 -84022,Sony PlayStation Portable,Eiyuu Densetsu: Sora no Kiseki SC (Disc 2),英雄伝説 ~空の軌跡SC~,Games,Japan,"ULJM 05278, ULJM 08035",1.01,1569947648,720d46a0,98d16325f3cf8719f677f11e918e8729,3a52824fc094db35280baf8c11e33a67677e86b0 -84023,Sony PlayStation Portable,God Eater 2,ゴッドイーター2,Games,Japan,ULJS 00597,1.01,1748860928,0c73ad4f,d58a52ebc9373f9a8588e1c6481a55ce,622496cb103fee10d6397d980200236a0113aff4 -84024,Sony PlayStation Portable,God Eater Burst: Append-ban,ゴッドイーター バースト アペンド版,Games,Japan,ULJS 00350,1.01,1462468608,c9fccb74,a40134b0a4991f2e3ffddbecfc71304c,1f93cdb6220d892a04deaaf9a51b32dc28f64aca -84025,Sony PlayStation Portable,"Hanayaka Nari, Wa ga Ichizoku",華ヤカ哉、我ガ一族,Games,Japan,ULJM 05691,1.01,1665105920,5750c5ea,ba8b4456c1a8a8ffa6c03b8e2a756e4d,61750d1680739069757196f1be967cac6bc34458 -84026,Sony PlayStation Portable,Prinny: Ore ga Shujinkou de Iinsuka?,プリニー ~オレが主人公でイイんスか?~,Games,"Japan, Korea","UCKS 45104, ULJS 00150",1.01,500465664,5923a074,1dc916de1dcfda43954a54b9aded128b,f63f364efe9df05b3fe96dc68642dba003667464 -84027,Sony PlayStation Portable,Pro Yakyuu Spirits 2013,プロ野球スピリッツ2013,Games,Japan,ULJM 06240,1.00,1477541888,82bb0277,0d381f60d9599d56b40251140fed6b29,0bd649e24600859132811c0568c9ce95a31ea71f -84028,Sony PlayStation Portable,Sengoku Musou 3 Z Special,戦国無双3 Z Special,Games,Japan,ULJM 06024,1.01,1786347520,a1e44b33,2989260a13e0bbfa46b1a6e2427f02dc,052f3798ec6fae49c34b835d160e32ac03535e3d -84029,Sony PlayStation Portable,Shin Sangoku Musou 5 Empires,真・三國無双5 Empires,Games,Japan,ULJM 05584,1.02,1230897152,416c1c60,b28e51b5de803ea1b98f81bb1a23d429,9d9597f9d10898f3336ff6446364e00ff567de79 -84030,Sony PlayStation Portable,Taiko no Tatsujin Portable 2,太鼓の達人 ぽ~たぶる2,Games,Japan,ULJS 00081,1.00,904658944,5941bb18,524f3deaf71cabb6737cc9a04b4d09c4,17be59411f89c10d6c60f4d6895849d7fb8cb01d -84031,Sony PlayStation Portable,Uta no Prince-sama: Music 2,うたの☆プリンスさまっ♪MUSIC2,Games,Japan,ULJM 06292,1.02,1399062528,baf9c7f2,e09688dd37aa644c9c406c73c6d9c60b,37f51a93564ee0107ca918dcca996946f6307b55 -84032,Sony PlayStation Portable,World Soccer Winning Eleven 2010: Aoki Samurai no Chousen,WORLD SOCCER Winning Eleven 2010 蒼き侍の挑戦,Games,Japan,ULJM 05648,1.01,1616445440,50e892d0,e0b47a62d4d806e8de8d5740ceae38da,bafb8009256ac58b236f22b443aedb68a93dd5f9 -85177,Sony PlayStation Portable,Dragon Ball Z: Jinmudohoe,드래곤볼 Z 진무도회,Games,Korea,ULKS 46085,1.00,313262080,67db6eb0,36edd5fa8cae8b2810e8cde2c240f292,fd1093d7a6ee7e5ff0b0ea7a0a50833756d32416 -85178,Sony PlayStation Portable,Naruto: Narutimate Portable: Muhwanseongui Gwon,나루토 나루티밋 포터블 무환성의 권,Games,Korea,ULKS 46086,1.00,634257408,e91cf41c,2c0dbd3496d69f85ec1059a4f27990f3,8fb7e835ac50982585cf25a37673430dad932311 -85182,Sony PlayStation Portable,Burnout Legends,バーンアウト レジェンド,Games,Japan,ULJM 05049,1.01,505905152,ce08d14c,0d41a20d6d3363800bb70870d4cdafa7,aff5ae33a7c1e3af919719453e4eb3c8e91e701b -85183,Sony PlayStation Portable,Coded Soul: Uketsugareshi Idea,Coded Soul: 受け継がれしイデア:,Games,Japan,UCJS 10061,1.00,388595712,3ec7b2ac,342d1a49c0fe37d559ad0ea3106aecfb,690d7fc4cd6e1b2998ac455f275d1836bc660a87 -85184,Sony PlayStation Portable,D.C. Girl's Symphony Pocket,~ダ・カーポ~ ガールズシンフォニーポケット,Games,Japan,ULJM 05690,1.01,576290816,7a4f38a3,975f288ac99c72759035656c64488811,5e37b60da7cded5a57a5ff39b752a341a95a3a50 -85185,Sony PlayStation Portable,Eiyuu Densetsu Gagharv Trilogy: Shiroki Majo,英雄伝説 ガガーブトリロジー 白き魔女,Games,Japan,ULJS 00004,1.01,1001586688,f42e8652,e94d11d57b093d3314ced2952a819319,53a05bbd53d578f7f0d30fb5421cfe1e75a4195a -85186,Sony PlayStation Portable,Gundam Assault Survive,ガンダムアサルトサヴァイブ,Games,Japan,ULJS 00281,1.02,854491136,8587b889,7406e7f7b8ad4136583431bd94da759b,0a3c648d59000d8d7fed44dafa2a6aeb173368b4 -85187,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu Portable 4,実況パワフルプロ野球ポータブル4,Games,Japan,ULJM 05421,1.01,1802010624,4b68995d,e50d432c02ada6d849fcc35beb7b4a14,86d6daf32b370d84f1c886c7cf8461bb14583460 -85188,Sony PlayStation Portable,Kenka Banchou 3: Zenkoku Seiha,喧嘩番長3~全国制覇~,Games,Japan,ULJS 19030,1.00,531857408,f0c65909,72c6b08b2690ab6d240e501a7c004217,8daef52fa422be7f3766cb97092f02b79ca97250 -85189,Sony PlayStation Portable,LittleBigPlanet Portable,リトルビッグプラネット ポータブル,Games,Japan,UCJS 10107,1.01,1501233152,db6d9bdb,61c6d19c0739227b1213ee89abbd8310,289702a1b1ab30f3cc0f31208366427229060bec -85190,Sony PlayStation Portable,Makai Senki Disgaea Portable,魔界戦記ディスガイア PORTABLE,Games,Japan,ULJS 00089,1.01,903380992,e6cd4078,471db350a897ff88736107abd2c16b29,cad0393514758f6ba04065bc9e231719d42277a6 -85191,Sony PlayStation Portable,Nobunaga no Yabou: Shouseiroku,信長の野望 将星録,Games,Japan,"ULJM 05072, ULJM 05329",1.01,317849600,988a2563,9789decda74cb704411a52da8b4d6cae,d005efaebd62821b004fc7f91e6c1852ccd8a136 -85192,Sony PlayStation Portable,Patapon,パタポン,Games,Japan,"UCJS 10077, UCJS 18027",1.00,366510080,1a4fd1d2,37d3e1f3faf8ad1b1a67bac92bcb6f61,3811435db7415b33d10873d71640fcde10ee5596 -85193,Sony PlayStation Portable,Ratchet & Clank 5: Gekitotsu! Dodeka Ginga no MiriMiri Gundan,ラチェット&クランク5 激突!ドデカ銀河のミリミリ軍団,Games,Japan,UCJS 10052,1.00,659685376,d04d879a,f3bcf15253073439179191786b60aa6b,beb99884c974e6ee37c0c4a9b199bb950f3f0a33 -85194,Sony PlayStation Portable,Sangoku-hime: Sangoku Ransei: Haten no Saihai,三極姫~三国乱世・覇天の采配~,Games,Japan,ULJS 00434,1.00,1601601536,837dddc2,706d32586fe0d486a4438470b9e79638,97af6241f032619389bcc9043581cc9acbc533ff -85195,Sony PlayStation Portable,Sangokushi VIII,三國志Ⅷ,Games,Japan,ULJM 05398,1.01,192086016,c9513d47,c1fddef5f92ddcdba7318524612cdb7b,8778f06eed1c81db3b328802141ce408497de8a4 -85196,Sony PlayStation Portable,Senritsu no Stratus,戦律のストラタス,Games,Japan,ULJM 05934,1.01,1255342080,e330a1a1,05ce8adc3fac075bdac0b8b3aa6c735d,d1b5ba8dc74610c8823757ad09da80233fc6fec8 -85197,Sony PlayStation Portable,Starry Sky: In Spring Portable,Starry☆Sky~In Spring~Portable,Games,Japan,ULJM 05683,1.02,746291200,da4471c7,d6e9c8d9f35a0e03ec53293f27d237d0,1328f378413df045fce71457119b62738ceb509c -85198,Sony PlayStation Portable,Twelve: Sengoku Fuushinden,Twelve ~戦国封神伝~,Games,Japan,ULJM 05031,1.01,1733165056,8fdc1bc5,8094e8d532b0c904cafb0c7c56a19f1d,0ce3a92dba5e49c35f46914d75ee2d46a1af1cd2 -85199,Sony PlayStation Portable,Uta no Prince-sama: Sweet Serenade,うたの☆プリンスさまっ♪ −Sweet Serenade−,Games,Japan,ULJM 05817,1.01,1359609856,2022efff,e9132235d3626e65ec4e8d5112a8c369,e41e86843ffd8d66e89db8c52da90e4ee0f7968f -85200,Sony PlayStation Portable,Wand of Fortune 2: Jikuu ni Shizumu Mokushiroku,ワンド オブ フォーチュン2 ~時空に沈む黙示録~,Games,Japan,ULJM 05834,1.02,1649901568,476ed132,c4731e1e7229b6c7a6ebe6a49a083282,18d567d242c4530cd5f9a28ed1952fea187d9c30 -85201,Sony PlayStation Portable,World Soccer Winning Eleven 2012,ワールドサッカー ウイニングイレブン 2012,Games,Japan,ULJM 05922,1.00,1410793472,f4f1b3ca,eddc0b390d34a14b9cb8c0d0469f90e0,8af54f39a1179537bed63194067bc0a355138d17 -85298,Sony PlayStation Portable,Disney · Pixar Rottatouille,,Games,Norway,ULES-00745,1.00,906362880,6dc91b4e,3518c1cf57de9d015ac5515fb49c36ed,e151d816c7593b2594d8e5b17427b4257da15849 -85299,Sony PlayStation Portable,Personal Utility Disc Ver. 1.0,,Applications,Korea,UCKM 84003,2.00,141426688,f43ebc61,786377670a144c9e57c5589c87a4909d,a2c757f77e1de025caf9288c8c40e2b1287d58fa -85300,Sony PlayStation Portable,Untold Legends: Brotherhood of the Blade,언톨드레전드,Games,Korea,ULKS 46015,1.01,407601152,c29b5f05,9635bfd4383d66de1dd073b52016febc,851d3d9d5b9a63333fc10157aba02df92c44db19 -85541,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,,Games,USA,ULUS-10041,2.00,1255243776,b8f8b576,8daab3bd252db96b477710a02d00c1f6,acb6242564d05a033ff56ab028466872001e5a8c -85542,Sony PlayStation Portable,Grand Theft Auto: Liberty City Stories,グランドセフトオート: リバティーシティストーリーズ,Games,Japan,ULJM 05885,1.00,1320943616,0c2e4159,6deeae920efd43ca6967a8c6914be585,a8718725dd78532b704a8c520f2a8f8dcb15303a -85764,Sony PlayStation Portable,Need for Speed: ProStreet,ニード・フォー・スピード プロストリート,Games,Japan,"ULJM 05308, ULJM 05443",1.01,896270336,ba7db6e9,af93903de6e7e078f3da1d7349ac418d,aa92404a57ebd4fccfc02e36d4852de7158da6e8 -85765,Sony PlayStation Portable,Saru! Get You! P!,サルゲッチュP!,Games,Japan,UCJS 10004,1.06,749142016,174b05ce,6a585f68939783d38dbf1a6261fb2aab,df2fe4ff772cc0ebb2c375f3df8caf6e1cc2007a -85766,Sony PlayStation Portable,Shining Blade,シャイニング・ブレイド,Games,Japan,ULJM 06020,1.00,1013415936,1873f673,788d75d479b2feb2aa688bc2dc75c7d1,df177818626a3e253e1a0908fb663829a9bc77e5 -85767,Sony PlayStation Portable,World Soccer Winning Eleven 9: Ubiquitous Evolution,월드사커 위닝일레븐 9 : 유비쿼터스 에볼루션,Games,Korea,ULKS 46024,1.01,982581248,794b1e1c,155cafda2ec8c8f5022d7dd08261e2e2,b3f141aed674a4a9efd3c50b32b341dd1f05f082 -85906,Sony PlayStation Portable,Akiba's Trip,アキバズトリップ,Games,Japan,ULJM 05868,1.07,704086016,2e84c72b,e2297d8d02c51862fdc63359296b1246,20dddb535f10c9dbcb06e4b77b24e10b8fd9019c -85907,Sony PlayStation Portable,Durarara!! 3way Standoff,デュラララ!! 3way standoff,Games,Japan,"ULJS 00317, ULJS 00318",1.01,1595506688,e812b824,763b39827852e6ff17446d10c8da8222,c5fb17611a1acef74fca93b9bbeede94ec9f56ea -85908,Sony PlayStation Portable,Fukufuku no Shima,福福の島,Games,Japan,UCJS 10016,3.01,719323136,54ad85b6,f4ade11283409fe9c524d10db1c1cee4,e638abdff1cf32740c31d90d8fe144dc48f636b5 -85909,Sony PlayStation Portable,Gundam Memories: Tatakai no Kioku,ガンダムメモリーズ ~戦いの記憶~,Games,Japan,ULJS 00393,1.01,427032576,6c8510e3,33e8bd14d293ef5f3039df638be1bb93,453c7b0f5103dadae5b0775e6ca7cab8ce146338 -85910,Sony PlayStation Portable,"Hanayaka Nari, Wa ga Ichizoku: Kinema Mosaic",華ヤカ哉、我ガ一族 キネマモザイク,Games,Japan,ULJM 05998,1.01,1751515136,e150323f,77c25d32b7ac652f74ee10831a4da88a,8fbc42d6929b37da83d42bdb512ae0a99763045f -85911,Sony PlayStation Portable,Katekyoo Hitman Reborn! Kizuna no Tag Battle,家庭教師ヒットマンREBORN! 絆のタッグバトル,Games,Japan,ULJS 00257,1.01,366444544,c5268469,667330883cac197edbe0e39316171000,aad4a45522b070a8d6a9b99377042623fe0f0cc8 -85912,Sony PlayStation Portable,Kuroko no Baske: Kiseki no Game,黒子のバスケ キセキの試合,Games,Japan,"ULJS 00523, ULJS 19097",1.01,713523200,9aff413d,5098c0c383c6b78f71a934a1fc394a7c,f2338aec0960d50a6cb4e2fdef9ef9cbfff64298 -85913,Sony PlayStation Portable,Minna no Chizu 2,みんなの地図2,Applications,Japan,ULJS 00103,1.01,1812692992,699e2af4,58f6dfb1c6939cad68ab941bf4bae18d,6c917fa60126ba6bf6f9092b1f3617ed677a053a -85914,Sony PlayStation Portable,Puyo Puyo! Puyopuyo 15th Anniversary,ぷよぷよ! Puyopuyo 15th anniversary,Games,"Japan, Asia","ULAS 42098, ULJM 05177, ULJM 05342",1.00,256409600,4e41136c,5ae45cfd512006ca037ca8d39f3e787a,402f594d22035d4ef9c4f243f40565c9ce88d686 -85915,Sony PlayStation Portable,Uta no Prince-sama: Repeat,うたの☆プリンスさまっ♪Repeat,Games,Japan,ULJM 05905,1.01,1603764224,af387004,99781ae9d7898da748ada2346019d919,e2751eac1fae76b01ab1f95d343052bb1012c8c3 -85919,Sony PlayStation Portable,Steins;Gate,シュタインズ・ゲート,Games,Japan,ULJM 05887,1.01,1379696640,577ec8d5,5ed76b04eac58b0e459bed06108eed74,9c6c99d60056ed42d89b1e01340dde7328d23c62 -85920,Sony PlayStation Portable,Winning Post 7 2010,ウイニングポスト7 2010,Games,Japan,ULJM 05739,1.01,1304395776,ee091fb2,01021b5d4548d6cf07e19c12023f800e,e042a7f11876a335aa4c8e2ee5e39bd6322d0d41 -86010,Sony PlayStation Portable,Ken to Mahou to Gakuen Mono. 3,剣と魔法と学園モノ。3,Games,Japan,ULJM 05735,1.02,972226560,6ad2644d,9d51a181ad47835910ebf1f59e2f943f,4436518853013e523c7886d8ac739025ed790b1c -86084,Sony PlayStation Portable,Phantasy Star Portable 2,ファンタシースターポータブル2,Demos,Japan,ULJM 91018,1.01,1503494144,6fd0d880,0c86757d86fe151cd0f88171f91d091f,d2824547d7df22d55526d13a5fc32ee3f6ee92cd -86143,Sony PlayStation Portable,Kamen Rider: Climax Heroes OOO,仮面ライダー クライマックスヒーローズ オーズ,Games,Japan,ULJS 00331,1.02,609386496,624af327,0a8d178fed0bf879c3b287aaa656272d,06adc8b0fab645e594ef99a0458e551980fdcaf9 -86144,Sony PlayStation Portable,Starry Sky: In Summer Portable,Starry☆Sky ~in Summer~ Portable,Games,Japan,"HONEY-002, ULJM 05740",1.02,873725952,e40fd10e,821702d4406ecbe5960b5cff5a0c1a97,89868b86dac59d8ae422f9cfb6816a7d033c284a -86145,Sony PlayStation Portable,Super Robot Taisen A Portable,スーパーロボット大戦A ポータブル,Games,Japan,ULJS 00143,1.02,1497792512,5d2ab6b1,982f761fecca87e5919ab0c743c7ddda,96424debb24da5479ccd6f0830f06d48057b2652 -86146,Sony PlayStation Portable,Uta no Prince-sama: Amazing Aria,うたの☆プリンスさまっ♪ −Amazing Aria−,Games,Japan,ULJM 05785,1.02,1182629888,dde4f12f,97030613eb0e3289772a31214de7dd00,5298a43318ef5968874531dd1a072f63fa40b1be -86282,Sony PlayStation Portable,Sengoku Basara: Chronicle Heroes,戦国BASARA クロニクルヒーローズ,Games,"Japan, Korea","ULJM 05903, ULKS 46259",1.01,1355448320,676352bd,e34eb8ad25796837ece1b860d7a4fc50,acd42afa1311852ee792498da1b48e762c1cbefa -86305,Sony PlayStation Portable,Bleach: Heat the Soul 7,블리치 히트 더 소울 7,Games,Korea,UCKS 45158,1.01,560496640,c7c5cd4a,19e2f6092f7dc8faa70bab3f7245f03f,32200f44000c703435223ca3b864458eb9da4984 -86324,Sony PlayStation Portable,Taiko no Tatsujin Portable DX,太鼓の達人 ぽ~たぶるDX,Games,"Japan, Korea","ULJS 00383, ULKS 46273",1.02,891977728,ddcc23c2,7db90cc61cadfafe533fd20a7c37314b,d15278da6e9570be05655f9b62afb81c0eb1ed49 -86325,Sony PlayStation Portable,DJ Max Portable: Hot Tunes,디제이맥스 포터블: 핫튠즈,Games,Korea,ULKS 46240,1.02,1643413504,e94a89b9,4adaa05c8d866f7e125f7bf48b7451ca,6e2b4ebcf8655d311a071b21d2a56d9bb7570364 -86360,Sony PlayStation Portable,Koukyou Shihen Eureka Seven,交響詩篇エウレカセブン,Games,Japan,ULJS 00056,1.02,1101922304,36862b0e,33f1da793dc5292529661f9978acfae1,a16ec7b5c160edf0f25adf0cea35bbd0a7d5fbd5 -86361,Sony PlayStation Portable,Patapon 3,パタポン3,Games,Japan,UCJS 10113,1.00,538968064,3d9d38fa,7f18e61d81c0731204073d40d66b16dd,512613069b39271616f5feb5ce8b82dbd576f119 -86362,Sony PlayStation Portable,Silhwang Powerful Pro Yagu 2011,실황 파워풀 프로야구 2011,Games,Korea,ULKS 46270,1.01,1493958656,cf2b9693,5cdcf7f6bc4b3fad72ac4f3383464be2,6c7cbc16a7d77773c1ca3eaa520589355cb24dfc -86817,Sony PlayStation Portable,Bleach: Heat the Soul 6,ブリーチ ヒート・ザ・ソウル 6,Games,Japan,UCJS 10093,1.01,693174272,bf5fd5d2,cda713361d8761bf8de17610fe4d8ce5,28928ff3e7f00d6ac010c96b4960a6ac7cfd4079 -86818,Sony PlayStation Portable,Gungnir: Masou no Gunshin to Eiyuu Sensou,グングニル -魔槍の軍神と英雄戦争-,Games,Japan,ULJM 05779,1.01,905740288,8dc11614,a421bde35b7342c4ade63f0e57608e85,6b8451f071c8c5314dcfcdc2b3237ab51d1394f5 -86819,Sony PlayStation Portable,Ken to Mahou to Gakuen Mono.,剣と魔法と学園モノ。,Games,Japan,ULJM 05343,1.01,333381632,f0ede5f2,16193ef44611dfc8ab3ee43ae2cb1bb2,e5f3d6bdd03412ed5eaa183ce37c3ace9fa2da98 -86820,Sony PlayStation Portable,Ren'ai Banchou 2: Midnight Lesson!!!,恋愛番長2 Midnight Lesson!!!,Games,Japan,ULJM 06001,1.03,1226080256,14536209,c7883324c0676134dab0219d94325e72,4e3332f8fb1869bb5cf3e826d3078434d6fdaff7 -87355,Sony PlayStation Portable,NCAA Football 07,,Games,USA,ULUS 10116,1.00,1637810176,7aca131c,14d62586dd249677b4cd60b2f6d5c961,be9e4dd01f4c2254d6e6880ccba9d9b106ebe136 -87356,Sony PlayStation Portable,Ace Combat X2: Joint Assault,エースコンバットX2 ジョイントアサルト,Games,Japan,ULJS 19057,1.01,1768390656,3e6c38ef,f216860bb66128beebd14401cbfac05d,7ea719d0adc20fcbe2b378a4c23e74a7b8d8e953 -87357,Sony PlayStation Portable,Another Century's Episode Portable,アナザーセンチュリーズエピソード ポータブル,Games,Japan,ULJS 00322,1.01,864944128,139e1c85,5b16cb3c9b1018ae7a51775027a35e83,1d656ef4d9ebe75652613326d2ebc7ca6a6a8ed5 -87358,Sony PlayStation Portable,Boku no Natsuyasumi 4: Setouchi Shounen Tanteidan: Boku to Himitsu no Chizu,ぼくのなつやすみ4 瀬戸内少年探偵団 ボクと秘密の地図,Games,Japan,UCJS 10095,1.02,632455168,a3dcaa21,ada9f1a0b849e353844f66dee0ed5c57,accf3a0493ae2282b46cf6fd65d8c1e736513294 -87359,Sony PlayStation Portable,"Daito Giken Koushiki Pachi-Slot Simulator: Ossu! Misao, Maguro Densetsu Portable",大都技研公式パチスロシミュレーター 押忍!操・鮪伝説 PORTABLE,Games,Japan,ULJS 00309,1.02,616660992,9ce8a263,469917368fafb539e78611435c61c640,3fe45b183117c3593497f7128d8f9c630984604f -87360,Sony PlayStation Portable,Digimon Adventure,デジモンアドベンチャー,Games,Japan,ULJS 00541,1.00,1673494528,de0dd20a,eba82c117b27857aba96f3de3c6a4975,8c6a5bf10fa8af0285ccba13872cc345a2007342 -87361,Sony PlayStation Portable,Fairy Tail: Portable Guild,フェアリーテイル ポータブルギルド,Games,Japan,"ULJM 05608, ULJM 08050",1.03,1332412416,7eec66a3,f4a7475420a5de968f6784e364144240,08c83e897ccbeb3824462efe7c6f1db2299b9cb5 -87362,Sony PlayStation Portable,Gundam Battle Chronicle,ガンダムバトルクロニクル,Games,Japan,ULJS 00122,1.02,572686336,2c65c4a9,8f5c5ac509a65942cca01c098f33190c,a5fa1488329f3692af689f55ef8fbaef08259d2e -87363,Sony PlayStation Portable,Heroes Phantasia,ヒーローズファンタジア,Games,Japan,ULJS 00456,1.02,1415020544,a69c3e01,b88fe18c312c7b821d09343c23957de5,323a05f5a92a7e221026aa0d8e52de969f7aaf7a -87364,Sony PlayStation Portable,The Idolmaster Shiny Festa: Funky Note,アイドルマスター シャイニーフェスタ ファンキー ノート,Games,Japan,ULJS 00546,1.02,1612251136,95bc1f52,691214a569fd5dbd58bab0370113b49b,e55a5c3b90f33db7454f74c0446fc0c090b508fc -87365,Sony PlayStation Portable,The Idolmaster Shiny Festa: Honey Sound,アイドルマスター シャイニーフェスタ ハニー サウンド,Games,Japan,ULJS 00544,1.02,1618640896,ee2434e5,702b7c95f9f6b1231debee487d9d8437,31a04eb02cc7577698151dab233e536abd0c4ec1 -87366,Sony PlayStation Portable,Katekyoo Hitman Reborn! Battle Arena 2: Spirits Burst,家庭教師ヒットマンREBORN!バトルアリーナ2 スピリットバースト,Games,Japan,ULJS 00218,1.03,964591616,25d07046,8d153546934a94df9019cf54589cbd19,a2555e61d65a810fc69a2c33200af20306314d94 -87367,Sony PlayStation Portable,Kenka Banchou Bros. Tokyo Battle Royale,喧嘩番長Bros. トーキョーバトルロイヤル,Games,Japan,ULJS 00517,1.02,974258176,d7a0b664,30d1bab97251e29a09b9f895cb1773b5,ae04cc6641f414d5f0e7b42654efc240229f3110 -87368,Sony PlayStation Portable,Kurohyou 2: Ryuu ga Gotoku Ashura-hen,クロヒョウ2 龍が如く 阿修羅編,Games,Japan,ULJM 05989,1.01,1680670720,d360b096,0a5a379d0edffcab5a503966140965dc,ba2657825b6e9ee49fca9217c44a4de14d9b8dfb -87369,Sony PlayStation Portable,Lord of Apocalypse,ロードオブアポカリプス,Games,Japan,ULJM 05982,1.01,1068498944,a0ea68dd,88d9822763842ff4ae543b6ef773d309,e7809b45b8044aef33081a6c39ed9f1cff755eeb -87370,Sony PlayStation Portable,Star Ocean: Second Evolution,スターオーシャン2 Second Evolution,Games,Japan,"ULJM 05325, ULJM 05591",1.01,1644429312,543960a0,67d809e14e9d132a4bc820681e374c1a,c63d3e484a2ee397137de553e2978ff0363139ff -87371,Sony PlayStation Portable,Toriko: Gourmet Survival,トリコ グルメサバイバル!,Games,Japan,ULJS 00389,1.01,811237376,ded050f9,32038e43520d2d3b467cc10d93a5f7d6,243db178be2116555b8e912c68300acdb8334389 -87372,Sony PlayStation Portable,Winning Post 7 2012,ウイニングポスト 7 2012,Games,Japan,ULJM 06038,1.02,1481637888,1253f110,b207f4d8f5906ea6153b8321c8be7dbd,adaa7ccef92e70dc78d05879a986793145a486fa -87373,Sony PlayStation Portable,Yggdra Union,ユグドラ・ユニオン,Games,Japan,ULJM 05299,1.01,578912256,506381df,f17672a28892efb68e438e0dc0923a46,66c8c6f1ae7e71f17f5b42a9d5455f2e1796f516 -87504,Sony PlayStation Portable,Black Wolves Saga: Last Hope,ブラック ウルヴス サーガ ラストホープ,Games,Japan,ULJM 06219,1.03,1542750208,549d1b9a,09aa964ba7b387ac0538caf9fca6daea,224a04b7dec48d89fd8dcd3a4a88365eb11c2213 -87505,Sony PlayStation Portable,Panic Palette Portable,パニック パレット ポータブル,Games,Japan,ULJM 05344,1.01,1481146368,ea02a711,c90125f63ba21e4ab86990ad8e7cc3ab,c430e47380a0c67388c867d6110d0383c21bc141 -87788,Sony PlayStation Portable,AI Mahjong,AI麻雀,Games,Japan,ULJS 00007,1.03,26116096,6ecf6acd,f6171118dc4a69330c790a6d0cb043f4,e80f4cab196e63200f76f8a822b5f42de2463788 -87789,Sony PlayStation Portable,Bokujou Monogatari: Sugar Mura to Minna no Negai,牧場物語 シュガー村とみんなの願い,Games,Japan,ULJS 00188,1.02,405733376,da32a165,42808ad446ca486339c382337085e1b2,39e7f809e8cd12b8a79c39ecea1b01eb8fee8ebe -87790,Sony PlayStation Portable,TalkMan,トークマン,Games,Japan,UCJS 18018,1.00,1228505088,3c5ee677,73015df3a3dd7b66746621f0e2ffc13a,5bdcb676b40e3962fe8aac73777e8ce83783742a -87791,Sony PlayStation Portable,Yu-Gi-Oh! 5D's Tag Force 5,遊戯王5D's タッグフォース 5,Games,Japan,ULJM 05734,1.02,1802469376,01a550b2,91a934dc94029d69557dc2bfbaf6490b,4016bf5697c06a33f2b2ae4075c82b605962e2db -87816,Sony PlayStation Portable,Nendoroid Generation,ねんどろいど じぇねれ~しょん,Games,Japan,"ULJS 00440, ULJS 00441",1.02,816513024,2456e4ea,c93e0d38eeeeb964bed1fca0acc25af6,bd436139bc9cbf149759f6d7ba99ccebf5802d19 -87817,Sony PlayStation Portable,Tokimeki Memorial 4,ときめきメモリアル4,Games,Japan,ULJM 05541,1.01,1774354432,8c6e35cd,e5e8094b6e10f1886456e272b4e3a300,cca63ab1dac057825ee33d2809f0508be96c38e9 -87818,Sony PlayStation Portable,Zill O'll Infinite Plus,ジルオール ~インフィニット プラス~,Games,Japan,ULJM 05410,1.03,728104960,6a7ba34f,6cf68d870e72883e7c3b39235a6adb63,7e3326ffbfda8bee90d5ba45a1d66fd89f24ff66 -87819,Sony PlayStation Portable,L'Arnaqueur,The Con,Games,France,ULES-00510,1.02,795967488,8a96795a,a62db4706c40b8f0c040a79c52fd5c33,22dbb1597c6e63ee725be3bc1eb5a6e9aee175c2 -88260,Sony PlayStation Portable,K-ON! Houkago Live!!,けいおん! 放課後ライブ!!,Games,Japan,"ULJM 05709, ULJM 08048",1.01,1756659712,2f89d4e5,fab6e288b6fad5570dd8e9d9c63afb17,7e0120b1557249a3678315d57b72c6fe4cbcfb92 -88333,Sony PlayStation Portable,Blade Dancer: Sennen no Yakusoku,ブレイドダンサー ~千年の約束~,Games,Japan,UCJS 10021,1.02,288227328,67d06f7d,f650d10c72cb11048604e797df7cbfca,96ff052a95be1ad4f2e59c87b129a967921646a5 -88334,Sony PlayStation Portable,Kin'iro no Corda 3: Another Sky feat. Jinnan,金色のコルダ3 AnotherSky feat.神南,Games,Japan,ULJM 06349,1.01,1224638464,69528775,d2dc4e75538b2f16a5c715ea582254a3,01c0ced613552296161ecf0b10d6123884f14582 -88335,Sony PlayStation Portable,Planetarium Creator Oohira Takayuki Kanshuu: Homestar Portable,プラネタリウムクリエイター 大平貴之監修 ホームスター ポータブル,Games,Japan,ULJM 05184,1.00,614465536,33dfdcb5,bb24364384c88ad0df51f04612820311,f012831b0baaf1feec7ded2eaf4c1f815d7d770f -88495,Sony PlayStation Portable,12-ji no Kane to Cinderella: Halloween Wedding,12時の鐘とシンデレラ ~Halloween Wedding~,Games,Japan,ULJM 06023,1.02,1233485824,58826fb9,8ada91fcfacc600580e88f281d6b6a97,d94e054447bdadbb79480d482d43f23d1bc1d4f8 -88496,Sony PlayStation Portable,Amatsumi Sora ni! Kumo no Hatate ni (Disc 1),あまつみそらに! 雲のはたてに,Games,Japan,ULJM 05992,1.01,412352512,fb2c22c7,16b3b0d386c19c655e0175693c21c4c9,0da68af35188a5a02102bf8a858f7a55df8d0eb4 -88497,Sony PlayStation Portable,Bleach: Heat the Soul 4,BLEACH ~ヒート・ザ・ソウル4~,Games,Japan,UCJS 10057,2.00,824737792,ff29be66,bf3955f0e09faed5ad22b64d1e0b002e,523c68fffc880504faef6c972a86293f03f1356d -88498,Sony PlayStation Portable,Boku wa Tomodachi ga Sukunai Portable,僕は友達が少ない ぽーたぶる,Games,Japan,ULJS 00459,1.03,1807384576,ab6c0284,ebb4fe13db7fd608f848a7878607fa98,86284249ccf36ae86c44e0553f9701c09f330310 -88500,Sony PlayStation Portable,Chronicle of Dungeon Maker II,クロニクルオブダンジョンメーカーⅡ,Games,Japan,ULJM 05294,1.01,173342720,1294f2a4,ce635a070eb4aced1c5c48913c528bca,38cb1601695581cc4d8e27a019c2976e18e3f87a -88501,Sony PlayStation Portable,Daito Giken Koushiki Pachi-Slot Simulator: Yoshimune Portable,大都技研公式パチスロシミュレーター 吉宗 ポータブル,Games,Japan,ULJS 00060,1.02,136806400,a0691b7c,4389b61678527388383cc977be149a45,868b9f65557270168a732d3d1ececde016ab9bb8 -88502,Sony PlayStation Portable,Hanaoni: Koisomeru Koku: Eikyuu no Shirushi,華鬼 ~恋い初める刻 永久の印~,Games,Japan,ULJM 05847,1.01,1764851712,b2e06f36,fa17b06e7c24b3ef6176fcc2ce49b55e,308eccd2f4aa0d052102d045d87903eeeeca3793 -88503,Sony PlayStation Portable,Harukanaru Toki no Naka de 5,遙かなる時空の中で5,Games,Japan,ULJM 05843,1.01,1226276864,e64ee5ee,b4027729c4fc08d45600afd4b7c737e8,8067bf3f50a780b8ee1350d0a81747a5c71036ad -88504,Sony PlayStation Portable,Hisshou Pachinko: Pachi-Slot Kouryaku Series Portable Vol. 1: Shin Seiki Evangelion: Tamashii no Kiseki,必勝パチンコ★パチスロ攻略シリーズ Portable Vol.1 新世紀エヴァンゲリオン~魂の軌跡~,Games,Japan,ULJS 00295,1.01,1786052608,2ccd546e,3c9f2dcfd59e00466cadbb571d4db5cb,857a4d420c1bb4dcf62dbd027c649d0ee17dd1d4 -88508,Sony PlayStation Portable,Innocent Life: Shin Bokujou Monogatari,イノセントライフ ~ 新牧場物語,Games,Japan,ULJS 00063,1.02,208961536,2e2d6af2,7f7c5d853b08e5426efccba5ce3b1be2,e82153b0d95b6e2ee884ed3916850d8032fa6283 -88509,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2011 Ketteiban,実況パワフルプロ野球2011 決定版,Games,Japan,ULJM 05991,1.01,1730510848,3cffa39d,4169dc823a274288910eab542ec515a0,b5a9bb28f6048fdf52abc5f0dff0912979a03473 -88510,Sony PlayStation Portable,Kidou Senshi Gundam: Gihren no Yabou: Axis no Kyoui,機動戦士ガンダム ギレンの野望 アクシズの脅威,Games,Japan,ULJS 00131,1.03,1224605696,9c72e910,07c087edae157f91996d3cc861be61bb,8f24782fdbf9891767500fc81989c05091e3968f -88511,Sony PlayStation Portable,Medal of Honor: Heroes,メダル オブ オナー ヒーローズ,Games,Japan,"ULJM 05213, ULJM 05318",1.00,1448837120,bca095c3,1b07cbde84888c9b18972e9676b543c1,397404de5455a7cedebc4511a091c6068a7d6308 -88512,Sony PlayStation Portable,NBA Live 09,NBAライブ09,Games,Japan,ULJM 05386,1.01,1500217344,d1324957,2e30f681761a558aca87fcc407276f75,965fe495ba5843c2d1c80f2755ece2f4f3fc857f -88513,Sony PlayStation Portable,NBA Live 10,NBAライブ10,Games,Japan,"ULJM 05536, ULJM 05737",1.00,1183744000,05005a92,eafc3ec0be04a05773c471691044f5e9,caed9b98d1146cee4a2bf3e7e64ace73c70b6522 -88514,Sony PlayStation Portable,Numpla & Oekaki Puzzle,ナンプレ&お絵かきパズル,Games,Japan,ULJM 05140,1.01,146833408,c4c2b7a6,0dea18f1afa5df1241c5f428a4c661c4,103463cb43f03d6e52439ddf7d7aa2c30689ce3d -88515,Sony PlayStation Portable,Persona 3 Portable,ペルソナ3ポータブル,Games,Japan,"ULJM 05489, ULJM 08044",1.02,1388773376,85d186df,d37f5e4227404ea13ec137bce352d003,399a74263119629e8198619737f6b2baa951333b -88516,Sony PlayStation Portable,Pop'n Music Portable,ポップンミュージック ポータブル,Games,Japan,ULJM 05605,1.01,1164967936,e0f5537b,f45e12e21c319c47b26380b1e06f503b,41633a5ac0e4154615ef4c88a5f64f06c75bffbd -88517,Sony PlayStation Portable,Power Pro Success Legends,パワプロサクセスレジェンズ,Games,Japan,ULJM 05537,1.01,292716544,ae01ee67,9c3e09a9776f7dce7c5770bcd7c2de87,373015243afbfb6ff7e0f12aa6055a3583ba91bd -88518,Sony PlayStation Portable,Puyo Puyo 7,ぷよぷよ7,Games,Japan,ULJM 05539,1.01,292159488,ecc9a60b,11a22b667d708b1d85377320512dd3cb,fd514c3b409c30243072f41fbbd9f2ec07515ec4 -88519,Sony PlayStation Portable,Shougi ga Tsuyokunaru: Gekisashi: Jouseki Doujou,将棋が強くなる 激指 定跡道場,Games,Japan,ULJM 05263,1.02,169115648,25d92f59,f4177278f4d64993ed3711b4266f4fcc,6bb5b9217a5caccabc71314cc8b07fe85ebfaef3 -88520,Sony PlayStation Portable,Sudoku,SUDOKU 数独,Games,Japan,ULJM 05146,1.00,51085312,1216780c,f739ab387c6b0e8c4136ec52fb3b113d,f2c2b553bb2c8e57c34830c4e3c11eb0a91539a6 -88521,Sony PlayStation Portable,Summon Night 5,サモンナイト5,Games,Japan,ULJS 00553,1.01,1754464256,d5a42d59,a41d258aec516b560d0f1b00203c20e9,2a83691ee969e486034c66e067e7d7514b64319b -88522,Sony PlayStation Portable,Suzumiya Haruhi-chan no Mahjong,涼宮ハルヒちゃんの麻雀,Games,Japan,ULJM 05751,1.02,521371648,f1cda263,6d8df36c981d0673081f93744322a851,3e6e95e93c6b74de0dbed03bd89c909ca23a2527 -88523,Sony PlayStation Portable,Taiko no Tatsujin Portable,太鼓の達人 ぽ~たぶる,Games,Japan,ULJS 00020,1.01,389906432,5eba3f96,45515e8925e88ae7e1d1b3ca0b0502cf,1689ca6875bc75e99a815634d9d450a184e0a67d -88524,Sony PlayStation Portable,Uta no Prince-sama: All Star After Secret,うたの☆プリンスさまっ♪All Star After Secret,Games,Japan,ULJM 06381,1.03,1765900288,97f0e30b,85b402a210ac54813a34b6737484156f,83ade7c9ac7963ccb8161a61bc39f65b6bcae14a -88525,Sony PlayStation Portable,Weiss Schwarz Portable: 2 Turn-me,ヴァイスシュヴァルツ ポータブル 2ターン目,Games,Japan,ULJS 00427,1.02,1246396416,570bdae3,5826c32067d4432596c0cdf379a18c49,36fab0a9ddf077e46fc9a79a7b8f61baf3ba6625 -88526,Sony PlayStation Portable,Weiss Schwarz Portable: Boost Weiss,ヴァイスシュヴァルツ ポータブル ブーストヴァイス,Games,Japan,ULJS 00421,1.02,1249771520,2819cfbd,9c9de3dc16260677248ac3a63fe487c2,caa406a1ba50bc0430071aec40c14f02c67f7932 -88802,Sony PlayStation Portable,Boku wa Koukuu Kanseikan: Airport Hero Narita,ぼくは航空管制官 エアポートヒーロー 成田,Games,Japan,ULJM 05128,1.02,166428672,2cd195b5,a4e759c3d50e6a10161a1becf4f6c49f,d8c7c199f3707418a1b7e93638246a21be9f1ef3 -88803,Sony PlayStation Portable,Minna no Golf-jou Vol. 1 (Disc 2),みんなのGOLF場 Vol.1,Games,Japan,UCJS 10056,1.02,1674444800,322ece25,f389074bdfd3278c1cb67ae3a1feaf97,2c2ced62defc7dbdb8d337aabb740d6602e675f6 -88804,Sony PlayStation Portable,Minna no Navi (Disc 1),みんなのナビ,Games,Japan,ULJS 00211,1.07,1801945088,d35ed41c,1a204467c6a21f3bdeaa8781875f262f,be1bd61a24904f05d2eccd144b25c78a61c05ace -88805,Sony PlayStation Portable,Minna no Navi (Disc 2),みんなのナビ,Games,Japan,ULJS 00212,1.07,1812135936,ed4eed29,6b2c0d4bfd43409fba5c445ed493552d,6baa692f57c2e596201565aa8072dd434deb77de -88806,Sony PlayStation Portable,Warship Gunner 2 Portable,ウォーシップガンナー2 ポータブル,Games,Japan,ULJM 05553,1.01,894828544,3927193e,2948f4218314e9161114ddc88ae7c9e2,d61cc5d2a1004042149f0780ff05d1e9fae35c99 -89066,Sony PlayStation Portable,Rockman Rockman,ロックマンロックマン,Games,Japan,ULJM 05391,1.01,331284480,09852bf5,f2cd23a784e9a27ac304cf413bb40f5d,280b16c48a9a811c1521f6ed93548fc249b1d2ca -89067,Sony PlayStation Portable,Classic Dungeon: Fuyoku no Masoujin,クラシックダンジョン ~扶翼の魔装陣~,Games,Japan,ULJS 00270,1.01,294879232,095cf618,f33297f8fa06bdf1c10ed95b1af45988,9b72f4aef6079393ae89c735b836b96d70cda910 -89081,Sony PlayStation Portable,Rurouni Kenshin: Meiji Kenkaku Romantan Saisen,るろうに剣心−明治剣客浪漫譚− 再閃,Games,Japan,ULJS 00360,1.01,504823808,406b6fad,c1d9c75577aaae22caa77863191afc3d,88be3c31fe410c4a9085c65fe2f4447d740c4c44 -89082,Sony PlayStation Portable,Mahjong Taikai,麻雀大会,Games,Japan,ULJM 05004,1.03,209813504,2c54301e,6380a657c17d217fdc21e9680be6eb11,12fb2e30185d59a0d4c6a3368ab55262a8ebe645 -89098,Sony PlayStation Portable,Pro Yakyuu Spirits 2012,プロ野球スピリッツ2012,Games,Japan,ULJM 06012,1.00,1581776896,f7d698fb,b99cdc5f932f8d1b6631f7db42e859b7,b9a2f30120d214aec3065260a8314deb5ef52b99 -89099,Sony PlayStation Portable,Tales of Eternia,テイルズ オブ エターニア,Games,Japan,"ULJS 00015, ULJS 19004",1.00,880607232,4129997d,911a68d170b133168a26e2d080284d25,5dc43389e7659b7bb18b2c2d81533994c216a39d -89100,Sony PlayStation Portable,Tales of the World: Radiant Mythology,テイルズ オブ ザ ワールド レディアントマイソロジー,Games,Japan,ULJM 95004,1.01,501481472,b5a0f0c3,0e6eb27cf8e1dabdc0724f6fd81a0a2a,ed671cb29700e58bce0265849b212f69e8c11b55 -89101,Sony PlayStation Portable,UnchainBlades EXXiV,アンチェインブレイズ エクシヴ,Games,Japan,ULJM 06135,1.02,1243840512,23bd3d60,1ff760bee7af33d3d60516b38e10ad30,ffddf0937dcaeaf37e4218ab25be0a2d4e01c782 -89113,Sony PlayStation Portable,Nikoli no Sudoku Lite Daisan-shuu,ニコリの数独LITE 第三集,Games,Japan,ULJM 06153,1.01,137625600,6c4fd0bc,ab74fe50f28fad8841464b8d1f61a23c,a7dfa77a440c27bb4afd77be6d293438cd8592b0 -89243,Sony PlayStation Portable,Ridge Racers 2,實感賽車 2,Games,Asia,"UCAS 40113, UCKS 45032",1.01,1523023872,9804e701,254aa71733a69e66307515391c45e134,8e4ebc9daff6c1d02091554b5f842ecca462ccba -89307,Sony PlayStation Portable,Makai Senki Disgaea 2 Portable,魔界戦記ディスガイア2 PORTABLE,Games,Japan,"ULJS 00182, ULJS 19053",1.02,854360064,6e817c68,05ea6aa0e41884a7caffb8b872c01517,48555a6538d43f4dde5fea17ccd05cdc7c6d5b30 -89308,Sony PlayStation Portable,Juuza Engi: Engetsu Sangokuden,十三支演義 ~偃月三国伝~,Games,Japan,ULJM 06089,1.01,1797652480,a1e9d94b,c87e450f83d94535002f22b0e9376bc0,f210339f05fccd82d330777a97a39cecf7cd8b91 -89309,Sony PlayStation Portable,Soukoku no Kusabi: Hiiro no Kakera 3: Ashita e no Tobira,蒼黒の楔 緋色の欠片3 明日への扉,Games,Japan,ULJM 06071,1.04,1273069568,b7501acc,6310190ff5b852b5b8c6491a2a508ce3,fd8d8562162b92e2b3895622acf795da754637c4 -89312,Sony PlayStation Portable,Kirameki School Life SP: The Wonder Years,きらめきスクールライフSP,Games,Japan,ULJS 00458,1.03,1357971456,1d99a5bf,f68f522e136e63125d528f0f3fc24add,baf163055e64d0792fe0b5659f210a1067269cd8 -89313,Sony PlayStation Portable,"Shinobi, Koiutsutsu",忍び、恋うつつ,Games,Japan,ULJM 06352,1.01,1503625216,9e456049,2dae34757fee36079f282e4deb5ce37b,a73f8f5bc71c8c636a5d0e55bbf507979a24a4b2 -89314,Sony PlayStation Portable,Tales of Destiny 2,テイルズ オブ デスティニー2,Games,Japan,ULJS 00097,1.00,1404928000,9de4f587,1758c4163e164944288881072590624b,92f6aa2d1e5135902e032935196d06a3abbf4be2 -89356,Sony PlayStation Portable,Kin'iro no Corda 3: Full Voice Special,金色のコルダ3 フルボイス Special,Games,Japan,"KTGS P0230, ULJM 06322",1.01,1670348800,72ffbb4f,c52f80d2e7f9e21b3bfaa88abbc01e35,36cd52bc94bfb18939b7fb370bbba42cb57d1f43 -89357,Sony PlayStation Portable,Persona 2: Tsumi: Innocent Sin,ペルソナ2 罪,Games,Japan,ULJM 05759,1.01,1121681408,a1dbeede,1f5bff956b76eeb22fafbcd2b91b2721,794813f9b56e9bed681c2d30a8dbf15c10343130 -89358,Sony PlayStation Portable,Satomi Hakkenden: Hamaji Hime no Ki,里見八犬伝~浜路姫之記~,Games,Japan,ULJM 06379,1.03,1617690624,6777a5c5,eb5794a05f0baa4d90f9ac8b890eab92,07dd8f49884dd553199e36fd0a9fe93580de60c2 -89373,Sony PlayStation Portable,Metal Gear Ac!d,メタルギア アシッド,Games,Japan,ULJM 05001,1.02,183730176,2f2f8398,5d1451c53e42d14ea49de85c4c189f55,2a65221a93d4422990ec9d55a0c536b8e812abcd -89455,Sony PlayStation Portable,Nayuta no Kiseki,那由多の軌跡,Games,Japan,ULJM 06113,1.01,831291392,c3b0c989,02adefbdef8197cca872268d5c01b277,126139a10911e02fa27f1e49b165887eac8759f2 -89456,Sony PlayStation Portable,PoPoLoCrois Monogatari: Pietro Ouji no Bouken,ポポロクロイス物語 ~ピエトロ王子の冒険~,Games,Japan,UCJS 10005,2.01,1168572416,5e21d6b9,7cd263eb25237c7d73127315ffd08ed1,2e9d651a6ae68f2761e6ec98f4015f0ecdab2b27 -89457,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs Portable,ソーコム:U.S. ネイビーシールズ ポータブル,Games,Japan,UCJS 10102,1.01,1437532160,1ac62588,d2dadaac9b30f47fb5e960aac4b54ab1,6c85a8a041f21e5b0677ecf26e19543a58a903d8 -89458,Sony PlayStation Portable,Vitamin Z Revolution,ビタミンZ レボリューション,Games,Japan,ULJS 00277,1.02,1672904704,bea2bba7,b90a1369204636e37004cfc885e47263,5b878b26a0a6a57f474be28bf90fd6268c2d1e87 -89459,Sony PlayStation Portable,Yuusha no Kuse ni Namaiki da.,勇者のくせになまいきだ。,Games,Japan,UCJS 10076,1.00,93126656,340fd0a3,3773e7217c2d40acc88fd5dfdb5003ed,cd3fa7519490284a232262ff64ad00e39c6583ed -89460,Sony PlayStation Portable,Princess Crown,プリンセス クラウン,Games,Japan,"ULJM 05040, ULJM 05236",1.03,278003712,716deee6,87896ad4dd9794ee7e1f985a23a92040,fd4f8f746f344b69d0efa46081b01a2d54b77ae7 -89660,Sony PlayStation Portable,Buzz! Le Plus Malin des Français,,Games,France,UCES-01197,1.01,849510400,c16106e5,d7b03817e8bd49e79b50b388bf3ab75a,150176e17cf00ce7c11231acc54f8e370bcd3355 -89663,Sony PlayStation Portable,FIFA 06,,Games,France,ULES-00162,1.00,1225097216,9448c76c,2c7fd63438971ad56692b510f8b8868d,2159183ca07b746ea2a4989d2b0801729a1cd3da -89664,Sony PlayStation Portable,FIFA 10,,Games,France,ULES-01326,1.00,1304166400,15a49c4b,e8a2858813c60fd715557a6254d78564,03f687c747ef72b6833e3d2a438d2fdb92e75d77 -89682,Sony PlayStation Portable,FIFA 11,,Games,France,ULES-01476#,2.01,1303707648,97cb6907,f1e1a3c744b696ffa6a387876b387400,e15c9dde79a3030b78d6f51473176a4a3b9cf25b -89683,Sony PlayStation Portable,FIFA 12,,Games,France,ULES-01546,1.00,1303707648,2c851237,c565cfc2259a455c1a2425de63d75cf2,5f903b226fcb2d8d1cd300d2bc981334cd5ba712 -89684,Sony PlayStation Portable,FIFA 14,,Games,France,ULES-01587,1.00,1303740416,553b0e43,89a108e6737d7ae152ef51e88c9c74ce,88d85f3fe2b7fd20fdd107d83f889645729e56f2 -89685,Sony PlayStation Portable,NBA Live 06,,Games,France,ULES-00157,1.00,1166409728,832a7fbb,414ed5cd7e52a537f2cffb3a1b949449,ba38f988626c8f5ec0ef0758f2a3fe0c391a6fbb -89774,Sony PlayStation Portable,"Shin Master of Monsters Final EX: Mukunaru Nageki, Tenmei no Saika",真・マスターオブモンスターズ Final EX ~無垢なる嘆き、天冥の災禍~,Games,Japan,ULJS 00282,1.01,508755968,a304a6b2,1a8d442a9dc1af18184cdc09f19bd651,ae069c9cf82391f9b8f007628a6df4a0eab813c9 -89776,Sony PlayStation Portable,Silent Hill: Shattered Memories,サイレントヒル SHATTERED MEMORIES,Games,Japan,"ULJM 05564, ULJM 05828",1.00,1012236288,02cb62fc,fef1cd13f41688365d5d5894b8a292d1,f3f28ec0f0e85d447ad4f5ae98de22b507850db0 -89834,Sony PlayStation Portable,Go!Explore,,Applications,France,UCES-00882,1.01,906362880,ee6211f4,44a858b82367ff6bc92963486f276da9,cd23131bd487573b1bab03013673450d03bfcb76 -89969,Sony PlayStation Portable,Ford Street Racing XR Edition,,Games,Australia,ULES-00588,1.00,734003200,26cf329b,821db5c2451e39531aa6e7bf0a885649,f970d504ec9fbd64cd22d9f7f9c867cc66c14ee4 -89970,Sony PlayStation Portable,Micro Machines V4,,Games,USA,ULUS 10129,1.01,602013696,067abc92,29b14fb3a2d0c89f91ca03b04b259f49,81b596baabff64e49a351dfec23a96a6e12e8dfb -89971,Sony PlayStation Portable,Samurai Shodown Anthology,,Games,USA,"ULUS 10401, ULUS 10401F",1.02,1331822592,7d694190,ed7032fa5850a74b8b962f82fd002752,c78aadb68bb6cbe37adb6bef29ca7074b3a66346 -90178,Sony PlayStation Portable,Dissidia Final Fantasy,,Games,Russia,UCES-01229,1.00,1632239616,4a1bab57,469b48aa662b1333e7b26830144e95da,30aca4fc2a4b54e8e49136e7de5ff24849d6a1db -90210,Sony PlayStation Portable,Field Commander,,Preproduction,USA,ULUX-80153,1.10,1198948352,ebbb5607,b7c690331a973d499d32354f12b06c68,9820aa6d00b6bb4b8c3e76dbffc68a42c47fe404 -90223,Sony PlayStation Portable,NBA 09: The Inside,,Preproduction,USA,UCUS-98715,0.30,1079508992,bb85ddf7,e47159b4d2c858ad9c2f30a80ba01b09,138cbfcdb54ea4bc55dee375b323e5012f70bd5a -90260,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,France,ULES-00558,1.00,1446871040,5c21dc8e,8f36411ae432126dd72a44d54168eb66,592411d6ce358e9d454b3bb510013585cdf3e2d9 -90264,Sony PlayStation Portable,Mercury Meltdown,,Preproduction,USA,ULUX-80215,1.00,265093120,de80084f,a57a9d7d0a269bf5c20d3a8d2cc44988,9b9ef1fce8e437de91d29f433b9f0d01010685de -90265,Sony PlayStation Portable,Puyo Puyo!! Puyopuyo 20th Anniversary,ぷよぷよ!! Puyopuyo 20th anniversary,Games,Japan,"ULJM 05964, ULJM 06212",1.00,1353154560,7135fbd3,2e16af56ad7f4bb7f6711d2834d1cb7c,6f26c508108d9a10a08f912a7822513118bcf4bb -90274,Sony PlayStation Portable,Demo Disc for PSP Vol. 1,,Demos,Japan,UCJB 98001,1.00,768770048,26937752,7a408cae0149439f287828ca61817a82,6758969b22973eee4a72094f9f5c84a0d95db377 -90275,Sony PlayStation Portable,Demo Disc for PSP Vol. 2,,Demos,Japan,UCJB 98002,1.00,640122880,e9e5212b,f7263f653d204fda6af40825bd010df8,87adb4e951df28f3f5d5ced7a2ae12d0f3463d87 -90276,Sony PlayStation Portable,Kenka Banchou 5: Otoko no Rule,喧嘩番長5 ~漢の法則~,Games,Japan,ULJS 19062,2.00,1271398400,a797ec05,b9e3c2439ea2f53b1790ff907399b8f4,bc9b98e33ce53e80f88c677fb245bca526848608 -90277,Sony PlayStation Portable,Tomoyo After: It's a Wonderful Life: CS Edition,智代アフター ~It's a Wonderful Life~ CS Edition,Games,Japan,ULJM 05411,2.01,963608576,2d6c705c,6abcde4663030e3ec3a925737ee46170,504896be50bbfb151c82b80b9d5a7609088c8f59 -90278,Sony PlayStation Portable,Metal Gear Solid: Peace Walker,メタルギアソリッド ピースウォーカー,Games,Japan,ULJM 08038,1.03,1583775744,0f932bf0,c0ae1785b4b94e9fdd7a0a25f5ef4d45,db2de4f7bf43ec9bb927938145e24849e1dcd679 -90279,Sony PlayStation Portable,Tegami Bachi: Kokoro Tsumugu Mono e,テガミバチ こころ紡ぐ者へ,Games,Japan,ULJM 05587,1.01,429457408,d29ae807,46a837fffb7459e75c053432881f22cc,a6cf14a4c2a240743220697bad245ba7c74e163b -90291,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Cars Quatre Roues,Games,France,ULES-00321,1.01,906362880,d8d640e7,6aad184eb3b57f875f9a4551248e505d,2b6d519478ebff479e39b3a3d10e362fc7f33bd7 -90294,Sony PlayStation Portable,Medal of Honor: Heroes 2,メダル オブ オナー ヒーローズ 2,Games,Japan,ULJM 05430,1.00,1231880192,1a9136f1,2a3146e729fb589e1a7cfaa1a8331346,1fffca2fab5358863242626fa856755563a0780d -90392,Sony PlayStation Portable,Syphon Filter: Logan's Shadow,,Preproduction,USA,UCUS-98606,0.10,1300135936,5604004b,e33858959563ad207ce3cae2e96fb8c2,63e6ae75a8f73bed5b92b41ce9bc56238ca1099a -90414,Sony PlayStation Portable,LocoRoco 2,ロコロコ2,Preproduction,Japan,UCJP-00161 #11,1.00,178618368,28ccb37d,eade0561eed1aab0e551e66e31fa75f1,ce3f7aa90442c449c23986650e9d2995a8d1b2a5 -90528,Sony PlayStation Portable,MX vs. ATV Extrême Limite,,Games,France,ULES-00994,1.00,295501824,9d848d05,246f2edc1a8e04c140f8f8902b852778,593105da42088724a14fcad457c91f5354476556 -90551,Sony PlayStation Portable,Kao Challengers,,Preproduction,Europe,ULET-00148/0.01,0.01,616824832,90217723,840538c598d39f3afbc0332dfb4851f6,a302251477b6e1be1cd9481a90be7b92d990e9cc -90854,Sony PlayStation Portable,Buzz! Quiz World,,Games,Europe,UCES-01291,1.00,1604321280,d6056a62,4457ae09514b06b1a66f6fd6f746c227,68d370a44e7ec613b6e04201c33be16f81c58d0f -90855,Sony PlayStation Portable,FIFA 11,,Games,France,ULES-01476,1.00,1303707648,c9b6a3ed,598a86867b2cfb7214c02ecb453e84a1,d5fa2dcd6bd558ae6560327fcf8b9a51b3cbfa36 -91360,Sony PlayStation Portable,FIFA Soccer 09,,Games,Canada,ULUS 10394,1.00,1652326400,d887c4bd,4a826cef1dc8cda6a25a21390be32706,549715d7dc69b6fdd95c15cb51b69f6023d5ff2d -91636,Sony PlayStation Portable,Prince of Persia: Zabytye peski,Prince of Persia: Забытые пески,Games,Russia,ULES-01438,1.00,661979136,70601ae9,60a167fcc1904a10784953ee4d9453f7,5ed27d47132c5df8c6a1c7b2088cd6dc916fea27 -91637,Sony PlayStation Portable,Il-2 Shturmovik: Krylatye xishhniki,Ил-2 Штурмовик: Крылатые хищники,Games,Russia,ULES-01317,1.01,658669568,1e9314e4,08654e28966fd3ed60b5d6e0c5545636,4bd910f672cd9ed9f89896d15b04024609046b2b -91638,Sony PlayStation Portable,LEGO Piraty Karibskogo morya: Videoigra,LEGO Пираты Карибского моря: Видеоигра,Games,Russia,ULES-01529,1.00,1478426624,3b7c4d5d,dfbbd21c1c95c6c61e3a8828920d6823,5d00b36c9aba06ba620222af77cde0d19b24aaa4 -91716,Sony PlayStation Portable,E'ragon,Эрагон,Games,Russia,ULES-00475,1.00,253034496,b6c9faac,9b18865072f070c3fe336fca5b462f29,8d5edc94136f270c08f5b1fe77ab9056452f6264 -91901,Sony PlayStation Portable,Imagine: Champion Rider,,Games,Russia,ULES-01273,1.01,1421803520,93c4d5bd,e92401c9f705702f51e8ece7fa3c726b,23e774f15ee19597995d258124b78598403730b5 -91945,Sony PlayStation Portable,Burnout Dominator,バーンアウト ドミネーター,Games,Japan,ULJM 05371,1.00,691077120,36672b2c,9b4c413177f53a671406020600d277df,e424cdad7cfee1b71c78e1760877ce1a86b1ffbe -91946,Sony PlayStation Portable,Burnout Dominator,橫衝直撞:公路霸主,Games,Asia,ULAS 42095,1.01,691109888,caea2a45,f576731a916907a652de72ff276ff119,2c3237d1769d3ac848215897a51376ae422160ec -91947,Sony PlayStation Portable,The Simpsons Game,,Games,Asia,ULAS 42115,1.00,764805120,901dcec8,62874de1e7bf32a3212a69d70176390c,4fd8dad47ac4e2358f0a5cef044b548d3ce14a1c -92032,Sony PlayStation Portable,FIFA 11,,Games,Russia,ULES-01480,1.00,1360756736,3b11df6f,d47d2da3a65d5710e83a473996c5c479,9b5efce217167cb1995f7d12cbd891e578beb4a4 -92033,Sony PlayStation Portable,"Oblachno, vozmozhny osadki v vide frikadelek","Облачно, возможны осадки в виде фрикаделек",Games,Russia,ULES-01361,1.00,1001783296,b63fc36b,11e4d2d33c30cd7608a4d396957fae52,706c515976be415548607a136ad1a300de20be60 -92034,Sony PlayStation Portable,Disney TRON: Evolution,Disney ТРОН: Эволюция,Games,Russia,ULES-01495,1.00,278659072,f5c7210f,4f0e4b3229e1846d0561c57512ec5433,f0ce33663af6fc7a37089d7d19947e2e9f125dc3 -92062,Sony PlayStation Portable,Sega Rally,,Games,Russia,ULES-00911,1.00,197394432,3b5f4850,a46689a43837a2814828ec63c582e278,b8b4252370c75663685412dd667dc44289c170aa -92561,Sony PlayStation Portable,M.A.C.H.: Modified Air Combat Heroes,M.A.C.H.: Модифицированная авиация специального назначения,Games,Russia,ULES-00566,1.02,338100224,cab435bf,a878c520a003371b54d3804abf5b35e3,0927e20e413e8fd55d4f0171ffd2ed9313091b7d -92562,Sony PlayStation Portable,FIFA 08,,Games,Russia,ULES-01057,1.00,1230995456,cd44f363,7aa0a65899448bbc234a7dfef0105954,83a5448fe84a5679c6c156ff54a76fa4acd3264f -92770,Sony PlayStation Portable,Twinkle Crusaders Starlit Brave,ティンクル☆くるせいだーず スターリットブレイブ,Games,Japan,ULJS 00313,1.01,1111523328,9c8f064b,284e7d7af79ac90b224bbba7fec6da6f,2ad2d342d2d9b87cc75828b41bdb47e3ef433c86 -92771,Sony PlayStation Portable,Kenka Banchou 5: Otoko no Rule,喧嘩番長5 ~漢の法則~,Games,Japan,ULJS 00359,1.02,1271398400,461e32ca,723e516267bf85f30c917fd0f0535ed2,0cbd611e5f7885e63a23ac7862c53258a9f9240a -92808,Sony PlayStation Portable,Venus & Braves: Majo to Megami to Horobi no Yogen,ヴィーナス&ブレイブス ~魔女と女神と滅びの予言~,Games,Japan,ULJS 00308,1.00,695599104,cf97b79a,a9e1749cd19e109ee8e864246d8fbf09,2d2d5f65f513c6965bd5ee81d53f21c91e3d28db -92820,Sony PlayStation Portable,Patapon 2: Don-Chaka,パタポン2 ドンチャカ♪,Games,Japan,"UCJS 10089, UCJS 18036, UCJS 18053",1.00,565575680,75a4f0ca,1f45e904b2daafa383157a3f5927d4f0,889c79f8d78ff4f764fcd3b6fe90a75a3474382f -92823,Sony PlayStation Portable,Elminage II: Sousei no Megami to Unmei no Daichi,エルミナージュⅡ ~双生の女神と運命の大地~,Games,Japan,ULJM 05488,1.01,536608768,e40b5e86,79368a17fe4aa42db96d947daa2c0bc7,4a95571742ff6d06675722beb6a840068491b6d4 -92824,Sony PlayStation Portable,Elminage III: Ankoku no Shito to Taiyou no Kyuuden,エルミナージュⅢ ~暗黒の使徒と太陽の宮殿~,Games,Japan,ULJM 05883,1.03,717815808,74ae8a6c,249fbaee665c51ae809784099c323e96,e210f65c36cf206a22980a76305fcd6faa4efb45 -92825,Sony PlayStation Portable,Lumines II,ルミネスⅡ,Games,Japan,ULJM 05232,1.01,1009582080,cded24c9,01efab5ad06c4d07c3ea4399777cbd1e,58849766f1847ab4cbe15023cc18ee57910d56e3 -92826,Sony PlayStation Portable,Rengoku II: The Stairway to H.E.A.V.E.N.,煉獄弐 The Stairway to H.E.A.V.E.N,Games,Japan,ULJM 05055,1.02,322174976,04d5a317,f4e47ca15e9717df7015b520dacc54ca,0108da1102dbe174dd8daeb107184e700d31981b -92828,Sony PlayStation Portable,Densha de Go! Pocket: Tokaidosen-hen,電車でGO ポケット 東海道線編,Games,Japan,ULJM 05152,1.00,631701504,c81fd72f,e6b7e04f2d5910a003e7b42f5f8a3ba8,392cd9cf6b48de7d8304f11efdfe6e74cc7d32ff -92829,Sony PlayStation Portable,Elminage Original: Yami no Miko to Kamigami no Yubiwa,エルミナージュ Original ~闇の巫女と神々の指輪~,Games,Japan,ULJM 05864,1.01,594673664,9ef27f43,651690e30a3ffc9eb5527cf62d1fcbad,2048f33c3e9921f149df7486a1deb097aee88366 -92835,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2013,実況パワフルプロ野球2013,Games,Japan,ULJM 06319,1.01,1694859264,ad14c8fd,4f43719e5162cd8195e912d781c84ff8,2405949ccdff4aa542486b0229bd078ae63af6fd -92883,Sony PlayStation Portable,Ultraman All-Star Chronicle,ウルトラマン オールスタークロニクル,Games,Japan,ULJS 00564,1.01,1405157376,46410c10,18b6833bc7a3376c0849ae722869f084,28d238ae7adaf3ac3d528b56be42857837f9ab0a -92884,Sony PlayStation Portable,World Soccer Winning Eleven 2014,ワールドサッカー ウイニングイレブン 2014,Games,Japan,ULJM 06331,1.00,1284243456,06bf9fe2,5f3b204daf48c313f965fad4bc2e79f9,f7e9c018db3ce6e14cb8e62dbfa4c6f186334228 -93020,Sony PlayStation Portable,King's Field: Additional I,キングスフィールド アディショナル Ⅰ,Games,Asia,UCAS 40100,1.02,809369600,a828e439,e1363579ae40578c1a160e0196d2d937,0955d3e00ee2f89862e546492750f7fdf9503fae -93021,Sony PlayStation Portable,King's Field: Additional II,キングスフィールド アディショナル Ⅱ,Games,Asia,UCAS 40105,1.01,822738944,1067fa87,c7974c2c939b8a7b5a98d1215ab3c359,1c4c950bbb0d3b89aef5cb498568e158b1106a9b -93083,Sony PlayStation Portable,Disney/Pixar Istoriya igrushek: Bol'shoj pobeg,Disney/Pixar История игрушек: Большой побег,Games,Russia,ULES-01404,1.00,906035200,84a8cd5a,fe8f1915f2850df97633e4857d3bfe21,8cc5cae454d99ba1de3272f74c2421d69e778a6a -93234,Sony PlayStation Portable,Dia no Kuni no Alice: Wonderful Mirror World,ダイヤの国のアリス ~Wonderful Mirror World~,Games,Japan,ULJM 06295,1.02,1642758144,e52e6802,9a587c3965dad1ab12c4c14a836b41d0,71d38b59bb8dc48e98e8e4d8c4c7f118afb6342e -93348,Sony PlayStation Portable,Ore no Imouto ga Konna ni Kawaii wake ga Nai Portable,俺の妹がこんなに可愛いわけがない ポータブル,Games,Japan,"ULJS 00356, ULJS 00358",1.01,1573978112,df9e0546,fcd41fd688749229b28d27fe8c753053,83ececf561630b90f1d826175952052c212cf34a -93349,Sony PlayStation Portable,ToraDora Portable!,とらドラ・ポータブル!,Games,Japan,ULJS 00186,1.00,1708949504,60291298,5a7dc070c37034941c2d526319c1eceb,4515296523395e5a2185fe14207245dd7542ba4d -93350,Sony PlayStation Portable,Soul Eater: Battle Resonance,ソウルイーター バトルレゾナンス,Games,Japan,ULJS 00176,1.02,520683520,d3d7dfec,eb20e36c7eb23d94ac6288d8d765b5c8,33cb575acc7da5d8e5190041ac68239c13ba7c61 -93455,Sony PlayStation Portable,Kuroyuki-hime: Snow Black,黒雪姫 スノウ・ブラック,Games,Japan,ULJM 06362,1.03,1312718848,1fdddb6e,89c546b786a8a0da23aac8591bcccfd7,127389337322041f0a32cff1bb5ff9d4099e0643 -93568,Sony PlayStation Portable,Ikuze! Gen-san: Yuuyake Daiku Monogatari,いくぜっ!源さん ~夕焼け大工物語~,Games,Korea,UCKS 45092,1.01,237273088,d574b2fa,65f5ca09a87d995b1d94b1994199c489,cbf309c7e76f779d764ae79626ae6a7385793cba -93750,Sony PlayStation Portable,Amagami,アマガミ,Games,Japan,ULJS 00339,1.02,1608318976,8d82a828,b56e3e07d2672c55f4038d20490c6eb9,74f57af1986859e62346fb61e83a5de859cb53ca -93751,Sony PlayStation Portable,Planetarian: Chiisa na Hoshi no Yume,Planetarian ~ちいさなほしのゆめ~,Games,Japan,ULJM 05383,1.02,283213824,bfc444a2,756a33a6af9b9583a1b4a7c337b05bd3,150f1cd620558b2a5ad888b58131fc2d6ac822ae -94845,Sony PlayStation Portable,Magic Sudoku,魔法數獨,Games,Asia,UCAS 40139,1.01,154763264,454d70f7,26f26c685292a24179cf87b0801a68b2,984d2e73a5ab9e9369b7261b4e5d9c393a8e4b43 -94926,Sony PlayStation Portable,Bounty Hounds,バウンティ ハウンズ,Games,Japan,ULJS 00021,1.02,1149763584,19d92244,2087b094ab7df8346e0c6fe9abff899d,7ecc2c602489b117b8c45411ffa2c41b5a52f207 -94927,Sony PlayStation Portable,LocoRoco 2,ロコロコ2,Games,Japan,UCJS 10087,1.02,1805615104,e7e2eb98,a487d3fa767a22d8048b7b918a85b4c2,99fb19b9b852c4d714573db8449cf45a12f8bf5a -95193,Sony PlayStation Portable,La Pucelle: Ragnarok,ラ・ピュセル†ラグナロック,Games,Japan,ULJS 00243,1.01,857997312,295ca347,e45e0962228eba5b9dc4d558a2d30be7,a773aeb5a27074b679bca68f75d2af7b516d720c -95194,Sony PlayStation Portable,Lucky Star: Net Idol Meister,らき☆すた ネットアイドル・マイスター,Games,Japan,ULJM 05542,1.01,1257930752,1dedaba6,16755255ef12158ae85272dbf5297ba7,33c8094210f77d5765fa2631ed95075744ac8c7f -95195,Sony PlayStation Portable,Suzumiya Haruhi no Yakusoku,涼宮ハルヒの約束,Games,Japan,ULJS 00123,1.06,1539833856,4dc8daff,aa70d4223762399ccef051adcf3c1fa4,fac8783f0bb928263bb08cce2902570cabee7665 -96260,Sony PlayStation Portable,Kanon,カノン,Games,Japan,ULJM 05203,1.02,1668939776,b69a1265,68a762a89f36eb866f0680aed3669962,fc1c78c487b8e2bc174cea87226d34dbeaabb720 -96261,Sony PlayStation Portable,Ao no Exorcist: Genkoku no Labyrinth,青の祓魔師 幻刻の迷宮,Games,Japan,"ULJS 00423, ULJS 00424",1.00,712441856,b306ac52,2f6a8c0329bac23f495567568175873c,8c38b52ef989ef70f89bd8d542905e289c75f9aa -96262,Sony PlayStation Portable,Durarara!! 3way Standoff: Alley,デュラララ!! 3way standoff -alley-,Games,Japan,ULJS 00399,1.01,1274806272,5954d0a3,0ec4c8ff68a1f46922b2e1d9f63b08e7,1b84ee5f4957649080a0d4ba3ae098c3385ae1dd -96263,Sony PlayStation Portable,Toaru Kagaku no Railgun,とある科学の超電磁砲,Games,Japan,ULJS 00353,1.02,1242038272,9e382c79,ca5aa916e97e958f40acc6f0d271d763,933557b8b8cced72da456d703df3bd9ef1c1e38a -96264,Sony PlayStation Portable,Weiss Schwarz Portable: Boost Schwarz,ヴァイスシュヴァルツ ポータブル ブーストシュヴァルツ,Games,Japan,ULJS 00420,1.02,1249771520,bd70df96,6a4313ad2beffd38ca3c8536a4bd100a,718c41e03b1b7188c135dd4a199ded9ddbcb8b0b -96265,Sony PlayStation Portable,Zettai Zetsumei Toshi 3: Kowareyuku Machi to Kanojo no Uta,絶体絶命都市3 ~壊れゆく街と彼女の歌~,Games,Japan,ULJS 00191,1.02,1717567488,d327e49a,bd692f4dbb56c26fa02abda96c04c9f8,6bcd825f99f04f813abaf6b2f50cdeb1a2260e51 -96421,Sony PlayStation Portable,FIFA 06,,Games,Japan,ULJM 05061,1.02,1281818624,50a3f85d,a56c0923b6e60ea9a15990d6dc5e4665,95e4f5bf5dcef3d07ab52f429261829f7d777b7c -96422,Sony PlayStation Portable,Formula 1: F1 05 Portable,フォーミュラワン 05 ポータブル,Games,Japan,UCJS 10019,1.01,694091776,183f388b,8092292e476ccf460c2c27f3b31f2287,fd0183ef9318b67481b1ec3222462abe05083c9e -96423,Sony PlayStation Portable,Kollon,ころん,Games,Japan,ULJS 00010,1.03,40075264,a950f5e8,17c32164f58f20aad3766e01cfaaf002,576bb4abfeffca2beb8a5b53138e7366df4fb3a4 -96424,Sony PlayStation Portable,Musou Orochi 2 Special,無双OROCHI2 Special,Games,Japan,ULJM 06097,1.01,1798832128,c5c4332a,abf2b0e1c2847eee9137647efc02554d,6a85e2f74760f4994296ec979f0942262d3f6239 -96425,Sony PlayStation Portable,Pilot ni Narou! Flying All Stars,パイロットになろう! フライングオールスターズ,Games,Japan,ULJS 00059,1.04,327876608,069e8522,1ce2f6d776be2da61ff49361071f4d08,c321fa26485ec4b8926844fe4b2d82529324d9c5 -96426,Sony PlayStation Portable,Tekken 6,鉄拳6,Games,Japan,ULJS 19054,1.00,855703552,1f6e51ca,7d8180cd6ae8e80bdd3180a1e7313bbc,9287e62f05e0db86a52f362768cba0085d591b52 -96427,Sony PlayStation Portable,Valhalla Knights,ヴァルハラナイツ,Games,Japan,ULJS 00075,1.03,685670400,9164e6a0,518596b63979718af32256cfb573a981,d7e0488ebde59719e547a976d8550ad7d775343b -96428,Sony PlayStation Portable,World Soccer Winning Eleven 2013,ワールドサッカー ウイニングイレブン 2013,Games,Japan,ULJM 06161,1.00,1347846144,9d6d8841,58ee52974816dc13dc2b1ee51efd0981,c8ff0df28474b904dc10c727b85cf71d8a10e15b -96429,Sony PlayStation Portable,Yu-Gi-Oh! Duel Monsters GX: Tag Force 3,遊☆戯☆王デュエルモンスターズGX タッグフォース 3,Games,Japan,ULJM 05373,1.04,1561755648,c36612b8,86447c851e3ec93e956d9e488640b029,289b23097c8bcc8ed4e3cb51fc48c01ebd32c168 -96439,Sony PlayStation Portable,007: Russia yori Ai o Komete,007 ロシアより愛をこめて,Games,Japan,ULJM 05129,1.00,736460800,b3978b21,f44d317823a132cc91e84da9bbe26eb3,838d54726bc668cbc43b309389e5cd383607b39e -96440,Sony PlayStation Portable,Airou de Puzzle,アイルーでパズルー,Games,Japan,ULJM 06112,1.00,180060160,7da82d25,e609690075b2402cfc7ab1f0b58ff93d,a2a5cf688d8e25c755186a42188ecb240da78468 -96441,Sony PlayStation Portable,Amnesia Later,アムネシアレイター,Games,Japan,ULJM 06043,1.01,1388019712,d582d26c,8fc65f370c2cf1555bbc3b125c6af475,967e03f495994a9b5adff49c8bbfed9792d44879 -96442,Sony PlayStation Portable,Carnage Heart Portable,カルネージハートポータブル,Games,Japan,ULJM 05138,1.02,259981312,db432503,c99cb086b4fed7a23828d1b9236a50ac,73c6e610b54a1674a923b8a4a8212d157d19a7dd -96443,Sony PlayStation Portable,Criminal Girls,クリミナルガールズ,Games,Japan,ULJS 00323,1.03,385712128,a115038c,9f69ed7dfb426589df5e7fef1551f4af,958f0c4b0d3c277c7ea7f172458f4290178039fe -96444,Sony PlayStation Portable,Danganronpa: Kibou no Gakuen to Zetsubou no Koukousei,ダンガンロンパ 希望の学園と絶望の高校生,Games,Japan,ULJS 00337,1.03,1792114688,53a9d24c,9ac3076486293a279c10e1d94ce82b0e,84a83bd56d459c37e20483179bea3a3cad90d4b5 -96445,Sony PlayStation Portable,Hagane no Renkinjutsushi: Fullmetal Alchemist: Senaka o Takuseshi Mono,鋼の錬金術師 FULLMETAL ALCHEMIST 背中を託せし者,Games,Japan,ULJS 00220,1.01,435617792,301da14e,1568b7e0d9d87711f67d567f66e44a7b,aafe218ee40fd87e7990f9cd80b7235960c165eb -96446,Sony PlayStation Portable,Heart no Kuni no Alice: Wonderful Wonder World (Disc 1),ハートの国のアリス Wonderful Wonder World,Games,Japan,ULJM 05497,1.04,612630528,f8fb2c74,b9317a8cdf87b454d7e753537b54b043,2a5ebcca0f6fd708211ac9c913a4d9b7e61e2ec4 -96447,Sony PlayStation Portable,Heart no Kuni no Alice: Wonderful Wonder World (Disc 2),ハートの国のアリス Wonderful Wonder World,Games,Japan,ULJM 05498,1.04,1804599296,8af0ad30,ca07c48f02c1307ab05496b796ddc61e,8906bed84081d83f3d83d52fc38f7846cca11b54 -96448,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2010,実況パワフルプロ野球2010,Games,Japan,ULJM 05678,1.02,1620410368,8e36a15f,421194c698671b78a4119bc3362da367,dba82bc30d36948c6e904bd32276935da14d6035 -96449,Sony PlayStation Portable,Ken to Mahou to Gakuen Mono. Final: Shinnyuusei wa Ohime-sama!,剣と魔法と学園モノ。Final ~新入生はお姫様!~,Games,Japan,ULJM 05965,1.01,1057193984,ec9aaeea,1d6c21e50da888ec9c00031ac3f3504c,fc892b3b66fa1e621430e8199a8e9749db5de73f -96450,Sony PlayStation Portable,Memories Off,メモリーズオフ,Games,Japan,ULJM 05334,1.02,600571904,45aa9c1e,fda22ab615f712cc2d3c54028abe84bf,3c80a005ffbd547dbde8187e0b39888ea5d9fb34 -96451,Sony PlayStation Portable,Namco Museum Vol. 2,ナムコミュージアム Vol.2,Games,Japan,ULJS 00047,1.01,295796736,9e7bb36a,56ae0b2d273030b47e01f196d1f2d281,dc7592caf69d512422e66890f3ed9af44b35d598 -96452,Sony PlayStation Portable,NBA 2K11,,Games,Japan,ULJM 05778,1.00,1467580416,2cdbc401,97da74f6739a8aea77e5acc3a04b5d83,513767e47f2bb3f736520e1cda1638942f635175 -96453,Sony PlayStation Portable,Nippon no Asoko de,ニッポンのあそこで,Games,Japan,UCJS 10080,1.01,785186816,4e65e9bf,f4bc6a73c445e1b8ef5f043cb3374fe3,3984fbb2e1c835eb70cde5ae91042411b57f120f -96454,Sony PlayStation Portable,Nouryoku Trainer Portable 2,脳力トレーナー ポータブル2,Games,Japan,ULJM 05126,1.01,68124672,276265b7,ee0f97c3194bb68f41a0039c6c303c20,802de54165f152dd6c7bf0dab6c69cdbf2c4e987 -96455,Sony PlayStation Portable,Pia Carrot e Youkoso!! G.P. Gakuen Princess Portable,Piaキャロットへようこそ!!G.P.~学園プリンセス~ ポータブル,Games,Japan,ULJM 05464,1.00,1445822464,9eb620e2,0f63fb9413af6172ff8c38adcbfbbcf0,b30f767986d3d94dda57fe4f65b807d85ae4f622 -96456,Sony PlayStation Portable,Sengoku Efuda Yuugi: Hototogisu Tairan,戦国絵札遊戯 不如帰 大乱,Games,Japan,ULJS 00326,1.02,347013120,3e2c5cf5,89c0b15a210988fd983f9390fb503c29,e81b849615ac64c2c9a88d6bbf522d8ce63a08a8 -96457,Sony PlayStation Portable,Shin Sangoku Musou: Multi Raid 2,真・三國無双マルチレイド2,Games,Japan,ULJM 05637,1.01,1703280640,05797f7e,1623a293edca9a32bc9e768fa5e37233,36df858b300051d473295240cd0ee2e50bb0bc2d -96458,Sony PlayStation Portable,Shin Seiki Evangelion 2: Tsukurareshi Sekai: Another Cases,新世紀エヴァンゲリオン2 造られしセカイ -another cases-,Games,Japan,ULJS 00061,1.01,891191296,fa548951,a2da18bf5bd108f9ce331035a70c9409,06b54db973558e656833414b6b34ce6959c16f83 -96459,Sony PlayStation Portable,Winning Post 6 2006,ウイニングポスト6 2006,Games,Japan,"ULJM 05095, ULJM 05312",1.05,613285888,725388d8,5f98c1bc84b814eb4592bf124fd40225,2a498cd6849f6dac37a549fecf588d4551ca2126 -96508,Sony PlayStation Portable,Yarudora Portable: Kisetsu o Dakishimete,やるドラ ポータブル 季節を抱きしめて,Games,Japan,UCJS 10013,1.05,1249771520,e83e2ecb,8759e970bfca865e959fc2d762f2faeb,9c630a4c291659b8e87ad10c5940fdbcbf26c862 -96509,Sony PlayStation Portable,Yarudora Portable: Yukiwari no Hana,やるドラ ポータブル 雪割りの花,Games,Japan,UCJS 10015,1.05,1266089984,b8f9b04e,cb126d5e6273f1d7ca9981a64c4e31e1,00a07b9b171251b93a31d2861b9bf7a7101c9dfe -97744,Sony PlayStation Portable,Fate/Unlimited Codes Portable,フェイト/アンリミテッドコード ポータブル,Games,Japan,ULJM 05451,1.00,738033664,2ed3b2b7,e6bf8eae243653a461a103ca016e526d,d56e4b3c77efc408313dec0bf2020c6c303aaa0b -97775,Sony PlayStation Portable,BlazBlue: Continuum Shift II,ブレイブルー コンティニュアムシフト Ⅱ,Games,Japan,ULJM 05850,1.01,1675460608,253b812a,a7db580196d394050e33b5a3a5ad3901,140f6c892f9ff394e3dbaf984dfe037ef884b430 -97776,Sony PlayStation Portable,Gakuen Hetalia Portable,学園ヘタリア Portable,Games,Japan,ULJM 05839,1.01,1018888192,998840a2,04435b2f6f9359e3e808edf638c8e4b2,c0e3718b194a393472903bc5c2838f3d49e3f09b -97777,Sony PlayStation Portable,Gran Turismo,グランツーリスモ,Games,Japan,UCJS 10100,1.01,1085308928,5672a54f,872677fe59d58dc6ea39b7228a98b2dd,7f7237d46324cbf38e15fe4f857e0046e613edbe -97778,Sony PlayStation Portable,Gran Turismo,グランツーリスモ,Games,Japan,UCJS 10100,2.00,1085308928,9200bc8a,bea34a64b2e6f32abc2b0de65c1ef4e7,2879620973e2d0df41f516ad71657d6c1c5640e8 -97995,Sony PlayStation Portable,Otome wa Oanesama Boku ni Koi Shiteru Portable,乙女はお姉さまに恋してる Portable,Games,Japan,ULJM 05647,1.02,1667497984,f914eeea,b57ee7b8f85b91147455d3aeb3978236,5af82919e6f5a414757131f1e02ed378128c1e21 -97996,Sony PlayStation Portable,Sakura Sakura: Haru Urara,さくらさくら -HARU URARA-,Games,Japan,ULJM 05758,1.02,1366818816,d515ecaf,5c17a5745531317248b90967e148d1b3,18be4744456b7e49b85b67105194d89bf0a30582 -97997,Sony PlayStation Portable,Zettai Zetsumei Toshi 3: Kowareyuku Machi to Kanojo no Uta,絶体絶命都市3 ~壊れゆく街と彼女の歌~,Games,Japan,ULJS 19050,2.00,1721270272,aee0579c,5f038b4777c16035a8d14ac67de48617,7ab97c9092b190fea93988c697df7538b70a8b05 -98056,Sony PlayStation Portable,Mahou Shoujo Lyrical Nanoha A's Portable: The Battle of Aces,魔法少女リリカルなのはA’s PORTABLE THE BATTLE OF ACES ,Games,Japan,ULJS 00240,1.01,501743616,1b2c7cb6,19faf12a3ec165297cc02cff81231ebb,982abebbcf732905216546a1da4baf49c838e2da -98057,Sony PlayStation Portable,Midnight Club: L.A. Remix,ミッドナイトクラブ LA リミックス,Games,Japan,ULJS 00180,1.01,922681344,6b9a2bf9,85ad387ed56806733bc0ad9d020fc75f,0fab6253fbd6a15ed8b8efc32b60a26aa74cff61 -98058,Sony PlayStation Portable,Valhalla Knights 2: Battle Stance,ヴァルハラナイツ2 バトルスタンス,Games,Japan,ULJS 00196,1.01,1329233920,deb05968,ad725f57d9b5428bdba5669a23f0b0f1,14efbd332e7de6e992991dbf52c0e9cbca5cae6b -98081,Sony PlayStation Portable,Boxer's Road 2: The Real,ボクサーズロード2 ザ・リアル,Games,Japan,ULJM 05125,1.10,1777041408,28b368ab,9b1b85efecb435341d479617423a5e0e,0b73fc45a568c66508aee92e6d9490f1b9b8fe2d -98082,Sony PlayStation Portable,PoPoLoCrois Monogatari: Pietro Ouji no Bouken,ポポロクロイス物語 ~ピエトロ王子の冒険~,Games,Japan,UCJS 10005,1.03,1168506880,83758ae2,7eb1cee71b4e4b9eb37f206233a44f9e,4286cece82e91409325c57d9271fc117717c5b6d -98255,Sony PlayStation Portable,Boku no Natsuyasumi Portable: Mushi Mushi Hakase to Teppen-yama no Himitsu!!,ぼくのなつやすみポータブル ムシムシ博士とてっぺん山の秘密!!,Games,Japan,UCJS 18013,1.00,397508608,edaa4a64,b4d363d59cb87e25ab76afc5384cca31,c7c9549fe565ee2702512a93a97353be208dd2cd -98256,Sony PlayStation Portable,FIFA 12: World Class Soccer,FIFA 12 ワールドクラス サッカー,Games,Japan,ULJM 05966,1.00,1261142016,6de02b56,6f3ff1ac47ac001a923f135b08c1cfe9,ba575039f4e2703d9c1b51049126842724a6511c -98257,Sony PlayStation Portable,Gachitora! Abarenbou Kyoushi in High School,ガチトラ! ~暴れん坊教師 in High School~,Games,Japan,ULJS 00355,1.02,1686568960,e94572cb,813aa8aeb9cbe8f8a6fbc6d709427c4a,8dab5b7f11c778b8a4d2dbb1ff43336b5576947e -98258,Sony PlayStation Portable,Mawaskes: Based on Carton-kun,マワスケス based on Carton-kun ,Games,Asia,UCAS 40158,1.01,133496832,c4bf9037,2c8be5a7d208dfbe2d0cd271d1328e6a,919e9b02f628d434877ebfbafb774f5a1043db30 -98786,Sony PlayStation Portable,Anohana: Ano Hi Mita Hana no Namae o Bokutachi wa Mada Shiranai.,あの日見た花の名前を僕達はまだ知らない。,Games,Japan,ULJM 06115,1.01,802553856,c776d7cf,ea19d00aaf08003d0a65fd41e738498e,4894d2d81dc4933d70dee636db97969a1ecfa56e -98787,Sony PlayStation Portable,Bakemonogatari Portable,化物語 ポータブル,Games,Japan,"ULJS 00507, ULJS 00508",1.03,1434320896,cf808aad,4aa23c7406e810f0c57cea5e5fb717f1,a30a918dde5a2964810daac500a1fa17ca469d16 -98788,Sony PlayStation Portable,Plus Plumb 2 Again,ぷらすぷらむ2again,Games,Japan,ULJS 00066,1.03,146112512,9f722993,224de420883a2f63862352b3ccc29f18,6935dcc010f5e17a8d59a702629e54ada3ae1a8b -98880,Sony PlayStation Portable,Storm Lover Kai!!,ストーム ラバー 快!!,Games,Japan,ULJS 00609,1.03,1685356544,e7fa1f9d,a8c243573a5ce048caac7a239bd50522,6d03d3503c037ef88b945102527eea829850b17e -98990,Sony PlayStation Portable,Hanakisou,花帰葬,Games,Japan,ULJM 05701,1.02,1358233600,a8de48de,f1e793c732dafceec2442925189480ad,70fac71c6eb0df55b68ce7e9da6a098bc9ab4fe2 -98991,Sony PlayStation Portable,Mizu no Senritsu,水の旋律,Games,Japan,ULJM 05829,1.00,1143799808,a54ed41c,9f6f2aef7c8b7f37500af95243b3bdb4,571a7f977ae1e7f5aae6551e276ac03227aee822 -99058,Sony PlayStation Portable,2010 FIFA World Cup: Minami Africa Taikai,2010 FIFA ワールドカップ 南アフリカ大会,Games,Japan,ULJM 05646,1.01,1665335296,33f4127f,10873d667b9774a7c090665294a5f598,8fa88cb1bea00d98eaca001da0fc339dfbfe0b6e -99059,Sony PlayStation Portable,All Kamen Rider: Rider Generation 2,オール仮面ライダー ライダージェネレーション2,Games,Japan,ULJS 00518,1.02,989003776,1287a7d6,387ac67833eeef61b9a8b0d507a2ef27,ca29d169c8fd70bfbfaf7e9be7de22dde65d97bd -99060,Sony PlayStation Portable,Battle Spirits: Kiseki no Hasha,バトルスピリッツ 輝石の覇者,Games,Japan,ULJS 00238,1.01,378273792,7c454e5b,67a029175523db13918ba613a09788cc,0a9ae707930f6745031063caa4f8428459da66de -99061,Sony PlayStation Portable,Busou Shinki: Battle Masters Mk. 2,武装神姫バトルマスターズMk.2,Games,Japan,ULJM 05844,2.01,1750925312,74bce0a5,3e0ba4287a2d3e909bfe6699b3fab686,28573dfb79a76d902c29576c585d9710861e21aa -99062,Sony PlayStation Portable,Kidou Senshi Gundam AGE: Universe Accel,機動戦士ガンダムAGE ユニバースアクセル,Games,Japan,ULJS 00475,1.03,1690337280,b0bf5654,86ae7e541e7bb1b3db96ade6798e6dac,85751ec1a447efb0950053732236291c05ef5f26 -99063,Sony PlayStation Portable,Mashiro Iro Symphony: Mutsu-no-hana,ましろ色シンフォニー mutsu-no-hana ,Games,Japan,ULJM 05889,1.00,1503592448,1fced4b8,71697047b3a8c8a67169fa9c5c682032,4732528de9dd8806559e34dc56d44a96146c4265 -99064,Sony PlayStation Portable,Rockman Dash: Hagane no Boukenshin,ロックマンDASH 鋼の冒険心,Games,Japan,"ULJM 05030, ULJM 05215",1.01,316735488,78dfd145,5d08a47576b4c0a277840e1eabd69172,c87174dba89d13a45ebe9fe072e2b28be237b68f -99065,Sony PlayStation Portable,Tiger & Bunny: On-Air Jack!,タイガー&バニー オンエアジャック!,Games,Japan,ULJS 00498,1.01,676921344,e1b4862d,931751069dff0d505e715a1a89fb3dc5,a189e9be2ccac938d1e4ade383cd4ac4f26b0f5a -99066,Sony PlayStation Portable,Time Travelers,タイムトラベラーズ,Games,Japan,ULJM 06085,1.04,1176698880,ce5bfd7d,6d31f819caeac34ab6fe565345805fd6,97e331dd97917695cd2115c0e5dca147148b4e64 -99067,Sony PlayStation Portable,Toukiden Kiwami,討鬼伝 極,Games,Japan,ULJM 06376,1.02,1667203072,2c8f3175,62ceee266062cdd7ff9b039201e95a3c,d18192564898e671943f4b4c670c1d8350409a41 -99083,Sony PlayStation Portable,Megpoid the Music#,メグッポイド ザ ミュージック シャープ,Games,Japan,ULJM 06226,1.04,737935360,e6068dfb,8a29a914f78eede846e125a5f14d4dab,19b62768a2c8f0efc55777cb8a538eb550afe18c -99084,Sony PlayStation Portable,Ace Combat X: Skies of Deception,에이스 컴뱃 X: 스카이즈 오브 디셉션,Games,Korea,"UCKS 45038, UCKS 45067",1.02,1121026048,ffaf8e9c,da124db58371ee32318705ed018ec8a5,7ac0573fcc79535f613954145cfa3ca48e3d8979 -99085,Sony PlayStation Portable,Coded Soul: Gyeseungdoeneun Idea,코디드 소울: 계승되는 이데아,Games,Korea,UCKS 45071,1.00,387350528,6124b97d,11bdd583c984c4a2abe2080e1041941e,5f9bab9e9b86278c37f1f05f81c0d0ede0b8b2b5 -99086,Sony PlayStation Portable,Dissidia Final Fantasy,디시디아 파이널 판타지,Games,Korea,UCKS 45107,1.03,1622802432,bfd4a647,bce0b41aaa795a6f397f0904df56e1e4,d9accb06e9484c985fef81360af1d59e77122f43 -99087,Sony PlayStation Portable,FIFA 08,피파 08,Games,Korea,ULKS 46153,1.00,1622999040,a7df128d,1f36e4cc7a5ad1175fef20476a527cb6,14643519dd528d63cce538ed088ac6d79678f42a -99088,Sony PlayStation Portable,Flowars,용쟁화투,Games,Korea,ULKS 46008,1.05,207880192,90b9d7ff,02e9f0ae8c83fa1d2da13b3cf0bfefc5,6265cde076164c96eed6a925b0683c145acb37ae -99089,Sony PlayStation Portable,Jak and Daxter: The Lost Frontier,잭 앤 덱스터: 더 로스트 프론티어,Games,Korea,UCKS 45131,1.00,1453916160,9d00cc72,2390c2d6380908144c4f411123913fa3,3d8ee2955d63d56410f2cbc4f68dcf90926c0389 -99090,Sony PlayStation Portable,Silhwang Powerful Pro Yagu 2010,실황 파워풀 프로야구 2010,Games,Korea,ULKS 46255,1.00,1620574208,fdacf27e,616ae5c6bd0f1072fa0c27398033d981,b92821c6c9cccd7a5e470f5f8c4ccd9a94d151ea -99091,Sony PlayStation Portable,Lord of Arcana,로드 오브 아르카나,Games,Korea,UCKS 45162,1.00,822050816,b8f05c1f,10bafecc87216f02f57bc20747b5bf8f,dad131d56d891833acc34365a408f1392e34c4a3 -99092,Sony PlayStation Portable,Echoshift,에코 쉬프트,Games,Korea,UCKS 45142,1.01,291110912,08da1716,9306a57a07b4f53ee6810ce46b51c957,cffe9fd18cd249dc3fd2b36c8c4e27ea15df250a -99093,Sony PlayStation Portable,Pro Yagu Spirits 2010,프로야구 스피리츠 2010,Games,Korea,ULKS 46249,1.01,1578303488,52d263b9,2b94a611542e8f09f3e5e439f66e547d,e196f86f7069c85dd48be011f94901e370c52517 -99094,Sony PlayStation Portable,Pro Yagu Spirits 2012,프로야구 스피리츠 2012,Games,Korea,ULKS 46281,1.00,1581613056,e6378e97,9a65b63b0b0f6d8729e00f0a3dc287d5,989ad3c1442b88d25b2ea52fbd730424714a700e -99095,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo 3,소콤 U.S.네이비 씰 파이어팀 브라보 3,Games,Korea,UCKS 45128,1.01,1219330048,dd295c75,0cb145ed31d63652b7460df9569ba3b8,2e0e18c318b973c8088791e5ac9fc5f8dd22732e -99096,Sony PlayStation Portable,Thrillville: Off the Rails,스릴빌: 오프 더 레일,Games,Korea,ULKS 46115,1.00,845807616,ca3f350c,0a84c6677899d997bfa30df030d36477,b652907463b8ec05d0f3a88cb1241db9e80bdc1b -99097,Sony PlayStation Portable,Win-TOEIC Beginners' LC,Win-TOEIC 초급 LC,Games,Korea,ULKS 46018,1.02,1716715520,68f1aa09,c73bc15a2e7962a2495e775d788d1d77,99599ec8dfaa3454b57f14b8c83edc246c65fcda -99098,Sony PlayStation Portable,DJ Max Portable 3,디제이맥스 포터블 3,Games,Korea,ULKS 46236,1.08,1777631232,d3ed5d32,17943f67bf6a45c85e5eaf53e972bcf9,d711609ad777985e369b7457a35b6d40498eefe2 -99099,Sony PlayStation Portable,Marriage Royale: Prism Story,マリッジロワイヤル プリズムストーリー,Games,Japan,ULJS 00272,1.04,1592426496,4be81abf,32ec18ae3de23d8f35407d543cd1bac0,4bc4811c363f2782e67e1f62a7866e36762b3cab -99264,Sony PlayStation Portable,Abunai: Koi no Sousa Shitsu,アブナイ 恋の捜査室,Games,Japan,ULJM 06050,1.03,1277722624,3f5304c3,633c991cf5757ca8bfb518e6f5849e44,4a7972322c7e222e444e716f7be46f897a36fbba -99265,Sony PlayStation Portable,Boku no Natsuyasumi Portable 2: Nazo Nazo Shimai to Chinbotsusen no Himitsu!,ぼくのなつやすみポータブル2 ナゾナゾ姉妹と沈没船の秘密,Games,Japan,UCJS 10111,1.01,834633728,e2dedda4,0a59def5972cead16d410742e2434e81,3e456b68c4e9c4f6c025a86459f63369310d894b -99266,Sony PlayStation Portable,Glass Heart Princess Platinum,グラスハート プリンセス:プラチナム,Games,Japan,ULJM 06309,1.02,1590984704,7711979c,e84745957097765bdcad0c65f1b57536,6191635d9d637abe82e486f3ef3a61bd30d5d1f0 -99267,Sony PlayStation Portable,Assassin's Creed: Bloodlines,어쌔신 크리드: 블러드라인,Games,Korea,ULKS 46231,1.00,809566208,f04bc218,297a115179b9d646ecbdf1d0ff3a861b,ac478f441dbe6c28dd561d284a9d6289ebe52ccc -99268,Sony PlayStation Portable,Exit,,Games,Korea,ULKS 46054,1.00,112852992,e0a3b86f,5d6d2ae5b94fcb7f2388580d6696b441,cb46bdddd791d2c355fe114007620dccb3af1a00 -99269,Sony PlayStation Portable,Gundam Battle Chronicle,건담 배틀 크로니클,Games,Korea,ULKS 46158,1.02,572686336,68087370,9773826c3f48b6b590626141f12bfb55,6612712c58ca7872deaf3323ca3754cad4810b39 -99270,Sony PlayStation Portable,Oh's Talk English (Disc 1),오석태의 말하는 영어,Games,Korea,ULKS 46082,1.02,1258127360,4e0f6cdd,b5ba311d5fe7d73e6da8a4e84d6a2765,1057a3717adcb662bff8a9136455abc66c3b1611 -99271,Sony PlayStation Portable,Oh's Talk English (Disc 2),오석태의 말하는 영어,Games,Korea,ULKS 46083,1.02,1281294336,ccc08a57,1cbdfc00d932f809da510da4246e6ca0,13eff9a54abd023d70add822998e7daf4ef0c942 -99272,Sony PlayStation Portable,Tokobot,토코봇,Games,Korea,ULKS 46100,1.00,328269824,b071491d,eee78901905183096bb0bcee0f4c96c0,a03bebc78dcc7a9c32cc91e8a8a786b42419d310 -99312,Sony PlayStation Portable,Coded Gun,코디드 건,Games,Korea,ULKS 46016,1.00,183730176,a928ae76,92c47ce768a6429b0935c572d383495b,b5e7fdb02bec3b92a4c0df7e8559d05249ba3c9f -99313,Sony PlayStation Portable,Dante's Inferno,단테스 인페르노,Games,Korea,ULKS 46248,1.01,1812725760,6f0d124d,5097dc438dcc62e27afff249eade120d,88ca8b3e4b8db6fa2f71661f845850b3dfbbde5b -99314,Sony PlayStation Portable,Himawari: Pebble in the Sky Portable,ひまわり ーPebble in the Skyー Portable ,Games,Japan,ULJM 05614,1.01,1743847424,c66053fc,b626b505ee3ae1396b18135903864d81,4ee8ada904b2543d125f75023a4cc062e881174c -99315,Sony PlayStation Portable,Last Escort: Club Katze,ラストエスコート クラブカッツェ,Games,Japan,ULJS 00255,1.02,671744000,66ca2ff3,c82d8e2044f553d1b3db7230918ad486,c557f65e4e9f194b1c3219f652fe336dfc9ef003 -99316,Sony PlayStation Portable,S.Y.K Renshouden Portable,S.Y.K ~蓮咲伝~ Portable,Games,Japan,ULJM 05866,1.01,1683554304,b15da108,34eacc217e33d93bbef132119d626e88,414e2fea1b55982c987955926c9df63237666cc8 -99317,Sony PlayStation Portable,Starry Sky: In Autumn Portable,Starry☆Sky~In Autumn~Portable,Games,Japan,ULJM 05809,1.01,1371439104,0d52eee4,a86fe1590ba7587cb9cc0c1b6e9b4e49,4ffe14bfd6498a2785cb4e2cf54bbd3021da2160 -99318,Sony PlayStation Portable,The Sims 2: Pets,심즈 2: 펫츠,Games,Korea,ULKS 46117,1.00,1517813760,f86e7f0b,7279861370b6cd55c7859b05dce69e08,e21e2d0cb1205b8e64e529126398b357f128961a -99319,Sony PlayStation Portable,Tokyo Yamanote Boys Portable: Super Mint Disc,Tokyo ヤマノテ Boys Portable Super Mint Disc,Games,Japan,ULJM 06172,1.01,1580924928,8a10a25a,1e0e3f8e2623f98294df223644caa8d7,c042c55ac005b459146a495b1e571e565c6dd9ae -99320,Sony PlayStation Portable,Vitamin X to Z,,Games,Japan,ULJS 00346,1.01,1449132032,a32b667c,77d5e8f6638ae22e4f6fb44fd57b9543,cd8e7b00d672e693e5eaadc49a23c3d78c3ef025 -99336,Sony PlayStation Portable,Fate/Extra CCC,フェイト/エクストラ CCC,Games,Japan,ULJS 00450,1.01,1184464896,bf2e4463,9d5d152415f36998d5886a29fdfe640a,58a689b4532fad38e171a0226c8f5a2035253497 -99337,Sony PlayStation Portable,Kokoro Connect: Yochi Random,ココロコネクト ヨチランダム,Games,Japan,ULJS 00534,1.01,1655046144,17a20f19,add445c986452b54983052a05ea48f47,85b92d37f5f1413d2085b4a695b5a535f591cfa2 -99338,Sony PlayStation Portable,Minna no Chizu,みんなの地図,Applications,Japan,ULJS 00051,1.01,574226432,e96ad97b,24977f66042237d897cf18651a875075,6d96eef6b6eea709b2033a1a2f622ae893ff970f -99516,Sony PlayStation Portable,Pro Yakyuu Spirits 2014,プロ野球スピリッツ2014,Games,Japan,ULJM 06348,1.00,1401618432,be8dad08,71fac4a8e23b8957bdc1fa0dd4436238,3eba923a584730b4b6364375847fd9f583ef71df -99517,Sony PlayStation Portable,Storm Lover Natsukoi!!,ストーム ラバー 夏恋!!,Games,Japan,ULJS 00396,1.02,1182662656,877a5c1b,5a9228ab4c6370b7e7df21bece1af61b,a8ef50763031a482a124c021c04b32ddff184c34 -99689,Sony PlayStation Portable,Bomberman Portable,ボンバーマン ポータブル,Games,Japan,ULJM 05034,1.02,110231552,7ec06d91,57c6766a718d7dcd909d76856ff737a3,164742a0a2552058a9d7b90808783b28b72d1b75 -99690,Sony PlayStation Portable,Bomberman: Panic Bomber,ボンバーマン ぱにっくボンバー,Games,Japan,ULJM 05023,1.00,61079552,645acd02,2b7f4a22b0c8f419e54bac0fc5b9b479,cb35996e940bee5d115bf09dc5c3523bbc836b02 -99691,Sony PlayStation Portable,Gurumin,ぐるみん,Games,Japan,ULJM 05579,1.01,829456384,005bde71,2c64e9b2f32625427c4b1497d0d2170f,db19c47e784b251a521d17faaa5c7e7107ec9e2f -99692,Sony PlayStation Portable,Rockman Dash 2: Episode 2: Ooinaru Isan,ロックマンDASH2 エピソード2 大いなる遺産,Games,Japan,"ULJM 05037, ULJM 05216",1.04,349503488,40f10de6,e757d9fac4c714e49592c0c2144ceb56,9b1287a7c5f44508f1fcbd6ae6c8d03d77fe4007 -99693,Sony PlayStation Portable,Saru! Get You! Piposaru Senki,サルゲッチュ ピポサル戦記,Games,Japan,UCJS 10091,1.00,853803008,661d8029,eed72786cd2fa44e99dbc2ce37556fed,881e7fad1a24a30933b8018c7d5ed7c83d864101 -99856,Sony PlayStation Portable,Lumines,ルミネス,Games,Japan,ULJS 19005,1.02,276398080,ff5f5ae0,e56962be508d293e97a2b44b392631b2,f33457a11c8c6cc47e0fa535049a1330f6235af9 -99861,Sony PlayStation Portable,Shutokou Battle,首都高バトル,Games,Japan,"ULJM 05017, ULJM 08051",1.01,446889984,922ac5b4,d1ee7b50d1036563eb5a1956b9614c8f,b057ae65567f6852590ef0a6744c970616d903dc -99863,Sony PlayStation Portable,Super Robot Taisen OG Saga: Masoukishin: The Lord of Elemental,スーパーロボット大戦OGサーガ 魔装機神 THE LORD OF ELEMENTAL,Games,Japan,ULJS 00445,1.01,967868416,15e628f5,5018703465ff6452f5500937186d4fdd,7e0459d25b3f5031ee66198917a3a20e2d962315 -99923,Sony PlayStation Portable,Mana-Khemia: Gakuen no Renkinjutsushi-tachi Portable +,マナケミア ~学園の錬金術士たち~ ポータブルプラス,Games,Japan,ULJM 05345,1.04,1369309184,80874ffb,099026eef546d1585292c0e7666397bc,2e36845d242b25893f5212693b787836f107ac23 -99953,Sony PlayStation Portable,Mother Goose no Himitsu no Yakata: Blue Label,マザーグースの秘密の館 ~BLUE LABEL~,Games,Japan,ULJM 05950,1.01,1494614016,9fa24d09,37449282c8e6dfcc9c3b4a5a1c162b8b,7c51ba9c22625612f1ad64e131f9161bbf269a33 -100254,Sony PlayStation Portable,Syphon Filter: Dark Mirror,,Demos,Europe,UCED-00413/9677079,1.01,835977216,45b5148b,9275eb1fbe3496d95c373ba4080a5813,7bbc9112406b53a2e4e72aac1decafdcf756b25e -100259,Sony PlayStation Portable,Secret Agent Clank,,Preproduction,USA,UCUS-98697,.01,1491501056,8488ac9c,9524a8d83b50c900f32b1bceb83d3087,59502ad5b93a9bd2d67fc79a93ec2321ab91ef47 -100286,Sony PlayStation Portable,Naruto Shippuden: Ultimate Ninja Impact,,Demos,France,ULED-01539 / 7003769,1.00,1036320768,f98da96a,32c947339e9acf69b9e568d3ef660f46,31b12ba00c36e72a9933a61458e39c22e85d4ea3 -100358,Sony PlayStation Portable,Le Seigneur des Anneaux: Tactics,,Games,France,ULES-00199,1.00,544014336,d48c4137,87a21d53b6dc04a07b2c30364e7528d9,d09782445db6fd36030b3c4d61a65429810fed0e -100802,Sony PlayStation Portable,Arcana Famiglia 2: La Storia della Arcana Famiglia,アルカナ・ファミリア2,Games,Japan,ULJM 06291,1.04,1576402944,041ee002,ca8698efbd97fce5c58f787fc8dae89d,ae577402081f5a8fdecf0a1ce4a969fec24294bb -100803,Sony PlayStation Portable,Boku wa Koukuu Kanseikan: Airport Hero Shinchitose,ぼくは航空管制官 エアポートヒーロー新千歳,Games,Japan,ULJM 05453,1.02,191201280,e5845b16,a0ea26604f57d7aaa26a3795d082b563,03061bb53a42d4b38457aa02291ce33119dab9b1 -100804,Sony PlayStation Portable,Kiniro no Corda 2f Encore,金色のコルダ2フォルテ アンコール,Games,Japan,ULJM 05508,1.01,1351909376,5b67aba4,8d117c6691b95145d6a0439d367de8cf,31278e2745c707ad3133ea0c278d94b133f6db16 -100805,Sony PlayStation Portable,NBA 10: The Inside,,Games,Asia,UCAS 40279,1.00,1087471616,c13d2f1a,5d90069f3a38f36d80c39e451d230bfe,d2124dec27f2cdb8659304302dcc0286137fddfb -100806,Sony PlayStation Portable,NBA Live 07,勁爆美國職籃07,Games,Asia,ULAS 42076,1.00,1551433728,ce51c337,83bd8feb39cc56d61b897e382b285f19,ae8b58a17305d6527b2722e82b081877e9193481 -100852,Sony PlayStation Portable,Neo Angelique Special,ネオアンジェリークSpecial,Games,Japan,ULJM 05374,1.01,1674149888,76e1b0b0,22e9d0957503874b1f7ca699b9a020ba,b5cbe811315913be690e77a4968aea1bbee91438 -100958,Sony PlayStation Portable,FIFA 11,,Games,Europe,ULES-01475#,2.01,1379008512,380cfa49,3f6a56e7d81d5206dafa79944fca8d9b,76c23aa220cf7fde09f0c92a3a60972bbb3a33df -101028,Sony PlayStation Portable,FIFA 11,,Games,Portugal,ULES-01481#,2.01,1334706176,2c1f464e,ce37851b2e8d62bcadcfe13615cbba3f,16a2f0c7364a020ad0f4d86607ec5008551bd165 -101029,Sony PlayStation Portable,Minna no Chizu 3 (Disc 1),みんなの地図3,Applications,Japan,ULJS 00139,1.01,1812692992,aab96414,3838a9a20c47f27fa6c92e37ef9877ba,78d3f13e8f316fc68b3ac6bae251deb719aa93f6 -101030,Sony PlayStation Portable,Minna no Chizu 3 (Disc 2),みんなの地図3,Games,Japan,ULJS 00140,1.01,1770979328,46c7ed81,031e9f559ab837a40beb4f1c4f7c3f40,984fb9ea5355d2d1880bd2527607dc6b9c3f68a9 -101031,Sony PlayStation Portable,Tales of Rebirth,テイルズ オブ リバース,Games,Japan,"ULJS 00132, ULJS 19033",1.02,1644199936,a18aa000,349b95b467841eb3c5fecee044fb0094,a336b8f41e8966ba4ac62e05a7c72fa5064fcd59 -101157,Sony PlayStation Portable,Ayakashibito: Genyou Ibunroku Portable,あやかしびとー幻妖異聞録ーPORTABLE,Games,Japan,ULJM 05426,1.03,1524170752,488eeaaa,bd9767969efead53f35822e30388176a,fd02cc8ce9203baa35d618141e6a5c345e508c2e -101158,Sony PlayStation Portable,Dora-Slot: Shuyaku wa Zenigata,ドラスロット 主役は銭形,Games,Japan,ULJM 05014,1.03,25722880,fee2a45e,b7cc174563805c245edc93435f1fb063,78c4668ddfdae31953845cafcc9a933358930cba -101159,Sony PlayStation Portable,Evangelion: Jo,ヱヴァンゲリヲン 序,Games,Japan,ULJS 00201,1.02,773881856,4375d1ca,d5717fb31da39cf9ea31f69e6764c28f,d757d16a942fe225852c2e041c5b6b15c5a25dce -101160,Sony PlayStation Portable,Every Extend Extra,エブリ エクステンド エクストラ,Games,Japan,ULJS 00054,1.02,301203456,55a2d15f,c6ce5728bc23a67c26fcb158fe59b979,772eac405fe29b4c21e16cb011357aa8ea69bd30 -101161,Sony PlayStation Portable,Jissen Pachi-Slot Hisshouhou! Hokuto no Ken Portable,実戦パチスロ必勝法! 北斗の拳ポータブル,Games,Japan,ULJM 05020,1.03,208699392,f6e6acdb,57a03b48baa685b07ff1f9b8dd19d8fb,1e39be4e9f3c866fffad03e30930e0b008bb4f1c -101162,Sony PlayStation Portable,Shin Seiki Evangelion 2: Tsukurareshi Sekai: Another Cases,新世紀エヴァンゲリオン2 造られしセカイ -another cases-,Games,Japan,ULJS 00064,1.01,891191296,1c8af7dd,4953ebbb73de0e868191a3b1d72e25e7,c5c91bc3e5a2e0e292dfbbe1ebca27b3cc1850c2 -101163,Sony PlayStation Portable,WRC: FIA World Rally Championship,,Games,Japan,ULJM 05114,1.02,1320321024,c2a53c19,d7e132f959ce4a03ae84f29f83972bd8,3e3efeca226d0e92dc327ca31fe2364d51830405 -101164,Sony PlayStation Portable,Yarudora Portable: Blood the Last Vampire,やるドラポータブル BLOOD THE LAST VAMPIRE,Games,Japan,UCJS 10025,1.00,1457455104,cd391c9c,77bee8f52903c3eb8f1024a13fec7931,0f2db5901f12ff109922d24182e83aea6004c329 -101191,Sony PlayStation Portable,Blood+: Final Piece: Saigo no Kakera,ブラッドプラス ファイナルピース 最後のかけら,Games,Japan,UCJS 10044,1.00,818577408,43f78ac8,a545bfdb450aec6a63e5101dde1d2e76,31c786563a852b50f37de045c59a7ece14ec9c7e -101192,Sony PlayStation Portable,Genroh,源狼,Games,Japan,ULJM 06144,1.02,1671102464,810c593a,6f42543ebd7bad7fa3d14bb2b7b40896,3ac013c7c576d257fb140d15c195841c4dfbe2db -101193,Sony PlayStation Portable,SuGirly Wish Limited,シュガーリィ ウィッシュ リミテッド,Games,Japan,ULJM 06205,1.02,1460600832,462686ce,478951ab5fd5341ade713944cd982612,443c51d6141467240579070f76dfe16a87a271e5 -101194,Sony PlayStation Portable,Yuusha no Kuse ni Namaikida :3D,勇者のくせになまいきだ:3D,Games,Japan,UCJS 10109,1.01,363069440,59dcd0df,044448660ca99b14bda8db741fc4a832,7b5e71452c2721f2dc24382a7af62999cb5036d6 -101195,Sony PlayStation Portable,FIFA 13,,Games,Portugal,ULES-01571,1.00,1334738944,aca11973,38a9f69de9f659ae5e541d1dd808f290,7ad3b723c75e75002e6dcadaac7c5a0e85c55573 -101269,Sony PlayStation Portable,Ken to Mahou to Gakuen Mono. 2,剣と魔法と学園モノ。2,Games,Japan,ULJM 05476,1.03,659095552,a5feccee,2911a7e3e099ce1d861173de5cd00288,398e74a6e39104fff91230473d17f5d54e942f3d -101317,Sony PlayStation Portable,Summon Night 3,サモンナイト3,Games,Japan,ULJS 00303,2.00,1658159104,9dcdca58,14797e1fd9646e59835b9f6f1092f5dd,02b38476a9e758db4f5f8ae4d02bbd02d4fa0649 -101399,Sony PlayStation Portable,Shin Seiki Evangelion: Koutetsu no Girlfriend 2nd Portable,新世紀エヴァンゲリオン 鋼鉄のガールフレンド2nd ポータブル,Games,Japan,ULJM 05477,1.01,407568384,d4aa9284,d015a4201ccf45738f11a3cbc9a5ca96,d01c166c75532d81e7ebd2910b5f6dc35d6fcb63 -101406,Sony PlayStation Portable,PES 2011: Pro Evolution Soccer,,Games,Canada,ULUS-10546,1.01,1438318592,fbe91b00,9d04b14b2554680ddcad885f5b0e8f49,caec099bf43bb5b396febf1355a5531c2e08d3cc -101407,Sony PlayStation Portable,Kaitou Apricot Portable,怪盗アプリコット ポータブル,Games,Japan,ULJM 05276,1.04,904757248,469d52b0,24d6e9dd852187093f256612fbe2703b,0388c78cf3e5d9fee0bd1f8c9ac713fc6140d923 -101585,Sony PlayStation Portable,Densha de Go! Pocket: Chuuousen-hen,電車でGO!POCKET 中央線編,Games,Japan,ULJM 05084,1.01,488112128,91bd706a,8160a0fa751cd5d9e575f68719d97581,ec698f7a2183d039094e54b5da61c2540187d1c7 -101736,Sony PlayStation Portable,Tokyo Mono Harashi: Karasu no Mori Gakuen Kitan,東京鬼祓師 鴉乃杜學園奇譚,Games,Japan,ULJM 05638,1.04,968622080,45e4eeca,f4b2213627197cb5f9c97c2d202f0257,1d68889899448f0374eddb4b199b9aa827ae9f7b -101822,Sony PlayStation Portable,Grand Theft Auto: Vice City Stories,グランド・セフト・オート・バイスシティ・ストーリーズ,Games,Japan,ULJM 05297,1.01,1750794240,b01f3cb4,6f2717cc3ced3a3646582533a3ce3ddc,59cef693a8038e85dcbc462b89794ffeaeeafeff -101914,Sony PlayStation Portable,Intelligent License 2,インテリジェント ライセンス 2,Games,Japan,ULJS 00087,1.05,684392448,ffe5a01b,0921b79e9cf04bb7bc6085435a1d4cbd,f6dec3a791235616a4eb5ac9942f9d5cf8dd7f94 -101915,Sony PlayStation Portable,"Iza, Shutsujin! Koi Ikusa",いざ、出陣!恋戦,Games,Japan,ULJM 05876,1.02,1039958016,dcfa5225,66d55198cfb388379eb84ad7113c5eac,b3f6550bf79334c63b5d6a1a096c38b6c260b8be -102000,Sony PlayStation Portable,Adventures to Go!,,Preproduction,USA,ULUS-10417,1.01,176128000,93915dfd,a49a8f4f26dc527c80347a76bdad0c8b,b0a0cb182b164fad9eae816cc8c67d02a92f27ec -102001,Sony PlayStation Portable,Atari Classics Evolved,,Preproduction,USA,ULUS-10325,1.00,84934656,d7935592,ad6e27fb0c3ff632183ef103f091ed02,438aa19d524fc3bc567004b172795b6a21f3e5d0 -102002,Sony PlayStation Portable,BlazBlue: Continuum Shift II,,Preproduction,USA,ULUS-10579,1.00,1651834880,e6726268,ebba238f156bf7decb40aeff8c9a6c9e,e1a98d6ffa9e009577828d9c2f6cc0364cc10d85 -102003,Sony PlayStation Portable,Crash: Mind over Mutant,,Preproduction,USA,ULUS-10377,1.00,1577713664,2e2f12b4,ecd79cddf2b98d659b643c652c76c8ad,ff5230cc2a7fe4983f2a152eafd92c830554b0f6 -102004,Sony PlayStation Portable,Disgaea Infinite,,Preproduction,USA,ULUS-10522,1.00,280297472,b3209e4d,beb0e1ed41e3a78a8af721f230c938df,120f5a7d8e53cb46914b99c6e7d1449d1adc93b2 -102005,Sony PlayStation Portable,Dungeon Maker: Hunting Ground,,Preproduction,USA,ULUS-10282,1.00,150437888,990f0b6b,967d2349b8849721f1dc1a9359f28647,15e731ebad445d0eb8e039b2f2b7742f11445d5b -102006,Sony PlayStation Portable,Hammerin' Hero,,Preproduction,USA,ULUS-10392,1.00,227966976,2179bdb1,0c0bc8a190c67a0da6a7278b8557644e,b160dcd1f4b2131ac7cdca8150ab13d8d7aa0754 -102007,Sony PlayStation Portable,"Holy Invasion of Privacy, Badman! What Did I Do to Deserve This?",,Preproduction,USA,ULUS-10456,1.01,157220864,14b84ca4,2e82733983f73574425624646cf38952,b38d41a754d7c54854851cb17914635e7481b973 -102009,Sony PlayStation Portable,Metal Slug XX,,Preproduction,USA,ULUS-10495,1.00,440696832,a9bf80ad,7bd50f0e4de94147ea8b13182e413058,15767f0d1ee66f42cefd1395250fcafe3682d907 -102010,Sony PlayStation Portable,Monster Hunter Freedom Unite,,Preproduction,USA,ULUS-10391,1.00,886702080,13972134,5dbd8d4e8de4216c4b0202617f80ddba,5e3e7ec86adaa23f79e7239d4b12b63ce6e26f04 -102011,Sony PlayStation Portable,Warriors Orochi 2,,Preproduction,USA,ULUS-10423,1.01,1808596992,616efe0c,af56eafc3d45275b9f17372d3b930a1d,f6b984edb986c45850eb8b78092be66412fd7436 -102026,Sony PlayStation Portable,Fuuun Shinsengumi Bakumatsuden Portable,風雲 新撰組 ー幕末伝ー Portable,Games,Japan,ULJM 05561,1.02,686653440,8e700811,1b85a282bdc245db44e1bd0ed0df58d9,72e0323ac11181584092e4d25179c51af07e18ba -102027,Sony PlayStation Portable,Tiger Woods PGA Tour 06,タイガー・ウッズ PGA TOUR 06,Games,Japan,ULJM 05059,1.03,1294008320,a3749680,b6c2a879a82098ac71e7bfd9376fbf15,164dab6b5150c29b0a92806bbe82fd73dcd4c879 -102029,Sony PlayStation Portable,Mana Khemia: Student Alliance,,Preproduction,USA,ULUS-10408,1.00,1084391424,76656557,ec762d00a390fcbe9cdb52058e14761d,8eca431c8eb081ff6ac278ef41857439874cc60b -102137,Sony PlayStation Portable,Elkrone no Atelier: Dear for Otomate,エルクローネのアトリエ ~Dear for Otomate~,Games,Japan,ULJM 06046,1.01,1466531840,9e3b98e5,029d3d6eb74ebdcc38529b327a08a8bf,c832b829c4ce53afa79e5af630fbc614c2d2593d -102138,Sony PlayStation Portable,Dante's Inferno,,Games,France,ULES-01385,1.00,1812725760,f1eefa4f,186489bdb60187e55ffc5463baff288e,9e85387c9a28a45c8a2018d77420e605e4625ecb -102139,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,Netherlands,ULES-00735,1.00,906362880,b58c2710,4c6e3189a3eae7fe8f379de293adea33,dcede61660c3097f21d026af21b6e72637bc0941 -102140,Sony PlayStation Portable,Le Parrain,,Games,France,ULES-00397,1.00,1353744384,876c9af4,cb5c773b692b587c98c0fe4246525c21,523e80b4b5365497ae54933474cd9a8dbd1f4d51 -102188,Sony PlayStation Portable,Tenchi no Mon 2: Busouden,天地の門2 ~武双伝~,Games,Japan,UCJS 10047,1.00,1190363136,edba6aa9,9f8132e8a08fbd22cc9727f2ef86f247,ddeff9250227f317a0089ad2af50db13263a915b -102263,Sony PlayStation Portable,MLB,,Games,Korea,UCKS 45010,1.00,1128792064,b28450fd,a9f70d620549f247e8d4fbb6dcceb7b9,a9834dd27536e7766070d60dbcf63634aa32e37d -102264,Sony PlayStation Portable,Puzzle Bobble Pocket,퍼즐버블 포켓,Games,Korea,ULKS 46002,1.00,17924096,6331d00b,fa6bf62dfc146fe7f22395f6323dd1fb,519050cd0353aa69e6c780bf63d01a6a12c88bb6 -102381,Sony PlayStation Portable,Daisenryaku Portable 2,大戦略 ポータブル 2,Games,Japan,ULJM 05205,1.01,414941184,ee720374,8451acb4b5513679d494ce246d1e341d,d251b187434595bde7835a3d1c49492e43d97972 -102514,Sony PlayStation Portable,Tube Mania,,Games,Europe,ULES-01168,1.00,322306048,c8ed4b91,1442e2a76636b001c50a695e91db4ee9,db88a2671fa8cb33aded8d7145a24d0695e758fb -102588,Sony PlayStation Portable,Tube Mania,,Games,France,ULES-01131,1.00,321847296,ab630ddf,1515425e06dc98c7f6d272a21a049093,0fd59e3105d2d113bb6bb38ceb51aad67d4ff004 -102589,Sony PlayStation Portable,Warriors Orochi,,Games,France,ULES-01055,1.00,906297344,74527c40,5f7234d0221aa2a4695404e731eac865,d1961b02b0368bb2925b65cfa9486ade53835f45 -102593,Sony PlayStation Portable,FIFA World Cup Germany 2006,Coupe du Monde de la FIFA 2006,Games,France,ULES-00341,1.02,1236762624,684d657e,f3f60f3f4a20bff6fca12a65ce315274,140754d3c9280a08ae1f75cb53a309d1053dd836 -102797,Sony PlayStation Portable,Buzz! Brain of the World,,Games,Europe,UCES-01201,1.00,1519321088,1dc06731,0296dce0d14e0375aafb9a9335c63e11,424743f02c8a05f62b94dc03e6853f1a79baec76 -102798,Sony PlayStation Portable,Planetarian: Chiisa na Hoshi no Yume,Planetarian ~ちいさなほしのゆめ~,Games,Japan,ULJM 05383,2.00,283213824,bd363315,40ed86779ae1ad875a64fc36db91338b,a25be92ccd77b2f2a2dcd3ec19abb6c01a17b2bc -102876,Sony PlayStation Portable,Nobunaga no Yabou: Soutenroku with Power-Up Kit,信長の野望 蒼天録 with パワーアップキット,Games,Japan,ULJM 05902,1.02,484769792,a55ba2d6,f6a68511834600fa19c351b4debe71ca,fd5b17af7d59e0893945469ae99e8b82e8407817 -103050,Sony PlayStation Portable,Boku wa Koukuu Kanseikan: Airport Hero Naha,ぼくは航空管制官 エアポートヒーロー那覇,Games,Japan,ULJM 05171,1.03,322928640,3d6613b7,ef828a1bc0f844f0e088d4211075ddc7,9abe1984c953b38d638ff0194db963ae76cfabcb -103051,Sony PlayStation Portable,Ginsei Shougi Portable,銀星将棋PORTABLE,Games,Japan,ULJS 00269,1.00,131301376,9cb27358,ef8c6bdae9100f59c974ee104cfee983,da0545c43bae8f28e6298b9eefffe562e299eefe -103052,Sony PlayStation Portable,Shirogane no Cal to Aoi no Joou,白銀のカルと蒼空の女王,Games,Japan,ULJM 05954,1.00,1285455872,4202438b,cf265294d96e0d0783251be3e131cc92,0ffc8da103b21ccc22ef16854773590ccec43401 -103110,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2010,実況パワフルプロ野球2010,Games,Japan,ULJM 05678,2.00,1620410368,073016f0,62655e6f4283b29e9b113fe073624b1f,56124e16896539fb70b6232eb0814b0e526525b4 -103112,Sony PlayStation Portable,Worms: Open Warfare 2,윔즈: 오픈 워페어 2,Games,Korea,ULKS 46151,1.02,196214784,eadf227b,effc33b35945b1780c897649223454b0,0641990c4c942b398b9a42a8936a5cd2faaf2e6a -103113,Sony PlayStation Portable,WWE SmackDown vs. Raw 2009,WWE 스맥다운 대 로우 2009,Games,Korea,ULKS 46195,1.00,1489567744,b015511d,d965b06a19feada21337d6c896b9169e,1114672a5a6ba826387cbb83045121074aa4001e -103114,Sony PlayStation Portable,WWE SmackDown vs. Raw 2011,WWE 스맥다운 대 로우 2011,Games,Korea,ULKS 46260,1.00,1746534400,86d35136,88966d1b1ad9cfc85b2a2f3bc076c8b5,86607de2fcc1bb25a4758452c14b0db640f879e2 -103138,Sony PlayStation Portable,Ultimate Ghosts'n Goblins,극마계촌,Games,Korea,ULKS 46268,1.00,431947776,9e73a0c3,1e9556bbe2cad1d8603548f0a2de63e8,8a857e6af4d24fc9f592a9708d9513ea59176bd9 -103273,Sony PlayStation Portable,Gitaroo Man Lives!,ギタルマン ライブ!,Games,Japan,ULJM 05130,1.03,1804894208,1bbbe33d,f497f77e2c455b9c1bb901db34c39d0f,f529fdd4ded3d27a381e09720721ca0427f01414 -103274,Sony PlayStation Portable,Dynasty Warriors Vol. 2,,Games,France,ULES-00605,1.00,279216128,6289865b,58084bcff98515658a40b4db749baa10,470ae86258975ee0cffd47457e6618ccc1bac37a -103275,Sony PlayStation Portable,L'Entraîneur 2006: Championship Manager,,Games,France,ULES-00331,1.00,206864384,d120a628,152b5f94047007369b1db25df6793407,5c0a8f92b01ac9f33c0cf2488499384051b7fc79 -103276,Sony PlayStation Portable,NBA Live 10,,Games,France,ULES-01309,1.06,1220182016,ded9143d,99946d354e4a64c610eb3bbb92bb64ad,d2de69831e4cc16ba9cb3e0fc2a11df9b88a625c -103277,Sony PlayStation Portable,Samurai Warriors: State of War,,Games,France,ULES-00298,1.00,328204288,de05235b,eac59ae9ceb9246c9a5e601b11a31204,b055d252aa9f7d246a955a3afe6d6fb684432989 -103278,Sony PlayStation Portable,Toaru Majutsu to Kagaku no Ensemble,とある魔術と科学の群奏活劇,Games,Japan,ULJS 00556,1.00,1152647168,7b4fb0f4,dedb8ce2716becf14529ca3f2f203565,39b6a8cc29bc6bb922fde3a325eac700b1810049 -103669,Sony PlayStation Portable,Killzone: Liberation,,Games,USA,UCUS-98646/0.30,0.30,581435392,8d12f46a,e4eef4bdb0bea225cc6a7563ab6747e4,2c58f1872fb768e16e360a746c92ab7c3f7c9b37 -103670,Sony PlayStation Portable,Jikkyou Powerful Pro Yakyuu 2012: Ketteiban,実況パワフルプロ野球2012 決定版,Games,Japan,ULJM 06206,1.01,1530789888,2145ccb0,06b1068527c22810d7ccde106b89558e,567c3b59292883bf2a48b80db0c7505f2826182f -103671,Sony PlayStation Portable,XI Coliseum,XIコロシアム,Games,Japan,UCJS 10031,1.01,436699136,0d109b72,fd5e62224250c31379e6c3f9fb7d60ec,faf336bfda887641483bb958ebd5ebbc5e5810b3 -103835,Sony PlayStation Portable,Winning Post 6 2008,ウイニングポスト6 2008,Games,Japan,ULJM 05341,1.01,642121728,9ad9ccdb,a1d5b0b3f38aefdc0eb0bbf0408e9b3a,94c11f583e627661de6e400c6df6716232944471 -104056,Sony PlayStation Portable,ATV Offroad Fury Pro,ATV Fury Pro,Preproduction,USA,UCUS-98648,0.30,623607808,91121d0c,3747e64c4eb6b0162e37e87f80cdfe60,6d69ad5644e10d72ebd69d764e49bf9f00086c12 -104064,Sony PlayStation Portable,FIFA 11,,Games,Russia,ULES-01480#,2.01,1360756736,7f07cb1e,974bcb51d2b6e7c0c3fc7aea5ae0290f,c1547a3b310dde85de790aef78961ed315466f0b -104065,Sony PlayStation Portable,Corpse Party: Blood Covered: Repeated Fear,コープスパーティー ブラッドカバー リピーティッドフィアー,Games,Japan,ULJM 05704,1.03,722042880,3f65f94c,cb12f82bfcc535fe86d1cf82f88aa13e,78a862f671d9aec3859b0b171b6e35272da5ad71 -104066,Sony PlayStation Portable,World Neverland: Nalulu Oukoku Monogatari,ワールド・ネバーランド ~ナルル王国物語~,Games,Japan,ULJS 00514,1.00,535494656,4c2f61be,98ceaacfe3a5acb183bdac2f60a215a0,d79c50de2cafe0a47b738019d3954f862d3a280d -104196,Sony PlayStation Portable,FIFA 12,,Games,Russia,ULES-01548,1.00,1360756736,31023b57,fe9b4b304277e1ec247e15a4d7aeeb06,41f1d95fe1b9ba02c7aa4bbf2611fe4de730b590 -104979,Sony PlayStation Portable,Bubble Bobble: Magical Tower Daisakusen,バブルボブル マジカルタワー大作戦!!,Games,Asia,UCAS 40097,1.05,631603200,42c9a81b,b115d55a64c2a716274b46712ec7ba43,0d8e3b8f4394d30cd19a413673dda5c96f8cf082 -105210,Sony PlayStation Portable,Space Invaders: Galaxy Beat,スペースインベーダー ギャラクシービート,Games,Japan,ULJM 05045,1.02,229507072,028edb0e,022d2dd4fc867fe685d4cd319e058e7b,e4851c4396563ec1689478679214bfc5bd5d07d1 -105218,Sony PlayStation Portable,Shinten Makai: GOC IV Another Side,新天魔界 ~GOCⅣ アナザサイド~,Games,Japan,ULJM 05013,1.06,928415744,c6812189,042e398d0e1461dfb9918876ac7993a8,c47fe01c932372e6a8031ca97241a4262d60601a -105219,Sony PlayStation Portable,FIFA Soccer 10,,Games,Canada,ULUS 10473,1.00,1706655744,0c12d439,9319deef4553aaa033a1ef333c807a00,9ac5e54a0d932e77d8ba402b50be3eb80c06e715 -105311,Sony PlayStation Portable,Yoake Mae Yori Ruriiro na Portable,夜明け前より瑠璃色な PORTABLE,Games,Japan,ULJM 05625,1.02,1516404736,113bd30a,4d2b5bd309f05142a786fe9ec46e449a,b5c92f223d5ce8b3fcde25b5f0899272053819f6 -105312,Sony PlayStation Portable,Sengoku-hime: Senran ni Mau Otome-tachi,戦極姫 ~戦乱に舞う乙女達~,Games,Japan,ULJM 05540,1.02,1295384576,24d9f729,34fed600e6c2970c39f467e2047d68e3,b57aa8c908431e6dffc802085f9057225f81dc95 -105527,Sony PlayStation Portable,Buzz! Brain of Switzerland,,Games,Switzerland,UCES-01208,1.00,1548353536,492a4cf1,ee32ef42385888e1f38cede91081a5e6,a72a6d1e743f041ca92cd1c6f7802e6e3d7efc0d -105528,Sony PlayStation Portable,Go!Explore,,Applications,Germany,UCES-00886,1.01,906362880,bd298a42,9ad6fc794b37a069feb2a0038ef40db3,a3b657e1693d256fad221f0ef046833290802832 -105529,Sony PlayStation Portable,Medal of Honor: Heroes,,Games,Germany,ULES-00559,1.00,1447067648,9e870e6a,f86eed8eca30863153f9c9c3d5ba24db,dcac3cff5ef6c5253c2ba6c70553dfe580310596 -105530,Sony PlayStation Portable,Transformers: Die Rache,,Games,Germany,ULES-01288,1.00,1634566144,e8621b86,40e3ea199b203cfedbe4efd1303f535d,ccfa4e0187095cd0ed6b1c42c9fb475957f70767 -105681,Sony PlayStation Portable,Uta no Prince-sama,うたの☆プリンスさまっ♪,Games,Japan,ULJM 05664,2.00,1754169344,8b237216,a5fb9af07e61e8298f993197955700a2,7f4e0857abb3b0a204a603b8346581ec36a9f741 -105750,Sony PlayStation Portable,Chou no Doku Hana no Kusari: Taishou Tsuya Koi Ibun,蝶の毒 華の鎖 ~大正艶恋異聞~,Games,Japan,ULJM 06343,1.02,1577517056,988d8d12,1b7ecaaea41ca4159f8adcaca948afe5,07ac176716e0632008fb1a12ad87668e1bad7275 -105760,Sony PlayStation Portable,Omerta: Chinmoku no Okite: The Legacy,オメルタ ~沈黙の掟~ THE LEGACY,Games,Japan,ULJM 06393,1.01,1530724352,a16fd7b6,9cd8338a36af447efb07c8c13620b92d,db25a71f8eb5735eaf0e1a2503031e43a65a7fbd -105761,Sony PlayStation Portable,PriPia: Prince Pia Carrot,プリPia ~プリンスPia♥キャロット~,Games,Japan,ULJM 06389,1.00,1478033408,f7233442,13502fb46b48b76668508603629c0340,6f6fe2e7c85bc5d348e4a5eead62261b74b2b24f -105762,Sony PlayStation Portable,Urakata Hakuouki: Akatsuki no Shirabe,裏語 薄桜鬼 ~暁の調べ~,Games,Japan,ULJM 06372,1.00,1522728960,b8921b9b,d6773603369f8c83aff02e90b04ae01f,36f89e5b813adc8ec1aa3401c6da7aede80fa323 -105851,Sony PlayStation Portable,FIFA 11,,Games,Germany,ULES-01478#,2.01,1458405376,23ec3528,3f91509edf95379985f5f7ce9b2bc266,d2ea6581a6842b5a2d3885c6a1e8deca2fb0de41 -105917,Sony PlayStation Portable,Memories Off 2nd,メモリーズオフ 2nd,Games,Japan,ULJM 05335,1.02,856129536,1d3f730d,27bd63f967bc200e835e461fbb2d3d8c,b0de5173da32ad305b1159f42d63c350355b7bc8 -105918,Sony PlayStation Portable,2010 FIFA World Cup South Africa,,Games,Canada,ULUS-10517,1.01,1752727552,8df1ac2f,fd80e9707731491a727364dcf45e9965,07f47ded7e1089f6fb2f94b640c1f996f21c1842 -105919,Sony PlayStation Portable,FIFA Soccer 13,,Games,Canada,ULUS-10596,1.00,1618935808,c9baeff8,c19744e0045e6c2a5b0966e74ce40605,3786a28f1badf99c93570b01b7e6394fb4d3a09e -106232,Sony PlayStation Portable,Buzz! Brain Bender,Buzz! Aivojumppa,Games,Scandinavia,UCES-01158,1.01,472121344,d05081b9,a5469f4d073c2ba3976f9b18b1643abb,7106e3ac21d8186de929af2a39fb485cb9da59c5 -106234,Sony PlayStation Portable,Buzz! Master Quiz,,Games,Europe,UCES-01034,1.00,1486487552,d630c2d6,468c9c84b12e245f102db90bb8c22918,b1086a09c9867a45d9c24ef3c52b902a64e433c5 -106235,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,Europe,ULES-01073,1.00,776699904,61852882,194388c486f90449eff2211da6a8e1fb,c55256b7eb369fc7f52bd215032ac386032c0a7b -106362,Sony PlayStation Portable,Hakuouki Portable,薄桜鬼ポータブル,Games,Japan,ULJM 05509,1.01,1192820736,31793e4c,8bc3ebcad9cb41c90501c51ffd92ba1a,c86507cf7225c1239f2df177263481e8cd10f24d -106364,Sony PlayStation Portable,Sangokushi VII,三國志Ⅶ,Games,Japan,ULJM 05083,1.03,199032832,66a72ed6,fe0a203048a6d71b973b40ac2d342e3f,ca9cd225f5b15701cc66a401d971d057a41a9708 -106370,Sony PlayStation Portable,Shinigami to Shoujo,死神と少女,Games,Japan,ULJS 00403,1.01,1367310336,44c8b2fc,86c073ae03057038df69a4e107702337,ac816a1cee097e15888de9b6b959e687a69c5a5c -106371,Sony PlayStation Portable,World Soccer Winning Eleven 2014: Aoki Samurai no Chousen,ワールドサッカー ウイニングイレブン 2014 蒼き侍の挑戦,Games,Japan,ULJM 06369,1.00,1443528704,605ae16e,b1d18d1d7d4cf73bde0bf7ba0eaad725,8b8d4aed9abd030eadb75455f78bf5b4b8efd6f1 -106385,Sony PlayStation Portable,Disney-Pixar WALL-E,,Games,United Arab Emirates,ULES-01079,1.00,866975744,bbae6bec,154ec031615e5d9278613d74232c1a98,f329eafb6fe8a29de3adb133f49e6c5742f1e075 -106386,Sony PlayStation Portable,Elminage Original,,Games,Europe,ULES-01599,1.01,568197120,bb6698ec,c5c0045631df27b4d9ed141a9299d2c5,5f60630b9fa64782cbdf784261df77565155c984 -106437,Sony PlayStation Portable,Starry Sky: After Spring Portable,Starry☆Sky~After Spring~Portable,Games,Japan,ULJM 06207,1.03,1489108992,1764c7f3,d93aa0b1178af59610d7aea6caaabb69,5ca9e933e4ed8d8d8246b0a3c7f3efc72f7130dd -106438,Sony PlayStation Portable,"Starry Sky: After Spring Portable: Etsuran Shite Please ""Etsu Puritsu 2""",Starry☆Sky~After Spring~Portable 閲覧してプリーズ"えつぷリっ2",Bonus Discs,Japan,ULJM 06227,1.03,490209280,b6e8aa03,d26cb71f5b23cb7bfc83bed13f46ca91,64d8d3f11e57b524ae251d74f08971c446912f54 -106466,Sony PlayStation Portable,Bara no Ki ni: Bara no Hanasaku,薔薇ノ木ニ薔薇ノ花咲ク,Games,Japan,ULJM 05802,1.01,670269440,62d64995,2317a2c372eb72b0a6f769a089e09992,cb8f9b7d58cc5c71d017998a4a7c3f5d0d42f2ed -106469,Sony PlayStation Portable,Wand of Fortune II FD: Kimi ni Sasageru Epilogue,ワンドオブフォーチュンⅡFD~君に捧げるエピローグ~,Games,Japan,ULJM 06193,1.01,1612644352,0bc39a28,47fa19052eb74bbfdb6c94e6eb5cd8c0,8d07677dad9dc6c8f32ef2a417440542fa892010 -106503,Sony PlayStation Portable,Aku Daikan Manyuki,悪代官漫遊記,Games,Japan,ULJM 05185,1.03,138575872,aa5e488d,af50717bd15a9813a6b9613861b34d7a,917c8f17ddeb10282c62fbd02d4d3b8bccdb9a2c -106505,Sony PlayStation Portable,Armored Core: Formula Front,アーマード・コア フォーミュラフロント,Games,Japan,ULJS 00003,1.01,842006528,17345912,7ab2f99e71b09a828c12c80ad6756bbe,74069fffca10d0469a893f8a4d7d83193f1c1b5e -106506,Sony PlayStation Portable,Armored Core: Last Raven Portable,アーマード・コア ラスト レイヴン ポータブル,Games,Japan,ULJM 05611,1.02,1202192384,0be8c7cb,c4b76591fe026918f4dcf2a4a4b18638,8600ab267e1eb5af9e04075d7c75eed738483bb4 -106507,Sony PlayStation Portable,Armored Core: Silent Line Portable,アーマード・コア サイレントライン ポータブル,Games,Japan,ULJM 05552,1.01,682721280,7d8da477,bb5fe4f1bcfab5303acb0f9d588c66cb,2ac91bf1d9f3ad12c94a4428c24d634bdce2b135 -106508,Sony PlayStation Portable,Carnage Heart EXA,カルネージハートエクサ,Games,Japan,ULJM 05698,1.01,834109440,990c41b0,6958526f1796ff8aad3294f523e8f88f,51efa90e347c5121a1b734946c07bf44734c8dd6 -106509,Sony PlayStation Portable,Zero Pilot: Daisanji Sekai Taisen 1946,ZERO PILOT 第三次世界大戦 1946,Games,Japan,ULJM 05649,1.01,624885760,adeb2fbe,47ad8fc06e25e67d84d862da97417a7e,2b9b8a55d070ad349450fbd102ffe91e3fa76d43 -106560,Sony PlayStation Portable,Senjou no Valkyria 3 E2: Extra Edition,戦場のヴァルキュリア3 E2: Extra Edition,Games,Japan,ULJM 05957,1.00,1459322880,6f0d3aa6,5cb612d3062149c15130a73383a627d2,70f2ce891ce45b1a79e8ac5a0845f5845da7c117 -106884,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Biler,Games,Norway,ULES-00326,1.01,906362880,eb0d12c0,0559d0d0a349acbe0fd95dd241962f30,33732823df3b08a798b9533f7ebcb21ea4675c13 -106885,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Biler,Games,Denmark,ULES-00328,1.00,906362880,ad4acb18,e39716da60990c046f0d76a3e8692436,4147dbfd4d60fb82083df48bf0c267ad28c18938 -106887,Sony PlayStation Portable,Disney/Pixar Ratatouille,,Games,Denmark,ULES-00742,1.00,906362880,d4b7558c,7dd1cb4b43f5d8c00100e3951f9736b8,cae68026baa1f1976f954dedd4ac9968ec565316 -106917,Sony PlayStation Portable,FIFA 14: Legacy Edition,,Games,Germany,ULES-01589,1.00,1458438144,5843e8cb,4a66d36e6d05dceee0171fbb35a2684b,108e42e2db66b1a01ff57e60adb384fce6918b6c -106923,Sony PlayStation Portable,Burnout Dominator,번아웃 도미네이터,Games,Korea,ULKS 46136,1.00,691109888,7103c532,9698b1e6480c5321f24f57ede2b37953,7514d448e441a53553d4477724be297ce051ab58 -106924,Sony PlayStation Portable,Burnout Legends,번아웃 레전드,Games,Korea,ULKS 46027,1.01,505905152,7c1078f7,810db28d105aa3927cd2d0503410f318,644d6562b7656931218837c334ae558e5eed8a0d -106943,Sony PlayStation Portable,Togainu no Chi: T B P,咎狗の血 T B P,Games,Japan,ULJM 05795,1.03,759169024,e2197d6c,15312bcc1d9bc69c33fa97b09a372224,fd4f65f571356ec0ffc6e80d31745f3c8831d4e0 -106956,Sony PlayStation Portable,Crash: Génération Mutant,Crash: Mind Over Mutant,Games,Europe,ULES-01173,1.00,1574895616,d9229e6b,8d1301828af3505c7a17304cb0fbcd1e,6516cf53bb9852f52f882e52fbfcc7dde818335e -106957,Sony PlayStation Portable,Pro Evolution Soccer 2013,,Games,Europe,ULES-01576,1.00,1263665152,e0b41540,1695abb62799df08c2a254f16eab377b,9a411b09c487b48d919598670977d3f6a47828ca -106958,Sony PlayStation Portable,Tiger Woods PGA Tour 07,,Games,France,ULES-00456,1.00,1256390656,1f455d4e,391f1fab9b44f938b4fd042a31a4ea43,31f8134f5afc0d47fda5e31c14bf672cd4f771c8 -106959,Sony PlayStation Portable,Tiger Woods PGA Tour 08,,Games,France,ULES-00846,1.02,1350696960,c4c52592,d51f6e7a72e719a2d205782dafb9acfc,6c659f9699f10fed8dfa26e015b0139e28c35141 -106960,Sony PlayStation Portable,SOCOM: U.S. Navy SEALs: Fireteam Bravo,,Preproduction,Europe,UCET-00222/0.01,0.01,839876608,c6b0f509,ac906500e3659fec20307b6e1cf6196c,36dc61d9bfcd0c2aa10e36161e1abe7f6b573ca8 -106968,Sony PlayStation Portable,Disney/Pixar Up,Disney/Pixar Là-Haut,Games,Europe,ULES-01263,1.00,671481856,72969120,26d616a57ca65eceb926500b075fa753,2fbb818ae2081634f1261b6939b84a33ef84d8c4 -106969,Sony PlayStation Portable,Fullmetal Alchemist: Brotherhood,,Games,France,ULES-01433,1.00,643792896,4cd6e3a4,d9784b37e9a9febd07851bbbbe190efe,0663995c7c99e4b83824b053123c7b82d58df000 -106979,Sony PlayStation Portable,Phase D: Souka no Shou,Phase D 蒼華の章,Games,Japan,ULJM 05983,1.01,267091968,ef85887c,e25e69d58c8c5fca3831c4ffb448a9f6,181214f6e55b702e2371651059f722bcf273ecf5 -107147,Sony PlayStation Portable,Starry Sky: In Winter Portable,Starry☆Sky~In Winter~Portable,Games,Japan,"HONEY-004, ULJM 05861",1.01,1352368128,4fb9467d,72a29e95e33dae44a73b4d25913a2d6e,c2c7b664d6c5500018fa977d5c0e610865b88827 -107258,Sony PlayStation Portable,FIFA 13,,Games,Netherlands,ULES-01567,1.00,1217626112,f7515259,d8cfab6b54a06e637d5c6f48e7831b49,e1dc52050465631624ac2b1b9b25b5c59c22a43c -107387,Sony PlayStation Portable,Hentai Ouji to Warawanai Neko.,変態王子と笑わない猫。,Games,Japan,ULJM 06305,1.01,1474396160,cdd1322f,7cc69834540ed4038ac7b562eebf6ec6,4705d29bfab5050217a43d827f438d6479b3647c -107482,Sony PlayStation Portable,Simple 2000 Series Portable!! Vol. 1: The Mahjong,SIMPLE2000シリーズシリーズポータブル!! Vol.1 THE 麻雀,Games,Japan,ULJS 00301,1.04,165969920,04afdf25,947a2b8735400a6ebd0a1b1d7230ef1b,abcf82cf4600f3489c6adbb46c1ff90ad40070db -107483,Sony PlayStation Portable,-8,マイナスエイト,Games,Japan,ULJM 06340,1.01,1207468032,b71764f4,4f7cff5ae7d96abfff141c420f530b68,3ba8af1354c8ae1e5119dbff19730793c21ad56e -107488,Sony PlayStation Portable,Adventure Player,アドベンチャープレイヤー,Games,Japan,ULJS 00011,1.05,800751616,a3ca9117,fd325910d2665bc6ef30c682ff73794a,f9f203075f4df894803ccfb36f4562e583fc2bb9 -107579,Sony PlayStation Portable,School Rumble: Anesan Jiken desu!,スクールランブル ~姉さん事件です!~,Games,Japan,ULJS 00019,1.00,1734868992,6c689d42,5bf0ac3fee7dd5857888c72ec32c7b9a,a2bac95fd90d59b380c89a83712496d187a89645 -107580,Sony PlayStation Portable,Simple 2500 Series Portable!! Vol. 4: The Unou Drill,SIMPLE2500シリーズポータブル!! Vol.4 THE 右脳ドリル,Games,Japan,ULJS 00039,1.01,84115456,047a3081,609a7d6c9912b7726044efd0a65ff4f1,af921d1db5f77ba84361c2b9c5f906f5377b09a3 -107688,Sony PlayStation Portable,Patito Feo,,Games,Europe,ULES-01493/POR,2.00,860160000,06874d98,cb72557f4b49a8c5a0d2290942178e66,ed5488aae166f65b1cf596843b595bc757f04c02 -107973,Sony PlayStation Portable,Worms: Open Warfare,,Preproduction,Europe,ULET-00317/0.01,0.01,225247232,5cdedfd5,a1a8f83f3b970b530868e5ff3d89c1df,0adadbf3c554480f13ccf706e768a6d1ce568abc -107974,Sony PlayStation Portable,Jak and Daxter: The Lost Frontier,,Preproduction,USA,,0.30,211189760,ffbf5891,a2fa0a4fe7320bfcb39a8865ea4cdc79,65b407bec7c7dbcb511c457068aa2a0bb35bfba1 -107975,Sony PlayStation Portable,Crash Tag Team Racing,,Games,Netherlands,ULES-00173,1.00,1540587520,13ca0e02,064fadeef79bb5406cabce8fa345e6f5,f9ba7e18e5f69c5d2beb50ea9d0b50bc4852c417 -107976,Sony PlayStation Portable,Disney/Pixar Cars,,Games,Netherlands,ULES-00322,1.01,906362880,54e63e95,a44edff8de342f36a580819eb544527e,c0176de769c85b1e25f8ecf3aeb50a491d6bf84d -107978,Sony PlayStation Portable,FIFA 14,,Games,Netherlands,ULES-01594,1.00,1217626112,212702f6,6dacf6a4fb10d284d6a3109d9761697d,c802798404c8f5aac4754db62bae1495b94e0888 -107979,Sony PlayStation Portable,FIFA 11,,Games,Netherlands,ULES-01482#,2.01,1217593344,183a968e,a8d76d6b0bfce87e9ae4042be88e6695,9cb94448bf090b4c1ca95feea8d8d3e8b4286741 -108005,Sony PlayStation Portable,Scooby-Doo! Qui Regarde Qui?,,Games,France,ULES-00572,1.00,618496000,6763e795,5e23eab7e14e4e9bc1e7da6a41870af1,2de19e74555e8edbb70d1f0cf04aa92e448b8bff -108006,Sony PlayStation Portable,Saki Portable,咲 -Saki- Portable,Games,Japan,ULJM 05556,1.01,698056704,0c92cb52,43a44a83042fbbe7c7d6bf65162c0406,33ef319ef80d86d26c9441927b877ac99df4ac0a -108007,Sony PlayStation Portable,Sangokushi IX with Power-Up Kit,三國志Ⅸ with パワーアップキット,Games,Japan,ULJM 05842,1.01,739409920,ecad04b4,0ddb572b3a4ce82eb69cad66cfd43377,e909a8eea23c1563cfbdb5db40c8a00ef1a2f04e -108008,Sony PlayStation Portable,Yu-Gi-Oh! Duel Monsters GX Tag Force,遊戯王デュエルモンスターズGX タッグフォース,Games,Japan,ULJM 05151,1.02,739508224,111eda24,1b1519daf589530421cdf7214808d380,ddc04e39101764eb1c262e810df447fbaf457656 -108009,Sony PlayStation Portable,Tekken 6,철권6,Games,Korea,ULKS 46235,1.00,855638016,8a9a8977,11db76eebe2dc10df5060030548dc955,3e7170029fc98e8710dec3ccad812f840ab16c33 -108010,Sony PlayStation Portable,Tekken 6,철권6,Games,Asia,ULAS 42214,1.00,855638016,4fc46387,282a42c539f8b0c9967f6d9801d196f8,40b09ac6e0d1371f3a4309671584bdecdc571845 -108023,Sony PlayStation Portable,FIFA Soccer 12,,Games,Canada,ULUS 10587,1.00,1619001344,b2ea6fc9,d54e8303e149c1a5b30a55b415835582,f46f4bd7d1f535f50cc4d95be2d7c28a06ce5d4b -108024,Sony PlayStation Portable,Tony Hawk's Underground 2 Remix,,Games,France,ULES-00034,1.03,1257537536,1623f9c0,03e551c2c8b54636078aad125d001a5a,6ea986f2a958e4f11d12d62c799e965c673d3cbd -108025,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,,Games,Scandinavia,UCES-01453,1.00,907640832,86660f92,1906b36bb49ce8fd7c19b0da73a29689,0b9a93b705ea930af7e2af0bbf312574b85f83c5 -108026,Sony PlayStation Portable,Persona 2: Batsu: Eternal Punishment,ペルソナ2 罰,Games,Japan,ULJM 06081,1.00,1297285120,93c35b9b,124e4a453afed1946873912823716b84,99ac0ea50e0789582cdfc053a8604944c98603da -108057,Sony PlayStation Portable,Daxter,,Preproduction,USA,UCUS-98618,0.40,1402667008,00ce2158,1ba454a45482c8dc61d52a76d17bb5b4,c844ee1490653cc346a11a7b75c4e1956a7f8d35 -108059,Sony PlayStation Portable,Secret Agent Clank,Clank: Agente-Secreto,Preproduction,Europe,UCET-01101,0.01,1626603520,03dd0e92,7aebf0176e81d8c70e95287735461aba,aefaf0b2ffde55e5e6bc526f00c3510d79dc124e -108060,Sony PlayStation Portable,Frantix,,Preproduction,USA,,1.00,405536768,b23268e8,a9cda8a58d74d6e19c7c6d4f1dd6b07c,784e39991fb5e14fa7c33dba83c2e66c14dc605b -108341,Sony PlayStation Portable,Issho ni Gohan. Portable,いっしょにごはん。ポータブル,Games,Japan,ULJM 06231,1.01,1019478016,030635c0,cfb92a348a8f15cf0d37cfee6fa3445b,74b13bce1ce8a7ac498a9ad0b4fbe6b236bed87a -108342,Sony PlayStation Portable,Buzz! Quiz World,Buzz!: Мировой турнир / Buzz!: Svijet Kviza,Games,Europe,UCES-01296,1.00,1485275136,62128317,9c76eab8b8b907630d74e4dc9a1d5bf2,36d087a3dafec665520692fd5dceb12fef078186 -108343,Sony PlayStation Portable,FIFA Soccer 11,,Games,Canada,ULUS 10545,1.00,1704427520,4f56f251,b6054f76aca22a255bb235bed91a8e9c,fce8f82c3d3eade23eb0884136aa245026db568e -108347,Sony PlayStation Portable,Killzone: Liberation,,Preproduction,USA,UCUS-98646,0.10,375488512,cc9aac7d,5d074458bf7569642a2a4daef3ea8188,48f3168dd50fd09385eec77fb1a4ae254acfb28c -108408,Sony PlayStation Portable,Memories Off #5: Togireta Film,メモリーズオフ#5 とぎれたフィルム,Games,Japan,ULJM 05394,1.01,1101660160,5706210b,0bd5c9b3db5969953752c618e8cdbdf5,b1a1258247014ddb160d7c1f6af03d5b5c3b4734 -108409,Sony PlayStation Portable,Memories Off: Sorekara,メモリーズオフ ~それから~,Games,Japan,ULJM 05594,1.01,1588101120,da3c0df9,98078383924bc077ffe84d634c2930f6,5f3b7fd8238c20944fd38410e16b839ca968d27a -108412,Sony PlayStation Portable,Steins;Gate: Hiyoku Renri no Darling,シュタインズ・ゲート 比翼愛理のだーりん,Games,Japan,ULJM 06040,1.02,1377959936,64a5777f,c56fb4e53e815402fb0fbe69748a44a2,1c9c356e373c84200f75a1315cec8831d731dcb2 -108413,Sony PlayStation Portable,Gintama no Sugoroku,銀魂のすごろく,Games,Japan,ULJS 00559,1.00,900235264,bb73d659,5c43da432fa4d6cbefc155c135131ac7,f7d559b6196925492ba9226de646a4eccde09847 -108414,Sony PlayStation Portable,Summon Night 4,サモンナイト4,Games,Japan,ULJS 00375,2.00,1556021248,673257d8,a486b6f61b1f67aa346aedcb2613de4b,5dbcb2f90cad30ac889efe881c579d661a7cb504 -108415,Sony PlayStation Portable,Sengoku Efuda Yuugi: Hototogisu Ran,戦国絵札遊戯 不如帰 乱,Games,Japan,ULJS 00159,1.02,467140608,5b29c36d,ef89cdfb816824bca12f1f61884de527,c1bf1db6d9c201f442eddb13ef8b068f9bf6a714 -108451,Sony PlayStation Portable,Sangokushi VI,三國志Ⅵ,Games,Japan,ULJM 05038,1.02,186548224,711c60d9,db928e74095ff39117754a94d598e1d3,5d7b8e68db97a3f3b87f3642e0379d784cb940ff -108452,Sony PlayStation Portable,NBA Live 08,NBAライブ08,Games,Japan,ULJM 05289,1.01,1616150528,996cdf2b,eabbc47f1addeaf13f191d65b4837e90,6618f3b327e1f6e132e7dff8f5f3c1f5170bc36e -108453,Sony PlayStation Portable,Chuumon Shiyouze! Oretachi no Sekai,注文しようぜ!俺たちの世界,Games,Japan,ULJM 05381,1.01,176128000,69bec625,4db573f6043ddac0d4af7ced8613ff14,b991dd09dbea377f545a58c1e79b5a5d1c8d4a03 -108454,Sony PlayStation Portable,Katekyoo Hitman Reborn! Battle Arena,家庭教師ヒットマンREBORN!バトルアリーナ,Games,Japan,ULJS 00157,1.01,395640832,41dbb3cc,8e2c90aa4b6be666bb1c3da28b51fc64,a5865ba97672ac44948449a90c365128f54a9291 -108455,Sony PlayStation Portable,Suzumiya Haruhi no Tsuisou,涼宮ハルヒの追想,Games,Japan,ULJS 00371,1.02,1418821632,41e84d24,861b7475a2568c4cd043d7dc35015f9c,eeec66a24af198d1f2216d6a2649ba1811a68ff0 -108456,Sony PlayStation Portable,Buzz! The Ultimate Music Quiz,Buzz! Το Απόλυτο Μουσικό Quiz,Games,Greece,UCES-01485,1.02,907706368,8e474768,411e4bbbda9a19117f615ef1da509090,bf11756ddea81b39cb658fe67775af1f2557dcbd -108457,Sony PlayStation Portable,Disney/Pixar Up,Ψηλα Στον Ουρανο,Games,Greece,ULES-01259,1.00,525926400,8ceaa057,e2e6af229636d8fea6bed7d9058bf0f5,2245f51ce1c2efada66305b40add17edcc44b995 -108701,Sony PlayStation Portable,Kingdom of Paradise,,Preproduction,USA,,0.20,1081573376,f24428d7,cd75581de66886f429d46a4c0001a0a6,5e79cc375e51cf9cc41adf92dc7d8398400ef23a -108702,Sony PlayStation Portable,Arthur and the Invisibles,Arthur & the Invisibles,Preproduction,USA,ULUS-10231,1.04,1776680960,635ecbe3,02fd1351eae6b789625b238d12fbbc5c,af38a7e5b664b6111999ff724c0d5dddf5075dce -108957,Sony PlayStation Portable,Umezawa Yukari no Yasashii Igo,梅沢由香里のやさしい囲碁,Games,Japan,ULJM 05805,1.01,66650112,a8c32664,f649d277167f6f166624c8aae2d12926,704023fbb18700e38c7f447b176a4038bacb179f -108958,Sony PlayStation Portable,Eiyuu Densetsu Gagharv Trilogy: Akai Shizuku,英雄伝説 ガガーブトリロジー 朱紅い雫,Games,Japan,ULJS 19027,1.01,753893376,fa67281f,b609202987ff2e537d98e9f22c8ce0bd,d4c4ef2658f80a5eef45d566a82e0c11605bc3bb -108959,Sony PlayStation Portable,Eiyuu Densetsu Gagharv Trilogy: Umi no Oriuta,英雄伝説 ガガーブトリロジー 海の檻歌,Games,Japan,ULJS 19028,1.02,872185856,f6485984,7ae35e3e9f027f286402e2fa2967c621,bfb7d84c99e294abfa0af3bab490601b98094309 -108967,Sony PlayStation Portable,Buzz! Quiz World,,Games,Europe,UCES-01294,1.00,1437532160,765c6b5d,91f41c14544968dc21dae3a54536b19f,66cd4689a2ca09e41b65ce716a7b96deeceeb3ec -108968,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Bilar,Games,Sweden,ULES-00327,1.00,906362880,8fbbd22d,358a9071fa61ad693b26eba57ed78067,32d7717755c1b001d00d26534e2c86a34db29275 -108969,Sony PlayStation Portable,Disney/Pixar Cars,Disney/Pixar Autot,Games,Finland,ULES-00329,1.00,906362880,c97e76ca,e48e787252654b2470eea81cde6c13be,442515f65fd3e7dd79bd0774a92b6a063344d168 -108970,Sony PlayStation Portable,Go!Explore,,Applications,Scandinavia,UCES-00883,1.01,906362880,561273f7,9b5903c235fa42946a43629558fa3675,42e27d77cf6b213d052cbd49cd74f66f6e76aaf8 -108971,Sony PlayStation Portable,Disney/Pixar Ratatouille,Disney/Pixar Råttatouille,Games,Sweden,ULES-00746,1.00,906362880,5f379f45,6629d9f23123914f486630b0203ab387,bb8efe55acd493a24c40604ded3d773636559abe -108972,Sony PlayStation Portable,Disney/Pixar WALL-E,,Games,Sweden,ULES-01074,1.00,773193728,861f8e1a,833cf13d29b6ec24a656c804b19856b8,a4dac8970c48d2bda227c684a8f6b41a3b34faff diff --git a/assets/sfx_achievement_unlocked.wav b/assets/sfx_achievement_unlocked.wav deleted file mode 100644 index e98228e11..000000000 Binary files a/assets/sfx_achievement_unlocked.wav and /dev/null differ diff --git a/assets/sfx_leaderbord_submitted.wav b/assets/sfx_leaderbord_submitted.wav deleted file mode 100644 index 5544fef32..000000000 Binary files a/assets/sfx_leaderbord_submitted.wav and /dev/null differ diff --git a/assets/shaders/bloomnoblur.fsh b/assets/shaders/bloomnoblur.fsh deleted file mode 100644 index 812af8bff..000000000 --- a/assets/shaders/bloomnoblur.fsh +++ /dev/null @@ -1,43 +0,0 @@ -// Simple Bloom shader; created to use in PPSSPP. -// Without excessive samples and complex nested loops -// (to make it compatible with low-end GPUs and to ensure ps_2_0 compatibility). - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D sampler0; -varying vec2 v_texcoord0; - -uniform vec4 u_setting; - -void main() -{ - //get the pixel color - vec3 color = texture2D(sampler0, v_texcoord0.xy).xyz; - gl_FragColor.rgb = color; - float gray = (color.r + color.g + color.b) / 3.0; - float saturation = (abs(color.r - gray) + abs(color.g - gray) + abs(color.b - gray)) / 3.0; - - //show the effect mainly on bright parts of the screen - float step = 0.001 * gray / max(saturation, 0.25) * u_setting.x; - - //sum the neightbor pixels - vec3 sum = vec3(0); - for (int x = -3; x <= 3; x += 2) - { - for (int y = -3; y <= 3; y += 2) - { - color = texture2D(sampler0, v_texcoord0 + vec2(x, y)*step).xyz; - gray = (color.r + color.g + color.b) / 3.0; - saturation = (abs(color.r - gray) + abs(color.g - gray) + abs(color.b - gray)) / 3.0; - sum += color * gray * gray / max(saturation, 0.25); - } - } - sum /= 16.0; - - //mix the color - gl_FragColor.rgb += sum * u_setting.y; - gl_FragColor.a = 1.0; -} diff --git a/assets/shaders/defaultshaders.ini b/assets/shaders/defaultshaders.ini index 8b80d1dc0..b7cd26873 100644 --- a/assets/shaders/defaultshaders.ini +++ b/assets/shaders/defaultshaders.ini @@ -38,18 +38,6 @@ SettingDefaultValue2=1.0 SettingMaxValue2=2.0 SettingMinValue2=0.5 SettingStep2=0.1 -[FakeReflections] -Name=Fake Reflections -Fragment=fakereflections.fsh -Vertex=fxaa.vsh -SettingName1=Amount -SettingDefaultValue1=0.6 -SettingMaxValue1=1.0 -SettingMinValue1=0.0 -SettingName2=Power -SettingDefaultValue2=0.5 -SettingMaxValue2=1.0 -SettingMinValue2=0.0 [Bloom] Name=Bloom Shader Fragment=bloom.fsh @@ -62,18 +50,6 @@ SettingName2=Power SettingDefaultValue2=0.5 SettingMaxValue2=1.0 SettingMinValue2=0.0 -[BloomNoBlur] -Name=Bloom (no blur) -Fragment=bloomnoblur.fsh -Vertex=fxaa.vsh -SettingName1=Amount -SettingDefaultValue1=0.6 -SettingMaxValue1=1.0 -SettingMinValue1=0.0 -SettingName2=Power -SettingDefaultValue2=0.5 -SettingMaxValue2=1.0 -SettingMinValue2=0.0 [Sharpen] Name=Sharpen Fragment=sharpen.fsh diff --git a/assets/shaders/fakereflections.fsh b/assets/shaders/fakereflections.fsh deleted file mode 100644 index b2302edd9..000000000 --- a/assets/shaders/fakereflections.fsh +++ /dev/null @@ -1,36 +0,0 @@ -// Simple fake reflection shader; created to use in PPSSPP. -// Without excessive samples and complex nested loops -// (to make it compatible with low-end GPUs and to ensure ps_2_0 compatibility). - -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D sampler0; -varying vec2 v_texcoord0; - -uniform vec4 u_setting; - -void main() -{ - //get the pixel color - vec3 color = texture2D(sampler0, v_texcoord0.xy).rgb; - float gray = (color.r + color.g + color.b) / 3.0; - float saturation = (abs(color.r - gray) + abs(color.g - gray) + abs(color.b - gray)) / 3.0; - - //persistent random offset to hide that the reflection is wrong - float rndx = mod(v_texcoord0.x + gray, 0.03) + mod(v_texcoord0.y + saturation, 0.05); - float rndy = mod(v_texcoord0.y + saturation, 0.03) + mod(v_texcoord0.x + gray, 0.05); - - //show the effect mainly on the bottom part of the screen - float step = (max(gray, saturation) + 0.1) * v_texcoord0.y; - - //the fake reflection is just a watered copy of the frame moved slightly lower - vec3 reflection = texture2D(sampler0, v_texcoord0 + vec2(rndx, rndy - min(v_texcoord0.y, 0.25)) * step).rgb; - - //apply parameters and mix the colors - reflection *= 4.0 * (1.0 - gray) * u_setting.x; - reflection *= reflection * step * u_setting.y; - gl_FragColor = vec4(color + reflection, 1.0); -} diff --git a/assets/ui_atlas.meta b/assets/ui_atlas.meta index 83517b60b..88c386e49 100644 Binary files a/assets/ui_atlas.meta and b/assets/ui_atlas.meta differ diff --git a/assets/ui_atlas.zim b/assets/ui_atlas.zim index 15b934c5d..465d54e6f 100644 Binary files a/assets/ui_atlas.zim and b/assets/ui_atlas.zim differ diff --git a/build.gradle b/build.gradle index 84b95f31b..7a9290a97 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.4' + classpath 'com.android.tools.build:gradle:8.0.0' } } diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 1031f6edf..e2b0f44a8 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -30,12 +30,6 @@ add_subdirectory(glslang EXCLUDE_FROM_ALL) add_subdirectory(snappy) add_subdirectory(udis86) add_subdirectory(SPIRV-Cross-build) -add_subdirectory(rcheevos-build) -if(NOT HTTPS_NOT_AVAILABLE) - add_subdirectory(naett-build) -endif() if(USE_DISCORD AND NOT IOS AND NOT LIBRETRO) add_subdirectory(discord-rpc-build) endif() - -add_subdirectory(libchdr-build) diff --git a/ext/cmake/cpu_features/CMakeLists.txt b/ext/cmake/cpu_features/CMakeLists.txt index 5524191d0..31446d908 100644 --- a/ext/cmake/cpu_features/CMakeLists.txt +++ b/ext/cmake/cpu_features/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.0) # option() honors normal variables. # see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html @@ -51,15 +51,14 @@ set(PROCESSOR_IS_X86 FALSE) set(PROCESSOR_IS_POWER FALSE) set(PROCESSOR_IS_S390X FALSE) set(PROCESSOR_IS_RISCV FALSE) -set(PROCESSOR_IS_LOONGARCH FALSE) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") set(PROCESSOR_IS_MIPS TRUE) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(^arm64)|(^ARM64)") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)") set(PROCESSOR_IS_AARCH64 TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") set(PROCESSOR_IS_ARM TRUE) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(x86_64)|(AMD64|amd64)|(^i.86$)") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)") set(PROCESSOR_IS_X86 TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") set(PROCESSOR_IS_POWER TRUE) @@ -67,8 +66,6 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)") set(PROCESSOR_IS_S390X TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv") set(PROCESSOR_IS_RISCV TRUE) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^loongarch") - set(PROCESSOR_IS_LOONGARCH TRUE) endif() macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) @@ -82,7 +79,6 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/cpuinfo_arm.h) elseif(PROCESSOR_IS_AARCH64) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/cpuinfo_aarch64.h) - list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/internal/windows_utils.h) elseif(PROCESSOR_IS_X86) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/cpuinfo_x86.h) list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/internal/cpuid_x86.h) @@ -93,8 +89,6 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/cpuinfo_s390x.h) elseif(PROCESSOR_IS_RISCV) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/cpuinfo_riscv.h) - elseif(PROCESSOR_IS_LOONGARCH) - list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/../../cpu_features/include/cpuinfo_loongarch.h) else() message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}") endif() @@ -148,14 +142,14 @@ endif() add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS}) set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}") setup_include_and_definitions(cpu_features) -if(NOT USE_LIBNX) - target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS}) -endif() +target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS}) target_include_directories(cpu_features PUBLIC $ ) -if(APPLE) - target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME) +if(PROCESSOR_IS_X86) + if(APPLE) + target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME) + endif() endif() add_library(CpuFeature::cpu_features ALIAS cpu_features) diff --git a/ext/cpu_features b/ext/cpu_features index fd4ffc163..75ec98818 160000 --- a/ext/cpu_features +++ b/ext/cpu_features @@ -1 +1 @@ -Subproject commit fd4ffc1632db7b4e763bd28ffa6fc9d761cf3587 +Subproject commit 75ec988188f62281efe7bf1d133338751369bb4c diff --git a/ext/cpu_features.vcxproj b/ext/cpu_features.vcxproj index d5bb23427..a0eddbd86 100644 --- a/ext/cpu_features.vcxproj +++ b/ext/cpu_features.vcxproj @@ -359,7 +359,6 @@ - diff --git a/ext/cpu_features.vcxproj.filters b/ext/cpu_features.vcxproj.filters index 9deba5386..b3ea5f445 100644 --- a/ext/cpu_features.vcxproj.filters +++ b/ext/cpu_features.vcxproj.filters @@ -111,9 +111,6 @@ Source Files - - Source Files - Source Files diff --git a/ext/glew/CMakeLists.txt b/ext/glew/CMakeLists.txt index 317b4b231..3b242d9ff 100644 --- a/ext/glew/CMakeLists.txt +++ b/ext/glew/CMakeLists.txt @@ -1,23 +1,21 @@ find_package(GLEW) -if(NOT USE_LIBNX) - if((NOT APPLE OR USE_SYSTEM_FFMPEG) AND GLEW_FOUND) - add_library(system_glew INTERFACE) - add_library(Ext::GLEW ALIAS system_glew) - target_link_libraries(system_glew INTERFACE GLEW::GLEW) - else() - find_package(OpenGL REQUIRED) - add_library(glew STATIC - GL/glew.h - GL/glxew.h - GL/wglew.h - glew.c - ) - add_library(Ext::GLEW ALIAS glew) - target_link_libraries(glew PUBLIC ${OPENGL_LIBRARIES}) - target_compile_definitions(glew PUBLIC GLEW_STATIC) - target_include_directories(glew PUBLIC . ${OPENGL_INCLUDE_DIR}) - set_target_properties(glew PROPERTIES - EXCLUDE_FROM_ALL ON - ) - endif() +if((NOT APPLE OR USE_SYSTEM_FFMPEG) AND GLEW_FOUND) + add_library(system_glew INTERFACE) + add_library(Ext::GLEW ALIAS system_glew) + target_link_libraries(system_glew INTERFACE GLEW::GLEW) +else() + find_package(OpenGL REQUIRED) + add_library(glew STATIC + GL/glew.h + GL/glxew.h + GL/wglew.h + glew.c + ) + add_library(Ext::GLEW ALIAS glew) + target_link_libraries(glew PUBLIC ${OPENGL_LIBRARIES}) + target_compile_definitions(glew PUBLIC GLEW_STATIC) + target_include_directories(glew PUBLIC . ${OPENGL_INCLUDE_DIR}) + set_target_properties(glew PROPERTIES + EXCLUDE_FROM_ALL ON + ) endif() diff --git a/ext/libchdr b/ext/libchdr deleted file mode 160000 index 9108f34a8..000000000 --- a/ext/libchdr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9108f34a892272f61c3ed3bff4bee728d4c1dd57 diff --git a/ext/libchdr-build/CMakeLists.txt b/ext/libchdr-build/CMakeLists.txt deleted file mode 100644 index 336d2e63e..000000000 --- a/ext/libchdr-build/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -cmake_minimum_required (VERSION 3.2.0) -project (chdr) - -set(LZMA_DIR ../libchdr/deps/lzma-22.01/src) -set(SRC_DIR ../libchdr/src) - -include_directories(../libchdr/deps/lzma-22.01/include) -include_directories(../libchdr/include) -include_directories(../zlib) - -add_definitions(-D_7ZIP_ST) - -# Hack - CpuArch.c has a workaround that we reuse. -add_definitions(-D__SWITCH__) - -set(ALL_SOURCE_FILES - ${LZMA_DIR}/Alloc.c - ${LZMA_DIR}/Bcj2.c - ${LZMA_DIR}/Bcj2Enc.c - ${LZMA_DIR}/Bra.c - ${LZMA_DIR}/Bra86.c - ${LZMA_DIR}/CpuArch.c - ${LZMA_DIR}/Delta.c - ${LZMA_DIR}/LzFind.c - ${LZMA_DIR}/LzFindOpt.c - ${LZMA_DIR}/LzmaDec.c - ${LZMA_DIR}/LzmaEnc.c - ${LZMA_DIR}/Lzma86Dec.c - ${LZMA_DIR}/Lzma86Enc.c - ${LZMA_DIR}/LzmaLib.c - ${LZMA_DIR}/Sort.c - ${SRC_DIR}/libchdr_bitstream.c - ${SRC_DIR}/libchdr_cdrom.c - ${SRC_DIR}/libchdr_chd.c - ${SRC_DIR}/libchdr_flac.c - ${SRC_DIR}/libchdr_huffman.c - ) - -add_library(chdr STATIC ${ALL_SOURCE_FILES}) diff --git a/ext/libchdr.vcxproj b/ext/libchdr.vcxproj deleted file mode 100644 index 89d56f3fb..000000000 --- a/ext/libchdr.vcxproj +++ /dev/null @@ -1,374 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {956F1F48-B612-46D8-89EE-96996DCD9383} - Win32Proj - libchdr - libchdr_static - Unicode - StaticLibrary - $(SolutionDir)..\ext\libchdr\bin\$(Platform)_$(Configuration)\ - $(SolutionDir)..\ext\libchdr\bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - 10.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(DefaultPlatformToolset) - - - true - $(DefaultPlatformToolset) - - - true - $(DefaultPlatformToolset) - - - true - $(DefaultPlatformToolset) - - - false - true - $(DefaultPlatformToolset) - - - false - true - $(DefaultPlatformToolset) - - - false - true - $(DefaultPlatformToolset) - - - false - true - $(DefaultPlatformToolset) - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath); - false - - - true - $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath); - false - - - false - $(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath); - false - - - - $(OutDir)$(TargetName).pdb - - - - - - - Level4 - _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - true - ProgramDatabase - false - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - MachineX86 - - - - - - - Level4 - _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - ProgramDatabase - false - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - - - - - - - Level4 - _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - ProgramDatabase - false - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - - - - - - - Level4 - _7ZIP_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - ProgramDatabase - false - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - - - - - Level4 - - - MaxSpeed - true - true - _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - MultiThreaded - true - ProgramDatabase - AnySuitable - Speed - true - false - StreamingSIMDExtensions2 - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - true - true - MachineX86 - - - - - Level4 - - - MaxSpeed - true - true - _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - false - MultiThreaded - true - ProgramDatabase - false - true - AnySuitable - Speed - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - false - MultiThreaded - true - ProgramDatabase - false - true - AnySuitable - Speed - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - _7ZIP_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - false - false - MultiThreaded - true - ProgramDatabase - false - true - AnySuitable - Speed - libchdr\include;libchdr\deps\lzma-22.01\include;zlib; - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/ext/libchdr.vcxproj.filters b/ext/libchdr.vcxproj.filters deleted file mode 100644 index d35dd7e48..000000000 --- a/ext/libchdr.vcxproj.filters +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - LZMA - - - - - - - - - - - - - - {ff31581b-3ff9-4e39-bb96-2f662896cf70} - - - \ No newline at end of file diff --git a/ext/libkirk/SHA1.c b/ext/libkirk/SHA1.c index 5d904d563..3a676bc60 100644 --- a/ext/libkirk/SHA1.c +++ b/ext/libkirk/SHA1.c @@ -138,8 +138,9 @@ void SHAInit(SHA_CTX *shsInfo) Note that this corrupts the shsInfo->data area */ -static void SHSTransform( UINT4 *digest, UINT4 *data ) -{ +static void SHSTransform( digest, data ) + UINT4 *digest, *data ; + { UINT4 A, B, C, D, E; /* Local vars */ UINT4 eData[ 16 ]; /* Expanded data */ diff --git a/ext/libzip/zip_source_file_win32_utf16.c b/ext/libzip/zip_source_file_win32_utf16.c index e77da8096..4b32ac3a7 100644 --- a/ext/libzip/zip_source_file_win32_utf16.c +++ b/ext/libzip/zip_source_file_win32_utf16.c @@ -41,29 +41,6 @@ static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); static char *utf16_strdup(const char *string); -#ifdef MS_UWP -static BOOL __stdcall GetFileAttr(const void* name, GET_FILEEX_INFO_LEVELS info_level, void* lpFileInformation) { - BOOL state = GetFileAttributesExFromAppW(name, info_level, lpFileInformation); - return state; -} - -static BOOL __stdcall DelFile(const void* name) { - BOOL state = DeleteFileFromAppW(name); - return state; -} - -zip_win32_file_operations_t ops_utf16 = { - utf16_allocate_tempname, - utf16_create_file, - DelFile, - GetFileAttributesW, - GetFileAttr, - utf16_make_tempname, - MoveFileExW, - SetFileAttributesW, - utf16_strdup -}; -#else zip_win32_file_operations_t ops_utf16 = { utf16_allocate_tempname, utf16_create_file, @@ -75,7 +52,6 @@ zip_win32_file_operations_t ops_utf16 = { SetFileAttributesW, utf16_strdup }; -#endif ZIP_EXTERN zip_source_t * zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) { diff --git a/ext/naett b/ext/naett deleted file mode 160000 index cd717c2d0..000000000 --- a/ext/naett +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cd717c2d04eee6fc86c5efc8b3012854a1d66902 diff --git a/ext/naett-build/CMakeLists.txt b/ext/naett-build/CMakeLists.txt deleted file mode 100644 index 6b3b48934..000000000 --- a/ext/naett-build/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -cmake_minimum_required (VERSION 3.2.0) -project (naett) - -set(SRC_DIR ../naett) - -set(ALL_SOURCE_FILES - ${SRC_DIR}/naett.c - ) - -add_library(naett STATIC ${ALL_SOURCE_FILES}) diff --git a/ext/native/tools/atlastool.cpp b/ext/native/tools/atlastool.cpp index 5833b90d2..080e313bb 100644 --- a/ext/native/tools/atlastool.cpp +++ b/ext/native/tools/atlastool.cpp @@ -294,7 +294,7 @@ struct Bucket { printf("PACKING FAIL : height=%i", (int)dest.dat.size()); exit(1); } - dest.resize(image_width, (int)dest.dat.size()); + dest.resize(image_width, NextPowerOf2((int)dest.dat.size())); // Output the glyph data. vector dats; diff --git a/ext/openxr/android/arm64-v8a/libopenxr_meta.so b/ext/openxr/android/arm64-v8a/libopenxr_meta.so index 6bc79cb2b..7b615830f 100755 Binary files a/ext/openxr/android/arm64-v8a/libopenxr_meta.so and b/ext/openxr/android/arm64-v8a/libopenxr_meta.so differ diff --git a/ext/openxr/android/arm64-v8a/libopenxr_pico.so b/ext/openxr/android/arm64-v8a/libopenxr_pico.so index f24e9e8ea..c93b4e444 100644 Binary files a/ext/openxr/android/arm64-v8a/libopenxr_pico.so and b/ext/openxr/android/arm64-v8a/libopenxr_pico.so differ diff --git a/ext/rcheevos b/ext/rcheevos deleted file mode 160000 index 6fb3ebca2..000000000 --- a/ext/rcheevos +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6fb3ebca22fe4f3a97e7a391e5e9c4623aa2286a diff --git a/ext/rcheevos-build/CMakeLists.txt b/ext/rcheevos-build/CMakeLists.txt deleted file mode 100644 index cf29f3a59..000000000 --- a/ext/rcheevos-build/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -cmake_minimum_required (VERSION 3.2.0) -project (RCheevos) - -set(SRC_DIR ../rcheevos/src) - -# format -set(ALL_SOURCE_FILES - # rapi - ${SRC_DIR}/rapi/rc_api_common.c - ${SRC_DIR}/rapi/rc_api_common.h - ${SRC_DIR}/rapi/rc_api_editor.c - ${SRC_DIR}/rapi/rc_api_info.c - ${SRC_DIR}/rapi/rc_api_runtime.c - ${SRC_DIR}/rapi/rc_api_user.c - # rcheevos - ${SRC_DIR}/rcheevos/alloc.c - ${SRC_DIR}/rcheevos/condition.c - ${SRC_DIR}/rcheevos/condset.c - ${SRC_DIR}/rcheevos/consoleinfo.c - ${SRC_DIR}/rcheevos/format.c - ${SRC_DIR}/rcheevos/lboard.c - ${SRC_DIR}/rcheevos/memref.c - ${SRC_DIR}/rcheevos/operand.c - ${SRC_DIR}/rc_compat.h - ${SRC_DIR}/rc_compat.h - ${SRC_DIR}/rc_compat.c - ${SRC_DIR}/rc_util.h - ${SRC_DIR}/rc_util.c - ${SRC_DIR}/rc_client.c - ${SRC_DIR}/rc_client_internal.h - ${SRC_DIR}/rc_version.h - ${SRC_DIR}/rcheevos/rc_internal.h - ${SRC_DIR}/rcheevos/rc_validate.h - ${SRC_DIR}/rcheevos/rc_validate.c - ${SRC_DIR}/rcheevos/richpresence.c - ${SRC_DIR}/rcheevos/runtime.c - ${SRC_DIR}/rcheevos/runtime_progress.c - ${SRC_DIR}/rcheevos/trigger.c - ${SRC_DIR}/rcheevos/value.c - # rhash - ${SRC_DIR}/rhash/cdreader.c - ${SRC_DIR}/rhash/hash.c - ${SRC_DIR}/rhash/md5.c - ${SRC_DIR}/rhash/md5.h - ) - -add_library(rcheevos STATIC ${ALL_SOURCE_FILES}) - -target_compile_definitions(rcheevos PUBLIC RC_DISABLE_LUA) -target_include_directories(rcheevos PUBLIC ../rcheevos/include ../rcheevos/src/rapi) diff --git a/ext/rcheevos-build/rcheevos.vcxproj b/ext/rcheevos-build/rcheevos.vcxproj deleted file mode 100644 index 066ccf5b7..000000000 --- a/ext/rcheevos-build/rcheevos.vcxproj +++ /dev/null @@ -1,370 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16.0 - Win32Proj - {31694510-a8c0-40f6-b09b-e8df825adefa} - rcheevos - - - - StaticLibrary - true - $(DefaultPlatformToolset) - Unicode - - - StaticLibrary - true - $(DefaultPlatformToolset) - Unicode - - - StaticLibrary - false - false - Unicode - $(DefaultPlatformToolset) - - - StaticLibrary - false - false - Unicode - $(DefaultPlatformToolset) - - - StaticLibrary - true - $(DefaultPlatformToolset) - Unicode - - - StaticLibrary - true - $(DefaultPlatformToolset) - Unicode - - - StaticLibrary - false - false - Unicode - $(DefaultPlatformToolset) - - - StaticLibrary - false - false - Unicode - $(DefaultPlatformToolset) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - RC_DISABLE_LUA;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - StreamingSIMDExtensions2 - Precise - Default - true - false - MultiThreadedDebug - - - - - true - - - - - Level3 - RC_DISABLE_LUA;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - false - NotSet - Precise - true - false - MultiThreadedDebug - - - - - true - - - - - Level3 - MaxSpeed - true - true - RC_DISABLE_LUA;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - StreamingSIMDExtensions2 - false - Precise - Speed - AnySuitable - true - MultiThreaded - - - - - true - true - true - - - - - Level3 - MaxSpeed - true - true - RC_DISABLE_LUA;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - false - AnySuitable - Speed - false - NotSet - Precise - true - MultiThreaded - - - - - true - true - true - - - - - Level3 - true - RC_DISABLE_LUA;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - false - NotSet - Precise - Default - true - false - MultiThreadedDebug - - - - - true - - - - - Level3 - true - RC_DISABLE_LUA;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - false - NotSet - Precise - Default - true - false - MultiThreadedDebug - - - - - true - - - - - Level3 - MaxSpeed - true - true - RC_DISABLE_LUA;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - false - AnySuitable - Speed - false - NotSet - Precise - true - MultiThreaded - - - - - true - true - true - - - - - Level3 - MaxSpeed - true - true - RC_DISABLE_LUA;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - pch.h - ../rcheevos/include - false - AnySuitable - Speed - false - NotSet - Precise - true - MultiThreaded - - - - - true - true - true - - - - - - \ No newline at end of file diff --git a/ext/rcheevos-build/rcheevos.vcxproj.filters b/ext/rcheevos-build/rcheevos.vcxproj.filters deleted file mode 100644 index 0fcd76bec..000000000 --- a/ext/rcheevos-build/rcheevos.vcxproj.filters +++ /dev/null @@ -1,159 +0,0 @@ - - - - - {d69c6a56-d9c2-4b21-96af-7adc52a4e0ea} - - - {0acc1fc7-94ca-4eee-967e-5a64a884dbf1} - - - {55ec06aa-6d34-4edf-8b0b-f93f93a064b4} - - - {9e049d1f-4b83-4aa5-89f3-01a42e1773e2} - - - - - rapi - - - rapi - - - rapi - - - rapi - - - rapi - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - rhash - - - rhash - - - rhash - - - rcheevos - - - rcheevos - - - rcheevos - - - - - rapi - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - include - - - rcheevos - - - rcheevos - - - rhash - - - include - - - rcheevos - - - rcheevos - - - rcheevos - - - rcheevos - - - \ No newline at end of file diff --git a/ext/riscv-disas.cpp b/ext/riscv-disas.cpp index 816c985cc..282bfa77b 100644 --- a/ext/riscv-disas.cpp +++ b/ext/riscv-disas.cpp @@ -119,7 +119,7 @@ static const rvc_constraint rvcc_jal_j[] = { rvc_rd_eq_x0, rvc_end }; static const rvc_constraint rvcc_jal_jal[] = { rvc_rd_eq_ra, rvc_end }; static const rvc_constraint rvcc_jalr_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, rvc_end }; static const rvc_constraint rvcc_jalr_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, rvc_end }; -static const rvc_constraint rvcc_jalr_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, rvc_imm_eq_zero, rvc_end }; +static const rvc_constraint rvcc_jalr_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, rvc_end }; static const rvc_constraint rvcc_addi_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, rvc_imm_eq_zero, rvc_end }; static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc00, rvc_end }; static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, rvc_end }; @@ -674,49 +674,6 @@ const rv_opcode_data opcode_data[] = { { "fsflags", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, { "fsrmi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 }, { "fsflagsi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 }, - { "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "andn", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "bclr", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "bclri", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "bext", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "bexti", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "binv", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "binvi", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "bset", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "bseti", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "clmul", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "clmulh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "clmulr", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "clz", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "clzw", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "cpop", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "cpopw", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "ctz", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "ctzw", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "min", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "minu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "orc.b", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "orn", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "rev8", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "rol", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "ror", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "rori", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "roriw", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "sext.b", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "sext.h", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "sh1add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "sh1add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "sh2add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "sh2add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "sh3add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "sh3add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "slli.uw", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, - { "xnor", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, - { "zext.h", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -1134,18 +1091,6 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 1: switch (((inst >> 27) & 0b11111)) { case 0: op = rv_op_slli; break; - case 5: op = rv_op_bseti; break; - case 9: op = rv_op_bclri; break; - case 12: - switch (((inst >> 20) & 0b11111)) { - case 0: op = rv_op_clz; break; - case 1: op = rv_op_ctz; break; - case 2: op = rv_op_cpop; break; - case 4: op = rv_op_sext_b; break; - case 5: op = rv_op_sext_h; break; - } - break; - case 13: op = rv_op_binvi; break; } break; case 2: op = rv_op_slti; break; @@ -1154,20 +1099,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 5: switch (((inst >> 27) & 0b11111)) { case 0: op = rv_op_srli; break; - case 5: - switch (((inst >> 20) & 0b1111111)) { - case 7: op = rv_op_orc_b; break; - } - break; case 8: op = rv_op_srai; break; - case 9: op = rv_op_bexti; break; - case 12: op = rv_op_rori; break; - case 13: - switch (((inst >> 20) & 0b1111111)) { - case 24: if (isa == rv32) op = rv_op_rev8; break; - case 56: if (isa == rv64) op = rv_op_rev8; break; - } - break; } break; case 6: op = rv_op_ori; break; @@ -1181,22 +1113,12 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 1: switch (((inst >> 25) & 0b1111111)) { case 0: op = rv_op_slliw; break; - case 4: op = rv_op_slli_uw; break; - case 5: op = rv_op_slli_uw; break; - case 48: - switch (((inst >> 20) & 0b11111)) { - case 0: op = rv_op_clzw; break; - case 1: op = rv_op_ctzw; break; - case 2: op = rv_op_cpopw; break; - } - break; } break; case 5: switch (((inst >> 25) & 0b1111111)) { case 0: op = rv_op_srliw; break; case 32: op = rv_op_sraiw; break; - case 48: op = rv_op_roriw; break; } break; } @@ -1285,32 +1207,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 13: op = rv_op_divu; break; case 14: op = rv_op_rem; break; case 15: op = rv_op_remu; break; - case 36: - switch (((inst >> 20) & 0b11111)) { - case 0: if (isa == rv32) op = rv_op_zext_h; break; - } - break; - case 41: op = rv_op_clmul; break; - case 42: op = rv_op_clmulr; break; - case 43: op = rv_op_clmulh; break; - case 44: op = rv_op_min; break; - case 45: op = rv_op_minu; break; - case 46: op = rv_op_max; break; - case 47: op = rv_op_maxu; break; - case 130: op = rv_op_sh1add; break; - case 132: op = rv_op_sh2add; break; - case 134: op = rv_op_sh3add; break; - case 161: op = rv_op_bset; break; case 256: op = rv_op_sub; break; - case 260: op = rv_op_xnor; break; case 261: op = rv_op_sra; break; - case 262: op = rv_op_orn; break; - case 263: op = rv_op_andn; break; - case 289: op = rv_op_bclr; break; - case 293: op = rv_op_bext; break; - case 385: op = rv_op_rol; break; - case 389: op = rv_op_ror; break; - case 417: op = rv_op_binv; break; } break; case 13: op = rv_op_lui; break; @@ -1324,19 +1222,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 13: op = rv_op_divuw; break; case 14: op = rv_op_remw; break; case 15: op = rv_op_remuw; break; - case 32: op = rv_op_add_uw; break; - case 36: - switch (((inst >> 20) & 0b11111)) { - case 0: if (isa == rv64) op = rv_op_zext_h; break; - } - break; - case 130: op = rv_op_sh1add_uw; break; - case 132: op = rv_op_sh2add_uw; break; - case 134: op = rv_op_sh3add_uw; break; case 256: op = rv_op_subw; break; case 261: op = rv_op_sraw; break; - case 385: op = rv_op_rolw; break; - case 389: op = rv_op_rorw; break; } break; case 16: @@ -2308,7 +2195,7 @@ static void decode_inst_lift_pseudo(rv_decode *dec) static char *append(char *buf, const char *src, const char *end) { while (buf < end && *src) - *buf++ = *src++; + *buf++ = *src++; return buf; } diff --git a/ext/riscv-disas.h b/ext/riscv-disas.h index b7fcdfa50..ebf557174 100644 --- a/ext/riscv-disas.h +++ b/ext/riscv-disas.h @@ -524,49 +524,6 @@ typedef enum { rv_op_fsflags, rv_op_fsrmi, rv_op_fsflagsi, - rv_op_add_uw, - rv_op_andn, - rv_op_bclr, - rv_op_bclri, - rv_op_bext, - rv_op_bexti, - rv_op_binv, - rv_op_binvi, - rv_op_bset, - rv_op_bseti, - rv_op_clmul, - rv_op_clmulh, - rv_op_clmulr, - rv_op_clz, - rv_op_clzw, - rv_op_cpop, - rv_op_cpopw, - rv_op_ctz, - rv_op_ctzw, - rv_op_max, - rv_op_maxu, - rv_op_min, - rv_op_minu, - rv_op_orc_b, - rv_op_orn, - rv_op_rev8, - rv_op_rol, - rv_op_rolw, - rv_op_ror, - rv_op_rori, - rv_op_roriw, - rv_op_rorw, - rv_op_sext_b, - rv_op_sext_h, - rv_op_sh1add, - rv_op_sh1add_uw, - rv_op_sh2add, - rv_op_sh2add_uw, - rv_op_sh3add, - rv_op_sh3add_uw, - rv_op_slli_uw, - rv_op_xnor, - rv_op_zext_h, } rv_op; /* structures */ diff --git a/ext/vulkan/macOS/Frameworks/libMoltenVK.dylib b/ext/vulkan/macOS/Frameworks/libMoltenVK.dylib index 030887a60..0238f282d 100755 Binary files a/ext/vulkan/macOS/Frameworks/libMoltenVK.dylib and b/ext/vulkan/macOS/Frameworks/libMoltenVK.dylib differ diff --git a/ext/vulkan/vk_enum_string_helper.h b/ext/vulkan/vk_enum_string_helper.h new file mode 100644 index 000000000..ff6ab7eca --- /dev/null +++ b/ext/vulkan/vk_enum_string_helper.h @@ -0,0 +1,10830 @@ +// *** THIS FILE IS GENERATED - DO NOT EDIT *** +// See helper_file_generator.py for modifications + + +/*************************************************************************** + * + * Copyright (c) 2015-2023 The Khronos Group Inc. + * Copyright (c) 2015-2023 Valve Corporation + * Copyright (c) 2015-2023 LunarG, Inc. + * Copyright (c) 2015-2023 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Mark Lobodzinski + * Author: Courtney Goeltzenleuchter + * Author: Tobin Ehlis + * Author: Chris Forbes + * Author: John Zulauf + * Author: Tony Barbour + * + ****************************************************************************/ + + +#pragma once +#ifdef _MSC_VER +#pragma warning( disable : 4065 ) +#endif + +#include +#include + + +static inline const char* string_VkResult(VkResult input_value) +{ + switch (input_value) + { + case VK_ERROR_COMPRESSION_EXHAUSTED_EXT: + return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT"; + case VK_ERROR_DEVICE_LOST: + return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_EXTENSION_NOT_PRESENT: + return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: + return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: + return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_FRAGMENTATION: + return "VK_ERROR_FRAGMENTATION"; + case VK_ERROR_FRAGMENTED_POOL: + return "VK_ERROR_FRAGMENTED_POOL"; + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; + case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: + return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: + return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; + case VK_ERROR_INCOMPATIBLE_DRIVER: + return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_INITIALIZATION_FAILED: + return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: + return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE: + return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; + case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: + return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS"; + case VK_ERROR_INVALID_SHADER_NV: + return "VK_ERROR_INVALID_SHADER_NV"; + case VK_ERROR_LAYER_NOT_PRESENT: + return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_MEMORY_MAP_FAILED: + return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: + return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_ERROR_NOT_PERMITTED_KHR: + return "VK_ERROR_NOT_PERMITTED_KHR"; + case VK_ERROR_OUT_OF_DATE_KHR: + return "VK_ERROR_OUT_OF_DATE_KHR"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: + return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_OUT_OF_HOST_MEMORY: + return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_POOL_MEMORY: + return "VK_ERROR_OUT_OF_POOL_MEMORY"; + case VK_ERROR_SURFACE_LOST_KHR: + return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_ERROR_TOO_MANY_OBJECTS: + return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_UNKNOWN: + return "VK_ERROR_UNKNOWN"; + case VK_ERROR_VALIDATION_FAILED_EXT: + return "VK_ERROR_VALIDATION_FAILED_EXT"; + case VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR"; + case VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR"; + case VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR"; + case VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR"; + case VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR: + return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR"; + case VK_EVENT_RESET: + return "VK_EVENT_RESET"; + case VK_EVENT_SET: + return "VK_EVENT_SET"; + case VK_INCOMPLETE: + return "VK_INCOMPLETE"; + case VK_NOT_READY: + return "VK_NOT_READY"; + case VK_OPERATION_DEFERRED_KHR: + return "VK_OPERATION_DEFERRED_KHR"; + case VK_OPERATION_NOT_DEFERRED_KHR: + return "VK_OPERATION_NOT_DEFERRED_KHR"; + case VK_PIPELINE_COMPILE_REQUIRED: + return "VK_PIPELINE_COMPILE_REQUIRED"; + case VK_SUBOPTIMAL_KHR: + return "VK_SUBOPTIMAL_KHR"; + case VK_SUCCESS: + return "VK_SUCCESS"; + case VK_THREAD_DONE_KHR: + return "VK_THREAD_DONE_KHR"; + case VK_THREAD_IDLE_KHR: + return "VK_THREAD_IDLE_KHR"; + case VK_TIMEOUT: + return "VK_TIMEOUT"; + default: + return "Unhandled VkResult"; + } +} + +static inline const char* string_VkStructureType(VkStructureType input_value) +{ + switch (input_value) + { + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR"; + case VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC: + return "VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_APPLICATION_INFO: + return "VK_STRUCTURE_TYPE_APPLICATION_INFO"; + case VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2: + return "VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2"; + case VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT: + return "VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT"; + case VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2: + return "VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2"; + case VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT: + return "VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT"; + case VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD: + return "VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD"; + case VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV: + return "VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV"; + case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO: + return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO"; + case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO: + return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO"; + case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: + return "VK_STRUCTURE_TYPE_BIND_SPARSE_INFO"; + case VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR: + return "VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR"; + case VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2: + return "VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2"; + case VK_STRUCTURE_TYPE_BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT: + return "VK_STRUCTURE_TYPE_BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT"; + case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA: + return "VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA"; + case VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_BUFFER_COPY_2: + return "VK_STRUCTURE_TYPE_BUFFER_COPY_2"; + case VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO"; + case VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2: + return "VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2"; + case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER: + return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER"; + case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2: + return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2"; + case VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2: + return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2"; + case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO"; + case VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT: + return "VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT"; + case VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV: + return "VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV"; + case VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV: + return "VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO"; + case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT: + return "VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT"; + case VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR: + return "VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR"; + case VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR: + return "VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR"; + case VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2: + return "VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2"; + case VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2: + return "VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2"; + case VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM: + return "VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM"; + case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET: + return "VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET"; + case VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2: + return "VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2"; + case VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2: + return "VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2"; + case VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR: + return "VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR"; + case VK_STRUCTURE_TYPE_COPY_MEMORY_TO_MICROMAP_INFO_EXT: + return "VK_STRUCTURE_TYPE_COPY_MEMORY_TO_MICROMAP_INFO_EXT"; + case VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT: + return "VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT"; + case VK_STRUCTURE_TYPE_COPY_MICROMAP_TO_MEMORY_INFO_EXT: + return "VK_STRUCTURE_TYPE_COPY_MICROMAP_TO_MEMORY_INFO_EXT"; + case VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX: + return "VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX"; + case VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX: + return "VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX"; + case VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX: + return "VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX"; + case VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR: + return "VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEPENDENCY_INFO: + return "VK_STRUCTURE_TYPE_DEPENDENCY_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS: + return "VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS"; + case VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS: + return "VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS"; + case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD: + return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD"; + case VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2: + return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2"; + case VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG: + return "VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG"; + case VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG: + return "VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG"; + case VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD: + return "VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD"; + case VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT: + return "VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT"; + case VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: + return "VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT"; + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: + return "VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT"; + case VK_STRUCTURE_TYPE_EVENT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EVENT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT: + return "VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT"; + case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES"; + case VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES"; + case VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID: + return "VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID"; + case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES"; + case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES"; + case VK_STRUCTURE_TYPE_FENCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_FENCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3: + return "VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3"; + case VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV"; + case VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV: + return "VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV"; + case VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV: + return "VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV"; + case VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV: + return "VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV"; + case VK_STRUCTURE_TYPE_GEOMETRY_NV: + return "VK_STRUCTURE_TYPE_GEOMETRY_NV"; + case VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV: + return "VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV"; + case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_HDR_METADATA_EXT: + return "VK_STRUCTURE_TYPE_HDR_METADATA_EXT"; + case VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMAGE_BLIT_2: + return "VK_STRUCTURE_TYPE_IMAGE_BLIT_2"; + case VK_STRUCTURE_TYPE_IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMAGE_COPY_2: + return "VK_STRUCTURE_TYPE_IMAGE_COPY_2"; + case VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER: + return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER"; + case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2: + return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2"; + case VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2: + return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2"; + case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2: + return "VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2"; + case VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2: + return "VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2"; + case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: + return "VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID"; + case VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV: + return "VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV"; + case VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL: + return "VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL"; + case VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK: + return "VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK"; + case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK: + return "VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK"; + case VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE: + return "VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE"; + case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_BARRIER: + return "VK_STRUCTURE_TYPE_MEMORY_BARRIER"; + case VK_STRUCTURE_TYPE_MEMORY_BARRIER_2: + return "VK_STRUCTURE_TYPE_MEMORY_BARRIER_2"; + case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: + return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS"; + case VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: + return "VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID"; + case VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV: + return "VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV"; + case VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2: + return "VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2"; + case VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA: + return "VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA"; + case VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT: + return "VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT"; + case VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT: + return "VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT"; + case VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT: + return "VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT"; + case VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT: + return "VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT"; + case VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX: + return "VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX"; + case VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV: + return "VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV"; + case VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV: + return "VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV"; + case VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV: + return "VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV"; + case VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR: + return "VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR"; + case VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR: + return "VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR"; + case VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR: + return "VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR"; + case VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES"; + case VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD: + return "VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD"; + case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP: + return "VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP"; + case VK_STRUCTURE_TYPE_PRESENT_ID_KHR: + return "VK_STRUCTURE_TYPE_PRESENT_ID_KHR"; + case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: + return "VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR"; + case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE: + return "VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE"; + case VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO: + return "VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO"; + case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL: + return "VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT: + return "VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO: + return "VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO"; + case VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_RENDERING_INFO: + return "VK_STRUCTURE_TYPE_RENDERING_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2: + return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2"; + case VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: + return "VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM"; + case VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2: + return "VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2"; + case VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT: + return "VK_STRUCTURE_TYPE_SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT"; + case VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO"; + case VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT: + return "VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT"; + case VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX: + return "VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX"; + case VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO"; + case VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT: + return "VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT"; + case VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2: + return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2"; + case VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP: + return "VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP"; + case VK_STRUCTURE_TYPE_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_SUBMIT_INFO_2: + return "VK_STRUCTURE_TYPE_SUBMIT_INFO_2"; + case VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2: + return "VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2"; + case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2: + return "VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2"; + case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE: + return "VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE"; + case VK_STRUCTURE_TYPE_SUBPASS_END_INFO: + return "VK_STRUCTURE_TYPE_SUBPASS_END_INFO"; + case VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM: + return "VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM"; + case VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT: + return "VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT"; + case VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI: + return "VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI"; + case VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT: + return "VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV"; + case VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR: + return "VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR"; + case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA: + return "VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA"; + case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD: + return "VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD"; + case VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM: + return "VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM"; + case VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT: + return "VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT"; + case VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT: + return "VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT"; + case VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT: + return "VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT"; + case VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN: + return "VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN"; + case VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR: + return "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR"; + case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV: + return "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV"; + case VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK"; + case VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR"; + default: + return "Unhandled VkStructureType"; + } +} + +static inline const char* string_VkPipelineCacheHeaderVersion(VkPipelineCacheHeaderVersion input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CACHE_HEADER_VERSION_ONE: + return "VK_PIPELINE_CACHE_HEADER_VERSION_ONE"; + default: + return "Unhandled VkPipelineCacheHeaderVersion"; + } +} + +static inline const char* string_VkAccessFlagBits(VkAccessFlagBits input_value) +{ + switch (input_value) + { + case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR: + return "VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR"; + case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: + return "VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; + case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: + return "VK_ACCESS_COLOR_ATTACHMENT_READ_BIT"; + case VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: + return "VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; + case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV: + return "VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV"; + case VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV: + return "VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV"; + case VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT: + return "VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT"; + case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: + return "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT"; + case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: + return "VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; + case VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_HOST_READ_BIT: + return "VK_ACCESS_HOST_READ_BIT"; + case VK_ACCESS_HOST_WRITE_BIT: + return "VK_ACCESS_HOST_WRITE_BIT"; + case VK_ACCESS_INDEX_READ_BIT: + return "VK_ACCESS_INDEX_READ_BIT"; + case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: + return "VK_ACCESS_INDIRECT_COMMAND_READ_BIT"; + case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: + return "VK_ACCESS_INPUT_ATTACHMENT_READ_BIT"; + case VK_ACCESS_MEMORY_READ_BIT: + return "VK_ACCESS_MEMORY_READ_BIT"; + case VK_ACCESS_MEMORY_WRITE_BIT: + return "VK_ACCESS_MEMORY_WRITE_BIT"; + case VK_ACCESS_NONE: + return "VK_ACCESS_NONE"; + case VK_ACCESS_SHADER_READ_BIT: + return "VK_ACCESS_SHADER_READ_BIT"; + case VK_ACCESS_SHADER_WRITE_BIT: + return "VK_ACCESS_SHADER_WRITE_BIT"; + case VK_ACCESS_TRANSFER_READ_BIT: + return "VK_ACCESS_TRANSFER_READ_BIT"; + case VK_ACCESS_TRANSFER_WRITE_BIT: + return "VK_ACCESS_TRANSFER_WRITE_BIT"; + case VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: + return "VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; + case VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: + return "VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; + case VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: + return "VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; + case VK_ACCESS_UNIFORM_READ_BIT: + return "VK_ACCESS_UNIFORM_READ_BIT"; + case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: + return "VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT"; + default: + return "Unhandled VkAccessFlagBits"; + } +} + +static inline std::string string_VkAccessFlags(VkAccessFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccessFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccessFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageLayout(VkImageLayout input_value) +{ + switch (input_value) + { + case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT: + return "VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT"; + case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: + return "VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT"; + case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR: + return "VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR"; + case VK_IMAGE_LAYOUT_GENERAL: + return "VK_IMAGE_LAYOUT_GENERAL"; + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return "VK_IMAGE_LAYOUT_PREINITIALIZED"; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR"; + case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR: + return "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR"; + case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL"; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL"; + case VK_IMAGE_LAYOUT_UNDEFINED: + return "VK_IMAGE_LAYOUT_UNDEFINED"; + case VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR"; + case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR"; + case VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkImageLayout"; + } +} + +static inline const char* string_VkImageAspectFlagBits(VkImageAspectFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_ASPECT_COLOR_BIT: + return "VK_IMAGE_ASPECT_COLOR_BIT"; + case VK_IMAGE_ASPECT_DEPTH_BIT: + return "VK_IMAGE_ASPECT_DEPTH_BIT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT"; + case VK_IMAGE_ASPECT_METADATA_BIT: + return "VK_IMAGE_ASPECT_METADATA_BIT"; + case VK_IMAGE_ASPECT_NONE: + return "VK_IMAGE_ASPECT_NONE"; + case VK_IMAGE_ASPECT_PLANE_0_BIT: + return "VK_IMAGE_ASPECT_PLANE_0_BIT"; + case VK_IMAGE_ASPECT_PLANE_1_BIT: + return "VK_IMAGE_ASPECT_PLANE_1_BIT"; + case VK_IMAGE_ASPECT_PLANE_2_BIT: + return "VK_IMAGE_ASPECT_PLANE_2_BIT"; + case VK_IMAGE_ASPECT_STENCIL_BIT: + return "VK_IMAGE_ASPECT_STENCIL_BIT"; + default: + return "Unhandled VkImageAspectFlagBits"; + } +} + +static inline std::string string_VkImageAspectFlags(VkImageAspectFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageAspectFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageAspectFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkObjectType(VkObjectType input_value) +{ + switch (input_value) + { + case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR: + return "VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR"; + case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV: + return "VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV"; + case VK_OBJECT_TYPE_BUFFER: + return "VK_OBJECT_TYPE_BUFFER"; + case VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA: + return "VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA"; + case VK_OBJECT_TYPE_BUFFER_VIEW: + return "VK_OBJECT_TYPE_BUFFER_VIEW"; + case VK_OBJECT_TYPE_COMMAND_BUFFER: + return "VK_OBJECT_TYPE_COMMAND_BUFFER"; + case VK_OBJECT_TYPE_COMMAND_POOL: + return "VK_OBJECT_TYPE_COMMAND_POOL"; + case VK_OBJECT_TYPE_CU_FUNCTION_NVX: + return "VK_OBJECT_TYPE_CU_FUNCTION_NVX"; + case VK_OBJECT_TYPE_CU_MODULE_NVX: + return "VK_OBJECT_TYPE_CU_MODULE_NVX"; + case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: + return "VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT"; + case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: + return "VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT"; + case VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR: + return "VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR"; + case VK_OBJECT_TYPE_DESCRIPTOR_POOL: + return "VK_OBJECT_TYPE_DESCRIPTOR_POOL"; + case VK_OBJECT_TYPE_DESCRIPTOR_SET: + return "VK_OBJECT_TYPE_DESCRIPTOR_SET"; + case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: + return "VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT"; + case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: + return "VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE"; + case VK_OBJECT_TYPE_DEVICE: + return "VK_OBJECT_TYPE_DEVICE"; + case VK_OBJECT_TYPE_DEVICE_MEMORY: + return "VK_OBJECT_TYPE_DEVICE_MEMORY"; + case VK_OBJECT_TYPE_DISPLAY_KHR: + return "VK_OBJECT_TYPE_DISPLAY_KHR"; + case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: + return "VK_OBJECT_TYPE_DISPLAY_MODE_KHR"; + case VK_OBJECT_TYPE_EVENT: + return "VK_OBJECT_TYPE_EVENT"; + case VK_OBJECT_TYPE_FENCE: + return "VK_OBJECT_TYPE_FENCE"; + case VK_OBJECT_TYPE_FRAMEBUFFER: + return "VK_OBJECT_TYPE_FRAMEBUFFER"; + case VK_OBJECT_TYPE_IMAGE: + return "VK_OBJECT_TYPE_IMAGE"; + case VK_OBJECT_TYPE_IMAGE_VIEW: + return "VK_OBJECT_TYPE_IMAGE_VIEW"; + case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV: + return "VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV"; + case VK_OBJECT_TYPE_INSTANCE: + return "VK_OBJECT_TYPE_INSTANCE"; + case VK_OBJECT_TYPE_MICROMAP_EXT: + return "VK_OBJECT_TYPE_MICROMAP_EXT"; + case VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV: + return "VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV"; + case VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL: + return "VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL"; + case VK_OBJECT_TYPE_PHYSICAL_DEVICE: + return "VK_OBJECT_TYPE_PHYSICAL_DEVICE"; + case VK_OBJECT_TYPE_PIPELINE: + return "VK_OBJECT_TYPE_PIPELINE"; + case VK_OBJECT_TYPE_PIPELINE_CACHE: + return "VK_OBJECT_TYPE_PIPELINE_CACHE"; + case VK_OBJECT_TYPE_PIPELINE_LAYOUT: + return "VK_OBJECT_TYPE_PIPELINE_LAYOUT"; + case VK_OBJECT_TYPE_PRIVATE_DATA_SLOT: + return "VK_OBJECT_TYPE_PRIVATE_DATA_SLOT"; + case VK_OBJECT_TYPE_QUERY_POOL: + return "VK_OBJECT_TYPE_QUERY_POOL"; + case VK_OBJECT_TYPE_QUEUE: + return "VK_OBJECT_TYPE_QUEUE"; + case VK_OBJECT_TYPE_RENDER_PASS: + return "VK_OBJECT_TYPE_RENDER_PASS"; + case VK_OBJECT_TYPE_SAMPLER: + return "VK_OBJECT_TYPE_SAMPLER"; + case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: + return "VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION"; + case VK_OBJECT_TYPE_SEMAPHORE: + return "VK_OBJECT_TYPE_SEMAPHORE"; + case VK_OBJECT_TYPE_SHADER_MODULE: + return "VK_OBJECT_TYPE_SHADER_MODULE"; + case VK_OBJECT_TYPE_SURFACE_KHR: + return "VK_OBJECT_TYPE_SURFACE_KHR"; + case VK_OBJECT_TYPE_SWAPCHAIN_KHR: + return "VK_OBJECT_TYPE_SWAPCHAIN_KHR"; + case VK_OBJECT_TYPE_UNKNOWN: + return "VK_OBJECT_TYPE_UNKNOWN"; + case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: + return "VK_OBJECT_TYPE_VALIDATION_CACHE_EXT"; + case VK_OBJECT_TYPE_VIDEO_SESSION_KHR: + return "VK_OBJECT_TYPE_VIDEO_SESSION_KHR"; + case VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR: + return "VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR"; + default: + return "Unhandled VkObjectType"; + } +} + +static inline const char* string_VkVendorId(VkVendorId input_value) +{ + switch (input_value) + { + case VK_VENDOR_ID_CODEPLAY: + return "VK_VENDOR_ID_CODEPLAY"; + case VK_VENDOR_ID_KAZAN: + return "VK_VENDOR_ID_KAZAN"; + case VK_VENDOR_ID_MESA: + return "VK_VENDOR_ID_MESA"; + case VK_VENDOR_ID_POCL: + return "VK_VENDOR_ID_POCL"; + case VK_VENDOR_ID_VIV: + return "VK_VENDOR_ID_VIV"; + case VK_VENDOR_ID_VSI: + return "VK_VENDOR_ID_VSI"; + default: + return "Unhandled VkVendorId"; + } +} + +static inline const char* string_VkSystemAllocationScope(VkSystemAllocationScope input_value) +{ + switch (input_value) + { + case VK_SYSTEM_ALLOCATION_SCOPE_CACHE: + return "VK_SYSTEM_ALLOCATION_SCOPE_CACHE"; + case VK_SYSTEM_ALLOCATION_SCOPE_COMMAND: + return "VK_SYSTEM_ALLOCATION_SCOPE_COMMAND"; + case VK_SYSTEM_ALLOCATION_SCOPE_DEVICE: + return "VK_SYSTEM_ALLOCATION_SCOPE_DEVICE"; + case VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE: + return "VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE"; + case VK_SYSTEM_ALLOCATION_SCOPE_OBJECT: + return "VK_SYSTEM_ALLOCATION_SCOPE_OBJECT"; + default: + return "Unhandled VkSystemAllocationScope"; + } +} + +static inline const char* string_VkInternalAllocationType(VkInternalAllocationType input_value) +{ + switch (input_value) + { + case VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE: + return "VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE"; + default: + return "Unhandled VkInternalAllocationType"; + } +} + +static inline const char* string_VkFormat(VkFormat input_value) +{ + switch (input_value) + { + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: + return "VK_FORMAT_A1R5G5B5_UNORM_PACK16"; + case VK_FORMAT_A2B10G10R10_SINT_PACK32: + return "VK_FORMAT_A2B10G10R10_SINT_PACK32"; + case VK_FORMAT_A2B10G10R10_SNORM_PACK32: + return "VK_FORMAT_A2B10G10R10_SNORM_PACK32"; + case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: + return "VK_FORMAT_A2B10G10R10_SSCALED_PACK32"; + case VK_FORMAT_A2B10G10R10_UINT_PACK32: + return "VK_FORMAT_A2B10G10R10_UINT_PACK32"; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + return "VK_FORMAT_A2B10G10R10_UNORM_PACK32"; + case VK_FORMAT_A2B10G10R10_USCALED_PACK32: + return "VK_FORMAT_A2B10G10R10_USCALED_PACK32"; + case VK_FORMAT_A2R10G10B10_SINT_PACK32: + return "VK_FORMAT_A2R10G10B10_SINT_PACK32"; + case VK_FORMAT_A2R10G10B10_SNORM_PACK32: + return "VK_FORMAT_A2R10G10B10_SNORM_PACK32"; + case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: + return "VK_FORMAT_A2R10G10B10_SSCALED_PACK32"; + case VK_FORMAT_A2R10G10B10_UINT_PACK32: + return "VK_FORMAT_A2R10G10B10_UINT_PACK32"; + case VK_FORMAT_A2R10G10B10_UNORM_PACK32: + return "VK_FORMAT_A2R10G10B10_UNORM_PACK32"; + case VK_FORMAT_A2R10G10B10_USCALED_PACK32: + return "VK_FORMAT_A2R10G10B10_USCALED_PACK32"; + case VK_FORMAT_A4B4G4R4_UNORM_PACK16: + return "VK_FORMAT_A4B4G4R4_UNORM_PACK16"; + case VK_FORMAT_A4R4G4B4_UNORM_PACK16: + return "VK_FORMAT_A4R4G4B4_UNORM_PACK16"; + case VK_FORMAT_A8B8G8R8_SINT_PACK32: + return "VK_FORMAT_A8B8G8R8_SINT_PACK32"; + case VK_FORMAT_A8B8G8R8_SNORM_PACK32: + return "VK_FORMAT_A8B8G8R8_SNORM_PACK32"; + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + return "VK_FORMAT_A8B8G8R8_SRGB_PACK32"; + case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: + return "VK_FORMAT_A8B8G8R8_SSCALED_PACK32"; + case VK_FORMAT_A8B8G8R8_UINT_PACK32: + return "VK_FORMAT_A8B8G8R8_UINT_PACK32"; + case VK_FORMAT_A8B8G8R8_UNORM_PACK32: + return "VK_FORMAT_A8B8G8R8_UNORM_PACK32"; + case VK_FORMAT_A8B8G8R8_USCALED_PACK32: + return "VK_FORMAT_A8B8G8R8_USCALED_PACK32"; + case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x10_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x10_UNORM_BLOCK"; + case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x6_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x6_UNORM_BLOCK"; + case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x8_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x8_UNORM_BLOCK"; + case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + return "VK_FORMAT_ASTC_12x10_SRGB_BLOCK"; + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + return "VK_FORMAT_ASTC_12x10_UNORM_BLOCK"; + case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + return "VK_FORMAT_ASTC_12x12_SRGB_BLOCK"; + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + return "VK_FORMAT_ASTC_12x12_UNORM_BLOCK"; + case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + return "VK_FORMAT_ASTC_4x4_SRGB_BLOCK"; + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + return "VK_FORMAT_ASTC_4x4_UNORM_BLOCK"; + case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + return "VK_FORMAT_ASTC_5x4_SRGB_BLOCK"; + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + return "VK_FORMAT_ASTC_5x4_UNORM_BLOCK"; + case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_5x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_5x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_6x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_6x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + return "VK_FORMAT_ASTC_6x6_SRGB_BLOCK"; + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + return "VK_FORMAT_ASTC_6x6_UNORM_BLOCK"; + case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_8x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_8x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + return "VK_FORMAT_ASTC_8x6_SRGB_BLOCK"; + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + return "VK_FORMAT_ASTC_8x6_UNORM_BLOCK"; + case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK: + return "VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK"; + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + return "VK_FORMAT_ASTC_8x8_SRGB_BLOCK"; + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + return "VK_FORMAT_ASTC_8x8_UNORM_BLOCK"; + case VK_FORMAT_B10G11R11_UFLOAT_PACK32: + return "VK_FORMAT_B10G11R11_UFLOAT_PACK32"; + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + return "VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16"; + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + return "VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16"; + case VK_FORMAT_B16G16R16G16_422_UNORM: + return "VK_FORMAT_B16G16R16G16_422_UNORM"; + case VK_FORMAT_B4G4R4A4_UNORM_PACK16: + return "VK_FORMAT_B4G4R4A4_UNORM_PACK16"; + case VK_FORMAT_B5G5R5A1_UNORM_PACK16: + return "VK_FORMAT_B5G5R5A1_UNORM_PACK16"; + case VK_FORMAT_B5G6R5_UNORM_PACK16: + return "VK_FORMAT_B5G6R5_UNORM_PACK16"; + case VK_FORMAT_B8G8R8A8_SINT: + return "VK_FORMAT_B8G8R8A8_SINT"; + case VK_FORMAT_B8G8R8A8_SNORM: + return "VK_FORMAT_B8G8R8A8_SNORM"; + case VK_FORMAT_B8G8R8A8_SRGB: + return "VK_FORMAT_B8G8R8A8_SRGB"; + case VK_FORMAT_B8G8R8A8_SSCALED: + return "VK_FORMAT_B8G8R8A8_SSCALED"; + case VK_FORMAT_B8G8R8A8_UINT: + return "VK_FORMAT_B8G8R8A8_UINT"; + case VK_FORMAT_B8G8R8A8_UNORM: + return "VK_FORMAT_B8G8R8A8_UNORM"; + case VK_FORMAT_B8G8R8A8_USCALED: + return "VK_FORMAT_B8G8R8A8_USCALED"; + case VK_FORMAT_B8G8R8G8_422_UNORM: + return "VK_FORMAT_B8G8R8G8_422_UNORM"; + case VK_FORMAT_B8G8R8_SINT: + return "VK_FORMAT_B8G8R8_SINT"; + case VK_FORMAT_B8G8R8_SNORM: + return "VK_FORMAT_B8G8R8_SNORM"; + case VK_FORMAT_B8G8R8_SRGB: + return "VK_FORMAT_B8G8R8_SRGB"; + case VK_FORMAT_B8G8R8_SSCALED: + return "VK_FORMAT_B8G8R8_SSCALED"; + case VK_FORMAT_B8G8R8_UINT: + return "VK_FORMAT_B8G8R8_UINT"; + case VK_FORMAT_B8G8R8_UNORM: + return "VK_FORMAT_B8G8R8_UNORM"; + case VK_FORMAT_B8G8R8_USCALED: + return "VK_FORMAT_B8G8R8_USCALED"; + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + return "VK_FORMAT_BC1_RGBA_SRGB_BLOCK"; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + return "VK_FORMAT_BC1_RGBA_UNORM_BLOCK"; + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + return "VK_FORMAT_BC1_RGB_SRGB_BLOCK"; + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + return "VK_FORMAT_BC1_RGB_UNORM_BLOCK"; + case VK_FORMAT_BC2_SRGB_BLOCK: + return "VK_FORMAT_BC2_SRGB_BLOCK"; + case VK_FORMAT_BC2_UNORM_BLOCK: + return "VK_FORMAT_BC2_UNORM_BLOCK"; + case VK_FORMAT_BC3_SRGB_BLOCK: + return "VK_FORMAT_BC3_SRGB_BLOCK"; + case VK_FORMAT_BC3_UNORM_BLOCK: + return "VK_FORMAT_BC3_UNORM_BLOCK"; + case VK_FORMAT_BC4_SNORM_BLOCK: + return "VK_FORMAT_BC4_SNORM_BLOCK"; + case VK_FORMAT_BC4_UNORM_BLOCK: + return "VK_FORMAT_BC4_UNORM_BLOCK"; + case VK_FORMAT_BC5_SNORM_BLOCK: + return "VK_FORMAT_BC5_SNORM_BLOCK"; + case VK_FORMAT_BC5_UNORM_BLOCK: + return "VK_FORMAT_BC5_UNORM_BLOCK"; + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + return "VK_FORMAT_BC6H_SFLOAT_BLOCK"; + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + return "VK_FORMAT_BC6H_UFLOAT_BLOCK"; + case VK_FORMAT_BC7_SRGB_BLOCK: + return "VK_FORMAT_BC7_SRGB_BLOCK"; + case VK_FORMAT_BC7_UNORM_BLOCK: + return "VK_FORMAT_BC7_UNORM_BLOCK"; + case VK_FORMAT_D16_UNORM: + return "VK_FORMAT_D16_UNORM"; + case VK_FORMAT_D16_UNORM_S8_UINT: + return "VK_FORMAT_D16_UNORM_S8_UINT"; + case VK_FORMAT_D24_UNORM_S8_UINT: + return "VK_FORMAT_D24_UNORM_S8_UINT"; + case VK_FORMAT_D32_SFLOAT: + return "VK_FORMAT_D32_SFLOAT"; + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return "VK_FORMAT_D32_SFLOAT_S8_UINT"; + case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: + return "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32"; + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: + return "VK_FORMAT_EAC_R11G11_SNORM_BLOCK"; + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + return "VK_FORMAT_EAC_R11G11_UNORM_BLOCK"; + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + return "VK_FORMAT_EAC_R11_SNORM_BLOCK"; + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + return "VK_FORMAT_EAC_R11_UNORM_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK"; + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + return "VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16"; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16"; + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + return "VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16"; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16"; + case VK_FORMAT_G16B16G16R16_422_UNORM: + return "VK_FORMAT_G16B16G16R16_422_UNORM"; + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + return "VK_FORMAT_G16_B16R16_2PLANE_420_UNORM"; + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + return "VK_FORMAT_G16_B16R16_2PLANE_422_UNORM"; + case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM: + return "VK_FORMAT_G16_B16R16_2PLANE_444_UNORM"; + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + return "VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM"; + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + return "VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM"; + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + return "VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM"; + case VK_FORMAT_G8B8G8R8_422_UNORM: + return "VK_FORMAT_G8B8G8R8_422_UNORM"; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + return "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM"; + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + return "VK_FORMAT_G8_B8R8_2PLANE_422_UNORM"; + case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM: + return "VK_FORMAT_G8_B8R8_2PLANE_444_UNORM"; + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + return "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM"; + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + return "VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM"; + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + return "VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM"; + case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: + return "VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16"; + case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: + return "VK_FORMAT_R10X6G10X6_UNORM_2PACK16"; + case VK_FORMAT_R10X6_UNORM_PACK16: + return "VK_FORMAT_R10X6_UNORM_PACK16"; + case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: + return "VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16"; + case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: + return "VK_FORMAT_R12X4G12X4_UNORM_2PACK16"; + case VK_FORMAT_R12X4_UNORM_PACK16: + return "VK_FORMAT_R12X4_UNORM_PACK16"; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return "VK_FORMAT_R16G16B16A16_SFLOAT"; + case VK_FORMAT_R16G16B16A16_SINT: + return "VK_FORMAT_R16G16B16A16_SINT"; + case VK_FORMAT_R16G16B16A16_SNORM: + return "VK_FORMAT_R16G16B16A16_SNORM"; + case VK_FORMAT_R16G16B16A16_SSCALED: + return "VK_FORMAT_R16G16B16A16_SSCALED"; + case VK_FORMAT_R16G16B16A16_UINT: + return "VK_FORMAT_R16G16B16A16_UINT"; + case VK_FORMAT_R16G16B16A16_UNORM: + return "VK_FORMAT_R16G16B16A16_UNORM"; + case VK_FORMAT_R16G16B16A16_USCALED: + return "VK_FORMAT_R16G16B16A16_USCALED"; + case VK_FORMAT_R16G16B16_SFLOAT: + return "VK_FORMAT_R16G16B16_SFLOAT"; + case VK_FORMAT_R16G16B16_SINT: + return "VK_FORMAT_R16G16B16_SINT"; + case VK_FORMAT_R16G16B16_SNORM: + return "VK_FORMAT_R16G16B16_SNORM"; + case VK_FORMAT_R16G16B16_SSCALED: + return "VK_FORMAT_R16G16B16_SSCALED"; + case VK_FORMAT_R16G16B16_UINT: + return "VK_FORMAT_R16G16B16_UINT"; + case VK_FORMAT_R16G16B16_UNORM: + return "VK_FORMAT_R16G16B16_UNORM"; + case VK_FORMAT_R16G16B16_USCALED: + return "VK_FORMAT_R16G16B16_USCALED"; + case VK_FORMAT_R16G16_S10_5_NV: + return "VK_FORMAT_R16G16_S10_5_NV"; + case VK_FORMAT_R16G16_SFLOAT: + return "VK_FORMAT_R16G16_SFLOAT"; + case VK_FORMAT_R16G16_SINT: + return "VK_FORMAT_R16G16_SINT"; + case VK_FORMAT_R16G16_SNORM: + return "VK_FORMAT_R16G16_SNORM"; + case VK_FORMAT_R16G16_SSCALED: + return "VK_FORMAT_R16G16_SSCALED"; + case VK_FORMAT_R16G16_UINT: + return "VK_FORMAT_R16G16_UINT"; + case VK_FORMAT_R16G16_UNORM: + return "VK_FORMAT_R16G16_UNORM"; + case VK_FORMAT_R16G16_USCALED: + return "VK_FORMAT_R16G16_USCALED"; + case VK_FORMAT_R16_SFLOAT: + return "VK_FORMAT_R16_SFLOAT"; + case VK_FORMAT_R16_SINT: + return "VK_FORMAT_R16_SINT"; + case VK_FORMAT_R16_SNORM: + return "VK_FORMAT_R16_SNORM"; + case VK_FORMAT_R16_SSCALED: + return "VK_FORMAT_R16_SSCALED"; + case VK_FORMAT_R16_UINT: + return "VK_FORMAT_R16_UINT"; + case VK_FORMAT_R16_UNORM: + return "VK_FORMAT_R16_UNORM"; + case VK_FORMAT_R16_USCALED: + return "VK_FORMAT_R16_USCALED"; + case VK_FORMAT_R32G32B32A32_SFLOAT: + return "VK_FORMAT_R32G32B32A32_SFLOAT"; + case VK_FORMAT_R32G32B32A32_SINT: + return "VK_FORMAT_R32G32B32A32_SINT"; + case VK_FORMAT_R32G32B32A32_UINT: + return "VK_FORMAT_R32G32B32A32_UINT"; + case VK_FORMAT_R32G32B32_SFLOAT: + return "VK_FORMAT_R32G32B32_SFLOAT"; + case VK_FORMAT_R32G32B32_SINT: + return "VK_FORMAT_R32G32B32_SINT"; + case VK_FORMAT_R32G32B32_UINT: + return "VK_FORMAT_R32G32B32_UINT"; + case VK_FORMAT_R32G32_SFLOAT: + return "VK_FORMAT_R32G32_SFLOAT"; + case VK_FORMAT_R32G32_SINT: + return "VK_FORMAT_R32G32_SINT"; + case VK_FORMAT_R32G32_UINT: + return "VK_FORMAT_R32G32_UINT"; + case VK_FORMAT_R32_SFLOAT: + return "VK_FORMAT_R32_SFLOAT"; + case VK_FORMAT_R32_SINT: + return "VK_FORMAT_R32_SINT"; + case VK_FORMAT_R32_UINT: + return "VK_FORMAT_R32_UINT"; + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + return "VK_FORMAT_R4G4B4A4_UNORM_PACK16"; + case VK_FORMAT_R4G4_UNORM_PACK8: + return "VK_FORMAT_R4G4_UNORM_PACK8"; + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + return "VK_FORMAT_R5G5B5A1_UNORM_PACK16"; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + return "VK_FORMAT_R5G6B5_UNORM_PACK16"; + case VK_FORMAT_R64G64B64A64_SFLOAT: + return "VK_FORMAT_R64G64B64A64_SFLOAT"; + case VK_FORMAT_R64G64B64A64_SINT: + return "VK_FORMAT_R64G64B64A64_SINT"; + case VK_FORMAT_R64G64B64A64_UINT: + return "VK_FORMAT_R64G64B64A64_UINT"; + case VK_FORMAT_R64G64B64_SFLOAT: + return "VK_FORMAT_R64G64B64_SFLOAT"; + case VK_FORMAT_R64G64B64_SINT: + return "VK_FORMAT_R64G64B64_SINT"; + case VK_FORMAT_R64G64B64_UINT: + return "VK_FORMAT_R64G64B64_UINT"; + case VK_FORMAT_R64G64_SFLOAT: + return "VK_FORMAT_R64G64_SFLOAT"; + case VK_FORMAT_R64G64_SINT: + return "VK_FORMAT_R64G64_SINT"; + case VK_FORMAT_R64G64_UINT: + return "VK_FORMAT_R64G64_UINT"; + case VK_FORMAT_R64_SFLOAT: + return "VK_FORMAT_R64_SFLOAT"; + case VK_FORMAT_R64_SINT: + return "VK_FORMAT_R64_SINT"; + case VK_FORMAT_R64_UINT: + return "VK_FORMAT_R64_UINT"; + case VK_FORMAT_R8G8B8A8_SINT: + return "VK_FORMAT_R8G8B8A8_SINT"; + case VK_FORMAT_R8G8B8A8_SNORM: + return "VK_FORMAT_R8G8B8A8_SNORM"; + case VK_FORMAT_R8G8B8A8_SRGB: + return "VK_FORMAT_R8G8B8A8_SRGB"; + case VK_FORMAT_R8G8B8A8_SSCALED: + return "VK_FORMAT_R8G8B8A8_SSCALED"; + case VK_FORMAT_R8G8B8A8_UINT: + return "VK_FORMAT_R8G8B8A8_UINT"; + case VK_FORMAT_R8G8B8A8_UNORM: + return "VK_FORMAT_R8G8B8A8_UNORM"; + case VK_FORMAT_R8G8B8A8_USCALED: + return "VK_FORMAT_R8G8B8A8_USCALED"; + case VK_FORMAT_R8G8B8_SINT: + return "VK_FORMAT_R8G8B8_SINT"; + case VK_FORMAT_R8G8B8_SNORM: + return "VK_FORMAT_R8G8B8_SNORM"; + case VK_FORMAT_R8G8B8_SRGB: + return "VK_FORMAT_R8G8B8_SRGB"; + case VK_FORMAT_R8G8B8_SSCALED: + return "VK_FORMAT_R8G8B8_SSCALED"; + case VK_FORMAT_R8G8B8_UINT: + return "VK_FORMAT_R8G8B8_UINT"; + case VK_FORMAT_R8G8B8_UNORM: + return "VK_FORMAT_R8G8B8_UNORM"; + case VK_FORMAT_R8G8B8_USCALED: + return "VK_FORMAT_R8G8B8_USCALED"; + case VK_FORMAT_R8G8_SINT: + return "VK_FORMAT_R8G8_SINT"; + case VK_FORMAT_R8G8_SNORM: + return "VK_FORMAT_R8G8_SNORM"; + case VK_FORMAT_R8G8_SRGB: + return "VK_FORMAT_R8G8_SRGB"; + case VK_FORMAT_R8G8_SSCALED: + return "VK_FORMAT_R8G8_SSCALED"; + case VK_FORMAT_R8G8_UINT: + return "VK_FORMAT_R8G8_UINT"; + case VK_FORMAT_R8G8_UNORM: + return "VK_FORMAT_R8G8_UNORM"; + case VK_FORMAT_R8G8_USCALED: + return "VK_FORMAT_R8G8_USCALED"; + case VK_FORMAT_R8_SINT: + return "VK_FORMAT_R8_SINT"; + case VK_FORMAT_R8_SNORM: + return "VK_FORMAT_R8_SNORM"; + case VK_FORMAT_R8_SRGB: + return "VK_FORMAT_R8_SRGB"; + case VK_FORMAT_R8_SSCALED: + return "VK_FORMAT_R8_SSCALED"; + case VK_FORMAT_R8_UINT: + return "VK_FORMAT_R8_UINT"; + case VK_FORMAT_R8_UNORM: + return "VK_FORMAT_R8_UNORM"; + case VK_FORMAT_R8_USCALED: + return "VK_FORMAT_R8_USCALED"; + case VK_FORMAT_S8_UINT: + return "VK_FORMAT_S8_UINT"; + case VK_FORMAT_UNDEFINED: + return "VK_FORMAT_UNDEFINED"; + case VK_FORMAT_X8_D24_UNORM_PACK32: + return "VK_FORMAT_X8_D24_UNORM_PACK32"; + default: + return "Unhandled VkFormat"; + } +} + +static inline const char* string_VkFormatFeatureFlagBits(VkFormatFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR: + return "VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"; + case VK_FORMAT_FEATURE_BLIT_DST_BIT: + return "VK_FORMAT_FEATURE_BLIT_DST_BIT"; + case VK_FORMAT_FEATURE_BLIT_SRC_BIT: + return "VK_FORMAT_FEATURE_BLIT_SRC_BIT"; + case VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT: + return "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT"; + case VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_DISJOINT_BIT: + return "VK_FORMAT_FEATURE_DISJOINT_BIT"; + case VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT: + return "VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT"; + case VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"; + case VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT: + return "VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT"; + case VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_TRANSFER_DST_BIT: + return "VK_FORMAT_FEATURE_TRANSFER_DST_BIT"; + case VK_FORMAT_FEATURE_TRANSFER_SRC_BIT: + return "VK_FORMAT_FEATURE_TRANSFER_SRC_BIT"; + case VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT: + return "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT"; + case VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR"; + case VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkFormatFeatureFlagBits"; + } +} + +static inline std::string string_VkFormatFeatureFlags(VkFormatFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFormatFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFormatFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageCreateFlagBits(VkImageCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT: + return "VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT"; + case VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT: + return "VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT"; + case VK_IMAGE_CREATE_ALIAS_BIT: + return "VK_IMAGE_CREATE_ALIAS_BIT"; + case VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT: + return "VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT"; + case VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV: + return "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV"; + case VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT: + return "VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT"; + case VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT: + return "VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT"; + case VK_IMAGE_CREATE_DISJOINT_BIT: + return "VK_IMAGE_CREATE_DISJOINT_BIT"; + case VK_IMAGE_CREATE_EXTENDED_USAGE_BIT: + return "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT"; + case VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM: + return "VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM"; + case VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT: + return "VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT"; + case VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT: + return "VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT"; + case VK_IMAGE_CREATE_PROTECTED_BIT: + return "VK_IMAGE_CREATE_PROTECTED_BIT"; + case VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT: + return "VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT"; + case VK_IMAGE_CREATE_SPARSE_ALIASED_BIT: + return "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT"; + case VK_IMAGE_CREATE_SPARSE_BINDING_BIT: + return "VK_IMAGE_CREATE_SPARSE_BINDING_BIT"; + case VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT: + return "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"; + case VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT: + return "VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT"; + case VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT: + return "VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT"; + default: + return "Unhandled VkImageCreateFlagBits"; + } +} + +static inline std::string string_VkImageCreateFlags(VkImageCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSampleCountFlagBits(VkSampleCountFlagBits input_value) +{ + switch (input_value) + { + case VK_SAMPLE_COUNT_16_BIT: + return "VK_SAMPLE_COUNT_16_BIT"; + case VK_SAMPLE_COUNT_1_BIT: + return "VK_SAMPLE_COUNT_1_BIT"; + case VK_SAMPLE_COUNT_2_BIT: + return "VK_SAMPLE_COUNT_2_BIT"; + case VK_SAMPLE_COUNT_32_BIT: + return "VK_SAMPLE_COUNT_32_BIT"; + case VK_SAMPLE_COUNT_4_BIT: + return "VK_SAMPLE_COUNT_4_BIT"; + case VK_SAMPLE_COUNT_64_BIT: + return "VK_SAMPLE_COUNT_64_BIT"; + case VK_SAMPLE_COUNT_8_BIT: + return "VK_SAMPLE_COUNT_8_BIT"; + default: + return "Unhandled VkSampleCountFlagBits"; + } +} + +static inline std::string string_VkSampleCountFlags(VkSampleCountFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSampleCountFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSampleCountFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageTiling(VkImageTiling input_value) +{ + switch (input_value) + { + case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: + return "VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT"; + case VK_IMAGE_TILING_LINEAR: + return "VK_IMAGE_TILING_LINEAR"; + case VK_IMAGE_TILING_OPTIMAL: + return "VK_IMAGE_TILING_OPTIMAL"; + default: + return "Unhandled VkImageTiling"; + } +} + +static inline const char* string_VkImageType(VkImageType input_value) +{ + switch (input_value) + { + case VK_IMAGE_TYPE_1D: + return "VK_IMAGE_TYPE_1D"; + case VK_IMAGE_TYPE_2D: + return "VK_IMAGE_TYPE_2D"; + case VK_IMAGE_TYPE_3D: + return "VK_IMAGE_TYPE_3D"; + default: + return "Unhandled VkImageType"; + } +} + +static inline const char* string_VkImageUsageFlagBits(VkImageUsageFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT: + return "VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; + case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT: + return "VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT"; + case VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI: + return "VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI"; + case VK_IMAGE_USAGE_SAMPLED_BIT: + return "VK_IMAGE_USAGE_SAMPLED_BIT"; + case VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM: + return "VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM"; + case VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM: + return "VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM"; + case VK_IMAGE_USAGE_STORAGE_BIT: + return "VK_IMAGE_USAGE_STORAGE_BIT"; + case VK_IMAGE_USAGE_TRANSFER_DST_BIT: + return "VK_IMAGE_USAGE_TRANSFER_DST_BIT"; + case VK_IMAGE_USAGE_TRANSFER_SRC_BIT: + return "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"; + case VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR"; + case VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR"; + case VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkImageUsageFlagBits"; + } +} + +static inline std::string string_VkImageUsageFlags(VkImageUsageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageUsageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageUsageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkInstanceCreateFlagBits(VkInstanceCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR: + return "VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR"; + default: + return "Unhandled VkInstanceCreateFlagBits"; + } +} + +static inline std::string string_VkInstanceCreateFlags(VkInstanceCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkInstanceCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkInstanceCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryHeapFlagBits(VkMemoryHeapFlagBits input_value) +{ + switch (input_value) + { + case VK_MEMORY_HEAP_DEVICE_LOCAL_BIT: + return "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT"; + case VK_MEMORY_HEAP_MULTI_INSTANCE_BIT: + return "VK_MEMORY_HEAP_MULTI_INSTANCE_BIT"; + default: + return "Unhandled VkMemoryHeapFlagBits"; + } +} + +static inline std::string string_VkMemoryHeapFlags(VkMemoryHeapFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryHeapFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryHeapFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryPropertyFlagBits(VkMemoryPropertyFlagBits input_value) +{ + switch (input_value) + { + case VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD: + return "VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD"; + case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT: + return "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT"; + case VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD: + return "VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD"; + case VK_MEMORY_PROPERTY_HOST_CACHED_BIT: + return "VK_MEMORY_PROPERTY_HOST_CACHED_BIT"; + case VK_MEMORY_PROPERTY_HOST_COHERENT_BIT: + return "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT"; + case VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT: + return "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT"; + case VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT: + return "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT"; + case VK_MEMORY_PROPERTY_PROTECTED_BIT: + return "VK_MEMORY_PROPERTY_PROTECTED_BIT"; + case VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV: + return "VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV"; + default: + return "Unhandled VkMemoryPropertyFlagBits"; + } +} + +static inline std::string string_VkMemoryPropertyFlags(VkMemoryPropertyFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryPropertyFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryPropertyFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPhysicalDeviceType(VkPhysicalDeviceType input_value) +{ + switch (input_value) + { + case VK_PHYSICAL_DEVICE_TYPE_CPU: + return "VK_PHYSICAL_DEVICE_TYPE_CPU"; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: + return "VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU"; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: + return "VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU"; + case VK_PHYSICAL_DEVICE_TYPE_OTHER: + return "VK_PHYSICAL_DEVICE_TYPE_OTHER"; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: + return "VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU"; + default: + return "Unhandled VkPhysicalDeviceType"; + } +} + +static inline const char* string_VkQueueFlagBits(VkQueueFlagBits input_value) +{ + switch (input_value) + { + case VK_QUEUE_COMPUTE_BIT: + return "VK_QUEUE_COMPUTE_BIT"; + case VK_QUEUE_GRAPHICS_BIT: + return "VK_QUEUE_GRAPHICS_BIT"; + case VK_QUEUE_OPTICAL_FLOW_BIT_NV: + return "VK_QUEUE_OPTICAL_FLOW_BIT_NV"; + case VK_QUEUE_PROTECTED_BIT: + return "VK_QUEUE_PROTECTED_BIT"; + case VK_QUEUE_SPARSE_BINDING_BIT: + return "VK_QUEUE_SPARSE_BINDING_BIT"; + case VK_QUEUE_TRANSFER_BIT: + return "VK_QUEUE_TRANSFER_BIT"; + case VK_QUEUE_VIDEO_DECODE_BIT_KHR: + return "VK_QUEUE_VIDEO_DECODE_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: + return "VK_QUEUE_VIDEO_ENCODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkQueueFlagBits"; + } +} + +static inline std::string string_VkQueueFlags(VkQueueFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueueFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueueFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceQueueCreateFlagBits(VkDeviceQueueCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT: + return "VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT"; + default: + return "Unhandled VkDeviceQueueCreateFlagBits"; + } +} + +static inline std::string string_VkDeviceQueueCreateFlags(VkDeviceQueueCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceQueueCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceQueueCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineStageFlagBits(VkPipelineStageFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: + return "VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; + case VK_PIPELINE_STAGE_ALL_COMMANDS_BIT: + return "VK_PIPELINE_STAGE_ALL_COMMANDS_BIT"; + case VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT: + return "VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT"; + case VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: + return "VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT"; + case VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV: + return "VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV"; + case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: + return "VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT"; + case VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: + return "VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT"; + case VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT: + return "VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; + case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: + return "VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT"; + case VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: + return "VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT"; + case VK_PIPELINE_STAGE_HOST_BIT: + return "VK_PIPELINE_STAGE_HOST_BIT"; + case VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT: + return "VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT"; + case VK_PIPELINE_STAGE_NONE: + return "VK_PIPELINE_STAGE_NONE"; + case VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT: + return "VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT"; + case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: + return "VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT"; + case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: + return "VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT"; + case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_TRANSFER_BIT: + return "VK_PIPELINE_STAGE_TRANSFER_BIT"; + case VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT: + return "VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT"; + case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: + return "VK_PIPELINE_STAGE_VERTEX_INPUT_BIT"; + case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: + return "VK_PIPELINE_STAGE_VERTEX_SHADER_BIT"; + default: + return "Unhandled VkPipelineStageFlagBits"; + } +} + +static inline std::string string_VkPipelineStageFlags(VkPipelineStageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineStageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineStageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSparseMemoryBindFlagBits(VkSparseMemoryBindFlagBits input_value) +{ + switch (input_value) + { + case VK_SPARSE_MEMORY_BIND_METADATA_BIT: + return "VK_SPARSE_MEMORY_BIND_METADATA_BIT"; + default: + return "Unhandled VkSparseMemoryBindFlagBits"; + } +} + +static inline std::string string_VkSparseMemoryBindFlags(VkSparseMemoryBindFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSparseMemoryBindFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSparseMemoryBindFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSparseImageFormatFlagBits(VkSparseImageFormatFlagBits input_value) +{ + switch (input_value) + { + case VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT: + return "VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT"; + case VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT: + return "VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT"; + case VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT: + return "VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT"; + default: + return "Unhandled VkSparseImageFormatFlagBits"; + } +} + +static inline std::string string_VkSparseImageFormatFlags(VkSparseImageFormatFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSparseImageFormatFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSparseImageFormatFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFenceCreateFlagBits(VkFenceCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_FENCE_CREATE_SIGNALED_BIT: + return "VK_FENCE_CREATE_SIGNALED_BIT"; + default: + return "Unhandled VkFenceCreateFlagBits"; + } +} + +static inline std::string string_VkFenceCreateFlags(VkFenceCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFenceCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFenceCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkEventCreateFlagBits(VkEventCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_EVENT_CREATE_DEVICE_ONLY_BIT: + return "VK_EVENT_CREATE_DEVICE_ONLY_BIT"; + default: + return "Unhandled VkEventCreateFlagBits"; + } +} + +static inline std::string string_VkEventCreateFlags(VkEventCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkEventCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkEventCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryPipelineStatisticFlagBits(VkQueryPipelineStatisticFlagBits input_value) +{ + switch (input_value) + { + case VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI: + return "VK_QUERY_PIPELINE_STATISTIC_CLUSTER_CULLING_SHADER_INVOCATIONS_BIT_HUAWEI"; + case VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT: + return "VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT"; + case VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT: + return "VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT"; + case VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT"; + default: + return "Unhandled VkQueryPipelineStatisticFlagBits"; + } +} + +static inline std::string string_VkQueryPipelineStatisticFlags(VkQueryPipelineStatisticFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueryPipelineStatisticFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueryPipelineStatisticFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryType(VkQueryType input_value) +{ + switch (input_value) + { + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR"; + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV"; + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR"; + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR"; + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR"; + case VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT: + return "VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT"; + case VK_QUERY_TYPE_MICROMAP_COMPACTED_SIZE_EXT: + return "VK_QUERY_TYPE_MICROMAP_COMPACTED_SIZE_EXT"; + case VK_QUERY_TYPE_MICROMAP_SERIALIZATION_SIZE_EXT: + return "VK_QUERY_TYPE_MICROMAP_SERIALIZATION_SIZE_EXT"; + case VK_QUERY_TYPE_OCCLUSION: + return "VK_QUERY_TYPE_OCCLUSION"; + case VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL: + return "VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL"; + case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: + return "VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR"; + case VK_QUERY_TYPE_PIPELINE_STATISTICS: + return "VK_QUERY_TYPE_PIPELINE_STATISTICS"; + case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT: + return "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT"; + case VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR: + return "VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR"; + case VK_QUERY_TYPE_TIMESTAMP: + return "VK_QUERY_TYPE_TIMESTAMP"; + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: + return "VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR: + return "VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkQueryType"; + } +} + +static inline const char* string_VkQueryResultFlagBits(VkQueryResultFlagBits input_value) +{ + switch (input_value) + { + case VK_QUERY_RESULT_64_BIT: + return "VK_QUERY_RESULT_64_BIT"; + case VK_QUERY_RESULT_PARTIAL_BIT: + return "VK_QUERY_RESULT_PARTIAL_BIT"; + case VK_QUERY_RESULT_WAIT_BIT: + return "VK_QUERY_RESULT_WAIT_BIT"; + case VK_QUERY_RESULT_WITH_AVAILABILITY_BIT: + return "VK_QUERY_RESULT_WITH_AVAILABILITY_BIT"; + case VK_QUERY_RESULT_WITH_STATUS_BIT_KHR: + return "VK_QUERY_RESULT_WITH_STATUS_BIT_KHR"; + default: + return "Unhandled VkQueryResultFlagBits"; + } +} + +static inline std::string string_VkQueryResultFlags(VkQueryResultFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueryResultFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueryResultFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBufferCreateFlagBits(VkBufferCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT: + return "VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT"; + case VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT: + return "VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT"; + case VK_BUFFER_CREATE_PROTECTED_BIT: + return "VK_BUFFER_CREATE_PROTECTED_BIT"; + case VK_BUFFER_CREATE_SPARSE_ALIASED_BIT: + return "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT"; + case VK_BUFFER_CREATE_SPARSE_BINDING_BIT: + return "VK_BUFFER_CREATE_SPARSE_BINDING_BIT"; + case VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT: + return "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT"; + default: + return "Unhandled VkBufferCreateFlagBits"; + } +} + +static inline std::string string_VkBufferCreateFlags(VkBufferCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBufferCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBufferCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBufferUsageFlagBits(VkBufferUsageFlagBits input_value) +{ + switch (input_value) + { + case VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR: + return "VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR"; + case VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR: + return "VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR"; + case VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_BUFFER_USAGE_INDEX_BUFFER_BIT: + return "VK_BUFFER_USAGE_INDEX_BUFFER_BIT"; + case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT: + return "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT"; + case VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT: + return "VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT"; + case VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT: + return "VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT"; + case VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR: + return "VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR"; + case VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT: + return "VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT"; + case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT: + return "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT"; + case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT: + return "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT"; + case VK_BUFFER_USAGE_TRANSFER_DST_BIT: + return "VK_BUFFER_USAGE_TRANSFER_DST_BIT"; + case VK_BUFFER_USAGE_TRANSFER_SRC_BIT: + return "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"; + case VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT: + return "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT"; + case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT: + return "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT"; + case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT: + return "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT"; + case VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR"; + case VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkBufferUsageFlagBits"; + } +} + +static inline std::string string_VkBufferUsageFlags(VkBufferUsageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBufferUsageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBufferUsageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSharingMode(VkSharingMode input_value) +{ + switch (input_value) + { + case VK_SHARING_MODE_CONCURRENT: + return "VK_SHARING_MODE_CONCURRENT"; + case VK_SHARING_MODE_EXCLUSIVE: + return "VK_SHARING_MODE_EXCLUSIVE"; + default: + return "Unhandled VkSharingMode"; + } +} + +static inline const char* string_VkComponentSwizzle(VkComponentSwizzle input_value) +{ + switch (input_value) + { + case VK_COMPONENT_SWIZZLE_A: + return "VK_COMPONENT_SWIZZLE_A"; + case VK_COMPONENT_SWIZZLE_B: + return "VK_COMPONENT_SWIZZLE_B"; + case VK_COMPONENT_SWIZZLE_G: + return "VK_COMPONENT_SWIZZLE_G"; + case VK_COMPONENT_SWIZZLE_IDENTITY: + return "VK_COMPONENT_SWIZZLE_IDENTITY"; + case VK_COMPONENT_SWIZZLE_ONE: + return "VK_COMPONENT_SWIZZLE_ONE"; + case VK_COMPONENT_SWIZZLE_R: + return "VK_COMPONENT_SWIZZLE_R"; + case VK_COMPONENT_SWIZZLE_ZERO: + return "VK_COMPONENT_SWIZZLE_ZERO"; + default: + return "Unhandled VkComponentSwizzle"; + } +} + +static inline const char* string_VkImageViewCreateFlagBits(VkImageViewCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT: + return "VK_IMAGE_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT"; + case VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT: + return "VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT"; + case VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT: + return "VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT"; + default: + return "Unhandled VkImageViewCreateFlagBits"; + } +} + +static inline std::string string_VkImageViewCreateFlags(VkImageViewCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageViewCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageViewCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageViewType(VkImageViewType input_value) +{ + switch (input_value) + { + case VK_IMAGE_VIEW_TYPE_1D: + return "VK_IMAGE_VIEW_TYPE_1D"; + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: + return "VK_IMAGE_VIEW_TYPE_1D_ARRAY"; + case VK_IMAGE_VIEW_TYPE_2D: + return "VK_IMAGE_VIEW_TYPE_2D"; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + return "VK_IMAGE_VIEW_TYPE_2D_ARRAY"; + case VK_IMAGE_VIEW_TYPE_3D: + return "VK_IMAGE_VIEW_TYPE_3D"; + case VK_IMAGE_VIEW_TYPE_CUBE: + return "VK_IMAGE_VIEW_TYPE_CUBE"; + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: + return "VK_IMAGE_VIEW_TYPE_CUBE_ARRAY"; + default: + return "Unhandled VkImageViewType"; + } +} + +static inline const char* string_VkPipelineCacheCreateFlagBits(VkPipelineCacheCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT: + return "VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT"; + default: + return "Unhandled VkPipelineCacheCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineCacheCreateFlags(VkPipelineCacheCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCacheCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCacheCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBlendFactor(VkBlendFactor input_value) +{ + switch (input_value) + { + case VK_BLEND_FACTOR_CONSTANT_ALPHA: + return "VK_BLEND_FACTOR_CONSTANT_ALPHA"; + case VK_BLEND_FACTOR_CONSTANT_COLOR: + return "VK_BLEND_FACTOR_CONSTANT_COLOR"; + case VK_BLEND_FACTOR_DST_ALPHA: + return "VK_BLEND_FACTOR_DST_ALPHA"; + case VK_BLEND_FACTOR_DST_COLOR: + return "VK_BLEND_FACTOR_DST_COLOR"; + case VK_BLEND_FACTOR_ONE: + return "VK_BLEND_FACTOR_ONE"; + case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR"; + case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR"; + case VK_BLEND_FACTOR_SRC1_ALPHA: + return "VK_BLEND_FACTOR_SRC1_ALPHA"; + case VK_BLEND_FACTOR_SRC1_COLOR: + return "VK_BLEND_FACTOR_SRC1_COLOR"; + case VK_BLEND_FACTOR_SRC_ALPHA: + return "VK_BLEND_FACTOR_SRC_ALPHA"; + case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: + return "VK_BLEND_FACTOR_SRC_ALPHA_SATURATE"; + case VK_BLEND_FACTOR_SRC_COLOR: + return "VK_BLEND_FACTOR_SRC_COLOR"; + case VK_BLEND_FACTOR_ZERO: + return "VK_BLEND_FACTOR_ZERO"; + default: + return "Unhandled VkBlendFactor"; + } +} + +static inline const char* string_VkBlendOp(VkBlendOp input_value) +{ + switch (input_value) + { + case VK_BLEND_OP_ADD: + return "VK_BLEND_OP_ADD"; + case VK_BLEND_OP_BLUE_EXT: + return "VK_BLEND_OP_BLUE_EXT"; + case VK_BLEND_OP_COLORBURN_EXT: + return "VK_BLEND_OP_COLORBURN_EXT"; + case VK_BLEND_OP_COLORDODGE_EXT: + return "VK_BLEND_OP_COLORDODGE_EXT"; + case VK_BLEND_OP_CONTRAST_EXT: + return "VK_BLEND_OP_CONTRAST_EXT"; + case VK_BLEND_OP_DARKEN_EXT: + return "VK_BLEND_OP_DARKEN_EXT"; + case VK_BLEND_OP_DIFFERENCE_EXT: + return "VK_BLEND_OP_DIFFERENCE_EXT"; + case VK_BLEND_OP_DST_ATOP_EXT: + return "VK_BLEND_OP_DST_ATOP_EXT"; + case VK_BLEND_OP_DST_EXT: + return "VK_BLEND_OP_DST_EXT"; + case VK_BLEND_OP_DST_IN_EXT: + return "VK_BLEND_OP_DST_IN_EXT"; + case VK_BLEND_OP_DST_OUT_EXT: + return "VK_BLEND_OP_DST_OUT_EXT"; + case VK_BLEND_OP_DST_OVER_EXT: + return "VK_BLEND_OP_DST_OVER_EXT"; + case VK_BLEND_OP_EXCLUSION_EXT: + return "VK_BLEND_OP_EXCLUSION_EXT"; + case VK_BLEND_OP_GREEN_EXT: + return "VK_BLEND_OP_GREEN_EXT"; + case VK_BLEND_OP_HARDLIGHT_EXT: + return "VK_BLEND_OP_HARDLIGHT_EXT"; + case VK_BLEND_OP_HARDMIX_EXT: + return "VK_BLEND_OP_HARDMIX_EXT"; + case VK_BLEND_OP_HSL_COLOR_EXT: + return "VK_BLEND_OP_HSL_COLOR_EXT"; + case VK_BLEND_OP_HSL_HUE_EXT: + return "VK_BLEND_OP_HSL_HUE_EXT"; + case VK_BLEND_OP_HSL_LUMINOSITY_EXT: + return "VK_BLEND_OP_HSL_LUMINOSITY_EXT"; + case VK_BLEND_OP_HSL_SATURATION_EXT: + return "VK_BLEND_OP_HSL_SATURATION_EXT"; + case VK_BLEND_OP_INVERT_EXT: + return "VK_BLEND_OP_INVERT_EXT"; + case VK_BLEND_OP_INVERT_OVG_EXT: + return "VK_BLEND_OP_INVERT_OVG_EXT"; + case VK_BLEND_OP_INVERT_RGB_EXT: + return "VK_BLEND_OP_INVERT_RGB_EXT"; + case VK_BLEND_OP_LIGHTEN_EXT: + return "VK_BLEND_OP_LIGHTEN_EXT"; + case VK_BLEND_OP_LINEARBURN_EXT: + return "VK_BLEND_OP_LINEARBURN_EXT"; + case VK_BLEND_OP_LINEARDODGE_EXT: + return "VK_BLEND_OP_LINEARDODGE_EXT"; + case VK_BLEND_OP_LINEARLIGHT_EXT: + return "VK_BLEND_OP_LINEARLIGHT_EXT"; + case VK_BLEND_OP_MAX: + return "VK_BLEND_OP_MAX"; + case VK_BLEND_OP_MIN: + return "VK_BLEND_OP_MIN"; + case VK_BLEND_OP_MINUS_CLAMPED_EXT: + return "VK_BLEND_OP_MINUS_CLAMPED_EXT"; + case VK_BLEND_OP_MINUS_EXT: + return "VK_BLEND_OP_MINUS_EXT"; + case VK_BLEND_OP_MULTIPLY_EXT: + return "VK_BLEND_OP_MULTIPLY_EXT"; + case VK_BLEND_OP_OVERLAY_EXT: + return "VK_BLEND_OP_OVERLAY_EXT"; + case VK_BLEND_OP_PINLIGHT_EXT: + return "VK_BLEND_OP_PINLIGHT_EXT"; + case VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT: + return "VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT"; + case VK_BLEND_OP_PLUS_CLAMPED_EXT: + return "VK_BLEND_OP_PLUS_CLAMPED_EXT"; + case VK_BLEND_OP_PLUS_DARKER_EXT: + return "VK_BLEND_OP_PLUS_DARKER_EXT"; + case VK_BLEND_OP_PLUS_EXT: + return "VK_BLEND_OP_PLUS_EXT"; + case VK_BLEND_OP_RED_EXT: + return "VK_BLEND_OP_RED_EXT"; + case VK_BLEND_OP_REVERSE_SUBTRACT: + return "VK_BLEND_OP_REVERSE_SUBTRACT"; + case VK_BLEND_OP_SCREEN_EXT: + return "VK_BLEND_OP_SCREEN_EXT"; + case VK_BLEND_OP_SOFTLIGHT_EXT: + return "VK_BLEND_OP_SOFTLIGHT_EXT"; + case VK_BLEND_OP_SRC_ATOP_EXT: + return "VK_BLEND_OP_SRC_ATOP_EXT"; + case VK_BLEND_OP_SRC_EXT: + return "VK_BLEND_OP_SRC_EXT"; + case VK_BLEND_OP_SRC_IN_EXT: + return "VK_BLEND_OP_SRC_IN_EXT"; + case VK_BLEND_OP_SRC_OUT_EXT: + return "VK_BLEND_OP_SRC_OUT_EXT"; + case VK_BLEND_OP_SRC_OVER_EXT: + return "VK_BLEND_OP_SRC_OVER_EXT"; + case VK_BLEND_OP_SUBTRACT: + return "VK_BLEND_OP_SUBTRACT"; + case VK_BLEND_OP_VIVIDLIGHT_EXT: + return "VK_BLEND_OP_VIVIDLIGHT_EXT"; + case VK_BLEND_OP_XOR_EXT: + return "VK_BLEND_OP_XOR_EXT"; + case VK_BLEND_OP_ZERO_EXT: + return "VK_BLEND_OP_ZERO_EXT"; + default: + return "Unhandled VkBlendOp"; + } +} + +static inline const char* string_VkColorComponentFlagBits(VkColorComponentFlagBits input_value) +{ + switch (input_value) + { + case VK_COLOR_COMPONENT_A_BIT: + return "VK_COLOR_COMPONENT_A_BIT"; + case VK_COLOR_COMPONENT_B_BIT: + return "VK_COLOR_COMPONENT_B_BIT"; + case VK_COLOR_COMPONENT_G_BIT: + return "VK_COLOR_COMPONENT_G_BIT"; + case VK_COLOR_COMPONENT_R_BIT: + return "VK_COLOR_COMPONENT_R_BIT"; + default: + return "Unhandled VkColorComponentFlagBits"; + } +} + +static inline std::string string_VkColorComponentFlags(VkColorComponentFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkColorComponentFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkColorComponentFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCompareOp(VkCompareOp input_value) +{ + switch (input_value) + { + case VK_COMPARE_OP_ALWAYS: + return "VK_COMPARE_OP_ALWAYS"; + case VK_COMPARE_OP_EQUAL: + return "VK_COMPARE_OP_EQUAL"; + case VK_COMPARE_OP_GREATER: + return "VK_COMPARE_OP_GREATER"; + case VK_COMPARE_OP_GREATER_OR_EQUAL: + return "VK_COMPARE_OP_GREATER_OR_EQUAL"; + case VK_COMPARE_OP_LESS: + return "VK_COMPARE_OP_LESS"; + case VK_COMPARE_OP_LESS_OR_EQUAL: + return "VK_COMPARE_OP_LESS_OR_EQUAL"; + case VK_COMPARE_OP_NEVER: + return "VK_COMPARE_OP_NEVER"; + case VK_COMPARE_OP_NOT_EQUAL: + return "VK_COMPARE_OP_NOT_EQUAL"; + default: + return "Unhandled VkCompareOp"; + } +} + +static inline const char* string_VkPipelineCreateFlagBits(VkPipelineCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT: + return "VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT"; + case VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR: + return "VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR"; + case VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR: + return "VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR"; + case VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT: + return "VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; + case VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV: + return "VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV"; + case VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT: + return "VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT"; + case VK_PIPELINE_CREATE_DERIVATIVE_BIT: + return "VK_PIPELINE_CREATE_DERIVATIVE_BIT"; + case VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT: + return "VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT"; + case VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT: + return "VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT"; + case VK_PIPELINE_CREATE_DISPATCH_BASE_BIT: + return "VK_PIPELINE_CREATE_DISPATCH_BASE_BIT"; + case VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT: + return "VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT"; + case VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT: + return "VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT"; + case VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV: + return "VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV"; + case VK_PIPELINE_CREATE_LIBRARY_BIT_KHR: + return "VK_PIPELINE_CREATE_LIBRARY_BIT_KHR"; + case VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT: + return "VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT"; + case VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT: + return "VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT"; + case VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT: + return "VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT"; + case VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV: + return "VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT: + return "VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT"; + case VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR"; + case VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT: + return "VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT"; + case VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT: + return "VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT"; + case VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT: + return "VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT"; + default: + return "Unhandled VkPipelineCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineCreateFlags(VkPipelineCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineShaderStageCreateFlagBits(VkPipelineShaderStageCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT: + return "VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT"; + case VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT: + return "VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT"; + default: + return "Unhandled VkPipelineShaderStageCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineShaderStageCreateFlags(VkPipelineShaderStageCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineShaderStageCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineShaderStageCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkShaderStageFlagBits(VkShaderStageFlagBits input_value) +{ + switch (input_value) + { + case VK_SHADER_STAGE_ALL: + return "VK_SHADER_STAGE_ALL"; + case VK_SHADER_STAGE_ALL_GRAPHICS: + return "VK_SHADER_STAGE_ALL_GRAPHICS"; + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + return "VK_SHADER_STAGE_ANY_HIT_BIT_KHR"; + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + return "VK_SHADER_STAGE_CALLABLE_BIT_KHR"; + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + return "VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR"; + case VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI: + return "VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI"; + case VK_SHADER_STAGE_COMPUTE_BIT: + return "VK_SHADER_STAGE_COMPUTE_BIT"; + case VK_SHADER_STAGE_FRAGMENT_BIT: + return "VK_SHADER_STAGE_FRAGMENT_BIT"; + case VK_SHADER_STAGE_GEOMETRY_BIT: + return "VK_SHADER_STAGE_GEOMETRY_BIT"; + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + return "VK_SHADER_STAGE_INTERSECTION_BIT_KHR"; + case VK_SHADER_STAGE_MESH_BIT_EXT: + return "VK_SHADER_STAGE_MESH_BIT_EXT"; + case VK_SHADER_STAGE_MISS_BIT_KHR: + return "VK_SHADER_STAGE_MISS_BIT_KHR"; + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + return "VK_SHADER_STAGE_RAYGEN_BIT_KHR"; + case VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI: + return "VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI"; + case VK_SHADER_STAGE_TASK_BIT_EXT: + return "VK_SHADER_STAGE_TASK_BIT_EXT"; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + return "VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT"; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + return "VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT"; + case VK_SHADER_STAGE_VERTEX_BIT: + return "VK_SHADER_STAGE_VERTEX_BIT"; + default: + return "Unhandled VkShaderStageFlagBits"; + } +} + +static inline std::string string_VkShaderStageFlags(VkShaderStageFlags input_value) +{ + if (input_value == VK_SHADER_STAGE_ALL) { return "VK_SHADER_STAGE_ALL"; } + if (input_value == VK_SHADER_STAGE_ALL_GRAPHICS) { return "VK_SHADER_STAGE_ALL_GRAPHICS"; } + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkShaderStageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkShaderStageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCullModeFlagBits(VkCullModeFlagBits input_value) +{ + switch (input_value) + { + case VK_CULL_MODE_BACK_BIT: + return "VK_CULL_MODE_BACK_BIT"; + case VK_CULL_MODE_FRONT_AND_BACK: + return "VK_CULL_MODE_FRONT_AND_BACK"; + case VK_CULL_MODE_FRONT_BIT: + return "VK_CULL_MODE_FRONT_BIT"; + case VK_CULL_MODE_NONE: + return "VK_CULL_MODE_NONE"; + default: + return "Unhandled VkCullModeFlagBits"; + } +} + +static inline std::string string_VkCullModeFlags(VkCullModeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCullModeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCullModeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDynamicState(VkDynamicState input_value) +{ + switch (input_value) + { + case VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT: + return "VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT"; + case VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT: + return "VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT"; + case VK_DYNAMIC_STATE_BLEND_CONSTANTS: + return "VK_DYNAMIC_STATE_BLEND_CONSTANTS"; + case VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT: + return "VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT"; + case VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT: + return "VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT"; + case VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT: + return "VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT"; + case VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT: + return "VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT"; + case VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT: + return "VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT"; + case VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT: + return "VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT"; + case VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV: + return "VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV"; + case VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV: + return "VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV"; + case VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV: + return "VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV"; + case VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV: + return "VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV"; + case VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV: + return "VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV"; + case VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV: + return "VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV"; + case VK_DYNAMIC_STATE_CULL_MODE: + return "VK_DYNAMIC_STATE_CULL_MODE"; + case VK_DYNAMIC_STATE_DEPTH_BIAS: + return "VK_DYNAMIC_STATE_DEPTH_BIAS"; + case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE: + return "VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE"; + case VK_DYNAMIC_STATE_DEPTH_BOUNDS: + return "VK_DYNAMIC_STATE_DEPTH_BOUNDS"; + case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE: + return "VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE"; + case VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP: + return "VK_DYNAMIC_STATE_DEPTH_COMPARE_OP"; + case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE: + return "VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE"; + case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE: + return "VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE"; + case VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT: + return "VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT"; + case VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV: + return "VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV"; + case VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT: + return "VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT"; + case VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR: + return "VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR"; + case VK_DYNAMIC_STATE_FRONT_FACE: + return "VK_DYNAMIC_STATE_FRONT_FACE"; + case VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT: + return "VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT"; + case VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT: + return "VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT"; + case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT: + return "VK_DYNAMIC_STATE_LINE_STIPPLE_EXT"; + case VK_DYNAMIC_STATE_LINE_WIDTH: + return "VK_DYNAMIC_STATE_LINE_WIDTH"; + case VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT: + return "VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT"; + case VK_DYNAMIC_STATE_LOGIC_OP_EXT: + return "VK_DYNAMIC_STATE_LOGIC_OP_EXT"; + case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT: + return "VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT"; + case VK_DYNAMIC_STATE_POLYGON_MODE_EXT: + return "VK_DYNAMIC_STATE_POLYGON_MODE_EXT"; + case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE: + return "VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE"; + case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY: + return "VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY"; + case VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT: + return "VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT"; + case VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT: + return "VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT"; + case VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT: + return "VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT"; + case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE: + return "VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE"; + case VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR: + return "VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR"; + case VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV: + return "VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV"; + case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT: + return "VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT"; + case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT: + return "VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT"; + case VK_DYNAMIC_STATE_SAMPLE_MASK_EXT: + return "VK_DYNAMIC_STATE_SAMPLE_MASK_EXT"; + case VK_DYNAMIC_STATE_SCISSOR: + return "VK_DYNAMIC_STATE_SCISSOR"; + case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT: + return "VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT"; + case VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV: + return "VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV"; + case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: + return "VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK"; + case VK_DYNAMIC_STATE_STENCIL_OP: + return "VK_DYNAMIC_STATE_STENCIL_OP"; + case VK_DYNAMIC_STATE_STENCIL_REFERENCE: + return "VK_DYNAMIC_STATE_STENCIL_REFERENCE"; + case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE: + return "VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE"; + case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: + return "VK_DYNAMIC_STATE_STENCIL_WRITE_MASK"; + case VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT: + return "VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT"; + case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE: + return "VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE"; + case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT: + return "VK_DYNAMIC_STATE_VERTEX_INPUT_EXT"; + case VK_DYNAMIC_STATE_VIEWPORT: + return "VK_DYNAMIC_STATE_VIEWPORT"; + case VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV"; + case VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV"; + case VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV"; + case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT: + return "VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT"; + case VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV"; + case VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV"; + default: + return "Unhandled VkDynamicState"; + } +} + +static inline const char* string_VkFrontFace(VkFrontFace input_value) +{ + switch (input_value) + { + case VK_FRONT_FACE_CLOCKWISE: + return "VK_FRONT_FACE_CLOCKWISE"; + case VK_FRONT_FACE_COUNTER_CLOCKWISE: + return "VK_FRONT_FACE_COUNTER_CLOCKWISE"; + default: + return "Unhandled VkFrontFace"; + } +} + +static inline const char* string_VkVertexInputRate(VkVertexInputRate input_value) +{ + switch (input_value) + { + case VK_VERTEX_INPUT_RATE_INSTANCE: + return "VK_VERTEX_INPUT_RATE_INSTANCE"; + case VK_VERTEX_INPUT_RATE_VERTEX: + return "VK_VERTEX_INPUT_RATE_VERTEX"; + default: + return "Unhandled VkVertexInputRate"; + } +} + +static inline const char* string_VkPrimitiveTopology(VkPrimitiveTopology input_value) +{ + switch (input_value) + { + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST"; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY"; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP"; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY"; + case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + return "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST"; + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return "VK_PRIMITIVE_TOPOLOGY_POINT_LIST"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY"; + default: + return "Unhandled VkPrimitiveTopology"; + } +} + +static inline const char* string_VkPolygonMode(VkPolygonMode input_value) +{ + switch (input_value) + { + case VK_POLYGON_MODE_FILL: + return "VK_POLYGON_MODE_FILL"; + case VK_POLYGON_MODE_FILL_RECTANGLE_NV: + return "VK_POLYGON_MODE_FILL_RECTANGLE_NV"; + case VK_POLYGON_MODE_LINE: + return "VK_POLYGON_MODE_LINE"; + case VK_POLYGON_MODE_POINT: + return "VK_POLYGON_MODE_POINT"; + default: + return "Unhandled VkPolygonMode"; + } +} + +static inline const char* string_VkPipelineDepthStencilStateCreateFlagBits(VkPipelineDepthStencilStateCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT: + return "VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT"; + case VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT: + return "VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT"; + default: + return "Unhandled VkPipelineDepthStencilStateCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineDepthStencilStateCreateFlags(VkPipelineDepthStencilStateCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineDepthStencilStateCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineDepthStencilStateCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkStencilOp(VkStencilOp input_value) +{ + switch (input_value) + { + case VK_STENCIL_OP_DECREMENT_AND_CLAMP: + return "VK_STENCIL_OP_DECREMENT_AND_CLAMP"; + case VK_STENCIL_OP_DECREMENT_AND_WRAP: + return "VK_STENCIL_OP_DECREMENT_AND_WRAP"; + case VK_STENCIL_OP_INCREMENT_AND_CLAMP: + return "VK_STENCIL_OP_INCREMENT_AND_CLAMP"; + case VK_STENCIL_OP_INCREMENT_AND_WRAP: + return "VK_STENCIL_OP_INCREMENT_AND_WRAP"; + case VK_STENCIL_OP_INVERT: + return "VK_STENCIL_OP_INVERT"; + case VK_STENCIL_OP_KEEP: + return "VK_STENCIL_OP_KEEP"; + case VK_STENCIL_OP_REPLACE: + return "VK_STENCIL_OP_REPLACE"; + case VK_STENCIL_OP_ZERO: + return "VK_STENCIL_OP_ZERO"; + default: + return "Unhandled VkStencilOp"; + } +} + +static inline const char* string_VkPipelineColorBlendStateCreateFlagBits(VkPipelineColorBlendStateCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT: + return "VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT"; + default: + return "Unhandled VkPipelineColorBlendStateCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineColorBlendStateCreateFlags(VkPipelineColorBlendStateCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineColorBlendStateCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineColorBlendStateCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkLogicOp(VkLogicOp input_value) +{ + switch (input_value) + { + case VK_LOGIC_OP_AND: + return "VK_LOGIC_OP_AND"; + case VK_LOGIC_OP_AND_INVERTED: + return "VK_LOGIC_OP_AND_INVERTED"; + case VK_LOGIC_OP_AND_REVERSE: + return "VK_LOGIC_OP_AND_REVERSE"; + case VK_LOGIC_OP_CLEAR: + return "VK_LOGIC_OP_CLEAR"; + case VK_LOGIC_OP_COPY: + return "VK_LOGIC_OP_COPY"; + case VK_LOGIC_OP_COPY_INVERTED: + return "VK_LOGIC_OP_COPY_INVERTED"; + case VK_LOGIC_OP_EQUIVALENT: + return "VK_LOGIC_OP_EQUIVALENT"; + case VK_LOGIC_OP_INVERT: + return "VK_LOGIC_OP_INVERT"; + case VK_LOGIC_OP_NAND: + return "VK_LOGIC_OP_NAND"; + case VK_LOGIC_OP_NOR: + return "VK_LOGIC_OP_NOR"; + case VK_LOGIC_OP_NO_OP: + return "VK_LOGIC_OP_NO_OP"; + case VK_LOGIC_OP_OR: + return "VK_LOGIC_OP_OR"; + case VK_LOGIC_OP_OR_INVERTED: + return "VK_LOGIC_OP_OR_INVERTED"; + case VK_LOGIC_OP_OR_REVERSE: + return "VK_LOGIC_OP_OR_REVERSE"; + case VK_LOGIC_OP_SET: + return "VK_LOGIC_OP_SET"; + case VK_LOGIC_OP_XOR: + return "VK_LOGIC_OP_XOR"; + default: + return "Unhandled VkLogicOp"; + } +} + +static inline const char* string_VkPipelineLayoutCreateFlagBits(VkPipelineLayoutCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT: + return "VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT"; + default: + return "Unhandled VkPipelineLayoutCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineLayoutCreateFlags(VkPipelineLayoutCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineLayoutCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineLayoutCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBorderColor(VkBorderColor input_value) +{ + switch (input_value) + { + case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: + return "VK_BORDER_COLOR_FLOAT_CUSTOM_EXT"; + case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: + return "VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK"; + case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: + return "VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE"; + case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: + return "VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK"; + case VK_BORDER_COLOR_INT_CUSTOM_EXT: + return "VK_BORDER_COLOR_INT_CUSTOM_EXT"; + case VK_BORDER_COLOR_INT_OPAQUE_BLACK: + return "VK_BORDER_COLOR_INT_OPAQUE_BLACK"; + case VK_BORDER_COLOR_INT_OPAQUE_WHITE: + return "VK_BORDER_COLOR_INT_OPAQUE_WHITE"; + case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: + return "VK_BORDER_COLOR_INT_TRANSPARENT_BLACK"; + default: + return "Unhandled VkBorderColor"; + } +} + +static inline const char* string_VkFilter(VkFilter input_value) +{ + switch (input_value) + { + case VK_FILTER_CUBIC_EXT: + return "VK_FILTER_CUBIC_EXT"; + case VK_FILTER_LINEAR: + return "VK_FILTER_LINEAR"; + case VK_FILTER_NEAREST: + return "VK_FILTER_NEAREST"; + default: + return "Unhandled VkFilter"; + } +} + +static inline const char* string_VkSamplerAddressMode(VkSamplerAddressMode input_value) +{ + switch (input_value) + { + case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: + return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER"; + case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: + return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE"; + case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: + return "VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT"; + case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: + return "VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE"; + case VK_SAMPLER_ADDRESS_MODE_REPEAT: + return "VK_SAMPLER_ADDRESS_MODE_REPEAT"; + default: + return "Unhandled VkSamplerAddressMode"; + } +} + +static inline const char* string_VkSamplerCreateFlagBits(VkSamplerCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT: + return "VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT"; + case VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM: + return "VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM"; + case VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT: + return "VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT"; + case VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT: + return "VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT"; + case VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT: + return "VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT"; + default: + return "Unhandled VkSamplerCreateFlagBits"; + } +} + +static inline std::string string_VkSamplerCreateFlags(VkSamplerCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSamplerCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSamplerCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSamplerMipmapMode(VkSamplerMipmapMode input_value) +{ + switch (input_value) + { + case VK_SAMPLER_MIPMAP_MODE_LINEAR: + return "VK_SAMPLER_MIPMAP_MODE_LINEAR"; + case VK_SAMPLER_MIPMAP_MODE_NEAREST: + return "VK_SAMPLER_MIPMAP_MODE_NEAREST"; + default: + return "Unhandled VkSamplerMipmapMode"; + } +} + +static inline const char* string_VkDescriptorPoolCreateFlagBits(VkDescriptorPoolCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT: + return "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT"; + case VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT: + return "VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT"; + case VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT: + return "VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT"; + default: + return "Unhandled VkDescriptorPoolCreateFlagBits"; + } +} + +static inline std::string string_VkDescriptorPoolCreateFlags(VkDescriptorPoolCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorPoolCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorPoolCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDescriptorType(VkDescriptorType input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return "VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR"; + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: + return "VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV"; + case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM: + return "VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM"; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER"; + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: + return "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK"; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT"; + case VK_DESCRIPTOR_TYPE_MUTABLE_EXT: + return "VK_DESCRIPTOR_TYPE_MUTABLE_EXT"; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE"; + case VK_DESCRIPTOR_TYPE_SAMPLER: + return "VK_DESCRIPTOR_TYPE_SAMPLER"; + case VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM: + return "VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM"; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER"; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC"; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + return "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + return "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER"; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER"; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC"; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + return "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER"; + default: + return "Unhandled VkDescriptorType"; + } +} + +static inline const char* string_VkDescriptorSetLayoutCreateFlagBits(VkDescriptorSetLayoutCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT"; + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT"; + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT"; + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR"; + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT"; + default: + return "Unhandled VkDescriptorSetLayoutCreateFlagBits"; + } +} + +static inline std::string string_VkDescriptorSetLayoutCreateFlags(VkDescriptorSetLayoutCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorSetLayoutCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorSetLayoutCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkAttachmentDescriptionFlagBits(VkAttachmentDescriptionFlagBits input_value) +{ + switch (input_value) + { + case VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT: + return "VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT"; + default: + return "Unhandled VkAttachmentDescriptionFlagBits"; + } +} + +static inline std::string string_VkAttachmentDescriptionFlags(VkAttachmentDescriptionFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAttachmentDescriptionFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAttachmentDescriptionFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkAttachmentLoadOp(VkAttachmentLoadOp input_value) +{ + switch (input_value) + { + case VK_ATTACHMENT_LOAD_OP_CLEAR: + return "VK_ATTACHMENT_LOAD_OP_CLEAR"; + case VK_ATTACHMENT_LOAD_OP_DONT_CARE: + return "VK_ATTACHMENT_LOAD_OP_DONT_CARE"; + case VK_ATTACHMENT_LOAD_OP_LOAD: + return "VK_ATTACHMENT_LOAD_OP_LOAD"; + case VK_ATTACHMENT_LOAD_OP_NONE_EXT: + return "VK_ATTACHMENT_LOAD_OP_NONE_EXT"; + default: + return "Unhandled VkAttachmentLoadOp"; + } +} + +static inline const char* string_VkAttachmentStoreOp(VkAttachmentStoreOp input_value) +{ + switch (input_value) + { + case VK_ATTACHMENT_STORE_OP_DONT_CARE: + return "VK_ATTACHMENT_STORE_OP_DONT_CARE"; + case VK_ATTACHMENT_STORE_OP_NONE: + return "VK_ATTACHMENT_STORE_OP_NONE"; + case VK_ATTACHMENT_STORE_OP_STORE: + return "VK_ATTACHMENT_STORE_OP_STORE"; + default: + return "Unhandled VkAttachmentStoreOp"; + } +} + +static inline const char* string_VkDependencyFlagBits(VkDependencyFlagBits input_value) +{ + switch (input_value) + { + case VK_DEPENDENCY_BY_REGION_BIT: + return "VK_DEPENDENCY_BY_REGION_BIT"; + case VK_DEPENDENCY_DEVICE_GROUP_BIT: + return "VK_DEPENDENCY_DEVICE_GROUP_BIT"; + case VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT: + return "VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT"; + case VK_DEPENDENCY_VIEW_LOCAL_BIT: + return "VK_DEPENDENCY_VIEW_LOCAL_BIT"; + default: + return "Unhandled VkDependencyFlagBits"; + } +} + +static inline std::string string_VkDependencyFlags(VkDependencyFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDependencyFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDependencyFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFramebufferCreateFlagBits(VkFramebufferCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT: + return "VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT"; + default: + return "Unhandled VkFramebufferCreateFlagBits"; + } +} + +static inline std::string string_VkFramebufferCreateFlags(VkFramebufferCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFramebufferCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFramebufferCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineBindPoint(VkPipelineBindPoint input_value) +{ + switch (input_value) + { + case VK_PIPELINE_BIND_POINT_COMPUTE: + return "VK_PIPELINE_BIND_POINT_COMPUTE"; + case VK_PIPELINE_BIND_POINT_GRAPHICS: + return "VK_PIPELINE_BIND_POINT_GRAPHICS"; + case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR: + return "VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR"; + case VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI: + return "VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI"; + default: + return "Unhandled VkPipelineBindPoint"; + } +} + +static inline const char* string_VkRenderPassCreateFlagBits(VkRenderPassCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM: + return "VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM"; + default: + return "Unhandled VkRenderPassCreateFlagBits"; + } +} + +static inline std::string string_VkRenderPassCreateFlags(VkRenderPassCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkRenderPassCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkRenderPassCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubpassDescriptionFlagBits(VkSubpassDescriptionFlagBits input_value) +{ + switch (input_value) + { + case VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT: + return "VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT"; + case VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM: + return "VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM"; + case VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX: + return "VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX"; + case VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX: + return "VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX"; + case VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT: + return "VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT"; + case VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT: + return "VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT"; + case VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT: + return "VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT"; + case VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM: + return "VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM"; + default: + return "Unhandled VkSubpassDescriptionFlagBits"; + } +} + +static inline std::string string_VkSubpassDescriptionFlags(VkSubpassDescriptionFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubpassDescriptionFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubpassDescriptionFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandPoolCreateFlagBits(VkCommandPoolCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_POOL_CREATE_PROTECTED_BIT: + return "VK_COMMAND_POOL_CREATE_PROTECTED_BIT"; + case VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT: + return "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT"; + case VK_COMMAND_POOL_CREATE_TRANSIENT_BIT: + return "VK_COMMAND_POOL_CREATE_TRANSIENT_BIT"; + default: + return "Unhandled VkCommandPoolCreateFlagBits"; + } +} + +static inline std::string string_VkCommandPoolCreateFlags(VkCommandPoolCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandPoolCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandPoolCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandPoolResetFlagBits(VkCommandPoolResetFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT: + return "VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT"; + default: + return "Unhandled VkCommandPoolResetFlagBits"; + } +} + +static inline std::string string_VkCommandPoolResetFlags(VkCommandPoolResetFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandPoolResetFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandPoolResetFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandBufferLevel(VkCommandBufferLevel input_value) +{ + switch (input_value) + { + case VK_COMMAND_BUFFER_LEVEL_PRIMARY: + return "VK_COMMAND_BUFFER_LEVEL_PRIMARY"; + case VK_COMMAND_BUFFER_LEVEL_SECONDARY: + return "VK_COMMAND_BUFFER_LEVEL_SECONDARY"; + default: + return "Unhandled VkCommandBufferLevel"; + } +} + +static inline const char* string_VkCommandBufferUsageFlagBits(VkCommandBufferUsageFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT: + return "VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT"; + case VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT: + return "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT"; + case VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT: + return "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT"; + default: + return "Unhandled VkCommandBufferUsageFlagBits"; + } +} + +static inline std::string string_VkCommandBufferUsageFlags(VkCommandBufferUsageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandBufferUsageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandBufferUsageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryControlFlagBits(VkQueryControlFlagBits input_value) +{ + switch (input_value) + { + case VK_QUERY_CONTROL_PRECISE_BIT: + return "VK_QUERY_CONTROL_PRECISE_BIT"; + default: + return "Unhandled VkQueryControlFlagBits"; + } +} + +static inline std::string string_VkQueryControlFlags(VkQueryControlFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueryControlFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueryControlFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandBufferResetFlagBits(VkCommandBufferResetFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT: + return "VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT"; + default: + return "Unhandled VkCommandBufferResetFlagBits"; + } +} + +static inline std::string string_VkCommandBufferResetFlags(VkCommandBufferResetFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandBufferResetFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandBufferResetFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkIndexType(VkIndexType input_value) +{ + switch (input_value) + { + case VK_INDEX_TYPE_NONE_KHR: + return "VK_INDEX_TYPE_NONE_KHR"; + case VK_INDEX_TYPE_UINT16: + return "VK_INDEX_TYPE_UINT16"; + case VK_INDEX_TYPE_UINT32: + return "VK_INDEX_TYPE_UINT32"; + case VK_INDEX_TYPE_UINT8_EXT: + return "VK_INDEX_TYPE_UINT8_EXT"; + default: + return "Unhandled VkIndexType"; + } +} + +static inline const char* string_VkStencilFaceFlagBits(VkStencilFaceFlagBits input_value) +{ + switch (input_value) + { + case VK_STENCIL_FACE_BACK_BIT: + return "VK_STENCIL_FACE_BACK_BIT"; + case VK_STENCIL_FACE_FRONT_AND_BACK: + return "VK_STENCIL_FACE_FRONT_AND_BACK"; + case VK_STENCIL_FACE_FRONT_BIT: + return "VK_STENCIL_FACE_FRONT_BIT"; + default: + return "Unhandled VkStencilFaceFlagBits"; + } +} + +static inline std::string string_VkStencilFaceFlags(VkStencilFaceFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkStencilFaceFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkStencilFaceFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubpassContents(VkSubpassContents input_value) +{ + switch (input_value) + { + case VK_SUBPASS_CONTENTS_INLINE: + return "VK_SUBPASS_CONTENTS_INLINE"; + case VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS: + return "VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS"; + default: + return "Unhandled VkSubpassContents"; + } +} + +static inline const char* string_VkSubgroupFeatureFlagBits(VkSubgroupFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_SUBGROUP_FEATURE_ARITHMETIC_BIT: + return "VK_SUBGROUP_FEATURE_ARITHMETIC_BIT"; + case VK_SUBGROUP_FEATURE_BALLOT_BIT: + return "VK_SUBGROUP_FEATURE_BALLOT_BIT"; + case VK_SUBGROUP_FEATURE_BASIC_BIT: + return "VK_SUBGROUP_FEATURE_BASIC_BIT"; + case VK_SUBGROUP_FEATURE_CLUSTERED_BIT: + return "VK_SUBGROUP_FEATURE_CLUSTERED_BIT"; + case VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV: + return "VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV"; + case VK_SUBGROUP_FEATURE_QUAD_BIT: + return "VK_SUBGROUP_FEATURE_QUAD_BIT"; + case VK_SUBGROUP_FEATURE_SHUFFLE_BIT: + return "VK_SUBGROUP_FEATURE_SHUFFLE_BIT"; + case VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT: + return "VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT"; + case VK_SUBGROUP_FEATURE_VOTE_BIT: + return "VK_SUBGROUP_FEATURE_VOTE_BIT"; + default: + return "Unhandled VkSubgroupFeatureFlagBits"; + } +} + +static inline std::string string_VkSubgroupFeatureFlags(VkSubgroupFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubgroupFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubgroupFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPeerMemoryFeatureFlagBits(VkPeerMemoryFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_PEER_MEMORY_FEATURE_COPY_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT"; + default: + return "Unhandled VkPeerMemoryFeatureFlagBits"; + } +} + +static inline std::string string_VkPeerMemoryFeatureFlags(VkPeerMemoryFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPeerMemoryFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPeerMemoryFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryAllocateFlagBits(VkMemoryAllocateFlagBits input_value) +{ + switch (input_value) + { + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT"; + default: + return "Unhandled VkMemoryAllocateFlagBits"; + } +} + +static inline std::string string_VkMemoryAllocateFlags(VkMemoryAllocateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryAllocateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryAllocateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPointClippingBehavior(VkPointClippingBehavior input_value) +{ + switch (input_value) + { + case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES: + return "VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES"; + case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY: + return "VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY"; + default: + return "Unhandled VkPointClippingBehavior"; + } +} + +static inline const char* string_VkTessellationDomainOrigin(VkTessellationDomainOrigin input_value) +{ + switch (input_value) + { + case VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT"; + case VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT"; + default: + return "Unhandled VkTessellationDomainOrigin"; + } +} + +static inline const char* string_VkSamplerYcbcrModelConversion(VkSamplerYcbcrModelConversion input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY"; + default: + return "Unhandled VkSamplerYcbcrModelConversion"; + } +} + +static inline const char* string_VkSamplerYcbcrRange(VkSamplerYcbcrRange input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: + return "VK_SAMPLER_YCBCR_RANGE_ITU_FULL"; + case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: + return "VK_SAMPLER_YCBCR_RANGE_ITU_NARROW"; + default: + return "Unhandled VkSamplerYcbcrRange"; + } +} + +static inline const char* string_VkChromaLocation(VkChromaLocation input_value) +{ + switch (input_value) + { + case VK_CHROMA_LOCATION_COSITED_EVEN: + return "VK_CHROMA_LOCATION_COSITED_EVEN"; + case VK_CHROMA_LOCATION_MIDPOINT: + return "VK_CHROMA_LOCATION_MIDPOINT"; + default: + return "Unhandled VkChromaLocation"; + } +} + +static inline const char* string_VkDescriptorUpdateTemplateType(VkDescriptorUpdateTemplateType input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET"; + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR"; + default: + return "Unhandled VkDescriptorUpdateTemplateType"; + } +} + +static inline const char* string_VkExternalMemoryHandleTypeFlagBits(VkExternalMemoryHandleTypeFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalMemoryHandleTypeFlagBits"; + } +} + +static inline std::string string_VkExternalMemoryHandleTypeFlags(VkExternalMemoryHandleTypeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryHandleTypeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryFeatureFlagBits(VkExternalMemoryFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalMemoryFeatureFlagBits"; + } +} + +static inline std::string string_VkExternalMemoryFeatureFlags(VkExternalMemoryFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalFenceHandleTypeFlagBits(VkExternalFenceHandleTypeFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT"; + default: + return "Unhandled VkExternalFenceHandleTypeFlagBits"; + } +} + +static inline std::string string_VkExternalFenceHandleTypeFlags(VkExternalFenceHandleTypeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceHandleTypeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceHandleTypeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalFenceFeatureFlagBits(VkExternalFenceFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalFenceFeatureFlagBits"; + } +} + +static inline std::string string_VkExternalFenceFeatureFlags(VkExternalFenceFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFenceImportFlagBits(VkFenceImportFlagBits input_value) +{ + switch (input_value) + { + case VK_FENCE_IMPORT_TEMPORARY_BIT: + return "VK_FENCE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkFenceImportFlagBits"; + } +} + +static inline std::string string_VkFenceImportFlags(VkFenceImportFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFenceImportFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFenceImportFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSemaphoreImportFlagBits(VkSemaphoreImportFlagBits input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT: + return "VK_SEMAPHORE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkSemaphoreImportFlagBits"; + } +} + +static inline std::string string_VkSemaphoreImportFlags(VkSemaphoreImportFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreImportFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreImportFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreHandleTypeFlagBits(VkExternalSemaphoreHandleTypeFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalSemaphoreHandleTypeFlagBits"; + } +} + +static inline std::string string_VkExternalSemaphoreHandleTypeFlags(VkExternalSemaphoreHandleTypeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreHandleTypeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreHandleTypeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreFeatureFlagBits(VkExternalSemaphoreFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalSemaphoreFeatureFlagBits"; + } +} + +static inline std::string string_VkExternalSemaphoreFeatureFlags(VkExternalSemaphoreFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDriverId(VkDriverId input_value) +{ + switch (input_value) + { + case VK_DRIVER_ID_AMD_OPEN_SOURCE: + return "VK_DRIVER_ID_AMD_OPEN_SOURCE"; + case VK_DRIVER_ID_AMD_PROPRIETARY: + return "VK_DRIVER_ID_AMD_PROPRIETARY"; + case VK_DRIVER_ID_ARM_PROPRIETARY: + return "VK_DRIVER_ID_ARM_PROPRIETARY"; + case VK_DRIVER_ID_BROADCOM_PROPRIETARY: + return "VK_DRIVER_ID_BROADCOM_PROPRIETARY"; + case VK_DRIVER_ID_COREAVI_PROPRIETARY: + return "VK_DRIVER_ID_COREAVI_PROPRIETARY"; + case VK_DRIVER_ID_GGP_PROPRIETARY: + return "VK_DRIVER_ID_GGP_PROPRIETARY"; + case VK_DRIVER_ID_GOOGLE_SWIFTSHADER: + return "VK_DRIVER_ID_GOOGLE_SWIFTSHADER"; + case VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA: + return "VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_IMAGINATION_PROPRIETARY: + return "VK_DRIVER_ID_IMAGINATION_PROPRIETARY"; + case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA: + return "VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS: + return "VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS"; + case VK_DRIVER_ID_JUICE_PROPRIETARY: + return "VK_DRIVER_ID_JUICE_PROPRIETARY"; + case VK_DRIVER_ID_MESA_DOZEN: + return "VK_DRIVER_ID_MESA_DOZEN"; + case VK_DRIVER_ID_MESA_LLVMPIPE: + return "VK_DRIVER_ID_MESA_LLVMPIPE"; + case VK_DRIVER_ID_MESA_NVK: + return "VK_DRIVER_ID_MESA_NVK"; + case VK_DRIVER_ID_MESA_PANVK: + return "VK_DRIVER_ID_MESA_PANVK"; + case VK_DRIVER_ID_MESA_RADV: + return "VK_DRIVER_ID_MESA_RADV"; + case VK_DRIVER_ID_MESA_TURNIP: + return "VK_DRIVER_ID_MESA_TURNIP"; + case VK_DRIVER_ID_MESA_V3DV: + return "VK_DRIVER_ID_MESA_V3DV"; + case VK_DRIVER_ID_MESA_VENUS: + return "VK_DRIVER_ID_MESA_VENUS"; + case VK_DRIVER_ID_MOLTENVK: + return "VK_DRIVER_ID_MOLTENVK"; + case VK_DRIVER_ID_NVIDIA_PROPRIETARY: + return "VK_DRIVER_ID_NVIDIA_PROPRIETARY"; + case VK_DRIVER_ID_QUALCOMM_PROPRIETARY: + return "VK_DRIVER_ID_QUALCOMM_PROPRIETARY"; + case VK_DRIVER_ID_SAMSUNG_PROPRIETARY: + return "VK_DRIVER_ID_SAMSUNG_PROPRIETARY"; + case VK_DRIVER_ID_VERISILICON_PROPRIETARY: + return "VK_DRIVER_ID_VERISILICON_PROPRIETARY"; + default: + return "Unhandled VkDriverId"; + } +} + +static inline const char* string_VkShaderFloatControlsIndependence(VkShaderFloatControlsIndependence input_value) +{ + switch (input_value) + { + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE"; + default: + return "Unhandled VkShaderFloatControlsIndependence"; + } +} + +static inline const char* string_VkResolveModeFlagBits(VkResolveModeFlagBits input_value) +{ + switch (input_value) + { + case VK_RESOLVE_MODE_AVERAGE_BIT: + return "VK_RESOLVE_MODE_AVERAGE_BIT"; + case VK_RESOLVE_MODE_MAX_BIT: + return "VK_RESOLVE_MODE_MAX_BIT"; + case VK_RESOLVE_MODE_MIN_BIT: + return "VK_RESOLVE_MODE_MIN_BIT"; + case VK_RESOLVE_MODE_NONE: + return "VK_RESOLVE_MODE_NONE"; + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: + return "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT"; + default: + return "Unhandled VkResolveModeFlagBits"; + } +} + +static inline std::string string_VkResolveModeFlags(VkResolveModeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkResolveModeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkResolveModeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDescriptorBindingFlagBits(VkDescriptorBindingFlagBits input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT: + return "VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT"; + case VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT: + return "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT"; + default: + return "Unhandled VkDescriptorBindingFlagBits"; + } +} + +static inline std::string string_VkDescriptorBindingFlags(VkDescriptorBindingFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorBindingFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorBindingFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSamplerReductionMode(VkSamplerReductionMode input_value) +{ + switch (input_value) + { + case VK_SAMPLER_REDUCTION_MODE_MAX: + return "VK_SAMPLER_REDUCTION_MODE_MAX"; + case VK_SAMPLER_REDUCTION_MODE_MIN: + return "VK_SAMPLER_REDUCTION_MODE_MIN"; + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: + return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE"; + default: + return "Unhandled VkSamplerReductionMode"; + } +} + +static inline const char* string_VkSemaphoreType(VkSemaphoreType input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_TYPE_BINARY: + return "VK_SEMAPHORE_TYPE_BINARY"; + case VK_SEMAPHORE_TYPE_TIMELINE: + return "VK_SEMAPHORE_TYPE_TIMELINE"; + default: + return "Unhandled VkSemaphoreType"; + } +} + +static inline const char* string_VkSemaphoreWaitFlagBits(VkSemaphoreWaitFlagBits input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_WAIT_ANY_BIT: + return "VK_SEMAPHORE_WAIT_ANY_BIT"; + default: + return "Unhandled VkSemaphoreWaitFlagBits"; + } +} + +static inline std::string string_VkSemaphoreWaitFlags(VkSemaphoreWaitFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreWaitFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreWaitFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineCreationFeedbackFlagBits(VkPipelineCreationFeedbackFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT: + return "VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT"; + case VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT: + return "VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT"; + case VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT: + return "VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT"; + default: + return "Unhandled VkPipelineCreationFeedbackFlagBits"; + } +} + +static inline std::string string_VkPipelineCreationFeedbackFlags(VkPipelineCreationFeedbackFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCreationFeedbackFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCreationFeedbackFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkToolPurposeFlagBits(VkToolPurposeFlagBits input_value) +{ + switch (input_value) + { + case VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT: + return "VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT"; + case VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT: + return "VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"; + case VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT: + return "VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"; + case VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT: + return "VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT"; + case VK_TOOL_PURPOSE_PROFILING_BIT: + return "VK_TOOL_PURPOSE_PROFILING_BIT"; + case VK_TOOL_PURPOSE_TRACING_BIT: + return "VK_TOOL_PURPOSE_TRACING_BIT"; + case VK_TOOL_PURPOSE_VALIDATION_BIT: + return "VK_TOOL_PURPOSE_VALIDATION_BIT"; + default: + return "Unhandled VkToolPurposeFlagBits"; + } +} + +static inline std::string string_VkToolPurposeFlags(VkToolPurposeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkToolPurposeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkToolPurposeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineStageFlagBits2(uint64_t input_value) +{ + switch (input_value) + { + case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT: + return "VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT"; + case VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT: + return "VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT"; + case VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT: + return "VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"; + case VK_PIPELINE_STAGE_2_BLIT_BIT: + return "VK_PIPELINE_STAGE_2_BLIT_BIT"; + case VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_2_CLEAR_BIT: + return "VK_PIPELINE_STAGE_2_CLEAR_BIT"; + case VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT: + return "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT"; + case VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV: + return "VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV"; + case VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_PIPELINE_STAGE_2_COPY_BIT: + return "VK_PIPELINE_STAGE_2_COPY_BIT"; + case VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT: + return "VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT"; + case VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT: + return "VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_HOST_BIT: + return "VK_PIPELINE_STAGE_2_HOST_BIT"; + case VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT: + return "VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT"; + case VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT: + return "VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT"; + case VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT: + return "VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT"; + case VK_PIPELINE_STAGE_2_NONE: + return "VK_PIPELINE_STAGE_2_NONE"; + case VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV: + return "VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV"; + case VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT: + return "VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT"; + case VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_RESOLVE_BIT: + return "VK_PIPELINE_STAGE_2_RESOLVE_BIT"; + case VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT: + return "VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT"; + case VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT: + return "VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT"; + case VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT: + return "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT"; + case VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT: + return "VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT"; + case VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkPipelineStageFlagBits2"; + } +} + +static inline std::string string_VkPipelineStageFlags2(VkPipelineStageFlags2 input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineStageFlagBits2(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineStageFlagBits2(static_cast(0))); + return ret; +} + +static inline const char* string_VkAccessFlagBits2(uint64_t input_value) +{ + switch (input_value) + { + case VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR: + return "VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"; + case VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: + return "VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; + case VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT"; + case VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; + case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV: + return "VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV"; + case VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV: + return "VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV"; + case VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT: + return "VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT"; + case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT: + return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT"; + case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT: + return "VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT"; + case VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: + return "VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; + case VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_2_HOST_READ_BIT: + return "VK_ACCESS_2_HOST_READ_BIT"; + case VK_ACCESS_2_HOST_WRITE_BIT: + return "VK_ACCESS_2_HOST_WRITE_BIT"; + case VK_ACCESS_2_INDEX_READ_BIT: + return "VK_ACCESS_2_INDEX_READ_BIT"; + case VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT: + return "VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT"; + case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT: + return "VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT"; + case VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI: + return "VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI"; + case VK_ACCESS_2_MEMORY_READ_BIT: + return "VK_ACCESS_2_MEMORY_READ_BIT"; + case VK_ACCESS_2_MEMORY_WRITE_BIT: + return "VK_ACCESS_2_MEMORY_WRITE_BIT"; + case VK_ACCESS_2_MICROMAP_READ_BIT_EXT: + return "VK_ACCESS_2_MICROMAP_READ_BIT_EXT"; + case VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT: + return "VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT"; + case VK_ACCESS_2_NONE: + return "VK_ACCESS_2_NONE"; + case VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV: + return "VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV"; + case VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV: + return "VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV"; + case VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR: + return "VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR"; + case VK_ACCESS_2_SHADER_READ_BIT: + return "VK_ACCESS_2_SHADER_READ_BIT"; + case VK_ACCESS_2_SHADER_SAMPLED_READ_BIT: + return "VK_ACCESS_2_SHADER_SAMPLED_READ_BIT"; + case VK_ACCESS_2_SHADER_STORAGE_READ_BIT: + return "VK_ACCESS_2_SHADER_STORAGE_READ_BIT"; + case VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT: + return "VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT"; + case VK_ACCESS_2_SHADER_WRITE_BIT: + return "VK_ACCESS_2_SHADER_WRITE_BIT"; + case VK_ACCESS_2_TRANSFER_READ_BIT: + return "VK_ACCESS_2_TRANSFER_READ_BIT"; + case VK_ACCESS_2_TRANSFER_WRITE_BIT: + return "VK_ACCESS_2_TRANSFER_WRITE_BIT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; + case VK_ACCESS_2_UNIFORM_READ_BIT: + return "VK_ACCESS_2_UNIFORM_READ_BIT"; + case VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT: + return "VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT"; + case VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR: + return "VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR"; + case VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR: + return "VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR: + return "VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR: + return "VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkAccessFlagBits2"; + } +} + +static inline std::string string_VkAccessFlags2(VkAccessFlags2 input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccessFlagBits2(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccessFlagBits2(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubmitFlagBits(VkSubmitFlagBits input_value) +{ + switch (input_value) + { + case VK_SUBMIT_PROTECTED_BIT: + return "VK_SUBMIT_PROTECTED_BIT"; + default: + return "Unhandled VkSubmitFlagBits"; + } +} + +static inline std::string string_VkSubmitFlags(VkSubmitFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubmitFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubmitFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkRenderingFlagBits(VkRenderingFlagBits input_value) +{ + switch (input_value) + { + case VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT: + return "VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT"; + case VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT: + return "VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT"; + case VK_RENDERING_RESUMING_BIT: + return "VK_RENDERING_RESUMING_BIT"; + case VK_RENDERING_SUSPENDING_BIT: + return "VK_RENDERING_SUSPENDING_BIT"; + default: + return "Unhandled VkRenderingFlagBits"; + } +} + +static inline std::string string_VkRenderingFlags(VkRenderingFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkRenderingFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkRenderingFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFormatFeatureFlagBits2(uint64_t input_value) +{ + switch (input_value) + { + case VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR: + return "VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"; + case VK_FORMAT_FEATURE_2_BLIT_DST_BIT: + return "VK_FORMAT_FEATURE_2_BLIT_DST_BIT"; + case VK_FORMAT_FEATURE_2_BLIT_SRC_BIT: + return "VK_FORMAT_FEATURE_2_BLIT_SRC_BIT"; + case VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM"; + case VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM"; + case VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT: + return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT"; + case VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_2_DISJOINT_BIT: + return "VK_FORMAT_FEATURE_2_DISJOINT_BIT"; + case VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT: + return "VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT"; + case VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV: + return "VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV"; + case VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV: + return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV"; + case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV: + return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV"; + case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV: + return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT"; + case VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT: + return "VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT"; + case VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT: + return "VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT"; + case VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT: + return "VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT"; + case VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR"; + case VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM"; + case VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM"; + default: + return "Unhandled VkFormatFeatureFlagBits2"; + } +} + +static inline std::string string_VkFormatFeatureFlags2(VkFormatFeatureFlags2 input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFormatFeatureFlagBits2(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFormatFeatureFlagBits2(static_cast(0))); + return ret; +} + +static inline const char* string_VkSurfaceTransformFlagBitsKHR(VkSurfaceTransformFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR"; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR"; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR"; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR"; + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: + return "VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR"; + case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR: + return "VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR"; + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + return "VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR"; + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + return "VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR"; + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + return "VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR"; + default: + return "Unhandled VkSurfaceTransformFlagBitsKHR"; + } +} + +static inline std::string string_VkSurfaceTransformFlagsKHR(VkSurfaceTransformFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSurfaceTransformFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSurfaceTransformFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPresentModeKHR(VkPresentModeKHR input_value) +{ + switch (input_value) + { + case VK_PRESENT_MODE_FIFO_KHR: + return "VK_PRESENT_MODE_FIFO_KHR"; + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: + return "VK_PRESENT_MODE_FIFO_RELAXED_KHR"; + case VK_PRESENT_MODE_IMMEDIATE_KHR: + return "VK_PRESENT_MODE_IMMEDIATE_KHR"; + case VK_PRESENT_MODE_MAILBOX_KHR: + return "VK_PRESENT_MODE_MAILBOX_KHR"; + case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: + return "VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR"; + case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: + return "VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR"; + default: + return "Unhandled VkPresentModeKHR"; + } +} + +static inline const char* string_VkColorSpaceKHR(VkColorSpaceKHR input_value) +{ + switch (input_value) + { + case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT: + return "VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT"; + case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: + return "VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT"; + case VK_COLOR_SPACE_BT2020_LINEAR_EXT: + return "VK_COLOR_SPACE_BT2020_LINEAR_EXT"; + case VK_COLOR_SPACE_BT709_LINEAR_EXT: + return "VK_COLOR_SPACE_BT709_LINEAR_EXT"; + case VK_COLOR_SPACE_BT709_NONLINEAR_EXT: + return "VK_COLOR_SPACE_BT709_NONLINEAR_EXT"; + case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: + return "VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT"; + case VK_COLOR_SPACE_DISPLAY_NATIVE_AMD: + return "VK_COLOR_SPACE_DISPLAY_NATIVE_AMD"; + case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT: + return "VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT"; + case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: + return "VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT"; + case VK_COLOR_SPACE_DOLBYVISION_EXT: + return "VK_COLOR_SPACE_DOLBYVISION_EXT"; + case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: + return "VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT"; + case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: + return "VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT"; + case VK_COLOR_SPACE_HDR10_HLG_EXT: + return "VK_COLOR_SPACE_HDR10_HLG_EXT"; + case VK_COLOR_SPACE_HDR10_ST2084_EXT: + return "VK_COLOR_SPACE_HDR10_ST2084_EXT"; + case VK_COLOR_SPACE_PASS_THROUGH_EXT: + return "VK_COLOR_SPACE_PASS_THROUGH_EXT"; + case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: + return "VK_COLOR_SPACE_SRGB_NONLINEAR_KHR"; + default: + return "Unhandled VkColorSpaceKHR"; + } +} + +static inline const char* string_VkCompositeAlphaFlagBitsKHR(VkCompositeAlphaFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR: + return "VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR"; + case VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR: + return "VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR"; + case VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR: + return "VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR"; + case VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR: + return "VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR"; + default: + return "Unhandled VkCompositeAlphaFlagBitsKHR"; + } +} + +static inline std::string string_VkCompositeAlphaFlagsKHR(VkCompositeAlphaFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCompositeAlphaFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCompositeAlphaFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSwapchainCreateFlagBitsKHR(VkSwapchainCreateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT: + return "VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT"; + case VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR: + return "VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR"; + case VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR: + return "VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR"; + case VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR: + return "VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR"; + default: + return "Unhandled VkSwapchainCreateFlagBitsKHR"; + } +} + +static inline std::string string_VkSwapchainCreateFlagsKHR(VkSwapchainCreateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSwapchainCreateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSwapchainCreateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceGroupPresentModeFlagBitsKHR(VkDeviceGroupPresentModeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR"; + case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR"; + case VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR"; + case VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR"; + default: + return "Unhandled VkDeviceGroupPresentModeFlagBitsKHR"; + } +} + +static inline std::string string_VkDeviceGroupPresentModeFlagsKHR(VkDeviceGroupPresentModeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceGroupPresentModeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceGroupPresentModeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDisplayPlaneAlphaFlagBitsKHR(VkDisplayPlaneAlphaFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR"; + case VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR"; + case VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR"; + case VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR"; + default: + return "Unhandled VkDisplayPlaneAlphaFlagBitsKHR"; + } +} + +static inline std::string string_VkDisplayPlaneAlphaFlagsKHR(VkDisplayPlaneAlphaFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDisplayPlaneAlphaFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDisplayPlaneAlphaFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoCodecOperationFlagBitsKHR(VkVideoCodecOperationFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: + return "VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR"; + case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: + return "VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT: + return "VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT: + return "VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_NONE_KHR: + return "VK_VIDEO_CODEC_OPERATION_NONE_KHR"; + default: + return "Unhandled VkVideoCodecOperationFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCodecOperationFlagsKHR(VkVideoCodecOperationFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCodecOperationFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCodecOperationFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoChromaSubsamplingFlagBitsKHR(VkVideoChromaSubsamplingFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR"; + default: + return "Unhandled VkVideoChromaSubsamplingFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoChromaSubsamplingFlagsKHR(VkVideoChromaSubsamplingFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoChromaSubsamplingFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoChromaSubsamplingFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoComponentBitDepthFlagBitsKHR(VkVideoComponentBitDepthFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR"; + case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR"; + case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR"; + case VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR"; + default: + return "Unhandled VkVideoComponentBitDepthFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoComponentBitDepthFlagsKHR(VkVideoComponentBitDepthFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoComponentBitDepthFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoComponentBitDepthFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoCapabilityFlagBitsKHR(VkVideoCapabilityFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR: + return "VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR"; + case VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR: + return "VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR"; + default: + return "Unhandled VkVideoCapabilityFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCapabilityFlagsKHR(VkVideoCapabilityFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCapabilityFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCapabilityFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoSessionCreateFlagBitsKHR(VkVideoSessionCreateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR: + return "VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR"; + default: + return "Unhandled VkVideoSessionCreateFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoSessionCreateFlagsKHR(VkVideoSessionCreateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoSessionCreateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoSessionCreateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoCodingControlFlagBitsKHR(VkVideoCodingControlFlagBitsKHR input_value) +{ + switch (input_value) + { +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR: + return "VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_LAYER_BIT_KHR: + return "VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_LAYER_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR: + return "VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR"; + default: + return "Unhandled VkVideoCodingControlFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCodingControlFlagsKHR(VkVideoCodingControlFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCodingControlFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCodingControlFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryResultStatusKHR(VkQueryResultStatusKHR input_value) +{ + switch (input_value) + { + case VK_QUERY_RESULT_STATUS_COMPLETE_KHR: + return "VK_QUERY_RESULT_STATUS_COMPLETE_KHR"; + case VK_QUERY_RESULT_STATUS_ERROR_KHR: + return "VK_QUERY_RESULT_STATUS_ERROR_KHR"; + case VK_QUERY_RESULT_STATUS_NOT_READY_KHR: + return "VK_QUERY_RESULT_STATUS_NOT_READY_KHR"; + default: + return "Unhandled VkQueryResultStatusKHR"; + } +} + +static inline const char* string_VkVideoDecodeCapabilityFlagBitsKHR(VkVideoDecodeCapabilityFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR: + return "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR"; + case VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR: + return "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR"; + default: + return "Unhandled VkVideoDecodeCapabilityFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoDecodeCapabilityFlagsKHR(VkVideoDecodeCapabilityFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoDecodeCapabilityFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoDecodeCapabilityFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoDecodeUsageFlagBitsKHR(VkVideoDecodeUsageFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_DECODE_USAGE_DEFAULT_KHR: + return "VK_VIDEO_DECODE_USAGE_DEFAULT_KHR"; + case VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR: + return "VK_VIDEO_DECODE_USAGE_OFFLINE_BIT_KHR"; + case VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR: + return "VK_VIDEO_DECODE_USAGE_STREAMING_BIT_KHR"; + case VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR: + return "VK_VIDEO_DECODE_USAGE_TRANSCODING_BIT_KHR"; + default: + return "Unhandled VkVideoDecodeUsageFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoDecodeUsageFlagsKHR(VkVideoDecodeUsageFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoDecodeUsageFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoDecodeUsageFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkVideoDecodeH264PictureLayoutFlagBitsKHR(VkVideoDecodeH264PictureLayoutFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR: + return "VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR"; + case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR: + return "VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR"; + case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR: + return "VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR"; + default: + return "Unhandled VkVideoDecodeH264PictureLayoutFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoDecodeH264PictureLayoutFlagsKHR(VkVideoDecodeH264PictureLayoutFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoDecodeH264PictureLayoutFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoDecodeH264PictureLayoutFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkRenderingFlagBitsKHR(VkRenderingFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT: + return "VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT"; + case VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT: + return "VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT"; + case VK_RENDERING_RESUMING_BIT: + return "VK_RENDERING_RESUMING_BIT"; + case VK_RENDERING_SUSPENDING_BIT: + return "VK_RENDERING_SUSPENDING_BIT"; + default: + return "Unhandled VkRenderingFlagBitsKHR"; + } +} + +static inline std::string string_VkRenderingFlagsKHR(VkRenderingFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkRenderingFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkRenderingFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPeerMemoryFeatureFlagBitsKHR(VkPeerMemoryFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_PEER_MEMORY_FEATURE_COPY_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT"; + default: + return "Unhandled VkPeerMemoryFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkPeerMemoryFeatureFlagsKHR(VkPeerMemoryFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPeerMemoryFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPeerMemoryFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryAllocateFlagBitsKHR(VkMemoryAllocateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT"; + default: + return "Unhandled VkMemoryAllocateFlagBitsKHR"; + } +} + +static inline std::string string_VkMemoryAllocateFlagsKHR(VkMemoryAllocateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryAllocateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryAllocateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryHandleTypeFlagBitsKHR(VkExternalMemoryHandleTypeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalMemoryHandleTypeFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalMemoryHandleTypeFlagsKHR(VkExternalMemoryHandleTypeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryHandleTypeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryFeatureFlagBitsKHR(VkExternalMemoryFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalMemoryFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalMemoryFeatureFlagsKHR(VkExternalMemoryFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreHandleTypeFlagBitsKHR(VkExternalSemaphoreHandleTypeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalSemaphoreHandleTypeFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalSemaphoreHandleTypeFlagsKHR(VkExternalSemaphoreHandleTypeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreHandleTypeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreHandleTypeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreFeatureFlagBitsKHR(VkExternalSemaphoreFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalSemaphoreFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalSemaphoreFeatureFlagsKHR(VkExternalSemaphoreFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSemaphoreImportFlagBitsKHR(VkSemaphoreImportFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT: + return "VK_SEMAPHORE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkSemaphoreImportFlagBitsKHR"; + } +} + +static inline std::string string_VkSemaphoreImportFlagsKHR(VkSemaphoreImportFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreImportFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreImportFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDescriptorUpdateTemplateTypeKHR(VkDescriptorUpdateTemplateTypeKHR input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET"; + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR"; + default: + return "Unhandled VkDescriptorUpdateTemplateTypeKHR"; + } +} + +static inline const char* string_VkExternalFenceHandleTypeFlagBitsKHR(VkExternalFenceHandleTypeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT"; + default: + return "Unhandled VkExternalFenceHandleTypeFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalFenceHandleTypeFlagsKHR(VkExternalFenceHandleTypeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceHandleTypeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceHandleTypeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalFenceFeatureFlagBitsKHR(VkExternalFenceFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalFenceFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalFenceFeatureFlagsKHR(VkExternalFenceFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkFenceImportFlagBitsKHR(VkFenceImportFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_FENCE_IMPORT_TEMPORARY_BIT: + return "VK_FENCE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkFenceImportFlagBitsKHR"; + } +} + +static inline std::string string_VkFenceImportFlagsKHR(VkFenceImportFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFenceImportFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFenceImportFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPerformanceCounterUnitKHR(VkPerformanceCounterUnitKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR"; + default: + return "Unhandled VkPerformanceCounterUnitKHR"; + } +} + +static inline const char* string_VkPerformanceCounterScopeKHR(VkPerformanceCounterScopeKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR: + return "VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR"; + case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR: + return "VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR"; + case VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR: + return "VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR"; + default: + return "Unhandled VkPerformanceCounterScopeKHR"; + } +} + +static inline const char* string_VkPerformanceCounterStorageKHR(VkPerformanceCounterStorageKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR"; + default: + return "Unhandled VkPerformanceCounterStorageKHR"; + } +} + +static inline const char* string_VkPerformanceCounterDescriptionFlagBitsKHR(VkPerformanceCounterDescriptionFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR: + return "VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR"; + case VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR: + return "VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR"; + default: + return "Unhandled VkPerformanceCounterDescriptionFlagBitsKHR"; + } +} + +static inline std::string string_VkPerformanceCounterDescriptionFlagsKHR(VkPerformanceCounterDescriptionFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPerformanceCounterDescriptionFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPerformanceCounterDescriptionFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPointClippingBehaviorKHR(VkPointClippingBehaviorKHR input_value) +{ + switch (input_value) + { + case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES: + return "VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES"; + case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY: + return "VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY"; + default: + return "Unhandled VkPointClippingBehaviorKHR"; + } +} + +static inline const char* string_VkTessellationDomainOriginKHR(VkTessellationDomainOriginKHR input_value) +{ + switch (input_value) + { + case VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT"; + case VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT"; + default: + return "Unhandled VkTessellationDomainOriginKHR"; + } +} + +static inline const char* string_VkSamplerYcbcrModelConversionKHR(VkSamplerYcbcrModelConversionKHR input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY"; + default: + return "Unhandled VkSamplerYcbcrModelConversionKHR"; + } +} + +static inline const char* string_VkSamplerYcbcrRangeKHR(VkSamplerYcbcrRangeKHR input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: + return "VK_SAMPLER_YCBCR_RANGE_ITU_FULL"; + case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: + return "VK_SAMPLER_YCBCR_RANGE_ITU_NARROW"; + default: + return "Unhandled VkSamplerYcbcrRangeKHR"; + } +} + +static inline const char* string_VkChromaLocationKHR(VkChromaLocationKHR input_value) +{ + switch (input_value) + { + case VK_CHROMA_LOCATION_COSITED_EVEN: + return "VK_CHROMA_LOCATION_COSITED_EVEN"; + case VK_CHROMA_LOCATION_MIDPOINT: + return "VK_CHROMA_LOCATION_MIDPOINT"; + default: + return "Unhandled VkChromaLocationKHR"; + } +} + +static inline const char* string_VkQueueGlobalPriorityKHR(VkQueueGlobalPriorityKHR input_value) +{ + switch (input_value) + { + case VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR"; + case VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR"; + case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR"; + case VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR"; + default: + return "Unhandled VkQueueGlobalPriorityKHR"; + } +} + +static inline const char* string_VkDriverIdKHR(VkDriverIdKHR input_value) +{ + switch (input_value) + { + case VK_DRIVER_ID_AMD_OPEN_SOURCE: + return "VK_DRIVER_ID_AMD_OPEN_SOURCE"; + case VK_DRIVER_ID_AMD_PROPRIETARY: + return "VK_DRIVER_ID_AMD_PROPRIETARY"; + case VK_DRIVER_ID_ARM_PROPRIETARY: + return "VK_DRIVER_ID_ARM_PROPRIETARY"; + case VK_DRIVER_ID_BROADCOM_PROPRIETARY: + return "VK_DRIVER_ID_BROADCOM_PROPRIETARY"; + case VK_DRIVER_ID_COREAVI_PROPRIETARY: + return "VK_DRIVER_ID_COREAVI_PROPRIETARY"; + case VK_DRIVER_ID_GGP_PROPRIETARY: + return "VK_DRIVER_ID_GGP_PROPRIETARY"; + case VK_DRIVER_ID_GOOGLE_SWIFTSHADER: + return "VK_DRIVER_ID_GOOGLE_SWIFTSHADER"; + case VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA: + return "VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_IMAGINATION_PROPRIETARY: + return "VK_DRIVER_ID_IMAGINATION_PROPRIETARY"; + case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA: + return "VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS: + return "VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS"; + case VK_DRIVER_ID_JUICE_PROPRIETARY: + return "VK_DRIVER_ID_JUICE_PROPRIETARY"; + case VK_DRIVER_ID_MESA_DOZEN: + return "VK_DRIVER_ID_MESA_DOZEN"; + case VK_DRIVER_ID_MESA_LLVMPIPE: + return "VK_DRIVER_ID_MESA_LLVMPIPE"; + case VK_DRIVER_ID_MESA_NVK: + return "VK_DRIVER_ID_MESA_NVK"; + case VK_DRIVER_ID_MESA_PANVK: + return "VK_DRIVER_ID_MESA_PANVK"; + case VK_DRIVER_ID_MESA_RADV: + return "VK_DRIVER_ID_MESA_RADV"; + case VK_DRIVER_ID_MESA_TURNIP: + return "VK_DRIVER_ID_MESA_TURNIP"; + case VK_DRIVER_ID_MESA_V3DV: + return "VK_DRIVER_ID_MESA_V3DV"; + case VK_DRIVER_ID_MESA_VENUS: + return "VK_DRIVER_ID_MESA_VENUS"; + case VK_DRIVER_ID_MOLTENVK: + return "VK_DRIVER_ID_MOLTENVK"; + case VK_DRIVER_ID_NVIDIA_PROPRIETARY: + return "VK_DRIVER_ID_NVIDIA_PROPRIETARY"; + case VK_DRIVER_ID_QUALCOMM_PROPRIETARY: + return "VK_DRIVER_ID_QUALCOMM_PROPRIETARY"; + case VK_DRIVER_ID_SAMSUNG_PROPRIETARY: + return "VK_DRIVER_ID_SAMSUNG_PROPRIETARY"; + case VK_DRIVER_ID_VERISILICON_PROPRIETARY: + return "VK_DRIVER_ID_VERISILICON_PROPRIETARY"; + default: + return "Unhandled VkDriverIdKHR"; + } +} + +static inline const char* string_VkShaderFloatControlsIndependenceKHR(VkShaderFloatControlsIndependenceKHR input_value) +{ + switch (input_value) + { + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE"; + default: + return "Unhandled VkShaderFloatControlsIndependenceKHR"; + } +} + +static inline const char* string_VkResolveModeFlagBitsKHR(VkResolveModeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_RESOLVE_MODE_AVERAGE_BIT: + return "VK_RESOLVE_MODE_AVERAGE_BIT"; + case VK_RESOLVE_MODE_MAX_BIT: + return "VK_RESOLVE_MODE_MAX_BIT"; + case VK_RESOLVE_MODE_MIN_BIT: + return "VK_RESOLVE_MODE_MIN_BIT"; + case VK_RESOLVE_MODE_NONE: + return "VK_RESOLVE_MODE_NONE"; + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: + return "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT"; + default: + return "Unhandled VkResolveModeFlagBitsKHR"; + } +} + +static inline std::string string_VkResolveModeFlagsKHR(VkResolveModeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkResolveModeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkResolveModeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSemaphoreTypeKHR(VkSemaphoreTypeKHR input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_TYPE_BINARY: + return "VK_SEMAPHORE_TYPE_BINARY"; + case VK_SEMAPHORE_TYPE_TIMELINE: + return "VK_SEMAPHORE_TYPE_TIMELINE"; + default: + return "Unhandled VkSemaphoreTypeKHR"; + } +} + +static inline const char* string_VkSemaphoreWaitFlagBitsKHR(VkSemaphoreWaitFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_WAIT_ANY_BIT: + return "VK_SEMAPHORE_WAIT_ANY_BIT"; + default: + return "Unhandled VkSemaphoreWaitFlagBitsKHR"; + } +} + +static inline std::string string_VkSemaphoreWaitFlagsKHR(VkSemaphoreWaitFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreWaitFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreWaitFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkFragmentShadingRateCombinerOpKHR(VkFragmentShadingRateCombinerOpKHR input_value) +{ + switch (input_value) + { + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR"; + default: + return "Unhandled VkFragmentShadingRateCombinerOpKHR"; + } +} + +static inline const char* string_VkPipelineExecutableStatisticFormatKHR(VkPipelineExecutableStatisticFormatKHR input_value) +{ + switch (input_value) + { + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR"; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR"; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR"; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR"; + default: + return "Unhandled VkPipelineExecutableStatisticFormatKHR"; + } +} + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeCapabilityFlagBitsKHR(VkVideoEncodeCapabilityFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR: + return "VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeCapabilityFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeCapabilityFlagsKHR(VkVideoEncodeCapabilityFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeCapabilityFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeCapabilityFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeRateControlModeFlagBitsKHR(VkVideoEncodeRateControlModeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR"; + case VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR"; + case VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeRateControlModeFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeRateControlModeFlagsKHR(VkVideoEncodeRateControlModeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeRateControlModeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeRateControlModeFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeUsageFlagBitsKHR(VkVideoEncodeUsageFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR: + return "VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR"; + case VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR: + return "VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR"; + case VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR: + return "VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR"; + case VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR: + return "VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR"; + case VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR: + return "VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeUsageFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeUsageFlagsKHR(VkVideoEncodeUsageFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeUsageFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeUsageFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeContentFlagBitsKHR(VkVideoEncodeContentFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR: + return "VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR"; + case VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR: + return "VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR"; + case VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR: + return "VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR"; + case VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR: + return "VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeContentFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeContentFlagsKHR(VkVideoEncodeContentFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeContentFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeContentFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeTuningModeKHR(VkVideoEncodeTuningModeKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR: + return "VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR"; + case VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR: + return "VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR"; + case VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR: + return "VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR"; + case VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR: + return "VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR"; + case VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR: + return "VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR"; + default: + return "Unhandled VkVideoEncodeTuningModeKHR"; + } +} +#endif // VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkPipelineStageFlagBits2KHR(uint64_t input_value) +{ + switch (input_value) + { + case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT: + return "VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT"; + case VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT: + return "VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT"; + case VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT: + return "VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"; + case VK_PIPELINE_STAGE_2_BLIT_BIT: + return "VK_PIPELINE_STAGE_2_BLIT_BIT"; + case VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_2_CLEAR_BIT: + return "VK_PIPELINE_STAGE_2_CLEAR_BIT"; + case VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT: + return "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT"; + case VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV: + return "VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV"; + case VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_PIPELINE_STAGE_2_COPY_BIT: + return "VK_PIPELINE_STAGE_2_COPY_BIT"; + case VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT: + return "VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT"; + case VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT: + return "VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_HOST_BIT: + return "VK_PIPELINE_STAGE_2_HOST_BIT"; + case VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT: + return "VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT"; + case VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT: + return "VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT"; + case VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT: + return "VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT"; + case VK_PIPELINE_STAGE_2_NONE: + return "VK_PIPELINE_STAGE_2_NONE"; + case VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV: + return "VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV"; + case VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT: + return "VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT"; + case VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_RESOLVE_BIT: + return "VK_PIPELINE_STAGE_2_RESOLVE_BIT"; + case VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT: + return "VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT"; + case VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT: + return "VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT"; + case VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT: + return "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT"; + case VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT: + return "VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT"; + case VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT: + return "VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT"; + case VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkPipelineStageFlagBits2KHR"; + } +} + +static inline std::string string_VkPipelineStageFlags2KHR(VkPipelineStageFlags2KHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineStageFlagBits2KHR(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineStageFlagBits2KHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkAccessFlagBits2KHR(uint64_t input_value) +{ + switch (input_value) + { + case VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR: + return "VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"; + case VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: + return "VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; + case VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT"; + case VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; + case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV: + return "VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV"; + case VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV: + return "VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV"; + case VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT: + return "VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT"; + case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT: + return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT"; + case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT: + return "VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT"; + case VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: + return "VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; + case VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_2_HOST_READ_BIT: + return "VK_ACCESS_2_HOST_READ_BIT"; + case VK_ACCESS_2_HOST_WRITE_BIT: + return "VK_ACCESS_2_HOST_WRITE_BIT"; + case VK_ACCESS_2_INDEX_READ_BIT: + return "VK_ACCESS_2_INDEX_READ_BIT"; + case VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT: + return "VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT"; + case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT: + return "VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT"; + case VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI: + return "VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI"; + case VK_ACCESS_2_MEMORY_READ_BIT: + return "VK_ACCESS_2_MEMORY_READ_BIT"; + case VK_ACCESS_2_MEMORY_WRITE_BIT: + return "VK_ACCESS_2_MEMORY_WRITE_BIT"; + case VK_ACCESS_2_MICROMAP_READ_BIT_EXT: + return "VK_ACCESS_2_MICROMAP_READ_BIT_EXT"; + case VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT: + return "VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT"; + case VK_ACCESS_2_NONE: + return "VK_ACCESS_2_NONE"; + case VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV: + return "VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV"; + case VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV: + return "VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV"; + case VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR: + return "VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR"; + case VK_ACCESS_2_SHADER_READ_BIT: + return "VK_ACCESS_2_SHADER_READ_BIT"; + case VK_ACCESS_2_SHADER_SAMPLED_READ_BIT: + return "VK_ACCESS_2_SHADER_SAMPLED_READ_BIT"; + case VK_ACCESS_2_SHADER_STORAGE_READ_BIT: + return "VK_ACCESS_2_SHADER_STORAGE_READ_BIT"; + case VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT: + return "VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT"; + case VK_ACCESS_2_SHADER_WRITE_BIT: + return "VK_ACCESS_2_SHADER_WRITE_BIT"; + case VK_ACCESS_2_TRANSFER_READ_BIT: + return "VK_ACCESS_2_TRANSFER_READ_BIT"; + case VK_ACCESS_2_TRANSFER_WRITE_BIT: + return "VK_ACCESS_2_TRANSFER_WRITE_BIT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; + case VK_ACCESS_2_UNIFORM_READ_BIT: + return "VK_ACCESS_2_UNIFORM_READ_BIT"; + case VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT: + return "VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT"; + case VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR: + return "VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR"; + case VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR: + return "VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR: + return "VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR: + return "VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkAccessFlagBits2KHR"; + } +} + +static inline std::string string_VkAccessFlags2KHR(VkAccessFlags2KHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccessFlagBits2KHR(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccessFlagBits2KHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubmitFlagBitsKHR(VkSubmitFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SUBMIT_PROTECTED_BIT: + return "VK_SUBMIT_PROTECTED_BIT"; + default: + return "Unhandled VkSubmitFlagBitsKHR"; + } +} + +static inline std::string string_VkSubmitFlagsKHR(VkSubmitFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubmitFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubmitFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkFormatFeatureFlagBits2KHR(uint64_t input_value) +{ + switch (input_value) + { + case VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR: + return "VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"; + case VK_FORMAT_FEATURE_2_BLIT_DST_BIT: + return "VK_FORMAT_FEATURE_2_BLIT_DST_BIT"; + case VK_FORMAT_FEATURE_2_BLIT_SRC_BIT: + return "VK_FORMAT_FEATURE_2_BLIT_SRC_BIT"; + case VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM"; + case VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM"; + case VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT: + return "VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT"; + case VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_2_DISJOINT_BIT: + return "VK_FORMAT_FEATURE_2_DISJOINT_BIT"; + case VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT: + return "VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT"; + case VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV: + return "VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV"; + case VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV: + return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV"; + case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV: + return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV"; + case VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV: + return "VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"; + case VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT: + return "VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT: + return "VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT"; + case VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT: + return "VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT"; + case VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT: + return "VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT"; + case VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT: + return "VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT"; + case VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR"; + case VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM"; + case VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM: + return "VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM"; + default: + return "Unhandled VkFormatFeatureFlagBits2KHR"; + } +} + +static inline std::string string_VkFormatFeatureFlags2KHR(VkFormatFeatureFlags2KHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFormatFeatureFlagBits2KHR(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFormatFeatureFlagBits2KHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDebugReportFlagBitsEXT(VkDebugReportFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_REPORT_DEBUG_BIT_EXT: + return "VK_DEBUG_REPORT_DEBUG_BIT_EXT"; + case VK_DEBUG_REPORT_ERROR_BIT_EXT: + return "VK_DEBUG_REPORT_ERROR_BIT_EXT"; + case VK_DEBUG_REPORT_INFORMATION_BIT_EXT: + return "VK_DEBUG_REPORT_INFORMATION_BIT_EXT"; + case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT: + return "VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT"; + case VK_DEBUG_REPORT_WARNING_BIT_EXT: + return "VK_DEBUG_REPORT_WARNING_BIT_EXT"; + default: + return "Unhandled VkDebugReportFlagBitsEXT"; + } +} + +static inline std::string string_VkDebugReportFlagsEXT(VkDebugReportFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDebugReportFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDebugReportFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDebugReportObjectTypeEXT(VkDebugReportObjectTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT"; + default: + return "Unhandled VkDebugReportObjectTypeEXT"; + } +} + +static inline const char* string_VkRasterizationOrderAMD(VkRasterizationOrderAMD input_value) +{ + switch (input_value) + { + case VK_RASTERIZATION_ORDER_RELAXED_AMD: + return "VK_RASTERIZATION_ORDER_RELAXED_AMD"; + case VK_RASTERIZATION_ORDER_STRICT_AMD: + return "VK_RASTERIZATION_ORDER_STRICT_AMD"; + default: + return "Unhandled VkRasterizationOrderAMD"; + } +} + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264CapabilityFlagBitsEXT(VkVideoEncodeH264CapabilityFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DISABLE_DIRECT_SPATIAL_MV_PRED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DISABLE_DIRECT_SPATIAL_MV_PRED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_PIC_INIT_QP_MINUS26_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_PIC_INIT_QP_MINUS26_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_SCALING_LISTS_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_SCALING_LISTS_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_SLICE_MB_COUNT_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_SLICE_MB_COUNT_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_EXPLICIT_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_EXPLICIT_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_IMPLICIT_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_IMPLICIT_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264CapabilityFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264CapabilityFlagsEXT(VkVideoEncodeH264CapabilityFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264CapabilityFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264CapabilityFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264InputModeFlagBitsEXT(VkVideoEncodeH264InputModeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264InputModeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264InputModeFlagsEXT(VkVideoEncodeH264InputModeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264InputModeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264InputModeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264OutputModeFlagBitsEXT(VkVideoEncodeH264OutputModeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264OutputModeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264OutputModeFlagsEXT(VkVideoEncodeH264OutputModeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264OutputModeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264OutputModeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264RateControlStructureEXT(VkVideoEncodeH264RateControlStructureEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_EXT: + return "VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_EXT"; + case VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_EXT: + return "VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_EXT"; + case VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT: + return "VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT"; + default: + return "Unhandled VkVideoEncodeH264RateControlStructureEXT"; + } +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH265CapabilityFlagBitsEXT(VkVideoEncodeH265CapabilityFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_DEBLOCKING_FILTER_OVERRIDE_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_DEBLOCKING_FILTER_OVERRIDE_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_ENTROPY_CODING_SYNC_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_ENTROPY_CODING_SYNC_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_INIT_QP_MINUS26_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_INIT_QP_MINUS26_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_PER_TILE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_PER_TILE_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_SLICE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_SLICE_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_PCM_ENABLE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_PCM_ENABLE_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_SAMPLE_ADAPTIVE_OFFSET_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_SAMPLE_ADAPTIVE_OFFSET_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_SIGN_DATA_HIDING_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_SIGN_DATA_HIDING_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_SLICE_SEGMENT_CTB_COUNT_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_SLICE_SEGMENT_CTB_COUNT_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_SPS_TEMPORAL_MVP_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_SPS_TEMPORAL_MVP_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_DISABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_DISABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSQUANT_BYPASS_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSQUANT_BYPASS_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_BIPRED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_BIPRED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH265CapabilityFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH265CapabilityFlagsEXT(VkVideoEncodeH265CapabilityFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH265CapabilityFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH265CapabilityFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH265InputModeFlagBitsEXT(VkVideoEncodeH265InputModeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH265InputModeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH265InputModeFlagsEXT(VkVideoEncodeH265InputModeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH265InputModeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH265InputModeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH265OutputModeFlagBitsEXT(VkVideoEncodeH265OutputModeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH265OutputModeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH265OutputModeFlagsEXT(VkVideoEncodeH265OutputModeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH265OutputModeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH265OutputModeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH265CtbSizeFlagBitsEXT(VkVideoEncodeH265CtbSizeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH265CtbSizeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH265CtbSizeFlagsEXT(VkVideoEncodeH265CtbSizeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH265CtbSizeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH265CtbSizeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH265TransformBlockSizeFlagBitsEXT(VkVideoEncodeH265TransformBlockSizeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_EXT"; + case VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_EXT: + return "VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH265TransformBlockSizeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH265TransformBlockSizeFlagsEXT(VkVideoEncodeH265TransformBlockSizeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH265TransformBlockSizeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH265TransformBlockSizeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH265RateControlStructureEXT(VkVideoEncodeH265RateControlStructureEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_EXT: + return "VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_EXT"; + case VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_EXT: + return "VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_EXT"; + case VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT: + return "VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT"; + default: + return "Unhandled VkVideoEncodeH265RateControlStructureEXT"; + } +} +#endif // VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkShaderInfoTypeAMD(VkShaderInfoTypeAMD input_value) +{ + switch (input_value) + { + case VK_SHADER_INFO_TYPE_BINARY_AMD: + return "VK_SHADER_INFO_TYPE_BINARY_AMD"; + case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD: + return "VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD"; + case VK_SHADER_INFO_TYPE_STATISTICS_AMD: + return "VK_SHADER_INFO_TYPE_STATISTICS_AMD"; + default: + return "Unhandled VkShaderInfoTypeAMD"; + } +} + +static inline const char* string_VkExternalMemoryHandleTypeFlagBitsNV(VkExternalMemoryHandleTypeFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV"; + default: + return "Unhandled VkExternalMemoryHandleTypeFlagBitsNV"; + } +} + +static inline std::string string_VkExternalMemoryHandleTypeFlagsNV(VkExternalMemoryHandleTypeFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryHandleTypeFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryFeatureFlagBitsNV(VkExternalMemoryFeatureFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV: + return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV"; + case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV: + return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV"; + case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV: + return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV"; + default: + return "Unhandled VkExternalMemoryFeatureFlagBitsNV"; + } +} + +static inline std::string string_VkExternalMemoryFeatureFlagsNV(VkExternalMemoryFeatureFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryFeatureFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkValidationCheckEXT(VkValidationCheckEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_CHECK_ALL_EXT: + return "VK_VALIDATION_CHECK_ALL_EXT"; + case VK_VALIDATION_CHECK_SHADERS_EXT: + return "VK_VALIDATION_CHECK_SHADERS_EXT"; + default: + return "Unhandled VkValidationCheckEXT"; + } +} + +static inline const char* string_VkPipelineRobustnessBufferBehaviorEXT(VkPipelineRobustnessBufferBehaviorEXT input_value) +{ + switch (input_value) + { + case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT: + return "VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT"; + case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT: + return "VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT"; + case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT: + return "VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT"; + case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT: + return "VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT"; + default: + return "Unhandled VkPipelineRobustnessBufferBehaviorEXT"; + } +} + +static inline const char* string_VkPipelineRobustnessImageBehaviorEXT(VkPipelineRobustnessImageBehaviorEXT input_value) +{ + switch (input_value) + { + case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT: + return "VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT"; + case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT: + return "VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT"; + case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT: + return "VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT"; + case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT: + return "VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT"; + default: + return "Unhandled VkPipelineRobustnessImageBehaviorEXT"; + } +} + +static inline const char* string_VkConditionalRenderingFlagBitsEXT(VkConditionalRenderingFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT: + return "VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT"; + default: + return "Unhandled VkConditionalRenderingFlagBitsEXT"; + } +} + +static inline std::string string_VkConditionalRenderingFlagsEXT(VkConditionalRenderingFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkConditionalRenderingFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkConditionalRenderingFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkSurfaceCounterFlagBitsEXT(VkSurfaceCounterFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_SURFACE_COUNTER_VBLANK_BIT_EXT: + return "VK_SURFACE_COUNTER_VBLANK_BIT_EXT"; + default: + return "Unhandled VkSurfaceCounterFlagBitsEXT"; + } +} + +static inline std::string string_VkSurfaceCounterFlagsEXT(VkSurfaceCounterFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSurfaceCounterFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSurfaceCounterFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDisplayPowerStateEXT(VkDisplayPowerStateEXT input_value) +{ + switch (input_value) + { + case VK_DISPLAY_POWER_STATE_OFF_EXT: + return "VK_DISPLAY_POWER_STATE_OFF_EXT"; + case VK_DISPLAY_POWER_STATE_ON_EXT: + return "VK_DISPLAY_POWER_STATE_ON_EXT"; + case VK_DISPLAY_POWER_STATE_SUSPEND_EXT: + return "VK_DISPLAY_POWER_STATE_SUSPEND_EXT"; + default: + return "Unhandled VkDisplayPowerStateEXT"; + } +} + +static inline const char* string_VkDeviceEventTypeEXT(VkDeviceEventTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT: + return "VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT"; + default: + return "Unhandled VkDeviceEventTypeEXT"; + } +} + +static inline const char* string_VkDisplayEventTypeEXT(VkDisplayEventTypeEXT input_value) +{ + switch (input_value) + { + case VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT: + return "VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT"; + default: + return "Unhandled VkDisplayEventTypeEXT"; + } +} + +static inline const char* string_VkViewportCoordinateSwizzleNV(VkViewportCoordinateSwizzleNV input_value) +{ + switch (input_value) + { + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV"; + default: + return "Unhandled VkViewportCoordinateSwizzleNV"; + } +} + +static inline const char* string_VkDiscardRectangleModeEXT(VkDiscardRectangleModeEXT input_value) +{ + switch (input_value) + { + case VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT: + return "VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT"; + case VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT: + return "VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT"; + default: + return "Unhandled VkDiscardRectangleModeEXT"; + } +} + +static inline const char* string_VkConservativeRasterizationModeEXT(VkConservativeRasterizationModeEXT input_value) +{ + switch (input_value) + { + case VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT: + return "VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT"; + case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT: + return "VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT"; + case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT: + return "VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT"; + default: + return "Unhandled VkConservativeRasterizationModeEXT"; + } +} + +static inline const char* string_VkDebugUtilsMessageSeverityFlagBitsEXT(VkDebugUtilsMessageSeverityFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT"; + default: + return "Unhandled VkDebugUtilsMessageSeverityFlagBitsEXT"; + } +} + +static inline std::string string_VkDebugUtilsMessageSeverityFlagsEXT(VkDebugUtilsMessageSeverityFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDebugUtilsMessageSeverityFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDebugUtilsMessageSeverityFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDebugUtilsMessageTypeFlagBitsEXT(VkDebugUtilsMessageTypeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT"; + default: + return "Unhandled VkDebugUtilsMessageTypeFlagBitsEXT"; + } +} + +static inline std::string string_VkDebugUtilsMessageTypeFlagsEXT(VkDebugUtilsMessageTypeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDebugUtilsMessageTypeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDebugUtilsMessageTypeFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkSamplerReductionModeEXT(VkSamplerReductionModeEXT input_value) +{ + switch (input_value) + { + case VK_SAMPLER_REDUCTION_MODE_MAX: + return "VK_SAMPLER_REDUCTION_MODE_MAX"; + case VK_SAMPLER_REDUCTION_MODE_MIN: + return "VK_SAMPLER_REDUCTION_MODE_MIN"; + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: + return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE"; + default: + return "Unhandled VkSamplerReductionModeEXT"; + } +} + +static inline const char* string_VkBlendOverlapEXT(VkBlendOverlapEXT input_value) +{ + switch (input_value) + { + case VK_BLEND_OVERLAP_CONJOINT_EXT: + return "VK_BLEND_OVERLAP_CONJOINT_EXT"; + case VK_BLEND_OVERLAP_DISJOINT_EXT: + return "VK_BLEND_OVERLAP_DISJOINT_EXT"; + case VK_BLEND_OVERLAP_UNCORRELATED_EXT: + return "VK_BLEND_OVERLAP_UNCORRELATED_EXT"; + default: + return "Unhandled VkBlendOverlapEXT"; + } +} + +static inline const char* string_VkCoverageModulationModeNV(VkCoverageModulationModeNV input_value) +{ + switch (input_value) + { + case VK_COVERAGE_MODULATION_MODE_ALPHA_NV: + return "VK_COVERAGE_MODULATION_MODE_ALPHA_NV"; + case VK_COVERAGE_MODULATION_MODE_NONE_NV: + return "VK_COVERAGE_MODULATION_MODE_NONE_NV"; + case VK_COVERAGE_MODULATION_MODE_RGBA_NV: + return "VK_COVERAGE_MODULATION_MODE_RGBA_NV"; + case VK_COVERAGE_MODULATION_MODE_RGB_NV: + return "VK_COVERAGE_MODULATION_MODE_RGB_NV"; + default: + return "Unhandled VkCoverageModulationModeNV"; + } +} + +static inline const char* string_VkValidationCacheHeaderVersionEXT(VkValidationCacheHeaderVersionEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT: + return "VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT"; + default: + return "Unhandled VkValidationCacheHeaderVersionEXT"; + } +} + +static inline const char* string_VkDescriptorBindingFlagBitsEXT(VkDescriptorBindingFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT: + return "VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT"; + case VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT: + return "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT"; + default: + return "Unhandled VkDescriptorBindingFlagBitsEXT"; + } +} + +static inline std::string string_VkDescriptorBindingFlagsEXT(VkDescriptorBindingFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorBindingFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorBindingFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkShadingRatePaletteEntryNV(VkShadingRatePaletteEntryNV input_value) +{ + switch (input_value) + { + case VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV"; + default: + return "Unhandled VkShadingRatePaletteEntryNV"; + } +} + +static inline const char* string_VkCoarseSampleOrderTypeNV(VkCoarseSampleOrderTypeNV input_value) +{ + switch (input_value) + { + case VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV"; + case VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV"; + case VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV"; + case VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV"; + default: + return "Unhandled VkCoarseSampleOrderTypeNV"; + } +} + +static inline const char* string_VkRayTracingShaderGroupTypeKHR(VkRayTracingShaderGroupTypeKHR input_value) +{ + switch (input_value) + { + case VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR"; + default: + return "Unhandled VkRayTracingShaderGroupTypeKHR"; + } +} + +static inline const char* string_VkRayTracingShaderGroupTypeNV(VkRayTracingShaderGroupTypeNV input_value) +{ + switch (input_value) + { + case VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR"; + default: + return "Unhandled VkRayTracingShaderGroupTypeNV"; + } +} + +static inline const char* string_VkGeometryTypeKHR(VkGeometryTypeKHR input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_TYPE_AABBS_KHR: + return "VK_GEOMETRY_TYPE_AABBS_KHR"; + case VK_GEOMETRY_TYPE_INSTANCES_KHR: + return "VK_GEOMETRY_TYPE_INSTANCES_KHR"; + case VK_GEOMETRY_TYPE_TRIANGLES_KHR: + return "VK_GEOMETRY_TYPE_TRIANGLES_KHR"; + default: + return "Unhandled VkGeometryTypeKHR"; + } +} + +static inline const char* string_VkGeometryTypeNV(VkGeometryTypeNV input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_TYPE_AABBS_KHR: + return "VK_GEOMETRY_TYPE_AABBS_KHR"; + case VK_GEOMETRY_TYPE_INSTANCES_KHR: + return "VK_GEOMETRY_TYPE_INSTANCES_KHR"; + case VK_GEOMETRY_TYPE_TRIANGLES_KHR: + return "VK_GEOMETRY_TYPE_TRIANGLES_KHR"; + default: + return "Unhandled VkGeometryTypeNV"; + } +} + +static inline const char* string_VkAccelerationStructureTypeKHR(VkAccelerationStructureTypeKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR"; + default: + return "Unhandled VkAccelerationStructureTypeKHR"; + } +} + +static inline const char* string_VkAccelerationStructureTypeNV(VkAccelerationStructureTypeNV input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR"; + default: + return "Unhandled VkAccelerationStructureTypeNV"; + } +} + +static inline const char* string_VkGeometryFlagBitsKHR(VkGeometryFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR: + return "VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR"; + case VK_GEOMETRY_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_OPAQUE_BIT_KHR"; + default: + return "Unhandled VkGeometryFlagBitsKHR"; + } +} + +static inline std::string string_VkGeometryFlagsKHR(VkGeometryFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkGeometryFlagBitsNV(VkGeometryFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR: + return "VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR"; + case VK_GEOMETRY_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_OPAQUE_BIT_KHR"; + default: + return "Unhandled VkGeometryFlagBitsNV"; + } +} + +static inline std::string string_VkGeometryFlagsNV(VkGeometryFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkGeometryInstanceFlagBitsKHR(VkGeometryInstanceFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT: + return "VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT"; + case VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT: + return "VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT"; + case VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR"; + default: + return "Unhandled VkGeometryInstanceFlagBitsKHR"; + } +} + +static inline std::string string_VkGeometryInstanceFlagsKHR(VkGeometryInstanceFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryInstanceFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryInstanceFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkGeometryInstanceFlagBitsNV(VkGeometryInstanceFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT: + return "VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT"; + case VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT: + return "VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT"; + case VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR"; + default: + return "Unhandled VkGeometryInstanceFlagBitsNV"; + } +} + +static inline std::string string_VkGeometryInstanceFlagsNV(VkGeometryInstanceFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryInstanceFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryInstanceFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkBuildAccelerationStructureFlagBitsKHR(VkBuildAccelerationStructureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV: + return "VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR"; + default: + return "Unhandled VkBuildAccelerationStructureFlagBitsKHR"; + } +} + +static inline std::string string_VkBuildAccelerationStructureFlagsKHR(VkBuildAccelerationStructureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBuildAccelerationStructureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBuildAccelerationStructureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkBuildAccelerationStructureFlagBitsNV(VkBuildAccelerationStructureFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV: + return "VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR"; + default: + return "Unhandled VkBuildAccelerationStructureFlagBitsNV"; + } +} + +static inline std::string string_VkBuildAccelerationStructureFlagsNV(VkBuildAccelerationStructureFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBuildAccelerationStructureFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBuildAccelerationStructureFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkCopyAccelerationStructureModeKHR(VkCopyAccelerationStructureModeKHR input_value) +{ + switch (input_value) + { + case VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR"; + default: + return "Unhandled VkCopyAccelerationStructureModeKHR"; + } +} + +static inline const char* string_VkCopyAccelerationStructureModeNV(VkCopyAccelerationStructureModeNV input_value) +{ + switch (input_value) + { + case VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR"; + default: + return "Unhandled VkCopyAccelerationStructureModeNV"; + } +} + +static inline const char* string_VkAccelerationStructureMemoryRequirementsTypeNV(VkAccelerationStructureMemoryRequirementsTypeNV input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV: + return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV"; + case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV: + return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV"; + case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV: + return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV"; + default: + return "Unhandled VkAccelerationStructureMemoryRequirementsTypeNV"; + } +} + +static inline const char* string_VkQueueGlobalPriorityEXT(VkQueueGlobalPriorityEXT input_value) +{ + switch (input_value) + { + case VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR"; + case VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR"; + case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR"; + case VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR: + return "VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR"; + default: + return "Unhandled VkQueueGlobalPriorityEXT"; + } +} + +static inline const char* string_VkTimeDomainEXT(VkTimeDomainEXT input_value) +{ + switch (input_value) + { + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT: + return "VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT"; + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT: + return "VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT"; + case VK_TIME_DOMAIN_DEVICE_EXT: + return "VK_TIME_DOMAIN_DEVICE_EXT"; + case VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT: + return "VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT"; + default: + return "Unhandled VkTimeDomainEXT"; + } +} + +static inline const char* string_VkMemoryOverallocationBehaviorAMD(VkMemoryOverallocationBehaviorAMD input_value) +{ + switch (input_value) + { + case VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD: + return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD"; + case VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD: + return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD"; + case VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD: + return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD"; + default: + return "Unhandled VkMemoryOverallocationBehaviorAMD"; + } +} + +static inline const char* string_VkPipelineCreationFeedbackFlagBitsEXT(VkPipelineCreationFeedbackFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT: + return "VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT"; + case VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT: + return "VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT"; + case VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT: + return "VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT"; + default: + return "Unhandled VkPipelineCreationFeedbackFlagBitsEXT"; + } +} + +static inline std::string string_VkPipelineCreationFeedbackFlagsEXT(VkPipelineCreationFeedbackFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCreationFeedbackFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCreationFeedbackFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkPerformanceConfigurationTypeINTEL(VkPerformanceConfigurationTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL: + return "VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL"; + default: + return "Unhandled VkPerformanceConfigurationTypeINTEL"; + } +} + +static inline const char* string_VkQueryPoolSamplingModeINTEL(VkQueryPoolSamplingModeINTEL input_value) +{ + switch (input_value) + { + case VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL: + return "VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL"; + default: + return "Unhandled VkQueryPoolSamplingModeINTEL"; + } +} + +static inline const char* string_VkPerformanceOverrideTypeINTEL(VkPerformanceOverrideTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL: + return "VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL"; + case VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL: + return "VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL"; + default: + return "Unhandled VkPerformanceOverrideTypeINTEL"; + } +} + +static inline const char* string_VkPerformanceParameterTypeINTEL(VkPerformanceParameterTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL: + return "VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL"; + case VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL: + return "VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL"; + default: + return "Unhandled VkPerformanceParameterTypeINTEL"; + } +} + +static inline const char* string_VkPerformanceValueTypeINTEL(VkPerformanceValueTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL"; + default: + return "Unhandled VkPerformanceValueTypeINTEL"; + } +} + +static inline const char* string_VkToolPurposeFlagBitsEXT(VkToolPurposeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT: + return "VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT"; + case VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT: + return "VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"; + case VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT: + return "VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"; + case VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT: + return "VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT"; + case VK_TOOL_PURPOSE_PROFILING_BIT: + return "VK_TOOL_PURPOSE_PROFILING_BIT"; + case VK_TOOL_PURPOSE_TRACING_BIT: + return "VK_TOOL_PURPOSE_TRACING_BIT"; + case VK_TOOL_PURPOSE_VALIDATION_BIT: + return "VK_TOOL_PURPOSE_VALIDATION_BIT"; + default: + return "Unhandled VkToolPurposeFlagBitsEXT"; + } +} + +static inline std::string string_VkToolPurposeFlagsEXT(VkToolPurposeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkToolPurposeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkToolPurposeFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkValidationFeatureEnableEXT(VkValidationFeatureEnableEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT"; + default: + return "Unhandled VkValidationFeatureEnableEXT"; + } +} + +static inline const char* string_VkValidationFeatureDisableEXT(VkValidationFeatureDisableEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_ALL_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT"; + default: + return "Unhandled VkValidationFeatureDisableEXT"; + } +} + +static inline const char* string_VkComponentTypeNV(VkComponentTypeNV input_value) +{ + switch (input_value) + { + case VK_COMPONENT_TYPE_FLOAT16_NV: + return "VK_COMPONENT_TYPE_FLOAT16_NV"; + case VK_COMPONENT_TYPE_FLOAT32_NV: + return "VK_COMPONENT_TYPE_FLOAT32_NV"; + case VK_COMPONENT_TYPE_FLOAT64_NV: + return "VK_COMPONENT_TYPE_FLOAT64_NV"; + case VK_COMPONENT_TYPE_SINT16_NV: + return "VK_COMPONENT_TYPE_SINT16_NV"; + case VK_COMPONENT_TYPE_SINT32_NV: + return "VK_COMPONENT_TYPE_SINT32_NV"; + case VK_COMPONENT_TYPE_SINT64_NV: + return "VK_COMPONENT_TYPE_SINT64_NV"; + case VK_COMPONENT_TYPE_SINT8_NV: + return "VK_COMPONENT_TYPE_SINT8_NV"; + case VK_COMPONENT_TYPE_UINT16_NV: + return "VK_COMPONENT_TYPE_UINT16_NV"; + case VK_COMPONENT_TYPE_UINT32_NV: + return "VK_COMPONENT_TYPE_UINT32_NV"; + case VK_COMPONENT_TYPE_UINT64_NV: + return "VK_COMPONENT_TYPE_UINT64_NV"; + case VK_COMPONENT_TYPE_UINT8_NV: + return "VK_COMPONENT_TYPE_UINT8_NV"; + default: + return "Unhandled VkComponentTypeNV"; + } +} + +static inline const char* string_VkScopeNV(VkScopeNV input_value) +{ + switch (input_value) + { + case VK_SCOPE_DEVICE_NV: + return "VK_SCOPE_DEVICE_NV"; + case VK_SCOPE_QUEUE_FAMILY_NV: + return "VK_SCOPE_QUEUE_FAMILY_NV"; + case VK_SCOPE_SUBGROUP_NV: + return "VK_SCOPE_SUBGROUP_NV"; + case VK_SCOPE_WORKGROUP_NV: + return "VK_SCOPE_WORKGROUP_NV"; + default: + return "Unhandled VkScopeNV"; + } +} + +static inline const char* string_VkCoverageReductionModeNV(VkCoverageReductionModeNV input_value) +{ + switch (input_value) + { + case VK_COVERAGE_REDUCTION_MODE_MERGE_NV: + return "VK_COVERAGE_REDUCTION_MODE_MERGE_NV"; + case VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV: + return "VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV"; + default: + return "Unhandled VkCoverageReductionModeNV"; + } +} + +static inline const char* string_VkProvokingVertexModeEXT(VkProvokingVertexModeEXT input_value) +{ + switch (input_value) + { + case VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT: + return "VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT"; + case VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT: + return "VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT"; + default: + return "Unhandled VkProvokingVertexModeEXT"; + } +} + + +#ifdef VK_USE_PLATFORM_WIN32_KHR + +static inline const char* string_VkFullScreenExclusiveEXT(VkFullScreenExclusiveEXT input_value) +{ + switch (input_value) + { + case VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT"; + case VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT"; + case VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT"; + case VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT"; + default: + return "Unhandled VkFullScreenExclusiveEXT"; + } +} +#endif // VK_USE_PLATFORM_WIN32_KHR + +static inline const char* string_VkLineRasterizationModeEXT(VkLineRasterizationModeEXT input_value) +{ + switch (input_value) + { + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + return "VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT"; + case VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT: + return "VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT"; + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: + return "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT"; + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + return "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT"; + default: + return "Unhandled VkLineRasterizationModeEXT"; + } +} + +static inline const char* string_VkPresentScalingFlagBitsEXT(VkPresentScalingFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT: + return "VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT"; + case VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT: + return "VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT"; + case VK_PRESENT_SCALING_STRETCH_BIT_EXT: + return "VK_PRESENT_SCALING_STRETCH_BIT_EXT"; + default: + return "Unhandled VkPresentScalingFlagBitsEXT"; + } +} + +static inline std::string string_VkPresentScalingFlagsEXT(VkPresentScalingFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPresentScalingFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPresentScalingFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkPresentGravityFlagBitsEXT(VkPresentGravityFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_PRESENT_GRAVITY_CENTERED_BIT_EXT: + return "VK_PRESENT_GRAVITY_CENTERED_BIT_EXT"; + case VK_PRESENT_GRAVITY_MAX_BIT_EXT: + return "VK_PRESENT_GRAVITY_MAX_BIT_EXT"; + case VK_PRESENT_GRAVITY_MIN_BIT_EXT: + return "VK_PRESENT_GRAVITY_MIN_BIT_EXT"; + default: + return "Unhandled VkPresentGravityFlagBitsEXT"; + } +} + +static inline std::string string_VkPresentGravityFlagsEXT(VkPresentGravityFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPresentGravityFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPresentGravityFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkIndirectStateFlagBitsNV(VkIndirectStateFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV: + return "VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV"; + default: + return "Unhandled VkIndirectStateFlagBitsNV"; + } +} + +static inline std::string string_VkIndirectStateFlagsNV(VkIndirectStateFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkIndirectStateFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkIndirectStateFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkIndirectCommandsTokenTypeNV(VkIndirectCommandsTokenTypeNV input_value) +{ + switch (input_value) + { + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV"; + default: + return "Unhandled VkIndirectCommandsTokenTypeNV"; + } +} + +static inline const char* string_VkIndirectCommandsLayoutUsageFlagBitsNV(VkIndirectCommandsLayoutUsageFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV: + return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV"; + case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV: + return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV"; + case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV: + return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV"; + default: + return "Unhandled VkIndirectCommandsLayoutUsageFlagBitsNV"; + } +} + +static inline std::string string_VkIndirectCommandsLayoutUsageFlagsNV(VkIndirectCommandsLayoutUsageFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkIndirectCommandsLayoutUsageFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkIndirectCommandsLayoutUsageFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceMemoryReportEventTypeEXT(VkDeviceMemoryReportEventTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT"; + default: + return "Unhandled VkDeviceMemoryReportEventTypeEXT"; + } +} + +static inline const char* string_VkDeviceDiagnosticsConfigFlagBitsNV(VkDeviceDiagnosticsConfigFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV"; + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV"; + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV"; + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV"; + default: + return "Unhandled VkDeviceDiagnosticsConfigFlagBitsNV"; + } +} + +static inline std::string string_VkDeviceDiagnosticsConfigFlagsNV(VkDeviceDiagnosticsConfigFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceDiagnosticsConfigFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceDiagnosticsConfigFlagBitsNV(static_cast(0))); + return ret; +} + + +#ifdef VK_USE_PLATFORM_METAL_EXT + +static inline const char* string_VkExportMetalObjectTypeFlagBitsEXT(VkExportMetalObjectTypeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT: + return "VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT"; + case VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT: + return "VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT"; + case VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT: + return "VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT"; + case VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT: + return "VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT"; + case VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT: + return "VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT"; + case VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT: + return "VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT"; + default: + return "Unhandled VkExportMetalObjectTypeFlagBitsEXT"; + } +} + +static inline std::string string_VkExportMetalObjectTypeFlagsEXT(VkExportMetalObjectTypeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExportMetalObjectTypeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExportMetalObjectTypeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_USE_PLATFORM_METAL_EXT + +static inline const char* string_VkGraphicsPipelineLibraryFlagBitsEXT(VkGraphicsPipelineLibraryFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT: + return "VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT"; + case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT: + return "VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT"; + case VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT: + return "VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT"; + case VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT: + return "VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT"; + default: + return "Unhandled VkGraphicsPipelineLibraryFlagBitsEXT"; + } +} + +static inline std::string string_VkGraphicsPipelineLibraryFlagsEXT(VkGraphicsPipelineLibraryFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGraphicsPipelineLibraryFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGraphicsPipelineLibraryFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkFragmentShadingRateTypeNV(VkFragmentShadingRateTypeNV input_value) +{ + switch (input_value) + { + case VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV: + return "VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV"; + case VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV: + return "VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV"; + default: + return "Unhandled VkFragmentShadingRateTypeNV"; + } +} + +static inline const char* string_VkFragmentShadingRateNV(VkFragmentShadingRateNV input_value) +{ + switch (input_value) + { + case VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV: + return "VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV"; + default: + return "Unhandled VkFragmentShadingRateNV"; + } +} + +static inline const char* string_VkAccelerationStructureMotionInstanceTypeNV(VkAccelerationStructureMotionInstanceTypeNV input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV: + return "VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV"; + case VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV: + return "VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV"; + case VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV: + return "VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV"; + default: + return "Unhandled VkAccelerationStructureMotionInstanceTypeNV"; + } +} + +static inline const char* string_VkImageCompressionFlagBitsEXT(VkImageCompressionFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_IMAGE_COMPRESSION_DEFAULT_EXT: + return "VK_IMAGE_COMPRESSION_DEFAULT_EXT"; + case VK_IMAGE_COMPRESSION_DISABLED_EXT: + return "VK_IMAGE_COMPRESSION_DISABLED_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT"; + default: + return "Unhandled VkImageCompressionFlagBitsEXT"; + } +} + +static inline std::string string_VkImageCompressionFlagsEXT(VkImageCompressionFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageCompressionFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageCompressionFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageCompressionFixedRateFlagBitsEXT(VkImageCompressionFixedRateFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT"; + case VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT: + return "VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT"; + default: + return "Unhandled VkImageCompressionFixedRateFlagBitsEXT"; + } +} + +static inline std::string string_VkImageCompressionFixedRateFlagsEXT(VkImageCompressionFixedRateFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageCompressionFixedRateFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageCompressionFixedRateFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceFaultAddressTypeEXT(VkDeviceFaultAddressTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT: + return "VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT"; + default: + return "Unhandled VkDeviceFaultAddressTypeEXT"; + } +} + +static inline const char* string_VkDeviceFaultVendorBinaryHeaderVersionEXT(VkDeviceFaultVendorBinaryHeaderVersionEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT: + return "VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT"; + default: + return "Unhandled VkDeviceFaultVendorBinaryHeaderVersionEXT"; + } +} + +static inline const char* string_VkDeviceAddressBindingFlagBitsEXT(VkDeviceAddressBindingFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT: + return "VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT"; + default: + return "Unhandled VkDeviceAddressBindingFlagBitsEXT"; + } +} + +static inline std::string string_VkDeviceAddressBindingFlagsEXT(VkDeviceAddressBindingFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceAddressBindingFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceAddressBindingFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceAddressBindingTypeEXT(VkDeviceAddressBindingTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT: + return "VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT"; + case VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT: + return "VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT"; + default: + return "Unhandled VkDeviceAddressBindingTypeEXT"; + } +} + + +#ifdef VK_USE_PLATFORM_FUCHSIA + +static inline const char* string_VkImageConstraintsInfoFlagBitsFUCHSIA(VkImageConstraintsInfoFlagBitsFUCHSIA input_value) +{ + switch (input_value) + { + case VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA: + return "VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA"; + case VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA: + return "VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA"; + case VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA: + return "VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA"; + case VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA: + return "VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA"; + case VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA: + return "VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA"; + default: + return "Unhandled VkImageConstraintsInfoFlagBitsFUCHSIA"; + } +} + +static inline std::string string_VkImageConstraintsInfoFlagsFUCHSIA(VkImageConstraintsInfoFlagsFUCHSIA input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageConstraintsInfoFlagBitsFUCHSIA(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageConstraintsInfoFlagBitsFUCHSIA(static_cast(0))); + return ret; +} +#endif // VK_USE_PLATFORM_FUCHSIA + +static inline const char* string_VkMicromapTypeEXT(VkMicromapTypeEXT input_value) +{ + switch (input_value) + { + case VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT: + return "VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT"; + default: + return "Unhandled VkMicromapTypeEXT"; + } +} + +static inline const char* string_VkBuildMicromapFlagBitsEXT(VkBuildMicromapFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_BUILD_MICROMAP_ALLOW_COMPACTION_BIT_EXT: + return "VK_BUILD_MICROMAP_ALLOW_COMPACTION_BIT_EXT"; + case VK_BUILD_MICROMAP_PREFER_FAST_BUILD_BIT_EXT: + return "VK_BUILD_MICROMAP_PREFER_FAST_BUILD_BIT_EXT"; + case VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT: + return "VK_BUILD_MICROMAP_PREFER_FAST_TRACE_BIT_EXT"; + default: + return "Unhandled VkBuildMicromapFlagBitsEXT"; + } +} + +static inline std::string string_VkBuildMicromapFlagsEXT(VkBuildMicromapFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBuildMicromapFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBuildMicromapFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkBuildMicromapModeEXT(VkBuildMicromapModeEXT input_value) +{ + switch (input_value) + { + case VK_BUILD_MICROMAP_MODE_BUILD_EXT: + return "VK_BUILD_MICROMAP_MODE_BUILD_EXT"; + default: + return "Unhandled VkBuildMicromapModeEXT"; + } +} + +static inline const char* string_VkMicromapCreateFlagBitsEXT(VkMicromapCreateFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT: + return "VK_MICROMAP_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT"; + default: + return "Unhandled VkMicromapCreateFlagBitsEXT"; + } +} + +static inline std::string string_VkMicromapCreateFlagsEXT(VkMicromapCreateFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMicromapCreateFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMicromapCreateFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkCopyMicromapModeEXT(VkCopyMicromapModeEXT input_value) +{ + switch (input_value) + { + case VK_COPY_MICROMAP_MODE_CLONE_EXT: + return "VK_COPY_MICROMAP_MODE_CLONE_EXT"; + case VK_COPY_MICROMAP_MODE_COMPACT_EXT: + return "VK_COPY_MICROMAP_MODE_COMPACT_EXT"; + case VK_COPY_MICROMAP_MODE_DESERIALIZE_EXT: + return "VK_COPY_MICROMAP_MODE_DESERIALIZE_EXT"; + case VK_COPY_MICROMAP_MODE_SERIALIZE_EXT: + return "VK_COPY_MICROMAP_MODE_SERIALIZE_EXT"; + default: + return "Unhandled VkCopyMicromapModeEXT"; + } +} + +static inline const char* string_VkOpacityMicromapFormatEXT(VkOpacityMicromapFormatEXT input_value) +{ + switch (input_value) + { + case VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT: + return "VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT"; + case VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT: + return "VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT"; + default: + return "Unhandled VkOpacityMicromapFormatEXT"; + } +} + +static inline const char* string_VkOpacityMicromapSpecialIndexEXT(VkOpacityMicromapSpecialIndexEXT input_value) +{ + switch (input_value) + { + case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT: + return "VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT"; + case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT: + return "VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT"; + case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT: + return "VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT"; + case VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT: + return "VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT"; + default: + return "Unhandled VkOpacityMicromapSpecialIndexEXT"; + } +} + +static inline const char* string_VkAccelerationStructureCompatibilityKHR(VkAccelerationStructureCompatibilityKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR: + return "VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR"; + case VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR: + return "VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR"; + default: + return "Unhandled VkAccelerationStructureCompatibilityKHR"; + } +} + +static inline const char* string_VkAccelerationStructureBuildTypeKHR(VkAccelerationStructureBuildTypeKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR: + return "VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR"; + case VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR: + return "VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR"; + case VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR: + return "VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR"; + default: + return "Unhandled VkAccelerationStructureBuildTypeKHR"; + } +} + +static inline const char* string_VkMemoryDecompressionMethodFlagBitsNV(uint64_t input_value) +{ + switch (input_value) + { + case VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV: + return "VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV"; + default: + return "Unhandled VkMemoryDecompressionMethodFlagBitsNV"; + } +} + +static inline std::string string_VkMemoryDecompressionMethodFlagsNV(VkMemoryDecompressionMethodFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryDecompressionMethodFlagBitsNV(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryDecompressionMethodFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubpassMergeStatusEXT(VkSubpassMergeStatusEXT input_value) +{ + switch (input_value) + { + case VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT: + return "VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT"; + case VK_SUBPASS_MERGE_STATUS_MERGED_EXT: + return "VK_SUBPASS_MERGE_STATUS_MERGED_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT"; + case VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT: + return "VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT"; + default: + return "Unhandled VkSubpassMergeStatusEXT"; + } +} + +static inline const char* string_VkDirectDriverLoadingModeLUNARG(VkDirectDriverLoadingModeLUNARG input_value) +{ + switch (input_value) + { + case VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG: + return "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG"; + case VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG: + return "VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG"; + default: + return "Unhandled VkDirectDriverLoadingModeLUNARG"; + } +} + +static inline const char* string_VkOpticalFlowGridSizeFlagBitsNV(VkOpticalFlowGridSizeFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_NV: + return "VK_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_NV"; + case VK_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_NV: + return "VK_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_NV"; + case VK_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_NV: + return "VK_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_NV"; + case VK_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_NV: + return "VK_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_NV"; + case VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV: + return "VK_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_NV"; + default: + return "Unhandled VkOpticalFlowGridSizeFlagBitsNV"; + } +} + +static inline std::string string_VkOpticalFlowGridSizeFlagsNV(VkOpticalFlowGridSizeFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkOpticalFlowGridSizeFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkOpticalFlowGridSizeFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkOpticalFlowUsageFlagBitsNV(VkOpticalFlowUsageFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_OPTICAL_FLOW_USAGE_COST_BIT_NV: + return "VK_OPTICAL_FLOW_USAGE_COST_BIT_NV"; + case VK_OPTICAL_FLOW_USAGE_GLOBAL_FLOW_BIT_NV: + return "VK_OPTICAL_FLOW_USAGE_GLOBAL_FLOW_BIT_NV"; + case VK_OPTICAL_FLOW_USAGE_HINT_BIT_NV: + return "VK_OPTICAL_FLOW_USAGE_HINT_BIT_NV"; + case VK_OPTICAL_FLOW_USAGE_INPUT_BIT_NV: + return "VK_OPTICAL_FLOW_USAGE_INPUT_BIT_NV"; + case VK_OPTICAL_FLOW_USAGE_OUTPUT_BIT_NV: + return "VK_OPTICAL_FLOW_USAGE_OUTPUT_BIT_NV"; + case VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV: + return "VK_OPTICAL_FLOW_USAGE_UNKNOWN_NV"; + default: + return "Unhandled VkOpticalFlowUsageFlagBitsNV"; + } +} + +static inline std::string string_VkOpticalFlowUsageFlagsNV(VkOpticalFlowUsageFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkOpticalFlowUsageFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkOpticalFlowUsageFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkOpticalFlowPerformanceLevelNV(VkOpticalFlowPerformanceLevelNV input_value) +{ + switch (input_value) + { + case VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_NV: + return "VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_NV"; + case VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_NV: + return "VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_NV"; + case VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_NV: + return "VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_NV"; + case VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_NV: + return "VK_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_NV"; + default: + return "Unhandled VkOpticalFlowPerformanceLevelNV"; + } +} + +static inline const char* string_VkOpticalFlowSessionBindingPointNV(VkOpticalFlowSessionBindingPointNV input_value) +{ + switch (input_value) + { + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_COST_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_COST_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_FLOW_VECTOR_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_BACKWARD_FLOW_VECTOR_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_COST_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_COST_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_FLOW_VECTOR_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_FLOW_VECTOR_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_GLOBAL_FLOW_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_GLOBAL_FLOW_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_HINT_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_HINT_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_INPUT_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_INPUT_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_REFERENCE_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_REFERENCE_NV"; + case VK_OPTICAL_FLOW_SESSION_BINDING_POINT_UNKNOWN_NV: + return "VK_OPTICAL_FLOW_SESSION_BINDING_POINT_UNKNOWN_NV"; + default: + return "Unhandled VkOpticalFlowSessionBindingPointNV"; + } +} + +static inline const char* string_VkOpticalFlowSessionCreateFlagBitsNV(VkOpticalFlowSessionCreateFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_OPTICAL_FLOW_SESSION_CREATE_ALLOW_REGIONS_BIT_NV: + return "VK_OPTICAL_FLOW_SESSION_CREATE_ALLOW_REGIONS_BIT_NV"; + case VK_OPTICAL_FLOW_SESSION_CREATE_BOTH_DIRECTIONS_BIT_NV: + return "VK_OPTICAL_FLOW_SESSION_CREATE_BOTH_DIRECTIONS_BIT_NV"; + case VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_COST_BIT_NV: + return "VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_COST_BIT_NV"; + case VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_GLOBAL_FLOW_BIT_NV: + return "VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_GLOBAL_FLOW_BIT_NV"; + case VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV: + return "VK_OPTICAL_FLOW_SESSION_CREATE_ENABLE_HINT_BIT_NV"; + default: + return "Unhandled VkOpticalFlowSessionCreateFlagBitsNV"; + } +} + +static inline std::string string_VkOpticalFlowSessionCreateFlagsNV(VkOpticalFlowSessionCreateFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkOpticalFlowSessionCreateFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkOpticalFlowSessionCreateFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkOpticalFlowExecuteFlagBitsNV(VkOpticalFlowExecuteFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV: + return "VK_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_NV"; + default: + return "Unhandled VkOpticalFlowExecuteFlagBitsNV"; + } +} + +static inline std::string string_VkOpticalFlowExecuteFlagsNV(VkOpticalFlowExecuteFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkOpticalFlowExecuteFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkOpticalFlowExecuteFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkRayTracingInvocationReorderModeNV(VkRayTracingInvocationReorderModeNV input_value) +{ + switch (input_value) + { + case VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV: + return "VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV"; + case VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV: + return "VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV"; + default: + return "Unhandled VkRayTracingInvocationReorderModeNV"; + } +} + +static inline const char* string_VkBuildAccelerationStructureModeKHR(VkBuildAccelerationStructureModeKHR input_value) +{ + switch (input_value) + { + case VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR"; + default: + return "Unhandled VkBuildAccelerationStructureModeKHR"; + } +} + +static inline const char* string_VkAccelerationStructureCreateFlagBitsKHR(VkAccelerationStructureCreateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT: + return "VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT"; + case VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR: + return "VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR"; + case VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV: + return "VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV"; + default: + return "Unhandled VkAccelerationStructureCreateFlagBitsKHR"; + } +} + +static inline std::string string_VkAccelerationStructureCreateFlagsKHR(VkAccelerationStructureCreateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccelerationStructureCreateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccelerationStructureCreateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkShaderGroupShaderKHR(VkShaderGroupShaderKHR input_value) +{ + switch (input_value) + { + case VK_SHADER_GROUP_SHADER_ANY_HIT_KHR: + return "VK_SHADER_GROUP_SHADER_ANY_HIT_KHR"; + case VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR: + return "VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR"; + case VK_SHADER_GROUP_SHADER_GENERAL_KHR: + return "VK_SHADER_GROUP_SHADER_GENERAL_KHR"; + case VK_SHADER_GROUP_SHADER_INTERSECTION_KHR: + return "VK_SHADER_GROUP_SHADER_INTERSECTION_KHR"; + default: + return "Unhandled VkShaderGroupShaderKHR"; + } +} + +static inline const char * GetPhysDevFeatureString(uint32_t index) { + const char * IndexToPhysDevFeatureString[] = { + "robustBufferAccess", + "fullDrawIndexUint32", + "imageCubeArray", + "independentBlend", + "geometryShader", + "tessellationShader", + "sampleRateShading", + "dualSrcBlend", + "logicOp", + "multiDrawIndirect", + "drawIndirectFirstInstance", + "depthClamp", + "depthBiasClamp", + "fillModeNonSolid", + "depthBounds", + "wideLines", + "largePoints", + "alphaToOne", + "multiViewport", + "samplerAnisotropy", + "textureCompressionETC2", + "textureCompressionASTC_LDR", + "textureCompressionBC", + "occlusionQueryPrecise", + "pipelineStatisticsQuery", + "vertexPipelineStoresAndAtomics", + "fragmentStoresAndAtomics", + "shaderTessellationAndGeometryPointSize", + "shaderImageGatherExtended", + "shaderStorageImageExtendedFormats", + "shaderStorageImageMultisample", + "shaderStorageImageReadWithoutFormat", + "shaderStorageImageWriteWithoutFormat", + "shaderUniformBufferArrayDynamicIndexing", + "shaderSampledImageArrayDynamicIndexing", + "shaderStorageBufferArrayDynamicIndexing", + "shaderStorageImageArrayDynamicIndexing", + "shaderClipDistance", + "shaderCullDistance", + "shaderFloat64", + "shaderInt64", + "shaderInt16", + "shaderResourceResidency", + "shaderResourceMinLod", + "sparseBinding", + "sparseResidencyBuffer", + "sparseResidencyImage2D", + "sparseResidencyImage3D", + "sparseResidency2Samples", + "sparseResidency4Samples", + "sparseResidency8Samples", + "sparseResidency16Samples", + "sparseResidencyAliased", + "variableMultisampleRate", + "inheritedQueries", + }; + + return IndexToPhysDevFeatureString[index]; +} + +static inline bool IsDuplicatePnext(VkStructureType input_value) +{ + switch (input_value) + { + case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT: + case VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT: + case VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO: + case VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT: + case VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT: + case VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT: + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: + case VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT: + case VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT: + case VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT: + return true; + default: + return false; + } +} diff --git a/ext/vulkan/vk_icd.h b/ext/vulkan/vk_icd.h index 59204a341..1133fa367 100644 --- a/ext/vulkan/vk_icd.h +++ b/ext/vulkan/vk_icd.h @@ -1,9 +1,23 @@ +// +// File: vk_icd.h +// /* - * Copyright 2015-2023 The Khronos Group Inc. - * Copyright 2015-2023 Valve Corporation - * Copyright 2015-2023 LunarG, Inc. + * Copyright (c) 2015-2023 LunarG, Inc. + * Copyright (c) 2015-2023 The Khronos Group Inc. + * Copyright (c) 2015-2023 Valve Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * SPDX-License-Identifier: Apache-2.0 */ #pragma once @@ -64,7 +78,7 @@ extern "C" { #endif VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion); VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName); - VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName); + VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance isntance, const char* pName); #if defined(VK_USE_PLATFORM_WIN32_KHR) VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); diff --git a/ext/vulkan/vk_layer.h b/ext/vulkan/vk_layer.h index 19d88fce4..6bd1c9a03 100644 --- a/ext/vulkan/vk_layer.h +++ b/ext/vulkan/vk_layer.h @@ -1,9 +1,23 @@ +// +// File: vk_layer.h +// /* - * Copyright 2015-2023 The Khronos Group Inc. - * Copyright 2015-2023 Valve Corporation - * Copyright 2015-2023 LunarG, Inc. + * Copyright (c) 2015-2023 LunarG, Inc. + * Copyright (c) 2015-2023 The Khronos Group Inc. + * Copyright (c) 2015-2023 Valve Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * SPDX-License-Identifier: Apache-2.0 */ #pragma once @@ -14,6 +28,14 @@ #include "vulkan_core.h" +#if defined(__GNUC__) && __GNUC__ >= 4 +#define VK_LAYER_EXPORT __attribute__((visibility("default"))) +#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) +#define VK_LAYER_EXPORT __attribute__((visibility("default"))) +#else +#define VK_LAYER_EXPORT +#endif + #define MAX_NUM_UNKNOWN_EXTS 250 // Loader-Layer version negotiation API. Versions add the following features: diff --git a/ext/vulkan/vk_platform.h b/ext/vulkan/vk_platform.h index ed67a6004..3ff8c5d14 100644 --- a/ext/vulkan/vk_platform.h +++ b/ext/vulkan/vk_platform.h @@ -2,7 +2,7 @@ // File: vk_platform.h // /* -** Copyright 2014-2023 The Khronos Group Inc. +** Copyright 2014-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/ext/vulkan/vk_video/vulkan_video_codec_h264std.h b/ext/vulkan/vk_video/vulkan_video_codec_h264std.h index a23789c68..d3ebec6a1 100644 --- a/ext/vulkan/vk_video/vulkan_video_codec_h264std.h +++ b/ext/vulkan/vk_video/vulkan_video_codec_h264std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,9 +19,8 @@ extern "C" { -// vulkan_video_codec_h264std is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h264std 1 -#include "vulkan_video_codecs_common.h" +#include #define STD_VIDEO_H264_CPB_CNT_LIST_SIZE 32 #define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6 #define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16 diff --git a/ext/vulkan/vk_video/vulkan_video_codec_h264std_decode.h b/ext/vulkan/vk_video/vulkan_video_codec_h264std_decode.h index dd24112e2..b1e79429d 100644 --- a/ext/vulkan/vk_video/vulkan_video_codec_h264std_decode.h +++ b/ext/vulkan/vk_video/vulkan_video_codec_h264std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,15 +19,13 @@ extern "C" { -// vulkan_video_codec_h264std_decode is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h264std_decode 1 -#include "vulkan_video_codec_h264std.h" #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) +#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2 #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_decode" -#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2 typedef enum StdVideoDecodeH264FieldOrderCount { STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_TOP = 0, diff --git a/ext/vulkan/vk_video/vulkan_video_codec_h264std_encode.h b/ext/vulkan/vk_video/vulkan_video_codec_h264std_encode.h index 2e0d706f6..7bd96aa7b 100644 --- a/ext/vulkan/vk_video/vulkan_video_codec_h264std_encode.h +++ b/ext/vulkan/vk_video/vulkan_video_codec_h264std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,13 +19,11 @@ extern "C" { -// vulkan_video_codec_h264std_encode is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h264std_encode 1 -#include "vulkan_video_codec_h264std.h" // Vulkan 0.9 provisional Vulkan video H.264 encode std specification version number -#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_10 VK_MAKE_VIDEO_STD_VERSION(0, 9, 10) +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_8 VK_MAKE_VIDEO_STD_VERSION(0, 9, 8) -#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_10 +#define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_0_9_8 #define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode" typedef struct StdVideoEncodeH264WeightTableFlags { uint32_t luma_weight_l0_flag; @@ -51,28 +49,25 @@ typedef struct StdVideoEncodeH264WeightTable { typedef struct StdVideoEncodeH264SliceHeaderFlags { uint32_t direct_spatial_mv_pred_flag : 1; uint32_t num_ref_idx_active_override_flag : 1; - uint32_t reserved : 30; + uint32_t no_output_of_prior_pics_flag : 1; + uint32_t adaptive_ref_pic_marking_mode_flag : 1; + uint32_t no_prior_references_available_flag : 1; } StdVideoEncodeH264SliceHeaderFlags; typedef struct StdVideoEncodeH264PictureInfoFlags { - uint32_t IdrPicFlag : 1; - uint32_t is_reference : 1; - uint32_t no_output_of_prior_pics_flag : 1; - uint32_t long_term_reference_flag : 1; - uint32_t adaptive_ref_pic_marking_mode_flag : 1; - uint32_t reserved : 27; + uint32_t idr_flag : 1; + uint32_t is_reference_flag : 1; + uint32_t used_for_long_term_reference : 1; } StdVideoEncodeH264PictureInfoFlags; typedef struct StdVideoEncodeH264ReferenceInfoFlags { uint32_t used_for_long_term_reference : 1; - uint32_t reserved : 31; } StdVideoEncodeH264ReferenceInfoFlags; -typedef struct StdVideoEncodeH264ReferenceListsInfoFlags { - uint32_t ref_pic_list_modification_flag_l0 : 1; - uint32_t ref_pic_list_modification_flag_l1 : 1; - uint32_t reserved : 30; -} StdVideoEncodeH264ReferenceListsInfoFlags; +typedef struct StdVideoEncodeH264RefMgmtFlags { + uint32_t ref_pic_list_modification_l0_flag : 1; + uint32_t ref_pic_list_modification_l1_flag : 1; +} StdVideoEncodeH264RefMgmtFlags; typedef struct StdVideoEncodeH264RefListModEntry { StdVideoH264ModificationOfPicNumsIdc modification_of_pic_nums_idc; @@ -88,53 +83,44 @@ typedef struct StdVideoEncodeH264RefPicMarkingEntry { uint16_t max_long_term_frame_idx_plus1; } StdVideoEncodeH264RefPicMarkingEntry; -typedef struct StdVideoEncodeH264ReferenceListsInfo { - StdVideoEncodeH264ReferenceListsInfoFlags flags; - uint8_t num_ref_idx_l0_active_minus1; - uint8_t num_ref_idx_l1_active_minus1; - uint8_t RefPicList0[STD_VIDEO_H264_MAX_NUM_LIST_REF]; - uint8_t RefPicList1[STD_VIDEO_H264_MAX_NUM_LIST_REF]; +typedef struct StdVideoEncodeH264RefMemMgmtCtrlOperations { + StdVideoEncodeH264RefMgmtFlags flags; uint8_t refList0ModOpCount; - uint8_t refList1ModOpCount; - uint8_t refPicMarkingOpCount; - uint8_t reserved1[7]; const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations; + uint8_t refList1ModOpCount; const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations; + uint8_t refPicMarkingOpCount; const StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations; -} StdVideoEncodeH264ReferenceListsInfo; +} StdVideoEncodeH264RefMemMgmtCtrlOperations; typedef struct StdVideoEncodeH264PictureInfo { - StdVideoEncodeH264PictureInfoFlags flags; - uint8_t seq_parameter_set_id; - uint8_t pic_parameter_set_id; - uint16_t idr_pic_id; - StdVideoH264PictureType primary_pic_type; - uint32_t frame_num; - int32_t PicOrderCnt; - uint8_t temporal_id; - uint8_t reserved1[3]; - const StdVideoEncodeH264ReferenceListsInfo* pRefLists; + StdVideoEncodeH264PictureInfoFlags flags; + uint8_t seq_parameter_set_id; + uint8_t pic_parameter_set_id; + StdVideoH264PictureType pictureType; + uint32_t frame_num; + int32_t PicOrderCnt; } StdVideoEncodeH264PictureInfo; typedef struct StdVideoEncodeH264ReferenceInfo { StdVideoEncodeH264ReferenceInfoFlags flags; - StdVideoH264PictureType primary_pic_type; uint32_t FrameNum; int32_t PicOrderCnt; uint16_t long_term_pic_num; uint16_t long_term_frame_idx; - uint8_t temporal_id; } StdVideoEncodeH264ReferenceInfo; typedef struct StdVideoEncodeH264SliceHeader { StdVideoEncodeH264SliceHeaderFlags flags; uint32_t first_mb_in_slice; StdVideoH264SliceType slice_type; - int8_t slice_alpha_c0_offset_div2; - int8_t slice_beta_offset_div2; - uint16_t reserved1; + uint16_t idr_pic_id; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; StdVideoH264CabacInitIdc cabac_init_idc; StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; const StdVideoEncodeH264WeightTable* pWeightTable; } StdVideoEncodeH264SliceHeader; diff --git a/ext/vulkan/vk_video/vulkan_video_codec_h265std.h b/ext/vulkan/vk_video/vulkan_video_codec_h265std.h index 793bdbcff..862f8817f 100644 --- a/ext/vulkan/vk_video/vulkan_video_codec_h265std.h +++ b/ext/vulkan/vk_video/vulkan_video_codec_h265std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,11 +19,9 @@ extern "C" { -// vulkan_video_codec_h265std is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h265std 1 -#include "vulkan_video_codecs_common.h" -#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32 #define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7 +#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32 #define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6 #define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16 #define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS 6 @@ -32,16 +30,16 @@ extern "C" { #define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS 64 #define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS 2 #define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64 +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3 +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128 +#define STD_VIDEO_H265_MAX_DPB_SIZE 16 +#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32 #define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6 #define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19 #define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21 -#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3 -#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128 #define STD_VIDEO_H265_MAX_NUM_LIST_REF 15 #define STD_VIDEO_H265_MAX_CHROMA_PLANES 2 #define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64 -#define STD_VIDEO_H265_MAX_DPB_SIZE 16 -#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32 #define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16 #define STD_VIDEO_H265_MAX_DELTA_POC 48 diff --git a/ext/vulkan/vk_video/vulkan_video_codec_h265std_decode.h b/ext/vulkan/vk_video/vulkan_video_codec_h265std_decode.h index 75cf4d094..d8660d12e 100644 --- a/ext/vulkan/vk_video/vulkan_video_codec_h265std_decode.h +++ b/ext/vulkan/vk_video/vulkan_video_codec_h265std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,15 +19,13 @@ extern "C" { -// vulkan_video_codec_h265std_decode is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h265std_decode 1 -#include "vulkan_video_codec_h265std.h" #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) +#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8 #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_decode" -#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8 typedef struct StdVideoDecodeH265PictureInfoFlags { uint32_t IrapPicFlag : 1; uint32_t IdrPicFlag : 1; diff --git a/ext/vulkan/vk_video/vulkan_video_codec_h265std_encode.h b/ext/vulkan/vk_video/vulkan_video_codec_h265std_encode.h index 25740398a..5a419b14b 100644 --- a/ext/vulkan/vk_video/vulkan_video_codec_h265std_encode.h +++ b/ext/vulkan/vk_video/vulkan_video_codec_h265std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,13 +19,11 @@ extern "C" { -// vulkan_video_codec_h265std_encode is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h265std_encode 1 -#include "vulkan_video_codec_h265std.h" // Vulkan 0.9 provisional Vulkan video H.265 encode std specification version number -#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_11 VK_MAKE_VIDEO_STD_VERSION(0, 9, 11) +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_9 VK_MAKE_VIDEO_STD_VERSION(0, 9, 9) -#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_11 +#define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_0_9_9 #define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode" typedef struct StdVideoEncodeH265WeightTableFlags { uint16_t luma_weight_l0_flag; @@ -50,7 +48,11 @@ typedef struct StdVideoEncodeH265WeightTable { typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags { uint32_t first_slice_segment_in_pic_flag : 1; + uint32_t no_output_of_prior_pics_flag : 1; uint32_t dependent_slice_segment_flag : 1; + uint32_t pic_output_flag : 1; + uint32_t short_term_ref_pic_set_sps_flag : 1; + uint32_t slice_temporal_mvp_enable_flag : 1; uint32_t slice_sao_luma_flag : 1; uint32_t slice_sao_chroma_flag : 1; uint32_t num_ref_idx_active_override_flag : 1; @@ -61,55 +63,8 @@ typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags { uint32_t slice_deblocking_filter_disabled_flag : 1; uint32_t collocated_from_l0_flag : 1; uint32_t slice_loop_filter_across_slices_enabled_flag : 1; - uint32_t reserved : 20; } StdVideoEncodeH265SliceSegmentHeaderFlags; -typedef struct StdVideoEncodeH265SliceSegmentHeader { - StdVideoEncodeH265SliceSegmentHeaderFlags flags; - StdVideoH265SliceType slice_type; - uint32_t slice_segment_address; - uint8_t collocated_ref_idx; - uint8_t MaxNumMergeCand; - int8_t slice_cb_qp_offset; - int8_t slice_cr_qp_offset; - int8_t slice_beta_offset_div2; - int8_t slice_tc_offset_div2; - int8_t slice_act_y_qp_offset; - int8_t slice_act_cb_qp_offset; - int8_t slice_act_cr_qp_offset; - uint8_t reserved1[3]; - const StdVideoEncodeH265WeightTable* pWeightTable; -} StdVideoEncodeH265SliceSegmentHeader; - -typedef struct StdVideoEncodeH265ReferenceListsInfoFlags { - uint32_t ref_pic_list_modification_flag_l0 : 1; - uint32_t ref_pic_list_modification_flag_l1 : 1; - uint32_t reserved : 30; -} StdVideoEncodeH265ReferenceListsInfoFlags; - -typedef struct StdVideoEncodeH265ReferenceListsInfo { - StdVideoEncodeH265ReferenceListsInfoFlags flags; - uint8_t num_ref_idx_l0_active_minus1; - uint8_t num_ref_idx_l1_active_minus1; - uint8_t RefPicList0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; - uint8_t RefPicList1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; - uint8_t list_entry_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF]; - uint8_t list_entry_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF]; -} StdVideoEncodeH265ReferenceListsInfo; - -typedef struct StdVideoEncodeH265PictureInfoFlags { - uint32_t is_reference : 1; - uint32_t IrapPicFlag : 1; - uint32_t used_for_long_term_reference : 1; - uint32_t discardable_flag : 1; - uint32_t cross_layer_bla_flag : 1; - uint32_t pic_output_flag : 1; - uint32_t no_output_of_prior_pics_flag : 1; - uint32_t short_term_ref_pic_set_sps_flag : 1; - uint32_t slice_temporal_mvp_enabled_flag : 1; - uint32_t reserved : 23; -} StdVideoEncodeH265PictureInfoFlags; - typedef struct StdVideoEncodeH265SliceSegmentLongTermRefPics { uint8_t num_long_term_sps; uint8_t num_long_term_pics; @@ -120,30 +75,65 @@ typedef struct StdVideoEncodeH265SliceSegmentLongTermRefPics { uint8_t delta_poc_msb_cycle_lt[STD_VIDEO_H265_MAX_DELTA_POC]; } StdVideoEncodeH265SliceSegmentLongTermRefPics; -typedef struct StdVideoEncodeH265PictureInfo { - StdVideoEncodeH265PictureInfoFlags flags; - StdVideoH265PictureType pic_type; - uint8_t sps_video_parameter_set_id; - uint8_t pps_seq_parameter_set_id; - uint8_t pps_pic_parameter_set_id; +typedef struct StdVideoEncodeH265SliceSegmentHeader { + StdVideoEncodeH265SliceSegmentHeaderFlags flags; + StdVideoH265SliceType slice_type; + uint32_t slice_segment_address; uint8_t short_term_ref_pic_set_idx; - int32_t PicOrderCntVal; - uint8_t TemporalId; - uint8_t reserved1[7]; - const StdVideoEncodeH265ReferenceListsInfo* pRefLists; + uint8_t collocated_ref_idx; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t MaxNumMergeCand; + int8_t slice_cb_qp_offset; + int8_t slice_cr_qp_offset; + int8_t slice_beta_offset_div2; + int8_t slice_tc_offset_div2; + int8_t slice_act_y_qp_offset; + int8_t slice_act_cb_qp_offset; + int8_t slice_act_cr_qp_offset; const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; const StdVideoEncodeH265SliceSegmentLongTermRefPics* pLongTermRefPics; + const StdVideoEncodeH265WeightTable* pWeightTable; +} StdVideoEncodeH265SliceSegmentHeader; + +typedef struct StdVideoEncodeH265ReferenceModificationFlags { + uint32_t ref_pic_list_modification_flag_l0 : 1; + uint32_t ref_pic_list_modification_flag_l1 : 1; +} StdVideoEncodeH265ReferenceModificationFlags; + +typedef struct StdVideoEncodeH265ReferenceModifications { + StdVideoEncodeH265ReferenceModificationFlags flags; + uint8_t referenceList0ModificationsCount; + const uint8_t* pReferenceList0Modifications; + uint8_t referenceList1ModificationsCount; + const uint8_t* pReferenceList1Modifications; +} StdVideoEncodeH265ReferenceModifications; + +typedef struct StdVideoEncodeH265PictureInfoFlags { + uint32_t is_reference_flag : 1; + uint32_t IrapPicFlag : 1; + uint32_t long_term_flag : 1; + uint32_t discardable_flag : 1; + uint32_t cross_layer_bla_flag : 1; +} StdVideoEncodeH265PictureInfoFlags; + +typedef struct StdVideoEncodeH265PictureInfo { + StdVideoEncodeH265PictureInfoFlags flags; + StdVideoH265PictureType PictureType; + uint8_t sps_video_parameter_set_id; + uint8_t pps_seq_parameter_set_id; + uint8_t pps_pic_parameter_set_id; + int32_t PicOrderCntVal; + uint8_t TemporalId; } StdVideoEncodeH265PictureInfo; typedef struct StdVideoEncodeH265ReferenceInfoFlags { uint32_t used_for_long_term_reference : 1; uint32_t unused_for_reference : 1; - uint32_t reserved : 30; } StdVideoEncodeH265ReferenceInfoFlags; typedef struct StdVideoEncodeH265ReferenceInfo { StdVideoEncodeH265ReferenceInfoFlags flags; - StdVideoH265PictureType pic_type; int32_t PicOrderCntVal; uint8_t TemporalId; } StdVideoEncodeH265ReferenceInfo; diff --git a/ext/vulkan/vk_video/vulkan_video_codecs_common.h b/ext/vulkan/vk_video/vulkan_video_codecs_common.h index 6568975ee..1e498265e 100644 --- a/ext/vulkan/vk_video/vulkan_video_codecs_common.h +++ b/ext/vulkan/vk_video/vulkan_video_codecs_common.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODECS_COMMON_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,12 +19,7 @@ extern "C" { -// vulkan_video_codecs_common is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codecs_common 1 -#if !defined(VK_NO_STDINT_H) - #include -#endif - #define VK_MAKE_VIDEO_STD_VERSION(major, minor, patch) \ ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) diff --git a/ext/vulkan/vulkan.h b/ext/vulkan/vulkan.h index 426cff58d..3510ac912 100644 --- a/ext/vulkan/vulkan.h +++ b/ext/vulkan/vulkan.h @@ -2,7 +2,7 @@ #define VULKAN_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -84,14 +84,6 @@ #include "vulkan_screen.h" #endif - -#ifdef VK_USE_PLATFORM_SCI -#include -#include -#include "vulkan_sci.h" -#endif - - #ifdef VK_ENABLE_BETA_EXTENSIONS #include "vulkan_beta.h" #endif diff --git a/ext/vulkan/vulkan_android.h b/ext/vulkan/vulkan_android.h index d86f43f2d..11f539796 100644 --- a/ext/vulkan/vulkan_android.h +++ b/ext/vulkan/vulkan_android.h @@ -2,7 +2,7 @@ #define VULKAN_ANDROID_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_KHR_android_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_android_surface 1 struct ANativeWindow; #define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 @@ -43,7 +42,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( #endif -// VK_ANDROID_external_memory_android_hardware_buffer is a preprocessor guard. Do not pass it to API calls. #define VK_ANDROID_external_memory_android_hardware_buffer 1 struct AHardwareBuffer; #define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 5 diff --git a/ext/vulkan/vulkan_beta.h b/ext/vulkan/vulkan_beta.h index f00ed3ff1..cfeda0eb3 100644 --- a/ext/vulkan/vulkan_beta.h +++ b/ext/vulkan/vulkan_beta.h @@ -2,7 +2,7 @@ #define VULKAN_BETA_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_KHR_portability_subset is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_portability_subset 1 #define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 #define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" @@ -51,9 +50,8 @@ typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { -// VK_KHR_video_encode_queue is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_encode_queue 1 -#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 9 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 7 #define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" typedef enum VkVideoEncodeTuningModeKHR { @@ -73,22 +71,13 @@ typedef enum VkVideoEncodeCapabilityFlagBitsKHR { typedef VkFlags VkVideoEncodeCapabilityFlagsKHR; typedef enum VkVideoEncodeRateControlModeFlagBitsKHR { - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR = 0, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR = 0x00000001, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 0x00000002, - VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 1, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 2, VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeRateControlModeFlagBitsKHR; typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR; -typedef enum VkVideoEncodeFeedbackFlagBitsKHR { - VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR = 0x00000001, - VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR = 0x00000002, - VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR = 0x00000004, - VK_VIDEO_ENCODE_FEEDBACK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkVideoEncodeFeedbackFlagBitsKHR; -typedef VkFlags VkVideoEncodeFeedbackFlagsKHR; - typedef enum VkVideoEncodeUsageFlagBitsKHR { VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR = 0, VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR = 0x00000001, @@ -112,9 +101,10 @@ typedef struct VkVideoEncodeInfoKHR { VkStructureType sType; const void* pNext; VkVideoEncodeFlagsKHR flags; - VkBuffer dstBuffer; - VkDeviceSize dstBufferOffset; - VkDeviceSize dstBufferRange; + uint32_t qualityLevel; + VkBuffer dstBitstreamBuffer; + VkDeviceSize dstBitstreamBufferOffset; + VkDeviceSize dstBitstreamBufferMaxRange; VkVideoPictureResourceInfoKHR srcPictureResource; const VkVideoReferenceSlotInfoKHR* pSetupReferenceSlot; uint32_t referenceSlotCount; @@ -127,19 +117,11 @@ typedef struct VkVideoEncodeCapabilitiesKHR { void* pNext; VkVideoEncodeCapabilityFlagsKHR flags; VkVideoEncodeRateControlModeFlagsKHR rateControlModes; - uint32_t maxRateControlLayers; - uint64_t maxBitrate; - uint32_t maxQualityLevels; - VkExtent2D encodeInputPictureGranularity; - VkVideoEncodeFeedbackFlagsKHR supportedEncodeFeedbackFlags; + uint8_t rateControlLayerCount; + uint8_t qualityLevelCount; + VkExtent2D inputImageDataFillAlignment; } VkVideoEncodeCapabilitiesKHR; -typedef struct VkQueryPoolVideoEncodeFeedbackCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoEncodeFeedbackFlagsKHR encodeFeedbackFlags; -} VkQueryPoolVideoEncodeFeedbackCreateInfoKHR; - typedef struct VkVideoEncodeUsageInfoKHR { VkStructureType sType; const void* pNext; @@ -151,10 +133,12 @@ typedef struct VkVideoEncodeUsageInfoKHR { typedef struct VkVideoEncodeRateControlLayerInfoKHR { VkStructureType sType; const void* pNext; - uint64_t averageBitrate; - uint64_t maxBitrate; + uint32_t averageBitrate; + uint32_t maxBitrate; uint32_t frameRateNumerator; uint32_t frameRateDenominator; + uint32_t virtualBufferSizeInMs; + uint32_t initialVirtualBufferSizeInMs; } VkVideoEncodeRateControlLayerInfoKHR; typedef struct VkVideoEncodeRateControlInfoKHR { @@ -162,165 +146,93 @@ typedef struct VkVideoEncodeRateControlInfoKHR { const void* pNext; VkVideoEncodeRateControlFlagsKHR flags; VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; - uint32_t layerCount; - const VkVideoEncodeRateControlLayerInfoKHR* pLayers; - uint32_t virtualBufferSizeInMs; - uint32_t initialVirtualBufferSizeInMs; + uint8_t layerCount; + const VkVideoEncodeRateControlLayerInfoKHR* pLayerConfigs; } VkVideoEncodeRateControlInfoKHR; -typedef struct VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR { - VkStructureType sType; - const void* pNext; - const VkVideoProfileInfoKHR* pVideoProfile; - uint32_t qualityLevel; -} VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR; - -typedef struct VkVideoEncodeQualityLevelPropertiesKHR { - VkStructureType sType; - void* pNext; - VkVideoEncodeRateControlModeFlagBitsKHR preferredRateControlMode; - uint32_t preferredRateControlLayerCount; -} VkVideoEncodeQualityLevelPropertiesKHR; - -typedef struct VkVideoEncodeQualityLevelInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t qualityLevel; -} VkVideoEncodeQualityLevelInfoKHR; - -typedef struct VkVideoEncodeSessionParametersGetInfoKHR { - VkStructureType sType; - const void* pNext; - VkVideoSessionParametersKHR videoSessionParameters; -} VkVideoEncodeSessionParametersGetInfoKHR; - -typedef struct VkVideoEncodeSessionParametersFeedbackInfoKHR { - VkStructureType sType; - void* pNext; - VkBool32 hasOverrides; -} VkVideoEncodeSessionParametersFeedbackInfoKHR; - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); -typedef VkResult (VKAPI_PTR *PFN_vkGetEncodedVideoSessionParametersKHR)(VkDevice device, const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, size_t* pDataSize, void* pData); typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, - VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetEncodedVideoSessionParametersKHR( - VkDevice device, - const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, - VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, - size_t* pDataSize, - void* pData); - VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); #endif -// VK_EXT_video_encode_h264 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_video_encode_h264 1 #include "vk_video/vulkan_video_codec_h264std.h" #include "vk_video/vulkan_video_codec_h264std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 11 +#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 9 #define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264" +typedef enum VkVideoEncodeH264RateControlStructureEXT { + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2, + VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264RateControlStructureEXT; + typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT { - VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x00000020, - VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_EXT = 0x00000040, - VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_EXT = 0x00000080, - VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_CAPABILITY_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H264_CAPABILITY_SCALING_LISTS_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H264_CAPABILITY_PIC_INIT_QP_MINUS26_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_EXPLICIT_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_IMPLICIT_BIT_EXT = 0x00000800, + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT = 0x00001000, + VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0x00002000, + VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0x00004000, + VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0x00008000, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00010000, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00020000, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00040000, + VK_VIDEO_ENCODE_H264_CAPABILITY_DISABLE_DIRECT_SPATIAL_MV_PRED_BIT_EXT = 0x00080000, + VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0x00100000, + VK_VIDEO_ENCODE_H264_CAPABILITY_SLICE_MB_COUNT_BIT_EXT = 0x00200000, + VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT = 0x00400000, + VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0x00800000, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x01000000, VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH264CapabilityFlagBitsEXT; typedef VkFlags VkVideoEncodeH264CapabilityFlagsEXT; -typedef enum VkVideoEncodeH264StdFlagBitsEXT { - VK_VIDEO_ENCODE_H264_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_STD_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG_SET_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_STD_CHROMA_QP_INDEX_OFFSET_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H264_STD_SECOND_CHROMA_QP_INDEX_OFFSET_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H264_STD_PIC_INIT_QP_MINUS26_BIT_EXT = 0x00000020, - VK_VIDEO_ENCODE_H264_STD_WEIGHTED_PRED_FLAG_SET_BIT_EXT = 0x00000040, - VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_EXPLICIT_BIT_EXT = 0x00000080, - VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_IMPLICIT_BIT_EXT = 0x00000100, - VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_EXT = 0x00000200, - VK_VIDEO_ENCODE_H264_STD_DIRECT_SPATIAL_MV_PRED_FLAG_UNSET_BIT_EXT = 0x00000400, - VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_UNSET_BIT_EXT = 0x00000800, - VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_SET_BIT_EXT = 0x00001000, - VK_VIDEO_ENCODE_H264_STD_DIRECT_8X8_INFERENCE_FLAG_UNSET_BIT_EXT = 0x00002000, - VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_EXT = 0x00004000, - VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00008000, - VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00010000, - VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00020000, - VK_VIDEO_ENCODE_H264_STD_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264StdFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264StdFlagsEXT; +typedef enum VkVideoEncodeH264InputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264InputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264InputModeFlagsEXT; -typedef enum VkVideoEncodeH264RateControlFlagBitsEXT { - VK_VIDEO_ENCODE_H264_RATE_CONTROL_ATTEMPT_HRD_COMPLIANCE_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H264_RATE_CONTROL_TEMPORAL_LAYER_PATTERN_DYADIC_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H264_RATE_CONTROL_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH264RateControlFlagBitsEXT; -typedef VkFlags VkVideoEncodeH264RateControlFlagsEXT; +typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264OutputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT; typedef struct VkVideoEncodeH264CapabilitiesEXT { VkStructureType sType; void* pNext; VkVideoEncodeH264CapabilityFlagsEXT flags; - StdVideoH264LevelIdc maxLevelIdc; - uint32_t maxSliceCount; - uint32_t maxPPictureL0ReferenceCount; - uint32_t maxBPictureL0ReferenceCount; - uint32_t maxL1ReferenceCount; - uint32_t maxTemporalLayerCount; - VkBool32 expectDyadicTemporalLayerPattern; - int32_t minQp; - int32_t maxQp; - VkBool32 prefersGopRemainingFrames; - VkBool32 requiresGopRemainingFrames; - VkVideoEncodeH264StdFlagsEXT stdSyntaxFlags; + VkVideoEncodeH264InputModeFlagsEXT inputModeFlags; + VkVideoEncodeH264OutputModeFlagsEXT outputModeFlags; + uint8_t maxPPictureL0ReferenceCount; + uint8_t maxBPictureL0ReferenceCount; + uint8_t maxL1ReferenceCount; + VkBool32 motionVectorsOverPicBoundariesFlag; + uint32_t maxBytesPerPicDenom; + uint32_t maxBitsPerMbDenom; + uint32_t log2MaxMvLengthHorizontal; + uint32_t log2MaxMvLengthVertical; } VkVideoEncodeH264CapabilitiesEXT; -typedef struct VkVideoEncodeH264QpEXT { - int32_t qpI; - int32_t qpP; - int32_t qpB; -} VkVideoEncodeH264QpEXT; - -typedef struct VkVideoEncodeH264QualityLevelPropertiesEXT { - VkStructureType sType; - void* pNext; - VkVideoEncodeH264RateControlFlagsEXT preferredRateControlFlags; - uint32_t preferredGopFrameCount; - uint32_t preferredIdrPeriod; - uint32_t preferredConsecutiveBFrameCount; - uint32_t preferredTemporalLayerCount; - VkVideoEncodeH264QpEXT preferredConstantQp; - uint32_t preferredMaxL0ReferenceCount; - uint32_t preferredMaxL1ReferenceCount; - VkBool32 preferredStdEntropyCodingModeFlag; -} VkVideoEncodeH264QualityLevelPropertiesEXT; - -typedef struct VkVideoEncodeH264SessionCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 useMaxLevelIdc; - StdVideoH264LevelIdc maxLevelIdc; -} VkVideoEncodeH264SessionCreateInfoEXT; - typedef struct VkVideoEncodeH264SessionParametersAddInfoEXT { VkStructureType sType; const void* pNext; @@ -338,44 +250,49 @@ typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT { const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo; } VkVideoEncodeH264SessionParametersCreateInfoEXT; -typedef struct VkVideoEncodeH264SessionParametersGetInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 writeStdSPS; - VkBool32 writeStdPPS; - uint32_t stdSPSId; - uint32_t stdPPSId; -} VkVideoEncodeH264SessionParametersGetInfoEXT; - -typedef struct VkVideoEncodeH264SessionParametersFeedbackInfoEXT { - VkStructureType sType; - void* pNext; - VkBool32 hasStdSPSOverrides; - VkBool32 hasStdPPSOverrides; -} VkVideoEncodeH264SessionParametersFeedbackInfoEXT; - -typedef struct VkVideoEncodeH264NaluSliceInfoEXT { - VkStructureType sType; - const void* pNext; - int32_t constantQp; - const StdVideoEncodeH264SliceHeader* pStdSliceHeader; -} VkVideoEncodeH264NaluSliceInfoEXT; - -typedef struct VkVideoEncodeH264PictureInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t naluSliceEntryCount; - const VkVideoEncodeH264NaluSliceInfoEXT* pNaluSliceEntries; - const StdVideoEncodeH264PictureInfo* pStdPictureInfo; - VkBool32 generatePrefixNalu; -} VkVideoEncodeH264PictureInfoEXT; - typedef struct VkVideoEncodeH264DpbSlotInfoEXT { VkStructureType sType; const void* pNext; + int8_t slotIndex; const StdVideoEncodeH264ReferenceInfo* pStdReferenceInfo; } VkVideoEncodeH264DpbSlotInfoEXT; +typedef struct VkVideoEncodeH264ReferenceListsInfoEXT { + VkStructureType sType; + const void* pNext; + uint8_t referenceList0EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pReferenceList0Entries; + uint8_t referenceList1EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pReferenceList1Entries; + const StdVideoEncodeH264RefMemMgmtCtrlOperations* pMemMgmtCtrlOperations; +} VkVideoEncodeH264ReferenceListsInfoEXT; + +typedef struct VkVideoEncodeH264NaluSliceInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t mbCount; + const VkVideoEncodeH264ReferenceListsInfoEXT* pReferenceFinalLists; + const StdVideoEncodeH264SliceHeader* pSliceHeaderStd; +} VkVideoEncodeH264NaluSliceInfoEXT; + +typedef struct VkVideoEncodeH264VclFrameInfoEXT { + VkStructureType sType; + const void* pNext; + const VkVideoEncodeH264ReferenceListsInfoEXT* pReferenceFinalLists; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH264NaluSliceInfoEXT* pNaluSliceEntries; + const StdVideoEncodeH264PictureInfo* pCurrentPictureInfo; +} VkVideoEncodeH264VclFrameInfoEXT; + +typedef struct VkVideoEncodeH264EmitPictureParametersInfoEXT { + VkStructureType sType; + const void* pNext; + uint8_t spsId; + VkBool32 emitSpsEnable; + uint32_t ppsIdEntryCount; + const uint8_t* ppsIdEntries; +} VkVideoEncodeH264EmitPictureParametersInfoEXT; + typedef struct VkVideoEncodeH264ProfileInfoEXT { VkStructureType sType; const void* pNext; @@ -383,15 +300,21 @@ typedef struct VkVideoEncodeH264ProfileInfoEXT { } VkVideoEncodeH264ProfileInfoEXT; typedef struct VkVideoEncodeH264RateControlInfoEXT { - VkStructureType sType; - const void* pNext; - VkVideoEncodeH264RateControlFlagsEXT flags; - uint32_t gopFrameCount; - uint32_t idrPeriod; - uint32_t consecutiveBFrameCount; - uint32_t temporalLayerCount; + VkStructureType sType; + const void* pNext; + uint32_t gopFrameCount; + uint32_t idrPeriod; + uint32_t consecutiveBFrameCount; + VkVideoEncodeH264RateControlStructureEXT rateControlStructure; + uint8_t temporalLayerCount; } VkVideoEncodeH264RateControlInfoEXT; +typedef struct VkVideoEncodeH264QpEXT { + int32_t qpI; + int32_t qpP; + int32_t qpB; +} VkVideoEncodeH264QpEXT; + typedef struct VkVideoEncodeH264FrameSizeEXT { uint32_t frameISize; uint32_t framePSize; @@ -401,6 +324,9 @@ typedef struct VkVideoEncodeH264FrameSizeEXT { typedef struct VkVideoEncodeH264RateControlLayerInfoEXT { VkStructureType sType; const void* pNext; + uint8_t temporalLayerId; + VkBool32 useInitialRcQp; + VkVideoEncodeH264QpEXT initialRcQp; VkBool32 useMinQp; VkVideoEncodeH264QpEXT minQp; VkBool32 useMaxQp; @@ -409,62 +335,67 @@ typedef struct VkVideoEncodeH264RateControlLayerInfoEXT { VkVideoEncodeH264FrameSizeEXT maxFrameSize; } VkVideoEncodeH264RateControlLayerInfoEXT; -typedef struct VkVideoEncodeH264GopRemainingFrameInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 useGopRemainingFrames; - uint32_t gopRemainingI; - uint32_t gopRemainingP; - uint32_t gopRemainingB; -} VkVideoEncodeH264GopRemainingFrameInfoEXT; - -// VK_EXT_video_encode_h265 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_video_encode_h265 1 #include "vk_video/vulkan_video_codec_h265std.h" #include "vk_video/vulkan_video_codec_h265std_encode.h" -#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 11 +#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 9 #define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265" +typedef enum VkVideoEncodeH265RateControlStructureEXT { + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT = 0, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_EXT = 1, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_EXT = 2, + VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265RateControlStructureEXT; + typedef enum VkVideoEncodeH265CapabilityFlagBitsEXT { - VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x00000020, - VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_EXT = 0x00000040, - VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_EXT = 0x00000080, - VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_EXT = 0x00000100, - VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_CAPABILITY_SAMPLE_ADAPTIVE_OFFSET_ENABLED_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_CAPABILITY_PCM_ENABLE_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_CAPABILITY_SPS_TEMPORAL_MVP_ENABLED_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H265_CAPABILITY_INIT_QP_MINUS26_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H265_CAPABILITY_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H265_CAPABILITY_SIGN_DATA_HIDING_ENABLED_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_ENABLED_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_DISABLED_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H265_CAPABILITY_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_BIT_EXT = 0x00000800, + VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_BIT_EXT = 0x00001000, + VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_BIPRED_BIT_EXT = 0x00002000, + VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT = 0x00004000, + VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSQUANT_BYPASS_ENABLED_BIT_EXT = 0x00008000, + VK_VIDEO_ENCODE_H265_CAPABILITY_ENTROPY_CODING_SYNC_ENABLED_BIT_EXT = 0x00010000, + VK_VIDEO_ENCODE_H265_CAPABILITY_DEBLOCKING_FILTER_OVERRIDE_ENABLED_BIT_EXT = 0x00020000, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_FRAME_BIT_EXT = 0x00040000, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_PER_TILE_BIT_EXT = 0x00080000, + VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_SLICE_BIT_EXT = 0x00100000, + VK_VIDEO_ENCODE_H265_CAPABILITY_SLICE_SEGMENT_CTB_COUNT_BIT_EXT = 0x00200000, + VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT = 0x00400000, + VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT = 0x00800000, + VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT = 0x01000000, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT = 0x02000000, VK_VIDEO_ENCODE_H265_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH265CapabilityFlagBitsEXT; typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; -typedef enum VkVideoEncodeH265StdFlagBitsEXT { - VK_VIDEO_ENCODE_H265_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H265_STD_SCALING_LIST_DATA_PRESENT_FLAG_SET_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H265_STD_PCM_ENABLED_FLAG_SET_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H265_STD_SPS_TEMPORAL_MVP_ENABLED_FLAG_SET_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H265_STD_INIT_QP_MINUS26_BIT_EXT = 0x00000020, - VK_VIDEO_ENCODE_H265_STD_WEIGHTED_PRED_FLAG_SET_BIT_EXT = 0x00000040, - VK_VIDEO_ENCODE_H265_STD_WEIGHTED_BIPRED_FLAG_SET_BIT_EXT = 0x00000080, - VK_VIDEO_ENCODE_H265_STD_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT = 0x00000100, - VK_VIDEO_ENCODE_H265_STD_SIGN_DATA_HIDING_ENABLED_FLAG_SET_BIT_EXT = 0x00000200, - VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_EXT = 0x00000400, - VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_EXT = 0x00000800, - VK_VIDEO_ENCODE_H265_STD_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG_SET_BIT_EXT = 0x00001000, - VK_VIDEO_ENCODE_H265_STD_TRANSQUANT_BYPASS_ENABLED_FLAG_SET_BIT_EXT = 0x00002000, - VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_EXT = 0x00004000, - VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_EXT = 0x00008000, - VK_VIDEO_ENCODE_H265_STD_DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_SET_BIT_EXT = 0x00010000, - VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_EXT = 0x00020000, - VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_EXT = 0x00040000, - VK_VIDEO_ENCODE_H265_STD_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH265StdFlagBitsEXT; -typedef VkFlags VkVideoEncodeH265StdFlagsEXT; +typedef enum VkVideoEncodeH265InputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265InputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265InputModeFlagsEXT; + +typedef enum VkVideoEncodeH265OutputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265OutputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265OutputModeFlagsEXT; typedef enum VkVideoEncodeH265CtbSizeFlagBitsEXT { VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0x00000001, @@ -482,63 +413,31 @@ typedef enum VkVideoEncodeH265TransformBlockSizeFlagBitsEXT { VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkVideoEncodeH265TransformBlockSizeFlagBitsEXT; typedef VkFlags VkVideoEncodeH265TransformBlockSizeFlagsEXT; - -typedef enum VkVideoEncodeH265RateControlFlagBitsEXT { - VK_VIDEO_ENCODE_H265_RATE_CONTROL_ATTEMPT_HRD_COMPLIANCE_BIT_EXT = 0x00000001, - VK_VIDEO_ENCODE_H265_RATE_CONTROL_REGULAR_GOP_BIT_EXT = 0x00000002, - VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_EXT = 0x00000004, - VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_DYADIC_BIT_EXT = 0x00000008, - VK_VIDEO_ENCODE_H265_RATE_CONTROL_TEMPORAL_SUB_LAYER_PATTERN_DYADIC_BIT_EXT = 0x00000010, - VK_VIDEO_ENCODE_H265_RATE_CONTROL_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkVideoEncodeH265RateControlFlagBitsEXT; -typedef VkFlags VkVideoEncodeH265RateControlFlagsEXT; typedef struct VkVideoEncodeH265CapabilitiesEXT { VkStructureType sType; void* pNext; VkVideoEncodeH265CapabilityFlagsEXT flags; - StdVideoH265LevelIdc maxLevelIdc; - uint32_t maxSliceSegmentCount; - VkExtent2D maxTiles; + VkVideoEncodeH265InputModeFlagsEXT inputModeFlags; + VkVideoEncodeH265OutputModeFlagsEXT outputModeFlags; VkVideoEncodeH265CtbSizeFlagsEXT ctbSizes; VkVideoEncodeH265TransformBlockSizeFlagsEXT transformBlockSizes; - uint32_t maxPPictureL0ReferenceCount; - uint32_t maxBPictureL0ReferenceCount; - uint32_t maxL1ReferenceCount; - uint32_t maxSubLayerCount; - VkBool32 expectDyadicTemporalSubLayerPattern; - int32_t minQp; - int32_t maxQp; - VkBool32 prefersGopRemainingFrames; - VkBool32 requiresGopRemainingFrames; - VkVideoEncodeH265StdFlagsEXT stdSyntaxFlags; + uint8_t maxPPictureL0ReferenceCount; + uint8_t maxBPictureL0ReferenceCount; + uint8_t maxL1ReferenceCount; + uint8_t maxSubLayersCount; + uint8_t minLog2MinLumaCodingBlockSizeMinus3; + uint8_t maxLog2MinLumaCodingBlockSizeMinus3; + uint8_t minLog2MinLumaTransformBlockSizeMinus2; + uint8_t maxLog2MinLumaTransformBlockSizeMinus2; + uint8_t minMaxTransformHierarchyDepthInter; + uint8_t maxMaxTransformHierarchyDepthInter; + uint8_t minMaxTransformHierarchyDepthIntra; + uint8_t maxMaxTransformHierarchyDepthIntra; + uint8_t maxDiffCuQpDeltaDepth; + uint8_t minMaxNumMergeCand; + uint8_t maxMaxNumMergeCand; } VkVideoEncodeH265CapabilitiesEXT; -typedef struct VkVideoEncodeH265SessionCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 useMaxLevelIdc; - StdVideoH265LevelIdc maxLevelIdc; -} VkVideoEncodeH265SessionCreateInfoEXT; - -typedef struct VkVideoEncodeH265QpEXT { - int32_t qpI; - int32_t qpP; - int32_t qpB; -} VkVideoEncodeH265QpEXT; - -typedef struct VkVideoEncodeH265QualityLevelPropertiesEXT { - VkStructureType sType; - void* pNext; - VkVideoEncodeH265RateControlFlagsEXT preferredRateControlFlags; - uint32_t preferredGopFrameCount; - uint32_t preferredIdrPeriod; - uint32_t preferredConsecutiveBFrameCount; - uint32_t preferredSubLayerCount; - VkVideoEncodeH265QpEXT preferredConstantQp; - uint32_t preferredMaxL0ReferenceCount; - uint32_t preferredMaxL1ReferenceCount; -} VkVideoEncodeH265QualityLevelPropertiesEXT; - typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT { VkStructureType sType; const void* pNext; @@ -559,46 +458,51 @@ typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT { const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo; } VkVideoEncodeH265SessionParametersCreateInfoEXT; -typedef struct VkVideoEncodeH265SessionParametersGetInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 writeStdVPS; - VkBool32 writeStdSPS; - VkBool32 writeStdPPS; - uint32_t stdVPSId; - uint32_t stdSPSId; - uint32_t stdPPSId; -} VkVideoEncodeH265SessionParametersGetInfoEXT; - -typedef struct VkVideoEncodeH265SessionParametersFeedbackInfoEXT { - VkStructureType sType; - void* pNext; - VkBool32 hasStdVPSOverrides; - VkBool32 hasStdSPSOverrides; - VkBool32 hasStdPPSOverrides; -} VkVideoEncodeH265SessionParametersFeedbackInfoEXT; - -typedef struct VkVideoEncodeH265NaluSliceSegmentInfoEXT { - VkStructureType sType; - const void* pNext; - int32_t constantQp; - const StdVideoEncodeH265SliceSegmentHeader* pStdSliceSegmentHeader; -} VkVideoEncodeH265NaluSliceSegmentInfoEXT; - -typedef struct VkVideoEncodeH265PictureInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t naluSliceSegmentEntryCount; - const VkVideoEncodeH265NaluSliceSegmentInfoEXT* pNaluSliceSegmentEntries; - const StdVideoEncodeH265PictureInfo* pStdPictureInfo; -} VkVideoEncodeH265PictureInfoEXT; - typedef struct VkVideoEncodeH265DpbSlotInfoEXT { VkStructureType sType; const void* pNext; + int8_t slotIndex; const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; } VkVideoEncodeH265DpbSlotInfoEXT; +typedef struct VkVideoEncodeH265ReferenceListsInfoEXT { + VkStructureType sType; + const void* pNext; + uint8_t referenceList0EntryCount; + const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList0Entries; + uint8_t referenceList1EntryCount; + const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList1Entries; + const StdVideoEncodeH265ReferenceModifications* pReferenceModifications; +} VkVideoEncodeH265ReferenceListsInfoEXT; + +typedef struct VkVideoEncodeH265NaluSliceSegmentInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t ctbCount; + const VkVideoEncodeH265ReferenceListsInfoEXT* pReferenceFinalLists; + const StdVideoEncodeH265SliceSegmentHeader* pSliceSegmentHeaderStd; +} VkVideoEncodeH265NaluSliceSegmentInfoEXT; + +typedef struct VkVideoEncodeH265VclFrameInfoEXT { + VkStructureType sType; + const void* pNext; + const VkVideoEncodeH265ReferenceListsInfoEXT* pReferenceFinalLists; + uint32_t naluSliceSegmentEntryCount; + const VkVideoEncodeH265NaluSliceSegmentInfoEXT* pNaluSliceSegmentEntries; + const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo; +} VkVideoEncodeH265VclFrameInfoEXT; + +typedef struct VkVideoEncodeH265EmitPictureParametersInfoEXT { + VkStructureType sType; + const void* pNext; + uint8_t vpsId; + uint8_t spsId; + VkBool32 emitVpsEnable; + VkBool32 emitSpsEnable; + uint32_t ppsIdEntryCount; + const uint8_t* ppsIdEntries; +} VkVideoEncodeH265EmitPictureParametersInfoEXT; + typedef struct VkVideoEncodeH265ProfileInfoEXT { VkStructureType sType; const void* pNext; @@ -606,15 +510,21 @@ typedef struct VkVideoEncodeH265ProfileInfoEXT { } VkVideoEncodeH265ProfileInfoEXT; typedef struct VkVideoEncodeH265RateControlInfoEXT { - VkStructureType sType; - const void* pNext; - VkVideoEncodeH265RateControlFlagsEXT flags; - uint32_t gopFrameCount; - uint32_t idrPeriod; - uint32_t consecutiveBFrameCount; - uint32_t subLayerCount; + VkStructureType sType; + const void* pNext; + uint32_t gopFrameCount; + uint32_t idrPeriod; + uint32_t consecutiveBFrameCount; + VkVideoEncodeH265RateControlStructureEXT rateControlStructure; + uint8_t subLayerCount; } VkVideoEncodeH265RateControlInfoEXT; +typedef struct VkVideoEncodeH265QpEXT { + int32_t qpI; + int32_t qpP; + int32_t qpB; +} VkVideoEncodeH265QpEXT; + typedef struct VkVideoEncodeH265FrameSizeEXT { uint32_t frameISize; uint32_t framePSize; @@ -624,6 +534,9 @@ typedef struct VkVideoEncodeH265FrameSizeEXT { typedef struct VkVideoEncodeH265RateControlLayerInfoEXT { VkStructureType sType; const void* pNext; + uint8_t temporalId; + VkBool32 useInitialRcQp; + VkVideoEncodeH265QpEXT initialRcQp; VkBool32 useMinQp; VkVideoEncodeH265QpEXT minQp; VkBool32 useMaxQp; @@ -632,174 +545,6 @@ typedef struct VkVideoEncodeH265RateControlLayerInfoEXT { VkVideoEncodeH265FrameSizeEXT maxFrameSize; } VkVideoEncodeH265RateControlLayerInfoEXT; -typedef struct VkVideoEncodeH265GopRemainingFrameInfoEXT { - VkStructureType sType; - const void* pNext; - VkBool32 useGopRemainingFrames; - uint32_t gopRemainingI; - uint32_t gopRemainingP; - uint32_t gopRemainingB; -} VkVideoEncodeH265GopRemainingFrameInfoEXT; - - - -// VK_AMDX_shader_enqueue is a preprocessor guard. Do not pass it to API calls. -#define VK_AMDX_shader_enqueue 1 -#define VK_AMDX_SHADER_ENQUEUE_SPEC_VERSION 1 -#define VK_AMDX_SHADER_ENQUEUE_EXTENSION_NAME "VK_AMDX_shader_enqueue" -#define VK_SHADER_INDEX_UNUSED_AMDX (~0U) -typedef struct VkPhysicalDeviceShaderEnqueueFeaturesAMDX { - VkStructureType sType; - void* pNext; - VkBool32 shaderEnqueue; -} VkPhysicalDeviceShaderEnqueueFeaturesAMDX; - -typedef struct VkPhysicalDeviceShaderEnqueuePropertiesAMDX { - VkStructureType sType; - void* pNext; - uint32_t maxExecutionGraphDepth; - uint32_t maxExecutionGraphShaderOutputNodes; - uint32_t maxExecutionGraphShaderPayloadSize; - uint32_t maxExecutionGraphShaderPayloadCount; - uint32_t executionGraphDispatchAddressAlignment; -} VkPhysicalDeviceShaderEnqueuePropertiesAMDX; - -typedef struct VkExecutionGraphPipelineScratchSizeAMDX { - VkStructureType sType; - void* pNext; - VkDeviceSize size; -} VkExecutionGraphPipelineScratchSizeAMDX; - -typedef struct VkExecutionGraphPipelineCreateInfoAMDX { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - uint32_t stageCount; - const VkPipelineShaderStageCreateInfo* pStages; - const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; - VkPipelineLayout layout; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkExecutionGraphPipelineCreateInfoAMDX; - -typedef union VkDeviceOrHostAddressConstAMDX { - VkDeviceAddress deviceAddress; - const void* hostAddress; -} VkDeviceOrHostAddressConstAMDX; - -typedef struct VkDispatchGraphInfoAMDX { - uint32_t nodeIndex; - uint32_t payloadCount; - VkDeviceOrHostAddressConstAMDX payloads; - uint64_t payloadStride; -} VkDispatchGraphInfoAMDX; - -typedef struct VkDispatchGraphCountInfoAMDX { - uint32_t count; - VkDeviceOrHostAddressConstAMDX infos; - uint64_t stride; -} VkDispatchGraphCountInfoAMDX; - -typedef struct VkPipelineShaderStageNodeCreateInfoAMDX { - VkStructureType sType; - const void* pNext; - const char* pName; - uint32_t index; -} VkPipelineShaderStageNodeCreateInfoAMDX; - -typedef VkResult (VKAPI_PTR *PFN_vkCreateExecutionGraphPipelinesAMDX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); -typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)(VkDevice device, VkPipeline executionGraph, VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); -typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)(VkDevice device, VkPipeline executionGraph, const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, uint32_t* pNodeIndex); -typedef void (VKAPI_PTR *PFN_vkCmdInitializeGraphScratchMemoryAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, const VkDispatchGraphCountInfoAMDX* pCountInfo); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, const VkDispatchGraphCountInfoAMDX* pCountInfo); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectCountAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceAddress countInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( - VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineScratchSizeAMDX( - VkDevice device, - VkPipeline executionGraph, - VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineNodeIndexAMDX( - VkDevice device, - VkPipeline executionGraph, - const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, - uint32_t* pNodeIndex); - -VKAPI_ATTR void VKAPI_CALL vkCmdInitializeGraphScratchMemoryAMDX( - VkCommandBuffer commandBuffer, - VkDeviceAddress scratch); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphAMDX( - VkCommandBuffer commandBuffer, - VkDeviceAddress scratch, - const VkDispatchGraphCountInfoAMDX* pCountInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectAMDX( - VkCommandBuffer commandBuffer, - VkDeviceAddress scratch, - const VkDispatchGraphCountInfoAMDX* pCountInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectCountAMDX( - VkCommandBuffer commandBuffer, - VkDeviceAddress scratch, - VkDeviceAddress countInfo); -#endif - - -// VK_NV_displacement_micromap is a preprocessor guard. Do not pass it to API calls. -#define VK_NV_displacement_micromap 1 -#define VK_NV_DISPLACEMENT_MICROMAP_SPEC_VERSION 2 -#define VK_NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME "VK_NV_displacement_micromap" - -typedef enum VkDisplacementMicromapFormatNV { - VK_DISPLACEMENT_MICROMAP_FORMAT_64_TRIANGLES_64_BYTES_NV = 1, - VK_DISPLACEMENT_MICROMAP_FORMAT_256_TRIANGLES_128_BYTES_NV = 2, - VK_DISPLACEMENT_MICROMAP_FORMAT_1024_TRIANGLES_128_BYTES_NV = 3, - VK_DISPLACEMENT_MICROMAP_FORMAT_MAX_ENUM_NV = 0x7FFFFFFF -} VkDisplacementMicromapFormatNV; -typedef struct VkPhysicalDeviceDisplacementMicromapFeaturesNV { - VkStructureType sType; - void* pNext; - VkBool32 displacementMicromap; -} VkPhysicalDeviceDisplacementMicromapFeaturesNV; - -typedef struct VkPhysicalDeviceDisplacementMicromapPropertiesNV { - VkStructureType sType; - void* pNext; - uint32_t maxDisplacementMicromapSubdivisionLevel; -} VkPhysicalDeviceDisplacementMicromapPropertiesNV; - -typedef struct VkAccelerationStructureTrianglesDisplacementMicromapNV { - VkStructureType sType; - void* pNext; - VkFormat displacementBiasAndScaleFormat; - VkFormat displacementVectorFormat; - VkDeviceOrHostAddressConstKHR displacementBiasAndScaleBuffer; - VkDeviceSize displacementBiasAndScaleStride; - VkDeviceOrHostAddressConstKHR displacementVectorBuffer; - VkDeviceSize displacementVectorStride; - VkDeviceOrHostAddressConstKHR displacedMicromapPrimitiveFlags; - VkDeviceSize displacedMicromapPrimitiveFlagsStride; - VkIndexType indexType; - VkDeviceOrHostAddressConstKHR indexBuffer; - VkDeviceSize indexStride; - uint32_t baseTriangle; - uint32_t usageCountsCount; - const VkMicromapUsageEXT* pUsageCounts; - const VkMicromapUsageEXT* const* ppUsageCounts; - VkMicromapEXT micromap; -} VkAccelerationStructureTrianglesDisplacementMicromapNV; - #ifdef __cplusplus } diff --git a/ext/vulkan/vulkan_core.h b/ext/vulkan/vulkan_core.h index c57485813..4c73571ef 100644 --- a/ext/vulkan/vulkan_core.h +++ b/ext/vulkan/vulkan_core.h @@ -2,7 +2,7 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_VERSION_1_0 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_0 1 #include "vk_platform.h" @@ -59,37 +58,37 @@ extern "C" { #endif #endif -#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ - ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) +// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) // DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. -//#define VK_API_VERSION VK_MAKE_API_VERSION(0, 1, 0, 0) // Patch version should always be set to 0 +//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 + +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) // Vulkan 1.0 version number #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 // Version of this file -#define VK_HEADER_VERSION 261 +#define VK_HEADER_VERSION 239 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) -// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. -#define VK_MAKE_VERSION(major, minor, patch) \ - ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) - // DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22U) +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) // DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) // DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) -#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) -#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) -#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) #define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) typedef uint32_t VkBool32; typedef uint64_t VkDeviceAddress; @@ -182,11 +181,7 @@ typedef enum VkResult { VK_THREAD_DONE_KHR = 1000268001, VK_OPERATION_DEFERRED_KHR = 1000268002, VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR = -1000299000, -#endif VK_ERROR_COMPRESSION_EXHAUSTED_EXT = -1000338000, - VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT = 1000482000, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, @@ -477,7 +472,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038002, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_EXT = 1000038003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038003, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038004, @@ -486,7 +481,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT = 1000038005, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_EXT = 1000038006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000038006, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT = 1000038007, @@ -498,16 +493,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT = 1000038010, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_EXT = 1000038011, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_EXT = 1000038012, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_EXT = 1000038013, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT = 1000038010, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000, @@ -519,7 +505,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039002, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_EXT = 1000039003, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039003, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039004, @@ -528,28 +514,19 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT = 1000039005, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_EXT = 1000039006, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000039006, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT = 1000039007, #endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT = 1000039008, +#endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT = 1000039010, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_EXT = 1000039011, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_EXT = 1000039012, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_EXT = 1000039013, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_EXT = 1000039014, #endif VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR = 1000040000, VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR = 1000040001, @@ -646,21 +623,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX = 1000134000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX = 1000134001, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_EXECUTION_GRAPH_PIPELINE_SCRATCH_SIZE_AMDX = 1000134002, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_EXECUTION_GRAPH_PIPELINE_CREATE_INFO_AMDX = 1000134003, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX = 1000134004, -#endif VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, @@ -815,18 +777,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT = 1000270000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT = 1000270001, - VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT = 1000270002, - VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT = 1000270003, - VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT = 1000270004, - VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT = 1000270005, - VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT = 1000270006, - VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO_EXT = 1000270007, - VK_STRUCTURE_TYPE_SUBRESOURCE_HOST_MEMCPY_SIZE_EXT = 1000270008, - VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = 1000270009, - VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR = 1000271000, - VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR = 1000271001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000, VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001, @@ -850,9 +800,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT = 1000283000, - VK_STRUCTURE_TYPE_DEPTH_BIAS_INFO_EXT = 1000283001, - VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT = 1000283002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, @@ -881,28 +828,9 @@ typedef enum VkStructureType { #endif #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR = 1000299005, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299006, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR = 1000299007, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299008, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR = 1000299009, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000299010, #endif VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, - VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT = 1000311002, @@ -952,6 +880,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000, VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT = 1000338001, + VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = 1000338002, + VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = 1000338003, VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, @@ -1006,8 +936,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT = 1000395000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT = 1000395001, VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT = 1000396000, VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT = 1000396001, VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT = 1000396002, @@ -1018,23 +946,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT = 1000396007, VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV = 1000397000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV = 1000397001, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV = 1000397002, -#endif VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000, - VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, @@ -1047,15 +963,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = 1000426001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = 1000427000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = 1000427001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, - VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, - VK_STRUCTURE_TYPE_PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001, VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000, @@ -1078,18 +990,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = 1000470000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = 1000470001, - VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR = 1000470003, - VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO_KHR = 1000470004, - VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR = 1000338002, - VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_KHR = 1000338003, - VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR = 1000470005, - VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR = 1000470006, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, - VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT = 1000482002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000, VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000, @@ -1101,19 +1001,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, - VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, - VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, - VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, - VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, - VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, - VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX = 1000529003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX = 1000529004, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, @@ -1276,8 +1163,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2, - VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR, - VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, @@ -1289,7 +1174,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS, VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, - VK_STRUCTURE_TYPE_SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; @@ -1394,7 +1278,6 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000, VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000, - VK_OBJECT_TYPE_SHADER_EXT = 1000482000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, @@ -1408,7 +1291,6 @@ typedef enum VkVendorId { VK_VENDOR_ID_CODEPLAY = 0x10004, VK_VENDOR_ID_MESA = 0x10005, VK_VENDOR_ID_POCL = 0x10006, - VK_VENDOR_ID_MOBILEYE = 0x10007, VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; @@ -1675,8 +1557,6 @@ typedef enum VkFormat { VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, VK_FORMAT_R16G16_S10_5_NV = 1000464000, - VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = 1000470000, - VK_FORMAT_A8_UNORM_KHR = 1000470001, VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, @@ -1769,7 +1649,7 @@ typedef enum VkQueryType { VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR = 1000299000, + VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000, #endif VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000, VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000, @@ -1925,13 +1805,10 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004, VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, - VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT = 1000099001, - VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT = 1000099002, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, - VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV = 1000205000, VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, @@ -1970,7 +1847,6 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV = 1000455030, VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV = 1000455031, VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV = 1000455032, - VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT = 1000524000, VK_DYNAMIC_STATE_CULL_MODE_EXT = VK_DYNAMIC_STATE_CULL_MODE, VK_DYNAMIC_STATE_FRONT_FACE_EXT = VK_DYNAMIC_STATE_FRONT_FACE, VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, @@ -2136,9 +2012,6 @@ typedef enum VkAttachmentStoreOp { typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX = 1000134000, -#endif VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, @@ -2332,7 +2205,6 @@ typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000, VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100, - VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT = 0x00400000, #ifdef VK_ENABLE_BETA_EXTENSIONS VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000, #endif @@ -2527,9 +2399,6 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_BUFFER_USAGE_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000, -#endif VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, @@ -2606,9 +2475,6 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000, VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000, VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000, -#endif VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000, VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000, VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, @@ -2726,7 +2592,6 @@ typedef enum VkDescriptorSetLayoutCreateFlagBits { VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00000010, VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT = 0x00000020, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00000080, VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT = 0x00000004, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT, @@ -4883,7 +4748,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( #endif -// VK_VERSION_1_1 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_1 1 // Vulkan 1.1 version number #define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 @@ -5001,7 +4865,6 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX = 0x00004000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, @@ -5750,7 +5613,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( #endif -// VK_VERSION_1_2 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_2 1 // Vulkan 1.2 version number #define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 @@ -6505,7 +6367,6 @@ VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( #endif -// VK_VERSION_1_3 is a preprocessor guard. Do not pass it to API calls. #define VK_VERSION_1_3 1 // Vulkan 1.3 version number #define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)// Patch version should always be set to 0 @@ -6615,7 +6476,6 @@ static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0 static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0x00080000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0x00100000ULL; -static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI = 0x8000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL; @@ -6781,7 +6641,6 @@ static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_K static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000ULL; -static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT = 0x400000000000ULL; #ifdef VK_ENABLE_BETA_EXTENSIONS static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; #endif @@ -7549,7 +7408,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirements( #endif -// VK_KHR_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_surface 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) #define VK_KHR_SURFACE_SPEC_VERSION 25 @@ -7664,7 +7522,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( #endif -// VK_KHR_swapchain is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_swapchain 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) #define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 @@ -7825,7 +7682,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( #endif -// VK_KHR_display is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_display 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) @@ -7951,7 +7807,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( #endif -// VK_KHR_display_swapchain is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_display_swapchain 1 #define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10 #define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" @@ -7975,13 +7830,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( #endif -// VK_KHR_sampler_mirror_clamp_to_edge is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_sampler_mirror_clamp_to_edge 1 #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3 #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" -// VK_KHR_video_queue is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_queue 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR) @@ -8037,9 +7890,6 @@ typedef VkFlags VkVideoCapabilityFlagsKHR; typedef enum VkVideoSessionCreateFlagBitsKHR { VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_PARAMETER_OPTIMIZATIONS_BIT_KHR = 0x00000002, -#endif VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoSessionCreateFlagBitsKHR; typedef VkFlags VkVideoSessionCreateFlagsKHR; @@ -8053,7 +7903,7 @@ typedef enum VkVideoCodingControlFlagBitsKHR { VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR = 0x00000002, #endif #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR = 0x00000004, + VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_LAYER_BIT_KHR = 0x00000004, #endif VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoCodingControlFlagBitsKHR; @@ -8277,7 +8127,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( #endif -// VK_KHR_video_decode_queue is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_decode_queue 1 #define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 7 #define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue" @@ -8332,7 +8181,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( #endif -// VK_KHR_video_decode_h264 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_decode_h264 1 #include "vk_video/vulkan_video_codec_h264std.h" #include "vk_video/vulkan_video_codec_h264std_decode.h" @@ -8393,7 +8241,6 @@ typedef struct VkVideoDecodeH264DpbSlotInfoKHR { -// VK_KHR_dynamic_rendering is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_dynamic_rendering 1 #define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 #define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" @@ -8456,7 +8303,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( #endif -// VK_KHR_multiview is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_multiview 1 #define VK_KHR_MULTIVIEW_SPEC_VERSION 1 #define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" @@ -8468,7 +8314,6 @@ typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesK -// VK_KHR_get_physical_device_properties2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_get_physical_device_properties2 1 #define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 #define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" @@ -8534,7 +8379,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( #endif -// VK_KHR_device_group is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_device_group 1 #define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4 #define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" @@ -8587,13 +8431,11 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( #endif -// VK_KHR_shader_draw_parameters is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_draw_parameters 1 #define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 #define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" -// VK_KHR_maintenance1 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance1 1 #define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 #define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" @@ -8611,7 +8453,6 @@ VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( #endif -// VK_KHR_device_group_creation is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_device_group_creation 1 #define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 #define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" @@ -8630,7 +8471,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( #endif -// VK_KHR_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_memory_capabilities 1 #define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" @@ -8665,7 +8505,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( #endif -// VK_KHR_external_memory is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_memory 1 #define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" @@ -8678,7 +8517,6 @@ typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; -// VK_KHR_external_memory_fd is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_memory_fd 1 #define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" @@ -8719,7 +8557,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( #endif -// VK_KHR_external_semaphore_capabilities is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_semaphore_capabilities 1 #define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" @@ -8745,7 +8582,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( #endif -// VK_KHR_external_semaphore is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_semaphore 1 #define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" @@ -8757,7 +8593,6 @@ typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; -// VK_KHR_external_semaphore_fd is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_semaphore_fd 1 #define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" @@ -8792,7 +8627,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( #endif -// VK_KHR_push_descriptor is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_push_descriptor 1 #define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 #define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" @@ -8823,7 +8657,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( #endif -// VK_KHR_shader_float16_int8 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_float16_int8 1 #define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1 #define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8" @@ -8833,7 +8666,6 @@ typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8Fea -// VK_KHR_16bit_storage is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_16bit_storage 1 #define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 #define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" @@ -8841,7 +8673,6 @@ typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeature -// VK_KHR_incremental_present is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_incremental_present 1 #define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 #define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" @@ -8865,7 +8696,6 @@ typedef struct VkPresentRegionsKHR { -// VK_KHR_descriptor_update_template is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_descriptor_update_template 1 typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; @@ -8903,7 +8733,6 @@ VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( #endif -// VK_KHR_imageless_framebuffer is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_imageless_framebuffer 1 #define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1 #define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer" @@ -8917,7 +8746,6 @@ typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR; -// VK_KHR_create_renderpass2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_create_renderpass2 1 #define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1 #define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2" @@ -8963,7 +8791,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( #endif -// VK_KHR_shared_presentable_image is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shared_presentable_image 1 #define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 #define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" @@ -8982,7 +8809,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( #endif -// VK_KHR_external_fence_capabilities is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_fence_capabilities 1 #define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" @@ -9008,7 +8834,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( #endif -// VK_KHR_external_fence is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_fence 1 #define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" @@ -9020,7 +8845,6 @@ typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; -// VK_KHR_external_fence_fd is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_fence_fd 1 #define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" @@ -9055,7 +8879,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( #endif -// VK_KHR_performance_query is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_performance_query 1 #define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1 #define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query" @@ -9196,7 +9019,6 @@ VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( #endif -// VK_KHR_maintenance2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance2 1 #define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 #define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" @@ -9218,7 +9040,6 @@ typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellation -// VK_KHR_get_surface_capabilities2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_get_surface_capabilities2 1 #define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 #define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" @@ -9257,7 +9078,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( #endif -// VK_KHR_variable_pointers is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_variable_pointers 1 #define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 #define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" @@ -9267,7 +9087,6 @@ typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointer -// VK_KHR_get_display_properties2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_get_display_properties2 1 #define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1 #define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2" @@ -9331,7 +9150,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( #endif -// VK_KHR_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_dedicated_allocation 1 #define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 #define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" @@ -9341,19 +9159,16 @@ typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; -// VK_KHR_storage_buffer_storage_class is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_storage_buffer_storage_class 1 #define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1 #define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" -// VK_KHR_relaxed_block_layout is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_relaxed_block_layout 1 #define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 #define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout" -// VK_KHR_get_memory_requirements2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_get_memory_requirements2 1 #define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 #define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" @@ -9390,7 +9205,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( #endif -// VK_KHR_image_format_list is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_image_format_list 1 #define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 #define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" @@ -9398,7 +9212,6 @@ typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR; -// VK_KHR_sampler_ycbcr_conversion is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_sampler_ycbcr_conversion 1 typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; @@ -9439,7 +9252,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( #endif -// VK_KHR_bind_memory2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_bind_memory2 1 #define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 #define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" @@ -9463,7 +9275,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( #endif -// VK_KHR_maintenance3 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance3 1 #define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 #define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" @@ -9483,7 +9294,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( #endif -// VK_KHR_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_draw_indirect_count 1 #define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 #define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count" @@ -9511,7 +9321,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( #endif -// VK_KHR_shader_subgroup_extended_types is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_subgroup_extended_types 1 #define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1 #define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types" @@ -9519,7 +9328,6 @@ typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShad -// VK_KHR_8bit_storage is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_8bit_storage 1 #define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1 #define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage" @@ -9527,7 +9335,6 @@ typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesK -// VK_KHR_shader_atomic_int64 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_atomic_int64 1 #define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 #define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" @@ -9535,7 +9342,6 @@ typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicIn -// VK_KHR_shader_clock is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_clock 1 #define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1 #define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock" @@ -9548,7 +9354,6 @@ typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { -// VK_KHR_video_decode_h265 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_decode_h265 1 #include "vk_video/vulkan_video_codec_h265std.h" #include "vk_video/vulkan_video_codec_h265std_decode.h" @@ -9587,11 +9392,11 @@ typedef struct VkVideoDecodeH265SessionParametersCreateInfoKHR { } VkVideoDecodeH265SessionParametersCreateInfoKHR; typedef struct VkVideoDecodeH265PictureInfoKHR { - VkStructureType sType; - const void* pNext; - const StdVideoDecodeH265PictureInfo* pStdPictureInfo; - uint32_t sliceSegmentCount; - const uint32_t* pSliceSegmentOffsets; + VkStructureType sType; + const void* pNext; + StdVideoDecodeH265PictureInfo* pStdPictureInfo; + uint32_t sliceSegmentCount; + const uint32_t* pSliceSegmentOffsets; } VkVideoDecodeH265PictureInfoKHR; typedef struct VkVideoDecodeH265DpbSlotInfoKHR { @@ -9602,7 +9407,6 @@ typedef struct VkVideoDecodeH265DpbSlotInfoKHR { -// VK_KHR_global_priority is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_global_priority 1 #define VK_MAX_GLOBAL_PRIORITY_SIZE_KHR 16U #define VK_KHR_GLOBAL_PRIORITY_SPEC_VERSION 1 @@ -9640,7 +9444,6 @@ typedef struct VkQueueFamilyGlobalPriorityPropertiesKHR { -// VK_KHR_driver_properties is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_driver_properties 1 #define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 #define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" @@ -9654,7 +9457,6 @@ typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR; -// VK_KHR_shader_float_controls is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_float_controls 1 #define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4 #define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls" @@ -9664,7 +9466,6 @@ typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPro -// VK_KHR_depth_stencil_resolve is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_depth_stencil_resolve 1 #define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1 #define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve" @@ -9678,13 +9479,11 @@ typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStenc -// VK_KHR_swapchain_mutable_format is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_swapchain_mutable_format 1 #define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1 #define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format" -// VK_KHR_timeline_semaphore is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_timeline_semaphore 1 #define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2 #define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore" @@ -9727,7 +9526,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( #endif -// VK_KHR_vulkan_memory_model is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_vulkan_memory_model 1 #define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3 #define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" @@ -9735,7 +9533,6 @@ typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryMo -// VK_KHR_shader_terminate_invocation is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_terminate_invocation 1 #define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 #define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" @@ -9743,7 +9540,6 @@ typedef VkPhysicalDeviceShaderTerminateInvocationFeatures VkPhysicalDeviceShader -// VK_KHR_fragment_shading_rate is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_fragment_shading_rate 1 #define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 2 #define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" @@ -9823,13 +9619,11 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( #endif -// VK_KHR_spirv_1_4 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_spirv_1_4 1 #define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 #define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" -// VK_KHR_surface_protected_capabilities is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_surface_protected_capabilities 1 #define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" @@ -9841,7 +9635,6 @@ typedef struct VkSurfaceProtectedCapabilitiesKHR { -// VK_KHR_separate_depth_stencil_layouts is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_separate_depth_stencil_layouts 1 #define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1 #define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts" @@ -9853,7 +9646,6 @@ typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayou -// VK_KHR_present_wait is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_present_wait 1 #define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 #define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" @@ -9874,7 +9666,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( #endif -// VK_KHR_uniform_buffer_standard_layout is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_uniform_buffer_standard_layout 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 #define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" @@ -9882,7 +9673,6 @@ typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUnif -// VK_KHR_buffer_device_address is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_buffer_device_address 1 #define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1 #define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address" @@ -9915,7 +9705,6 @@ VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( #endif -// VK_KHR_deferred_host_operations is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_deferred_host_operations 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) #define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 @@ -9951,7 +9740,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( #endif -// VK_KHR_pipeline_executable_properties is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_pipeline_executable_properties 1 #define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 #define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" @@ -10042,43 +9830,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR #endif -// VK_KHR_map_memory2 is a preprocessor guard. Do not pass it to API calls. -#define VK_KHR_map_memory2 1 -#define VK_KHR_MAP_MEMORY_2_SPEC_VERSION 1 -#define VK_KHR_MAP_MEMORY_2_EXTENSION_NAME "VK_KHR_map_memory2" -typedef VkFlags VkMemoryUnmapFlagsKHR; -typedef struct VkMemoryMapInfoKHR { - VkStructureType sType; - const void* pNext; - VkMemoryMapFlags flags; - VkDeviceMemory memory; - VkDeviceSize offset; - VkDeviceSize size; -} VkMemoryMapInfoKHR; - -typedef struct VkMemoryUnmapInfoKHR { - VkStructureType sType; - const void* pNext; - VkMemoryUnmapFlagsKHR flags; - VkDeviceMemory memory; -} VkMemoryUnmapInfoKHR; - -typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2KHR)(VkDevice device, const VkMemoryMapInfoKHR* pMemoryMapInfo, void** ppData); -typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2KHR)(VkDevice device, const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2KHR( - VkDevice device, - const VkMemoryMapInfoKHR* pMemoryMapInfo, - void** ppData); - -VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2KHR( - VkDevice device, - const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo); -#endif - - -// VK_KHR_shader_integer_dot_product is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_integer_dot_product 1 #define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 #define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" @@ -10088,7 +9839,6 @@ typedef VkPhysicalDeviceShaderIntegerDotProductProperties VkPhysicalDeviceShader -// VK_KHR_pipeline_library is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_pipeline_library 1 #define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 #define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" @@ -10101,13 +9851,11 @@ typedef struct VkPipelineLibraryCreateInfoKHR { -// VK_KHR_shader_non_semantic_info is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_non_semantic_info 1 #define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 #define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" -// VK_KHR_present_id is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_present_id 1 #define VK_KHR_PRESENT_ID_SPEC_VERSION 1 #define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" @@ -10126,7 +9874,6 @@ typedef struct VkPhysicalDevicePresentIdFeaturesKHR { -// VK_KHR_synchronization2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_synchronization2 1 #define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 #define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" @@ -10227,7 +9974,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( #endif -// VK_KHR_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_fragment_shader_barycentric 1 #define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 #define VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_KHR_fragment_shader_barycentric" @@ -10245,7 +9991,6 @@ typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { -// VK_KHR_shader_subgroup_uniform_control_flow is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_subgroup_uniform_control_flow 1 #define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 #define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" @@ -10257,7 +10002,6 @@ typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { -// VK_KHR_zero_initialize_workgroup_memory is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_zero_initialize_workgroup_memory 1 #define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 #define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" @@ -10265,7 +10009,6 @@ typedef VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures VkPhysicalDeviceZe -// VK_KHR_workgroup_memory_explicit_layout is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_workgroup_memory_explicit_layout 1 #define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 #define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" @@ -10280,7 +10023,6 @@ typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { -// VK_KHR_copy_commands2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_copy_commands2 1 #define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 #define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" @@ -10340,7 +10082,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( #endif -// VK_KHR_format_feature_flags2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_format_feature_flags2 1 #define VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION 2 #define VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME "VK_KHR_format_feature_flags2" @@ -10352,7 +10093,6 @@ typedef VkFormatProperties3 VkFormatProperties3KHR; -// VK_KHR_ray_tracing_maintenance1 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_ray_tracing_maintenance1 1 #define VK_KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION 1 #define VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_ray_tracing_maintenance1" @@ -10389,13 +10129,11 @@ VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirect2KHR( #endif -// VK_KHR_portability_enumeration is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_portability_enumeration 1 #define VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION 1 #define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration" -// VK_KHR_maintenance4 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance4 1 #define VK_KHR_MAINTENANCE_4_SPEC_VERSION 2 #define VK_KHR_MAINTENANCE_4_EXTENSION_NAME "VK_KHR_maintenance4" @@ -10430,263 +10168,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( #endif -// VK_KHR_maintenance5 is a preprocessor guard. Do not pass it to API calls. -#define VK_KHR_maintenance5 1 -#define VK_KHR_MAINTENANCE_5_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE_5_EXTENSION_NAME "VK_KHR_maintenance5" -typedef VkFlags64 VkPipelineCreateFlags2KHR; - -// Flag bits for VkPipelineCreateFlagBits2KHR -typedef VkFlags64 VkPipelineCreateFlagBits2KHR; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR = 0x00000001ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_ALLOW_DERIVATIVES_BIT_KHR = 0x00000002ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DERIVATIVE_BIT_KHR = 0x00000004ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR = 0x00000010ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DEFER_COMPILE_BIT_NV = 0x00000020ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_CAPTURE_STATISTICS_BIT_KHR = 0x00000040ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR = 0x00000100ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR = 0x00000200ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT = 0x00000400ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT = 0x00800000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR = 0x00000800ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_NV = 0x00040000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000ULL; -static const VkPipelineCreateFlagBits2KHR VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT = 0x20000000ULL; - -typedef VkFlags64 VkBufferUsageFlags2KHR; - -// Flag bits for VkBufferUsageFlagBits2KHR -typedef VkFlags64 VkBufferUsageFlagBits2KHR; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR = 0x00000001ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR = 0x00000002ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000004ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR = 0x00000010ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR = 0x00000020ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR = 0x00000040ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR = 0x00000080ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR = 0x00000100ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_RAY_TRACING_BIT_NV = 0x00000400ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR = 0x00004000ULL; -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000ULL; -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000ULL; -#endif -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR = 0x00020000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000ULL; -static const VkBufferUsageFlagBits2KHR VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT = 0x01000000ULL; - -typedef struct VkPhysicalDeviceMaintenance5FeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 maintenance5; -} VkPhysicalDeviceMaintenance5FeaturesKHR; - -typedef struct VkPhysicalDeviceMaintenance5PropertiesKHR { - VkStructureType sType; - void* pNext; - VkBool32 earlyFragmentMultisampleCoverageAfterSampleCounting; - VkBool32 earlyFragmentSampleMaskTestBeforeSampleCounting; - VkBool32 depthStencilSwizzleOneSupport; - VkBool32 polygonModePointSize; - VkBool32 nonStrictSinglePixelWideLinesUseParallelogram; - VkBool32 nonStrictWideLinesUseParallelogram; -} VkPhysicalDeviceMaintenance5PropertiesKHR; - -typedef struct VkRenderingAreaInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t viewMask; - uint32_t colorAttachmentCount; - const VkFormat* pColorAttachmentFormats; - VkFormat depthAttachmentFormat; - VkFormat stencilAttachmentFormat; -} VkRenderingAreaInfoKHR; - -typedef struct VkImageSubresource2KHR { - VkStructureType sType; - void* pNext; - VkImageSubresource imageSubresource; -} VkImageSubresource2KHR; - -typedef struct VkDeviceImageSubresourceInfoKHR { - VkStructureType sType; - const void* pNext; - const VkImageCreateInfo* pCreateInfo; - const VkImageSubresource2KHR* pSubresource; -} VkDeviceImageSubresourceInfoKHR; - -typedef struct VkSubresourceLayout2KHR { - VkStructureType sType; - void* pNext; - VkSubresourceLayout subresourceLayout; -} VkSubresourceLayout2KHR; - -typedef struct VkPipelineCreateFlags2CreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags2KHR flags; -} VkPipelineCreateFlags2CreateInfoKHR; - -typedef struct VkBufferUsageFlags2CreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkBufferUsageFlags2KHR usage; -} VkBufferUsageFlags2CreateInfoKHR; - -typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer2KHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); -typedef void (VKAPI_PTR *PFN_vkGetRenderingAreaGranularityKHR)(VkDevice device, const VkRenderingAreaInfoKHR* pRenderingAreaInfo, VkExtent2D* pGranularity); -typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSubresourceLayoutKHR)(VkDevice device, const VkDeviceImageSubresourceInfoKHR* pInfo, VkSubresourceLayout2KHR* pLayout); -typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2KHR)(VkDevice device, VkImage image, const VkImageSubresource2KHR* pSubresource, VkSubresourceLayout2KHR* pLayout); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2KHR( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkDeviceSize size, - VkIndexType indexType); - -VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularityKHR( - VkDevice device, - const VkRenderingAreaInfoKHR* pRenderingAreaInfo, - VkExtent2D* pGranularity); - -VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSubresourceLayoutKHR( - VkDevice device, - const VkDeviceImageSubresourceInfoKHR* pInfo, - VkSubresourceLayout2KHR* pLayout); - -VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2KHR( - VkDevice device, - VkImage image, - const VkImageSubresource2KHR* pSubresource, - VkSubresourceLayout2KHR* pLayout); -#endif - - -// VK_KHR_ray_tracing_position_fetch is a preprocessor guard. Do not pass it to API calls. -#define VK_KHR_ray_tracing_position_fetch 1 -#define VK_KHR_RAY_TRACING_POSITION_FETCH_SPEC_VERSION 1 -#define VK_KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME "VK_KHR_ray_tracing_position_fetch" -typedef struct VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 rayTracingPositionFetch; -} VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR; - - - -// VK_KHR_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. -#define VK_KHR_cooperative_matrix 1 -#define VK_KHR_COOPERATIVE_MATRIX_SPEC_VERSION 2 -#define VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_KHR_cooperative_matrix" - -typedef enum VkComponentTypeKHR { - VK_COMPONENT_TYPE_FLOAT16_KHR = 0, - VK_COMPONENT_TYPE_FLOAT32_KHR = 1, - VK_COMPONENT_TYPE_FLOAT64_KHR = 2, - VK_COMPONENT_TYPE_SINT8_KHR = 3, - VK_COMPONENT_TYPE_SINT16_KHR = 4, - VK_COMPONENT_TYPE_SINT32_KHR = 5, - VK_COMPONENT_TYPE_SINT64_KHR = 6, - VK_COMPONENT_TYPE_UINT8_KHR = 7, - VK_COMPONENT_TYPE_UINT16_KHR = 8, - VK_COMPONENT_TYPE_UINT32_KHR = 9, - VK_COMPONENT_TYPE_UINT64_KHR = 10, - VK_COMPONENT_TYPE_FLOAT16_NV = VK_COMPONENT_TYPE_FLOAT16_KHR, - VK_COMPONENT_TYPE_FLOAT32_NV = VK_COMPONENT_TYPE_FLOAT32_KHR, - VK_COMPONENT_TYPE_FLOAT64_NV = VK_COMPONENT_TYPE_FLOAT64_KHR, - VK_COMPONENT_TYPE_SINT8_NV = VK_COMPONENT_TYPE_SINT8_KHR, - VK_COMPONENT_TYPE_SINT16_NV = VK_COMPONENT_TYPE_SINT16_KHR, - VK_COMPONENT_TYPE_SINT32_NV = VK_COMPONENT_TYPE_SINT32_KHR, - VK_COMPONENT_TYPE_SINT64_NV = VK_COMPONENT_TYPE_SINT64_KHR, - VK_COMPONENT_TYPE_UINT8_NV = VK_COMPONENT_TYPE_UINT8_KHR, - VK_COMPONENT_TYPE_UINT16_NV = VK_COMPONENT_TYPE_UINT16_KHR, - VK_COMPONENT_TYPE_UINT32_NV = VK_COMPONENT_TYPE_UINT32_KHR, - VK_COMPONENT_TYPE_UINT64_NV = VK_COMPONENT_TYPE_UINT64_KHR, - VK_COMPONENT_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkComponentTypeKHR; - -typedef enum VkScopeKHR { - VK_SCOPE_DEVICE_KHR = 1, - VK_SCOPE_WORKGROUP_KHR = 2, - VK_SCOPE_SUBGROUP_KHR = 3, - VK_SCOPE_QUEUE_FAMILY_KHR = 5, - VK_SCOPE_DEVICE_NV = VK_SCOPE_DEVICE_KHR, - VK_SCOPE_WORKGROUP_NV = VK_SCOPE_WORKGROUP_KHR, - VK_SCOPE_SUBGROUP_NV = VK_SCOPE_SUBGROUP_KHR, - VK_SCOPE_QUEUE_FAMILY_NV = VK_SCOPE_QUEUE_FAMILY_KHR, - VK_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkScopeKHR; -typedef struct VkCooperativeMatrixPropertiesKHR { - VkStructureType sType; - void* pNext; - uint32_t MSize; - uint32_t NSize; - uint32_t KSize; - VkComponentTypeKHR AType; - VkComponentTypeKHR BType; - VkComponentTypeKHR CType; - VkComponentTypeKHR ResultType; - VkBool32 saturatingAccumulation; - VkScopeKHR scope; -} VkCooperativeMatrixPropertiesKHR; - -typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 cooperativeMatrix; - VkBool32 cooperativeMatrixRobustBufferAccess; -} VkPhysicalDeviceCooperativeMatrixFeaturesKHR; - -typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesKHR { - VkStructureType sType; - void* pNext; - VkShaderStageFlags cooperativeMatrixSupportedStages; -} VkPhysicalDeviceCooperativeMatrixPropertiesKHR; - -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesKHR* pProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR( - VkPhysicalDevice physicalDevice, - uint32_t* pPropertyCount, - VkCooperativeMatrixPropertiesKHR* pProperties); -#endif - - -// VK_EXT_debug_report is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) #define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 @@ -10794,25 +10275,21 @@ VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( #endif -// VK_NV_glsl_shader is a preprocessor guard. Do not pass it to API calls. #define VK_NV_glsl_shader 1 #define VK_NV_GLSL_SHADER_SPEC_VERSION 1 #define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" -// VK_EXT_depth_range_unrestricted is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_depth_range_unrestricted 1 #define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1 #define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted" -// VK_IMG_filter_cubic is a preprocessor guard. Do not pass it to API calls. #define VK_IMG_filter_cubic 1 #define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1 #define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic" -// VK_AMD_rasterization_order is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_rasterization_order 1 #define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 #define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" @@ -10830,19 +10307,16 @@ typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { -// VK_AMD_shader_trinary_minmax is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_trinary_minmax 1 #define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1 #define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax" -// VK_AMD_shader_explicit_vertex_parameter is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_explicit_vertex_parameter 1 #define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1 #define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter" -// VK_EXT_debug_marker is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_debug_marker 1 #define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 #define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" @@ -10899,13 +10373,11 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( #endif -// VK_AMD_gcn_shader is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_gcn_shader 1 #define VK_AMD_GCN_SHADER_SPEC_VERSION 1 #define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" -// VK_NV_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. #define VK_NV_dedicated_allocation 1 #define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 #define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" @@ -10930,7 +10402,6 @@ typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { -// VK_EXT_transform_feedback is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_transform_feedback 1 #define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 #define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" @@ -11018,7 +10489,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( #endif -// VK_NVX_binary_import is a preprocessor guard. Do not pass it to API calls. #define VK_NVX_binary_import 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) @@ -11090,7 +10560,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( #endif -// VK_NVX_image_view_handle is a preprocessor guard. Do not pass it to API calls. #define VK_NVX_image_view_handle 1 #define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 #define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" @@ -11124,7 +10593,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( #endif -// VK_AMD_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_draw_indirect_count 1 #define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2 #define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" @@ -11152,25 +10620,21 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( #endif -// VK_AMD_negative_viewport_height is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_negative_viewport_height 1 #define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 #define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" -// VK_AMD_gpu_shader_half_float is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_gpu_shader_half_float 1 #define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2 #define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" -// VK_AMD_shader_ballot is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_ballot 1 #define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1 #define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot" -// VK_AMD_texture_gather_bias_lod is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_texture_gather_bias_lod 1 #define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 #define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" @@ -11182,7 +10646,6 @@ typedef struct VkTextureLODGatherFormatPropertiesAMD { -// VK_AMD_shader_info is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_info 1 #define VK_AMD_SHADER_INFO_SPEC_VERSION 1 #define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" @@ -11224,13 +10687,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( #endif -// VK_AMD_shader_image_load_store_lod is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_image_load_store_lod 1 #define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 #define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" -// VK_NV_corner_sampled_image is a preprocessor guard. Do not pass it to API calls. #define VK_NV_corner_sampled_image 1 #define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 #define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" @@ -11242,13 +10703,11 @@ typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { -// VK_IMG_format_pvrtc is a preprocessor guard. Do not pass it to API calls. #define VK_IMG_format_pvrtc 1 #define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 #define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" -// VK_NV_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. #define VK_NV_external_memory_capabilities 1 #define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" @@ -11291,7 +10750,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesN #endif -// VK_NV_external_memory is a preprocessor guard. Do not pass it to API calls. #define VK_NV_external_memory 1 #define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" @@ -11309,7 +10767,6 @@ typedef struct VkExportMemoryAllocateInfoNV { -// VK_EXT_validation_flags is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_validation_flags 1 #define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 2 #define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" @@ -11328,19 +10785,16 @@ typedef struct VkValidationFlagsEXT { -// VK_EXT_shader_subgroup_ballot is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_subgroup_ballot 1 #define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1 #define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot" -// VK_EXT_shader_subgroup_vote is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_subgroup_vote 1 #define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1 #define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" -// VK_EXT_texture_compression_astc_hdr is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_texture_compression_astc_hdr 1 #define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1 #define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr" @@ -11348,7 +10802,6 @@ typedef VkPhysicalDeviceTextureCompressionASTCHDRFeatures VkPhysicalDeviceTextur -// VK_EXT_astc_decode_mode is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_astc_decode_mode 1 #define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1 #define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode" @@ -11366,7 +10819,6 @@ typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT { -// VK_EXT_pipeline_robustness is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pipeline_robustness 1 #define VK_EXT_PIPELINE_ROBUSTNESS_SPEC_VERSION 1 #define VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_pipeline_robustness" @@ -11412,7 +10864,6 @@ typedef struct VkPipelineRobustnessCreateInfoEXT { -// VK_EXT_conditional_rendering is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_conditional_rendering 1 #define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 #define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" @@ -11456,7 +10907,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( #endif -// VK_NV_clip_space_w_scaling is a preprocessor guard. Do not pass it to API calls. #define VK_NV_clip_space_w_scaling 1 #define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 #define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" @@ -11484,7 +10934,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( #endif -// VK_EXT_direct_mode_display is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_direct_mode_display 1 #define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 #define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" @@ -11497,7 +10946,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( #endif -// VK_EXT_display_surface_counter is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_display_surface_counter 1 #define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 #define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" @@ -11534,7 +10982,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( #endif -// VK_EXT_display_control is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_display_control 1 #define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 #define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" @@ -11611,7 +11058,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( #endif -// VK_GOOGLE_display_timing is a preprocessor guard. Do not pass it to API calls. #define VK_GOOGLE_display_timing 1 #define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 #define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" @@ -11656,19 +11102,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( #endif -// VK_NV_sample_mask_override_coverage is a preprocessor guard. Do not pass it to API calls. #define VK_NV_sample_mask_override_coverage 1 #define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 #define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" -// VK_NV_geometry_shader_passthrough is a preprocessor guard. Do not pass it to API calls. #define VK_NV_geometry_shader_passthrough 1 #define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1 #define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough" -// VK_NV_viewport_array2 is a preprocessor guard. Do not pass it to API calls. #define VK_NV_viewport_array2 1 #define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 #define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" @@ -11676,7 +11119,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( #define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME -// VK_NVX_multiview_per_view_attributes is a preprocessor guard. Do not pass it to API calls. #define VK_NVX_multiview_per_view_attributes 1 #define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 #define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" @@ -11688,7 +11130,6 @@ typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { -// VK_NV_viewport_swizzle is a preprocessor guard. Do not pass it to API calls. #define VK_NV_viewport_swizzle 1 #define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 #define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" @@ -11722,9 +11163,8 @@ typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { -// VK_EXT_discard_rectangles is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_discard_rectangles 1 -#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 2 +#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 #define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" typedef enum VkDiscardRectangleModeEXT { @@ -11749,8 +11189,6 @@ typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { } VkPipelineDiscardRectangleStateCreateInfoEXT; typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); -typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 discardRectangleEnable); -typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleModeEXT)(VkCommandBuffer commandBuffer, VkDiscardRectangleModeEXT discardRectangleMode); #ifndef VK_NO_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( @@ -11758,18 +11196,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEnableEXT( - VkCommandBuffer commandBuffer, - VkBool32 discardRectangleEnable); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleModeEXT( - VkCommandBuffer commandBuffer, - VkDiscardRectangleModeEXT discardRectangleMode); #endif -// VK_EXT_conservative_rasterization is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_conservative_rasterization 1 #define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 #define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" @@ -11805,7 +11234,6 @@ typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { -// VK_EXT_depth_clip_enable is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_depth_clip_enable 1 #define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1 #define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable" @@ -11825,13 +11253,11 @@ typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT { -// VK_EXT_swapchain_colorspace is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_swapchain_colorspace 1 #define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 4 #define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" -// VK_EXT_hdr_metadata is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_hdr_metadata 1 #define VK_EXT_HDR_METADATA_SPEC_VERSION 2 #define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" @@ -11864,20 +11290,17 @@ VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( #endif -// VK_EXT_external_memory_dma_buf is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_external_memory_dma_buf 1 #define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 #define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" -// VK_EXT_queue_family_foreign is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_queue_family_foreign 1 #define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 #define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" #define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) -// VK_EXT_debug_utils is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_debug_utils 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) #define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 @@ -12020,7 +11443,6 @@ VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( #endif -// VK_EXT_sampler_filter_minmax is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_sampler_filter_minmax 1 #define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2 #define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" @@ -12032,25 +11454,21 @@ typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFil -// VK_AMD_gpu_shader_int16 is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_gpu_shader_int16 1 #define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2 #define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" -// VK_AMD_mixed_attachment_samples is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_mixed_attachment_samples 1 #define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 #define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples" -// VK_AMD_shader_fragment_mask is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_fragment_mask 1 #define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1 #define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" -// VK_EXT_inline_uniform_block is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_inline_uniform_block 1 #define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1 #define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block" @@ -12064,13 +11482,11 @@ typedef VkDescriptorPoolInlineUniformBlockCreateInfo VkDescriptorPoolInlineUnifo -// VK_EXT_shader_stencil_export is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_stencil_export 1 #define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 #define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" -// VK_EXT_sample_locations is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_sample_locations 1 #define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 #define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" @@ -12145,7 +11561,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( #endif -// VK_EXT_blend_operation_advanced is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_blend_operation_advanced 1 #define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 #define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" @@ -12183,7 +11598,6 @@ typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { -// VK_NV_fragment_coverage_to_color is a preprocessor guard. Do not pass it to API calls. #define VK_NV_fragment_coverage_to_color 1 #define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 #define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" @@ -12198,7 +11612,6 @@ typedef struct VkPipelineCoverageToColorStateCreateInfoNV { -// VK_NV_framebuffer_mixed_samples is a preprocessor guard. Do not pass it to API calls. #define VK_NV_framebuffer_mixed_samples 1 #define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 #define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" @@ -12223,13 +11636,11 @@ typedef struct VkPipelineCoverageModulationStateCreateInfoNV { -// VK_NV_fill_rectangle is a preprocessor guard. Do not pass it to API calls. #define VK_NV_fill_rectangle 1 #define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1 #define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" -// VK_NV_shader_sm_builtins is a preprocessor guard. Do not pass it to API calls. #define VK_NV_shader_sm_builtins 1 #define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1 #define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins" @@ -12248,13 +11659,11 @@ typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { -// VK_EXT_post_depth_coverage is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_post_depth_coverage 1 #define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 #define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" -// VK_EXT_image_drm_format_modifier is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_drm_format_modifier 1 #define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 2 #define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" @@ -12324,7 +11733,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( #endif -// VK_EXT_validation_cache is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_validation_cache 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) #define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 @@ -12380,7 +11788,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( #endif -// VK_EXT_descriptor_indexing is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_descriptor_indexing 1 #define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2 #define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing" @@ -12400,13 +11807,11 @@ typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVaria -// VK_EXT_shader_viewport_index_layer is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_viewport_index_layer 1 #define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1 #define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" -// VK_NV_shading_rate_image is a preprocessor guard. Do not pass it to API calls. #define VK_NV_shading_rate_image 1 #define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 #define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" @@ -12507,7 +11912,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( #endif -// VK_NV_ray_tracing is a preprocessor guard. Do not pass it to API calls. #define VK_NV_ray_tracing 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) #define VK_NV_RAY_TRACING_SPEC_VERSION 3 @@ -12611,10 +12015,6 @@ typedef enum VkBuildAccelerationStructureFlagBitsKHR { VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 0x00000040, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 0x00000080, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 0x00000100, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = 0x00000200, -#endif - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = 0x00000800, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, @@ -12886,7 +12286,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( #endif -// VK_NV_representative_fragment_test is a preprocessor guard. Do not pass it to API calls. #define VK_NV_representative_fragment_test 1 #define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2 #define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" @@ -12904,7 +12303,6 @@ typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { -// VK_EXT_filter_cubic is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_filter_cubic 1 #define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3 #define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic" @@ -12923,13 +12321,11 @@ typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { -// VK_QCOM_render_pass_shader_resolve is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_render_pass_shader_resolve 1 #define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 #define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" -// VK_EXT_global_priority is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_global_priority 1 #define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 #define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" @@ -12939,7 +12335,6 @@ typedef VkDeviceQueueGlobalPriorityCreateInfoKHR VkDeviceQueueGlobalPriorityCrea -// VK_EXT_external_memory_host is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_external_memory_host 1 #define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 #define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" @@ -12973,7 +12368,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( #endif -// VK_AMD_buffer_marker is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_buffer_marker 1 #define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 #define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" @@ -12989,7 +12383,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( #endif -// VK_AMD_pipeline_compiler_control is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_pipeline_compiler_control 1 #define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1 #define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control" @@ -13006,7 +12399,6 @@ typedef struct VkPipelineCompilerControlCreateInfoAMD { -// VK_EXT_calibrated_timestamps is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_calibrated_timestamps 1 #define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 #define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" @@ -13042,7 +12434,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( #endif -// VK_AMD_shader_core_properties is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_core_properties 1 #define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2 #define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" @@ -13067,7 +12458,6 @@ typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { -// VK_AMD_memory_overallocation_behavior is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_memory_overallocation_behavior 1 #define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1 #define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior" @@ -13086,7 +12476,6 @@ typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { -// VK_EXT_vertex_attribute_divisor is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_vertex_attribute_divisor 1 #define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3 #define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" @@ -13117,7 +12506,6 @@ typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT { -// VK_EXT_pipeline_creation_feedback is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pipeline_creation_feedback 1 #define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 #define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" @@ -13131,13 +12519,11 @@ typedef VkPipelineCreationFeedback VkPipelineCreationFeedbackEXT; -// VK_NV_shader_subgroup_partitioned is a preprocessor guard. Do not pass it to API calls. #define VK_NV_shader_subgroup_partitioned 1 #define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 #define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" -// VK_NV_compute_shader_derivatives is a preprocessor guard. Do not pass it to API calls. #define VK_NV_compute_shader_derivatives 1 #define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 #define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" @@ -13150,7 +12536,6 @@ typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV { -// VK_NV_mesh_shader is a preprocessor guard. Do not pass it to API calls. #define VK_NV_mesh_shader 1 #define VK_NV_MESH_SHADER_SPEC_VERSION 1 #define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" @@ -13212,7 +12597,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( #endif -// VK_NV_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. #define VK_NV_fragment_shader_barycentric 1 #define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 #define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" @@ -13220,7 +12604,6 @@ typedef VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR VkPhysicalDeviceFra -// VK_NV_shader_image_footprint is a preprocessor guard. Do not pass it to API calls. #define VK_NV_shader_image_footprint 1 #define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2 #define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" @@ -13232,9 +12615,8 @@ typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { -// VK_NV_scissor_exclusive is a preprocessor guard. Do not pass it to API calls. #define VK_NV_scissor_exclusive 1 -#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 2 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1 #define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { VkStructureType sType; @@ -13249,16 +12631,9 @@ typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { VkBool32 exclusiveScissor; } VkPhysicalDeviceExclusiveScissorFeaturesNV; -typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorEnableNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkBool32* pExclusiveScissorEnables); typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorEnableNV( - VkCommandBuffer commandBuffer, - uint32_t firstExclusiveScissor, - uint32_t exclusiveScissorCount, - const VkBool32* pExclusiveScissorEnables); - VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, @@ -13267,7 +12642,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( #endif -// VK_NV_device_diagnostic_checkpoints is a preprocessor guard. Do not pass it to API calls. #define VK_NV_device_diagnostic_checkpoints 1 #define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 #define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" @@ -13299,7 +12673,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( #endif -// VK_INTEL_shader_integer_functions2 is a preprocessor guard. Do not pass it to API calls. #define VK_INTEL_shader_integer_functions2 1 #define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1 #define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2" @@ -13311,7 +12684,6 @@ typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { -// VK_INTEL_performance_query is a preprocessor guard. Do not pass it to API calls. #define VK_INTEL_performance_query 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) #define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 @@ -13450,7 +12822,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( #endif -// VK_EXT_pci_bus_info is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pci_bus_info 1 #define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 #define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" @@ -13465,7 +12836,6 @@ typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT { -// VK_AMD_display_native_hdr is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_display_native_hdr 1 #define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1 #define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr" @@ -13491,7 +12861,6 @@ VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( #endif -// VK_EXT_fragment_density_map is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_fragment_density_map 1 #define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 2 #define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" @@ -13519,7 +12888,6 @@ typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT { -// VK_EXT_scalar_block_layout is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_scalar_block_layout 1 #define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1 #define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout" @@ -13527,7 +12895,6 @@ typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLay -// VK_GOOGLE_hlsl_functionality1 is a preprocessor guard. Do not pass it to API calls. #define VK_GOOGLE_hlsl_functionality1 1 #define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 #define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" @@ -13535,13 +12902,11 @@ typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLay #define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME -// VK_GOOGLE_decorate_string is a preprocessor guard. Do not pass it to API calls. #define VK_GOOGLE_decorate_string 1 #define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1 #define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string" -// VK_EXT_subgroup_size_control is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_subgroup_size_control 1 #define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2 #define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control" @@ -13553,7 +12918,6 @@ typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkPipelineShaderStag -// VK_AMD_shader_core_properties2 is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_core_properties2 1 #define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1 #define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2" @@ -13571,7 +12935,6 @@ typedef struct VkPhysicalDeviceShaderCoreProperties2AMD { -// VK_AMD_device_coherent_memory is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_device_coherent_memory 1 #define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1 #define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory" @@ -13583,7 +12946,6 @@ typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { -// VK_EXT_shader_image_atomic_int64 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_image_atomic_int64 1 #define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 #define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" @@ -13596,7 +12958,6 @@ typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { -// VK_EXT_memory_budget is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_memory_budget 1 #define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 #define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" @@ -13609,7 +12970,6 @@ typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { -// VK_EXT_memory_priority is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_memory_priority 1 #define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 #define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority" @@ -13627,7 +12987,6 @@ typedef struct VkMemoryPriorityAllocateInfoEXT { -// VK_NV_dedicated_allocation_image_aliasing is a preprocessor guard. Do not pass it to API calls. #define VK_NV_dedicated_allocation_image_aliasing 1 #define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1 #define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing" @@ -13639,7 +12998,6 @@ typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV { -// VK_EXT_buffer_device_address is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_buffer_device_address 1 #define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2 #define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address" @@ -13670,7 +13028,6 @@ VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( #endif -// VK_EXT_tooling_info is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_tooling_info 1 #define VK_EXT_TOOLING_INFO_SPEC_VERSION 1 #define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info" @@ -13690,7 +13047,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( #endif -// VK_EXT_separate_stencil_usage is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_separate_stencil_usage 1 #define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1 #define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage" @@ -13698,7 +13054,6 @@ typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; -// VK_EXT_validation_features is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_validation_features 1 #define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 5 #define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" @@ -13734,14 +13089,32 @@ typedef struct VkValidationFeaturesEXT { -// VK_NV_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. #define VK_NV_cooperative_matrix 1 #define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1 #define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix" -typedef VkComponentTypeKHR VkComponentTypeNV; -typedef VkScopeKHR VkScopeNV; +typedef enum VkComponentTypeNV { + VK_COMPONENT_TYPE_FLOAT16_NV = 0, + VK_COMPONENT_TYPE_FLOAT32_NV = 1, + VK_COMPONENT_TYPE_FLOAT64_NV = 2, + VK_COMPONENT_TYPE_SINT8_NV = 3, + VK_COMPONENT_TYPE_SINT16_NV = 4, + VK_COMPONENT_TYPE_SINT32_NV = 5, + VK_COMPONENT_TYPE_SINT64_NV = 6, + VK_COMPONENT_TYPE_UINT8_NV = 7, + VK_COMPONENT_TYPE_UINT16_NV = 8, + VK_COMPONENT_TYPE_UINT32_NV = 9, + VK_COMPONENT_TYPE_UINT64_NV = 10, + VK_COMPONENT_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkComponentTypeNV; +typedef enum VkScopeNV { + VK_SCOPE_DEVICE_NV = 1, + VK_SCOPE_WORKGROUP_NV = 2, + VK_SCOPE_SUBGROUP_NV = 3, + VK_SCOPE_QUEUE_FAMILY_NV = 5, + VK_SCOPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkScopeNV; typedef struct VkCooperativeMatrixPropertiesNV { VkStructureType sType; void* pNext; @@ -13778,7 +13151,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( #endif -// VK_NV_coverage_reduction_mode is a preprocessor guard. Do not pass it to API calls. #define VK_NV_coverage_reduction_mode 1 #define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1 #define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode" @@ -13821,7 +13193,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSampl #endif -// VK_EXT_fragment_shader_interlock is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_fragment_shader_interlock 1 #define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1 #define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock" @@ -13835,7 +13206,6 @@ typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT { -// VK_EXT_ycbcr_image_arrays is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_ycbcr_image_arrays 1 #define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1 #define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays" @@ -13847,7 +13217,6 @@ typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { -// VK_EXT_provoking_vertex is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_provoking_vertex 1 #define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 #define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" @@ -13879,7 +13248,6 @@ typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { -// VK_EXT_headless_surface is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_headless_surface 1 #define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 #define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" @@ -13901,7 +13269,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( #endif -// VK_EXT_line_rasterization is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_line_rasterization 1 #define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1 #define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization" @@ -13949,7 +13316,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( #endif -// VK_EXT_shader_atomic_float is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_atomic_float 1 #define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 #define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" @@ -13972,7 +13338,6 @@ typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { -// VK_EXT_host_query_reset is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_host_query_reset 1 #define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 #define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" @@ -13989,7 +13354,6 @@ VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( #endif -// VK_EXT_index_type_uint8 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_index_type_uint8 1 #define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1 #define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8" @@ -14001,7 +13365,6 @@ typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT { -// VK_EXT_extended_dynamic_state is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_extended_dynamic_state 1 #define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 #define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" @@ -14086,146 +13449,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( #endif -// VK_EXT_host_image_copy is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_host_image_copy 1 -#define VK_EXT_HOST_IMAGE_COPY_SPEC_VERSION 1 -#define VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME "VK_EXT_host_image_copy" - -typedef enum VkHostImageCopyFlagBitsEXT { - VK_HOST_IMAGE_COPY_MEMCPY_EXT = 0x00000001, - VK_HOST_IMAGE_COPY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkHostImageCopyFlagBitsEXT; -typedef VkFlags VkHostImageCopyFlagsEXT; -typedef struct VkPhysicalDeviceHostImageCopyFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 hostImageCopy; -} VkPhysicalDeviceHostImageCopyFeaturesEXT; - -typedef struct VkPhysicalDeviceHostImageCopyPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t copySrcLayoutCount; - VkImageLayout* pCopySrcLayouts; - uint32_t copyDstLayoutCount; - VkImageLayout* pCopyDstLayouts; - uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE]; - VkBool32 identicalMemoryTypeRequirements; -} VkPhysicalDeviceHostImageCopyPropertiesEXT; - -typedef struct VkMemoryToImageCopyEXT { - VkStructureType sType; - const void* pNext; - const void* pHostPointer; - uint32_t memoryRowLength; - uint32_t memoryImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkMemoryToImageCopyEXT; - -typedef struct VkImageToMemoryCopyEXT { - VkStructureType sType; - const void* pNext; - void* pHostPointer; - uint32_t memoryRowLength; - uint32_t memoryImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkImageToMemoryCopyEXT; - -typedef struct VkCopyMemoryToImageInfoEXT { - VkStructureType sType; - const void* pNext; - VkHostImageCopyFlagsEXT flags; - VkImage dstImage; - VkImageLayout dstImageLayout; - uint32_t regionCount; - const VkMemoryToImageCopyEXT* pRegions; -} VkCopyMemoryToImageInfoEXT; - -typedef struct VkCopyImageToMemoryInfoEXT { - VkStructureType sType; - const void* pNext; - VkHostImageCopyFlagsEXT flags; - VkImage srcImage; - VkImageLayout srcImageLayout; - uint32_t regionCount; - const VkImageToMemoryCopyEXT* pRegions; -} VkCopyImageToMemoryInfoEXT; - -typedef struct VkCopyImageToImageInfoEXT { - VkStructureType sType; - const void* pNext; - VkHostImageCopyFlagsEXT flags; - VkImage srcImage; - VkImageLayout srcImageLayout; - VkImage dstImage; - VkImageLayout dstImageLayout; - uint32_t regionCount; - const VkImageCopy2* pRegions; -} VkCopyImageToImageInfoEXT; - -typedef struct VkHostImageLayoutTransitionInfoEXT { - VkStructureType sType; - const void* pNext; - VkImage image; - VkImageLayout oldLayout; - VkImageLayout newLayout; - VkImageSubresourceRange subresourceRange; -} VkHostImageLayoutTransitionInfoEXT; - -typedef struct VkSubresourceHostMemcpySizeEXT { - VkStructureType sType; - void* pNext; - VkDeviceSize size; -} VkSubresourceHostMemcpySizeEXT; - -typedef struct VkHostImageCopyDevicePerformanceQueryEXT { - VkStructureType sType; - void* pNext; - VkBool32 optimalDeviceAccess; - VkBool32 identicalMemoryLayout; -} VkHostImageCopyDevicePerformanceQueryEXT; - -typedef VkSubresourceLayout2KHR VkSubresourceLayout2EXT; - -typedef VkImageSubresource2KHR VkImageSubresource2EXT; - -typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToImageEXT)(VkDevice device, const VkCopyMemoryToImageInfoEXT* pCopyMemoryToImageInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToMemoryEXT)(VkDevice device, const VkCopyImageToMemoryInfoEXT* pCopyImageToMemoryInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToImageEXT)(VkDevice device, const VkCopyImageToImageInfoEXT* pCopyImageToImageInfo); -typedef VkResult (VKAPI_PTR *PFN_vkTransitionImageLayoutEXT)(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT* pTransitions); -typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2EXT)(VkDevice device, VkImage image, const VkImageSubresource2KHR* pSubresource, VkSubresourceLayout2KHR* pLayout); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToImageEXT( - VkDevice device, - const VkCopyMemoryToImageInfoEXT* pCopyMemoryToImageInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToMemoryEXT( - VkDevice device, - const VkCopyImageToMemoryInfoEXT* pCopyImageToMemoryInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToImageEXT( - VkDevice device, - const VkCopyImageToImageInfoEXT* pCopyImageToImageInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkTransitionImageLayoutEXT( - VkDevice device, - uint32_t transitionCount, - const VkHostImageLayoutTransitionInfoEXT* pTransitions); - -VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2EXT( - VkDevice device, - VkImage image, - const VkImageSubresource2KHR* pSubresource, - VkSubresourceLayout2KHR* pLayout); -#endif - - -// VK_EXT_shader_atomic_float2 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_atomic_float2 1 #define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 #define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" @@ -14248,7 +13471,6 @@ typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { -// VK_EXT_surface_maintenance1 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_surface_maintenance1 1 #define VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 #define VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_surface_maintenance1" @@ -14293,7 +13515,6 @@ typedef struct VkSurfacePresentModeCompatibilityEXT { -// VK_EXT_swapchain_maintenance1 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_swapchain_maintenance1 1 #define VK_EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION 1 #define VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_swapchain_maintenance1" @@ -14305,21 +13526,21 @@ typedef struct VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT { typedef struct VkSwapchainPresentFenceInfoEXT { VkStructureType sType; - const void* pNext; + void* pNext; uint32_t swapchainCount; const VkFence* pFences; } VkSwapchainPresentFenceInfoEXT; typedef struct VkSwapchainPresentModesCreateInfoEXT { VkStructureType sType; - const void* pNext; + void* pNext; uint32_t presentModeCount; const VkPresentModeKHR* pPresentModes; } VkSwapchainPresentModesCreateInfoEXT; typedef struct VkSwapchainPresentModeInfoEXT { VkStructureType sType; - const void* pNext; + void* pNext; uint32_t swapchainCount; const VkPresentModeKHR* pPresentModes; } VkSwapchainPresentModeInfoEXT; @@ -14349,7 +13570,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesEXT( #endif -// VK_EXT_shader_demote_to_helper_invocation is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_demote_to_helper_invocation 1 #define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 #define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" @@ -14357,7 +13577,6 @@ typedef VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures VkPhysicalDeviceS -// VK_NV_device_generated_commands is a preprocessor guard. Do not pass it to API calls. #define VK_NV_device_generated_commands 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) #define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 @@ -14373,8 +13592,6 @@ typedef enum VkIndirectCommandsTokenTypeNV { VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV = 1000428003, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV = 1000428004, VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF } VkIndirectCommandsTokenTypeNV; @@ -14551,7 +13768,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( #endif -// VK_NV_inherited_viewport_scissor is a preprocessor guard. Do not pass it to API calls. #define VK_NV_inherited_viewport_scissor 1 #define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 #define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" @@ -14571,7 +13787,6 @@ typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { -// VK_EXT_texel_buffer_alignment is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_texel_buffer_alignment 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" @@ -14585,7 +13800,6 @@ typedef VkPhysicalDeviceTexelBufferAlignmentProperties VkPhysicalDeviceTexelBuff -// VK_QCOM_render_pass_transform is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_render_pass_transform 1 #define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 3 #define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" @@ -14604,51 +13818,6 @@ typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { -// VK_EXT_depth_bias_control is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_depth_bias_control 1 -#define VK_EXT_DEPTH_BIAS_CONTROL_SPEC_VERSION 1 -#define VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME "VK_EXT_depth_bias_control" - -typedef enum VkDepthBiasRepresentationEXT { - VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT = 0, - VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT = 1, - VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT = 2, - VK_DEPTH_BIAS_REPRESENTATION_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDepthBiasRepresentationEXT; -typedef struct VkPhysicalDeviceDepthBiasControlFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 depthBiasControl; - VkBool32 leastRepresentableValueForceUnormRepresentation; - VkBool32 floatRepresentation; - VkBool32 depthBiasExact; -} VkPhysicalDeviceDepthBiasControlFeaturesEXT; - -typedef struct VkDepthBiasInfoEXT { - VkStructureType sType; - const void* pNext; - float depthBiasConstantFactor; - float depthBiasClamp; - float depthBiasSlopeFactor; -} VkDepthBiasInfoEXT; - -typedef struct VkDepthBiasRepresentationInfoEXT { - VkStructureType sType; - const void* pNext; - VkDepthBiasRepresentationEXT depthBiasRepresentation; - VkBool32 depthBiasExact; -} VkDepthBiasRepresentationInfoEXT; - -typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias2EXT)(VkCommandBuffer commandBuffer, const VkDepthBiasInfoEXT* pDepthBiasInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias2EXT( - VkCommandBuffer commandBuffer, - const VkDepthBiasInfoEXT* pDepthBiasInfo); -#endif - - -// VK_EXT_device_memory_report is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_device_memory_report 1 #define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 #define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" @@ -14694,7 +13863,6 @@ typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { -// VK_EXT_acquire_drm_display is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_acquire_drm_display 1 #define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 #define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" @@ -14715,7 +13883,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( #endif -// VK_EXT_robustness2 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_robustness2 1 #define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 #define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" @@ -14736,7 +13903,6 @@ typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { -// VK_EXT_custom_border_color is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_custom_border_color 1 #define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 #define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" @@ -14762,13 +13928,11 @@ typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { -// VK_GOOGLE_user_type is a preprocessor guard. Do not pass it to API calls. #define VK_GOOGLE_user_type 1 #define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 #define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" -// VK_NV_present_barrier is a preprocessor guard. Do not pass it to API calls. #define VK_NV_present_barrier 1 #define VK_NV_PRESENT_BARRIER_SPEC_VERSION 1 #define VK_NV_PRESENT_BARRIER_EXTENSION_NAME "VK_NV_present_barrier" @@ -14792,7 +13956,6 @@ typedef struct VkSwapchainPresentBarrierCreateInfoNV { -// VK_EXT_private_data is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_private_data 1 typedef VkPrivateDataSlot VkPrivateDataSlotEXT; @@ -14839,7 +14002,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( #endif -// VK_EXT_pipeline_creation_cache_control is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pipeline_creation_cache_control 1 #define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 #define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" @@ -14847,7 +14009,6 @@ typedef VkPhysicalDevicePipelineCreationCacheControlFeatures VkPhysicalDevicePip -// VK_NV_device_diagnostics_config is a preprocessor guard. Do not pass it to API calls. #define VK_NV_device_diagnostics_config 1 #define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 2 #define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" @@ -14874,25 +14035,11 @@ typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { -// VK_QCOM_render_pass_store_ops is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_render_pass_store_ops 1 #define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 #define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" -// VK_NV_low_latency is a preprocessor guard. Do not pass it to API calls. -#define VK_NV_low_latency 1 -#define VK_NV_LOW_LATENCY_SPEC_VERSION 1 -#define VK_NV_LOW_LATENCY_EXTENSION_NAME "VK_NV_low_latency" -typedef struct VkQueryLowLatencySupportNV { - VkStructureType sType; - const void* pNext; - void* pQueriedLowLatencyData; -} VkQueryLowLatencySupportNV; - - - -// VK_EXT_descriptor_buffer is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_descriptor_buffer 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) #define VK_EXT_DESCRIPTOR_BUFFER_SPEC_VERSION 1 @@ -15105,7 +14252,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureOpaqueCaptureDescriptor #endif -// VK_EXT_graphics_pipeline_library is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_graphics_pipeline_library 1 #define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION 1 #define VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME "VK_EXT_graphics_pipeline_library" @@ -15133,13 +14279,12 @@ typedef struct VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT { typedef struct VkGraphicsPipelineLibraryCreateInfoEXT { VkStructureType sType; - const void* pNext; + void* pNext; VkGraphicsPipelineLibraryFlagsEXT flags; } VkGraphicsPipelineLibraryCreateInfoEXT; -// VK_AMD_shader_early_and_late_fragment_tests is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_shader_early_and_late_fragment_tests 1 #define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION 1 #define VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME "VK_AMD_shader_early_and_late_fragment_tests" @@ -15151,7 +14296,6 @@ typedef struct VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD { -// VK_NV_fragment_shading_rate_enums is a preprocessor guard. Do not pass it to API calls. #define VK_NV_fragment_shading_rate_enums 1 #define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 #define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" @@ -15209,7 +14353,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( #endif -// VK_NV_ray_tracing_motion_blur is a preprocessor guard. Do not pass it to API calls. #define VK_NV_ray_tracing_motion_blur 1 #define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 #define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" @@ -15300,7 +14443,6 @@ typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { -// VK_EXT_ycbcr_2plane_444_formats is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_ycbcr_2plane_444_formats 1 #define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 #define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" @@ -15312,7 +14454,6 @@ typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { -// VK_EXT_fragment_density_map2 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_fragment_density_map2 1 #define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 #define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" @@ -15333,7 +14474,6 @@ typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { -// VK_QCOM_rotated_copy_commands is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_rotated_copy_commands 1 #define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 1 #define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" @@ -15345,7 +14485,6 @@ typedef struct VkCopyCommandTransformInfoQCOM { -// VK_EXT_image_robustness is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_robustness 1 #define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 #define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" @@ -15353,7 +14492,6 @@ typedef VkPhysicalDeviceImageRobustnessFeatures VkPhysicalDeviceImageRobustnessF -// VK_EXT_image_compression_control is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_compression_control 1 #define VK_EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION 1 #define VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME "VK_EXT_image_compression_control" @@ -15410,6 +14548,18 @@ typedef struct VkImageCompressionControlEXT { VkImageCompressionFixedRateFlagsEXT* pFixedRateFlags; } VkImageCompressionControlEXT; +typedef struct VkSubresourceLayout2EXT { + VkStructureType sType; + void* pNext; + VkSubresourceLayout subresourceLayout; +} VkSubresourceLayout2EXT; + +typedef struct VkImageSubresource2EXT { + VkStructureType sType; + void* pNext; + VkImageSubresource imageSubresource; +} VkImageSubresource2EXT; + typedef struct VkImageCompressionPropertiesEXT { VkStructureType sType; void* pNext; @@ -15417,9 +14567,17 @@ typedef struct VkImageCompressionPropertiesEXT { VkImageCompressionFixedRateFlagsEXT imageCompressionFixedRateFlags; } VkImageCompressionPropertiesEXT; +typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2EXT)(VkDevice device, VkImage image, const VkImageSubresource2EXT* pSubresource, VkSubresourceLayout2EXT* pLayout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2EXT( + VkDevice device, + VkImage image, + const VkImageSubresource2EXT* pSubresource, + VkSubresourceLayout2EXT* pLayout); +#endif -// VK_EXT_attachment_feedback_loop_layout is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_attachment_feedback_loop_layout 1 #define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_SPEC_VERSION 2 #define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_layout" @@ -15431,7 +14589,6 @@ typedef struct VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT { -// VK_EXT_4444_formats is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_4444_formats 1 #define VK_EXT_4444_FORMATS_SPEC_VERSION 1 #define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" @@ -15444,9 +14601,8 @@ typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { -// VK_EXT_device_fault is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_device_fault 1 -#define VK_EXT_DEVICE_FAULT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_FAULT_SPEC_VERSION 1 #define VK_EXT_DEVICE_FAULT_EXTENSION_NAME "VK_EXT_device_fault" typedef enum VkDeviceFaultAddressTypeEXT { @@ -15510,8 +14666,6 @@ typedef struct VkDeviceFaultVendorBinaryHeaderVersionOneEXT { uint32_t applicationNameOffset; uint32_t applicationVersion; uint32_t engineNameOffset; - uint32_t engineVersion; - uint32_t apiVersion; } VkDeviceFaultVendorBinaryHeaderVersionOneEXT; typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultInfoEXT)(VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); @@ -15524,7 +14678,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultInfoEXT( #endif -// VK_ARM_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. #define VK_ARM_rasterization_order_attachment_access 1 #define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 #define VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_ARM_rasterization_order_attachment_access" @@ -15540,7 +14693,6 @@ typedef VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT VkPhysical -// VK_EXT_rgba10x6_formats is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_rgba10x6_formats 1 #define VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION 1 #define VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME "VK_EXT_rgba10x6_formats" @@ -15552,7 +14704,6 @@ typedef struct VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT { -// VK_VALVE_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. #define VK_VALVE_mutable_descriptor_type 1 #define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 #define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" @@ -15582,7 +14733,6 @@ typedef VkMutableDescriptorTypeCreateInfoEXT VkMutableDescriptorTypeCreateInfoVA -// VK_EXT_vertex_input_dynamic_state is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_vertex_input_dynamic_state 1 #define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 #define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" @@ -15622,7 +14772,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( #endif -// VK_EXT_physical_device_drm is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_physical_device_drm 1 #define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 #define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" @@ -15639,7 +14788,6 @@ typedef struct VkPhysicalDeviceDrmPropertiesEXT { -// VK_EXT_device_address_binding_report is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_device_address_binding_report 1 #define VK_EXT_DEVICE_ADDRESS_BINDING_REPORT_SPEC_VERSION 1 #define VK_EXT_DEVICE_ADDRESS_BINDING_REPORT_EXTENSION_NAME "VK_EXT_device_address_binding_report" @@ -15672,7 +14820,6 @@ typedef struct VkDeviceAddressBindingCallbackDataEXT { -// VK_EXT_depth_clip_control is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_depth_clip_control 1 #define VK_EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION 1 #define VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME "VK_EXT_depth_clip_control" @@ -15690,7 +14837,6 @@ typedef struct VkPipelineViewportDepthClipControlCreateInfoEXT { -// VK_EXT_primitive_topology_list_restart is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_primitive_topology_list_restart 1 #define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION 1 #define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME "VK_EXT_primitive_topology_list_restart" @@ -15703,9 +14849,8 @@ typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { -// VK_HUAWEI_subpass_shading is a preprocessor guard. Do not pass it to API calls. #define VK_HUAWEI_subpass_shading 1 -#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 3 +#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 2 #define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { VkStructureType sType; @@ -15740,7 +14885,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( #endif -// VK_HUAWEI_invocation_mask is a preprocessor guard. Do not pass it to API calls. #define VK_HUAWEI_invocation_mask 1 #define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 #define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" @@ -15760,7 +14904,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( #endif -// VK_NV_external_memory_rdma is a preprocessor guard. Do not pass it to API calls. #define VK_NV_external_memory_rdma 1 typedef void* VkRemoteAddressNV; #define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 @@ -15788,7 +14931,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( #endif -// VK_EXT_pipeline_properties is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pipeline_properties 1 #define VK_EXT_PIPELINE_PROPERTIES_SPEC_VERSION 1 #define VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME "VK_EXT_pipeline_properties" @@ -15816,7 +14958,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelinePropertiesEXT( #endif -// VK_EXT_multisampled_render_to_single_sampled is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_multisampled_render_to_single_sampled 1 #define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION 1 #define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME "VK_EXT_multisampled_render_to_single_sampled" @@ -15841,7 +14982,6 @@ typedef struct VkMultisampledRenderToSingleSampledInfoEXT { -// VK_EXT_extended_dynamic_state2 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_extended_dynamic_state2 1 #define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 #define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" @@ -15882,7 +15022,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( #endif -// VK_EXT_color_write_enable is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_color_write_enable 1 #define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 #define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" @@ -15909,7 +15048,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWrite #endif -// VK_EXT_primitives_generated_query is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_primitives_generated_query 1 #define VK_EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION 1 #define VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME "VK_EXT_primitives_generated_query" @@ -15923,7 +15061,6 @@ typedef struct VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT { -// VK_EXT_global_priority_query is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_global_priority_query 1 #define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 #define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" @@ -15934,7 +15071,6 @@ typedef VkQueueFamilyGlobalPriorityPropertiesKHR VkQueueFamilyGlobalPriorityProp -// VK_EXT_image_view_min_lod is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_view_min_lod 1 #define VK_EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION 1 #define VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME "VK_EXT_image_view_min_lod" @@ -15952,7 +15088,6 @@ typedef struct VkImageViewMinLodCreateInfoEXT { -// VK_EXT_multi_draw is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_multi_draw 1 #define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 #define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" @@ -16002,7 +15137,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( #endif -// VK_EXT_image_2d_view_of_3d is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_2d_view_of_3d 1 #define VK_EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION 1 #define VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_2d_view_of_3d" @@ -16015,29 +15149,6 @@ typedef struct VkPhysicalDeviceImage2DViewOf3DFeaturesEXT { -// VK_EXT_shader_tile_image is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_shader_tile_image 1 -#define VK_EXT_SHADER_TILE_IMAGE_SPEC_VERSION 1 -#define VK_EXT_SHADER_TILE_IMAGE_EXTENSION_NAME "VK_EXT_shader_tile_image" -typedef struct VkPhysicalDeviceShaderTileImageFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 shaderTileImageColorReadAccess; - VkBool32 shaderTileImageDepthReadAccess; - VkBool32 shaderTileImageStencilReadAccess; -} VkPhysicalDeviceShaderTileImageFeaturesEXT; - -typedef struct VkPhysicalDeviceShaderTileImagePropertiesEXT { - VkStructureType sType; - void* pNext; - VkBool32 shaderTileImageCoherentReadAccelerated; - VkBool32 shaderTileImageReadSampleFromPixelRateInvocation; - VkBool32 shaderTileImageReadFromHelperInvocation; -} VkPhysicalDeviceShaderTileImagePropertiesEXT; - - - -// VK_EXT_opacity_micromap is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_opacity_micromap 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkMicromapEXT) #define VK_EXT_OPACITY_MICROMAP_SPEC_VERSION 2 @@ -16045,9 +15156,6 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkMicromapEXT) typedef enum VkMicromapTypeEXT { VK_MICROMAP_TYPE_OPACITY_MICROMAP_EXT = 0, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_MICROMAP_TYPE_DISPLACEMENT_MICROMAP_NV = 1000397000, -#endif VK_MICROMAP_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkMicromapTypeEXT; @@ -16309,15 +15417,13 @@ VKAPI_ATTR void VKAPI_CALL vkGetMicromapBuildSizesEXT( #endif -// VK_EXT_load_store_op_none is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_load_store_op_none 1 #define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 #define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" -// VK_HUAWEI_cluster_culling_shader is a preprocessor guard. Do not pass it to API calls. #define VK_HUAWEI_cluster_culling_shader 1 -#define VK_HUAWEI_CLUSTER_CULLING_SHADER_SPEC_VERSION 2 +#define VK_HUAWEI_CLUSTER_CULLING_SHADER_SPEC_VERSION 1 #define VK_HUAWEI_CLUSTER_CULLING_SHADER_EXTENSION_NAME "VK_HUAWEI_cluster_culling_shader" typedef struct VkPhysicalDeviceClusterCullingShaderFeaturesHUAWEI { VkStructureType sType; @@ -16332,7 +15438,6 @@ typedef struct VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI { uint32_t maxWorkGroupCount[3]; uint32_t maxWorkGroupSize[3]; uint32_t maxOutputClusterCount; - VkDeviceSize indirectBufferOffsetAlignment; } VkPhysicalDeviceClusterCullingShaderPropertiesHUAWEI; typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterHUAWEI)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); @@ -16352,7 +15457,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterIndirectHUAWEI( #endif -// VK_EXT_border_color_swizzle is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_border_color_swizzle 1 #define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 #define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" @@ -16372,7 +15476,6 @@ typedef struct VkSamplerBorderColorComponentMappingCreateInfoEXT { -// VK_EXT_pageable_device_local_memory is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pageable_device_local_memory 1 #define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION 1 #define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME "VK_EXT_pageable_device_local_memory" @@ -16392,41 +15495,6 @@ VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( #endif -// VK_ARM_shader_core_properties is a preprocessor guard. Do not pass it to API calls. -#define VK_ARM_shader_core_properties 1 -#define VK_ARM_SHADER_CORE_PROPERTIES_SPEC_VERSION 1 -#define VK_ARM_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_ARM_shader_core_properties" -typedef struct VkPhysicalDeviceShaderCorePropertiesARM { - VkStructureType sType; - void* pNext; - uint32_t pixelRate; - uint32_t texelRate; - uint32_t fmaRate; -} VkPhysicalDeviceShaderCorePropertiesARM; - - - -// VK_EXT_image_sliced_view_of_3d is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_image_sliced_view_of_3d 1 -#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_SPEC_VERSION 1 -#define VK_EXT_IMAGE_SLICED_VIEW_OF_3D_EXTENSION_NAME "VK_EXT_image_sliced_view_of_3d" -#define VK_REMAINING_3D_SLICES_EXT (~0U) -typedef struct VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 imageSlicedViewOf3D; -} VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT; - -typedef struct VkImageViewSlicedCreateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t sliceOffset; - uint32_t sliceCount; -} VkImageViewSlicedCreateInfoEXT; - - - -// VK_VALVE_descriptor_set_host_mapping is a preprocessor guard. Do not pass it to API calls. #define VK_VALVE_descriptor_set_host_mapping 1 #define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_SPEC_VERSION 1 #define VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_EXTENSION_NAME "VK_VALVE_descriptor_set_host_mapping" @@ -16466,7 +15534,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetHostMappingVALVE( #endif -// VK_EXT_depth_clamp_zero_one is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_depth_clamp_zero_one 1 #define VK_EXT_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION 1 #define VK_EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME "VK_EXT_depth_clamp_zero_one" @@ -16478,7 +15545,6 @@ typedef struct VkPhysicalDeviceDepthClampZeroOneFeaturesEXT { -// VK_EXT_non_seamless_cube_map is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_non_seamless_cube_map 1 #define VK_EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION 1 #define VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME "VK_EXT_non_seamless_cube_map" @@ -16490,7 +15556,6 @@ typedef struct VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT { -// VK_QCOM_fragment_density_map_offset is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_fragment_density_map_offset 1 #define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 1 #define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_QCOM_fragment_density_map_offset" @@ -16515,7 +15580,6 @@ typedef struct VkSubpassFragmentDensityMapOffsetEndInfoQCOM { -// VK_NV_copy_memory_indirect is a preprocessor guard. Do not pass it to API calls. #define VK_NV_copy_memory_indirect 1 #define VK_NV_COPY_MEMORY_INDIRECT_SPEC_VERSION 1 #define VK_NV_COPY_MEMORY_INDIRECT_EXTENSION_NAME "VK_NV_copy_memory_indirect" @@ -16567,7 +15631,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectNV( #endif -// VK_NV_memory_decompression is a preprocessor guard. Do not pass it to API calls. #define VK_NV_memory_decompression 1 #define VK_NV_MEMORY_DECOMPRESSION_SPEC_VERSION 1 #define VK_NV_MEMORY_DECOMPRESSION_EXTENSION_NAME "VK_NV_memory_decompression" @@ -16615,59 +15678,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryIndirectCountNV( #endif -// VK_NV_device_generated_commands_compute is a preprocessor guard. Do not pass it to API calls. -#define VK_NV_device_generated_commands_compute 1 -#define VK_NV_DEVICE_GENERATED_COMMANDS_COMPUTE_SPEC_VERSION 2 -#define VK_NV_DEVICE_GENERATED_COMMANDS_COMPUTE_EXTENSION_NAME "VK_NV_device_generated_commands_compute" -typedef struct VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV { - VkStructureType sType; - void* pNext; - VkBool32 deviceGeneratedCompute; - VkBool32 deviceGeneratedComputePipelines; - VkBool32 deviceGeneratedComputeCaptureReplay; -} VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV; - -typedef struct VkComputePipelineIndirectBufferInfoNV { - VkStructureType sType; - const void* pNext; - VkDeviceAddress deviceAddress; - VkDeviceSize size; - VkDeviceAddress pipelineDeviceAddressCaptureReplay; -} VkComputePipelineIndirectBufferInfoNV; - -typedef struct VkPipelineIndirectDeviceAddressInfoNV { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkPipeline pipeline; -} VkPipelineIndirectDeviceAddressInfoNV; - -typedef struct VkBindPipelineIndirectCommandNV { - VkDeviceAddress pipelineAddress; -} VkBindPipelineIndirectCommandNV; - -typedef void (VKAPI_PTR *PFN_vkGetPipelineIndirectMemoryRequirementsNV)(VkDevice device, const VkComputePipelineCreateInfo* pCreateInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkCmdUpdatePipelineIndirectBufferNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); -typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetPipelineIndirectDeviceAddressNV)(VkDevice device, const VkPipelineIndirectDeviceAddressInfoNV* pInfo); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkGetPipelineIndirectMemoryRequirementsNV( - VkDevice device, - const VkComputePipelineCreateInfo* pCreateInfo, - VkMemoryRequirements2* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkCmdUpdatePipelineIndirectBufferNV( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipeline pipeline); - -VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetPipelineIndirectDeviceAddressNV( - VkDevice device, - const VkPipelineIndirectDeviceAddressInfoNV* pInfo); -#endif - - -// VK_NV_linear_color_attachment is a preprocessor guard. Do not pass it to API calls. #define VK_NV_linear_color_attachment 1 #define VK_NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION 1 #define VK_NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME "VK_NV_linear_color_attachment" @@ -16679,13 +15689,11 @@ typedef struct VkPhysicalDeviceLinearColorAttachmentFeaturesNV { -// VK_GOOGLE_surfaceless_query is a preprocessor guard. Do not pass it to API calls. #define VK_GOOGLE_surfaceless_query 1 #define VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION 2 #define VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME "VK_GOOGLE_surfaceless_query" -// VK_EXT_image_compression_control_swapchain is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_compression_control_swapchain 1 #define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION 1 #define VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME "VK_EXT_image_compression_control_swapchain" @@ -16697,7 +15705,6 @@ typedef struct VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT { -// VK_QCOM_image_processing is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_image_processing 1 #define VK_QCOM_IMAGE_PROCESSING_SPEC_VERSION 1 #define VK_QCOM_IMAGE_PROCESSING_EXTENSION_NAME "VK_QCOM_image_processing" @@ -16728,19 +15735,6 @@ typedef struct VkPhysicalDeviceImageProcessingPropertiesQCOM { -// VK_EXT_external_memory_acquire_unmodified is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_external_memory_acquire_unmodified 1 -#define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_SPEC_VERSION 1 -#define VK_EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXTENSION_NAME "VK_EXT_external_memory_acquire_unmodified" -typedef struct VkExternalMemoryAcquireUnmodifiedEXT { - VkStructureType sType; - const void* pNext; - VkBool32 acquireUnmodifiedMemory; -} VkExternalMemoryAcquireUnmodifiedEXT; - - - -// VK_EXT_extended_dynamic_state3 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_extended_dynamic_state3 1 #define VK_EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION 2 #define VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME "VK_EXT_extended_dynamic_state3" @@ -16974,7 +15968,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageReductionModeNV( #endif -// VK_EXT_subpass_merge_feedback is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_subpass_merge_feedback 1 #define VK_EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION 2 #define VK_EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME "VK_EXT_subpass_merge_feedback" @@ -17032,7 +16025,6 @@ typedef struct VkRenderPassSubpassFeedbackCreateInfoEXT { -// VK_LUNARG_direct_driver_loading is a preprocessor guard. Do not pass it to API calls. #define VK_LUNARG_direct_driver_loading 1 #define VK_LUNARG_DIRECT_DRIVER_LOADING_SPEC_VERSION 1 #define VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME "VK_LUNARG_direct_driver_loading" @@ -17063,7 +16055,6 @@ typedef struct VkDirectDriverLoadingListLUNARG { -// VK_EXT_shader_module_identifier is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_module_identifier 1 #define VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT 32U #define VK_EXT_SHADER_MODULE_IDENTIFIER_SPEC_VERSION 1 @@ -17110,13 +16101,11 @@ VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleCreateInfoIdentifierEXT( #endif -// VK_EXT_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_rasterization_order_attachment_access 1 #define VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION 1 #define VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME "VK_EXT_rasterization_order_attachment_access" -// VK_NV_optical_flow is a preprocessor guard. Do not pass it to API calls. #define VK_NV_optical_flow 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkOpticalFlowSessionNV) #define VK_NV_OPTICAL_FLOW_SPEC_VERSION 1 @@ -17281,7 +16270,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdOpticalFlowExecuteNV( #endif -// VK_EXT_legacy_dithering is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_legacy_dithering 1 #define VK_EXT_LEGACY_DITHERING_SPEC_VERSION 1 #define VK_EXT_LEGACY_DITHERING_EXTENSION_NAME "VK_EXT_legacy_dithering" @@ -17293,7 +16281,6 @@ typedef struct VkPhysicalDeviceLegacyDitheringFeaturesEXT { -// VK_EXT_pipeline_protected_access is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_pipeline_protected_access 1 #define VK_EXT_PIPELINE_PROTECTED_ACCESS_SPEC_VERSION 1 #define VK_EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME "VK_EXT_pipeline_protected_access" @@ -17305,94 +16292,6 @@ typedef struct VkPhysicalDevicePipelineProtectedAccessFeaturesEXT { -// VK_EXT_shader_object is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_shader_object 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderEXT) -#define VK_EXT_SHADER_OBJECT_SPEC_VERSION 1 -#define VK_EXT_SHADER_OBJECT_EXTENSION_NAME "VK_EXT_shader_object" - -typedef enum VkShaderCodeTypeEXT { - VK_SHADER_CODE_TYPE_BINARY_EXT = 0, - VK_SHADER_CODE_TYPE_SPIRV_EXT = 1, - VK_SHADER_CODE_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkShaderCodeTypeEXT; - -typedef enum VkShaderCreateFlagBitsEXT { - VK_SHADER_CREATE_LINK_STAGE_BIT_EXT = 0x00000001, - VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000002, - VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000004, - VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT = 0x00000008, - VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT = 0x00000010, - VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT = 0x00000020, - VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00000040, - VK_SHADER_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkShaderCreateFlagBitsEXT; -typedef VkFlags VkShaderCreateFlagsEXT; -typedef struct VkPhysicalDeviceShaderObjectFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 shaderObject; -} VkPhysicalDeviceShaderObjectFeaturesEXT; - -typedef struct VkPhysicalDeviceShaderObjectPropertiesEXT { - VkStructureType sType; - void* pNext; - uint8_t shaderBinaryUUID[VK_UUID_SIZE]; - uint32_t shaderBinaryVersion; -} VkPhysicalDeviceShaderObjectPropertiesEXT; - -typedef struct VkShaderCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkShaderCreateFlagsEXT flags; - VkShaderStageFlagBits stage; - VkShaderStageFlags nextStage; - VkShaderCodeTypeEXT codeType; - size_t codeSize; - const void* pCode; - const char* pName; - uint32_t setLayoutCount; - const VkDescriptorSetLayout* pSetLayouts; - uint32_t pushConstantRangeCount; - const VkPushConstantRange* pPushConstantRanges; - const VkSpecializationInfo* pSpecializationInfo; -} VkShaderCreateInfoEXT; - -typedef VkPipelineShaderStageRequiredSubgroupSizeCreateInfo VkShaderRequiredSubgroupSizeCreateInfoEXT; - -typedef VkResult (VKAPI_PTR *PFN_vkCreateShadersEXT)(VkDevice device, uint32_t createInfoCount, const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkShaderEXT* pShaders); -typedef void (VKAPI_PTR *PFN_vkDestroyShaderEXT)(VkDevice device, VkShaderEXT shader, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetShaderBinaryDataEXT)(VkDevice device, VkShaderEXT shader, size_t* pDataSize, void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdBindShadersEXT)(VkCommandBuffer commandBuffer, uint32_t stageCount, const VkShaderStageFlagBits* pStages, const VkShaderEXT* pShaders); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateShadersEXT( - VkDevice device, - uint32_t createInfoCount, - const VkShaderCreateInfoEXT* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkShaderEXT* pShaders); - -VKAPI_ATTR void VKAPI_CALL vkDestroyShaderEXT( - VkDevice device, - VkShaderEXT shader, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderBinaryDataEXT( - VkDevice device, - VkShaderEXT shader, - size_t* pDataSize, - void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindShadersEXT( - VkCommandBuffer commandBuffer, - uint32_t stageCount, - const VkShaderStageFlagBits* pStages, - const VkShaderEXT* pShaders); -#endif - - -// VK_QCOM_tile_properties is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_tile_properties 1 #define VK_QCOM_TILE_PROPERTIES_SPEC_VERSION 1 #define VK_QCOM_TILE_PROPERTIES_EXTENSION_NAME "VK_QCOM_tile_properties" @@ -17427,7 +16326,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetDynamicRenderingTilePropertiesQCOM( #endif -// VK_SEC_amigo_profiling is a preprocessor guard. Do not pass it to API calls. #define VK_SEC_amigo_profiling 1 #define VK_SEC_AMIGO_PROFILING_SPEC_VERSION 1 #define VK_SEC_AMIGO_PROFILING_EXTENSION_NAME "VK_SEC_amigo_profiling" @@ -17446,7 +16344,6 @@ typedef struct VkAmigoProfilingSubmitInfoSEC { -// VK_QCOM_multiview_per_view_viewports is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_multiview_per_view_viewports 1 #define VK_QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_SPEC_VERSION 1 #define VK_QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_EXTENSION_NAME "VK_QCOM_multiview_per_view_viewports" @@ -17458,7 +16355,6 @@ typedef struct VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM { -// VK_NV_ray_tracing_invocation_reorder is a preprocessor guard. Do not pass it to API calls. #define VK_NV_ray_tracing_invocation_reorder 1 #define VK_NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION 1 #define VK_NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME "VK_NV_ray_tracing_invocation_reorder" @@ -17482,13 +16378,11 @@ typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV { -// VK_EXT_mutable_descriptor_type is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_mutable_descriptor_type 1 #define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 #define VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_EXT_mutable_descriptor_type" -// VK_ARM_shader_core_builtins is a preprocessor guard. Do not pass it to API calls. #define VK_ARM_shader_core_builtins 1 #define VK_ARM_SHADER_CORE_BUILTINS_SPEC_VERSION 2 #define VK_ARM_SHADER_CORE_BUILTINS_EXTENSION_NAME "VK_ARM_shader_core_builtins" @@ -17508,69 +16402,6 @@ typedef struct VkPhysicalDeviceShaderCoreBuiltinsPropertiesARM { -// VK_EXT_pipeline_library_group_handles is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_pipeline_library_group_handles 1 -#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_SPEC_VERSION 1 -#define VK_EXT_PIPELINE_LIBRARY_GROUP_HANDLES_EXTENSION_NAME "VK_EXT_pipeline_library_group_handles" -typedef struct VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 pipelineLibraryGroupHandles; -} VkPhysicalDevicePipelineLibraryGroupHandlesFeaturesEXT; - - - -// VK_EXT_dynamic_rendering_unused_attachments is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_dynamic_rendering_unused_attachments 1 -#define VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_SPEC_VERSION 1 -#define VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME "VK_EXT_dynamic_rendering_unused_attachments" -typedef struct VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 dynamicRenderingUnusedAttachments; -} VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT; - - - -// VK_QCOM_multiview_per_view_render_areas is a preprocessor guard. Do not pass it to API calls. -#define VK_QCOM_multiview_per_view_render_areas 1 -#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_SPEC_VERSION 1 -#define VK_QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME "VK_QCOM_multiview_per_view_render_areas" -typedef struct VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM { - VkStructureType sType; - void* pNext; - VkBool32 multiviewPerViewRenderAreas; -} VkPhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM; - -typedef struct VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM { - VkStructureType sType; - const void* pNext; - uint32_t perViewRenderAreaCount; - const VkRect2D* pPerViewRenderAreas; -} VkMultiviewPerViewRenderAreasRenderPassBeginInfoQCOM; - - - -// VK_EXT_attachment_feedback_loop_dynamic_state is a preprocessor guard. Do not pass it to API calls. -#define VK_EXT_attachment_feedback_loop_dynamic_state 1 -#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_SPEC_VERSION 1 -#define VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_attachment_feedback_loop_dynamic_state" -typedef struct VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 attachmentFeedbackLoopDynamicState; -} VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT; - -typedef void (VKAPI_PTR *PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)(VkCommandBuffer commandBuffer, VkImageAspectFlags aspectMask); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetAttachmentFeedbackLoopEnableEXT( - VkCommandBuffer commandBuffer, - VkImageAspectFlags aspectMask); -#endif - - -// VK_KHR_acceleration_structure is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_acceleration_structure 1 #define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 #define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" @@ -17846,7 +16677,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( #endif -// VK_KHR_ray_tracing_pipeline is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_ray_tracing_pipeline 1 #define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 #define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" @@ -17983,7 +16813,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( #endif -// VK_KHR_ray_query is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_ray_query 1 #define VK_KHR_RAY_QUERY_SPEC_VERSION 1 #define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" @@ -17995,7 +16824,6 @@ typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { -// VK_EXT_mesh_shader is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_mesh_shader 1 #define VK_EXT_MESH_SHADER_SPEC_VERSION 1 #define VK_EXT_MESH_SHADER_EXTENSION_NAME "VK_EXT_mesh_shader" diff --git a/ext/vulkan/vulkan_directfb.h b/ext/vulkan/vulkan_directfb.h index 1f11a0827..ab3504efa 100644 --- a/ext/vulkan/vulkan_directfb.h +++ b/ext/vulkan/vulkan_directfb.h @@ -2,7 +2,7 @@ #define VULKAN_DIRECTFB_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_EXT_directfb_surface is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_directfb_surface 1 #define VK_EXT_DIRECTFB_SURFACE_SPEC_VERSION 1 #define VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "VK_EXT_directfb_surface" diff --git a/ext/vulkan/vulkan_fuchsia.h b/ext/vulkan/vulkan_fuchsia.h index 76e156483..61774ff9c 100644 --- a/ext/vulkan/vulkan_fuchsia.h +++ b/ext/vulkan/vulkan_fuchsia.h @@ -2,7 +2,7 @@ #define VULKAN_FUCHSIA_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_FUCHSIA_imagepipe_surface is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_imagepipe_surface 1 #define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1 #define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface" @@ -42,7 +41,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA( #endif -// VK_FUCHSIA_external_memory is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_external_memory 1 #define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory" @@ -83,7 +81,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA( #endif -// VK_FUCHSIA_external_semaphore is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_external_semaphore 1 #define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 #define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore" @@ -118,7 +115,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA( #endif -// VK_FUCHSIA_buffer_collection is a preprocessor guard. Do not pass it to API calls. #define VK_FUCHSIA_buffer_collection 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) #define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 2 diff --git a/ext/vulkan/vulkan_ggp.h b/ext/vulkan/vulkan_ggp.h index 9783aa3b3..19dfd2261 100644 --- a/ext/vulkan/vulkan_ggp.h +++ b/ext/vulkan/vulkan_ggp.h @@ -2,7 +2,7 @@ #define VULKAN_GGP_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_GGP_stream_descriptor_surface is a preprocessor guard. Do not pass it to API calls. #define VK_GGP_stream_descriptor_surface 1 #define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1 #define VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME "VK_GGP_stream_descriptor_surface" @@ -42,7 +41,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP( #endif -// VK_GGP_frame_token is a preprocessor guard. Do not pass it to API calls. #define VK_GGP_frame_token 1 #define VK_GGP_FRAME_TOKEN_SPEC_VERSION 1 #define VK_GGP_FRAME_TOKEN_EXTENSION_NAME "VK_GGP_frame_token" diff --git a/ext/vulkan/vulkan_ios.h b/ext/vulkan/vulkan_ios.h index 211429ff4..579220543 100644 --- a/ext/vulkan/vulkan_ios.h +++ b/ext/vulkan/vulkan_ios.h @@ -2,7 +2,7 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_MVK_ios_surface is a preprocessor guard. Do not pass it to API calls. #define VK_MVK_ios_surface 1 #define VK_MVK_IOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" diff --git a/ext/vulkan/vulkan_macos.h b/ext/vulkan/vulkan_macos.h index c6509cc8c..8e197c7cf 100644 --- a/ext/vulkan/vulkan_macos.h +++ b/ext/vulkan/vulkan_macos.h @@ -2,7 +2,7 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_MVK_macos_surface is a preprocessor guard. Do not pass it to API calls. #define VK_MVK_macos_surface 1 #define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" diff --git a/ext/vulkan/vulkan_metal.h b/ext/vulkan/vulkan_metal.h index 94563a003..11b964091 100644 --- a/ext/vulkan/vulkan_metal.h +++ b/ext/vulkan/vulkan_metal.h @@ -2,7 +2,7 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_EXT_metal_surface is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_metal_surface 1 #ifdef __OBJC__ @class CAMetalLayer; @@ -48,7 +47,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT( #endif -// VK_EXT_metal_objects is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_metal_objects 1 #ifdef __OBJC__ @protocol MTLDevice; diff --git a/ext/vulkan/vulkan_screen.h b/ext/vulkan/vulkan_screen.h index 981738f73..f0ef40a6c 100644 --- a/ext/vulkan/vulkan_screen.h +++ b/ext/vulkan/vulkan_screen.h @@ -2,7 +2,7 @@ #define VULKAN_SCREEN_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_QNX_screen_surface is a preprocessor guard. Do not pass it to API calls. #define VK_QNX_screen_surface 1 #define VK_QNX_SCREEN_SURFACE_SPEC_VERSION 1 #define VK_QNX_SCREEN_SURFACE_EXTENSION_NAME "VK_QNX_screen_surface" @@ -48,59 +47,6 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceScreenPresentationSupportQNX( struct _screen_window* window); #endif - -// VK_QNX_external_memory_screen_buffer is a preprocessor guard. Do not pass it to API calls. -#define VK_QNX_external_memory_screen_buffer 1 -#define VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_SPEC_VERSION 1 -#define VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_EXTENSION_NAME "VK_QNX_external_memory_screen_buffer" -typedef struct VkScreenBufferPropertiesQNX { - VkStructureType sType; - void* pNext; - VkDeviceSize allocationSize; - uint32_t memoryTypeBits; -} VkScreenBufferPropertiesQNX; - -typedef struct VkScreenBufferFormatPropertiesQNX { - VkStructureType sType; - void* pNext; - VkFormat format; - uint64_t externalFormat; - uint64_t screenUsage; - VkFormatFeatureFlags formatFeatures; - VkComponentMapping samplerYcbcrConversionComponents; - VkSamplerYcbcrModelConversion suggestedYcbcrModel; - VkSamplerYcbcrRange suggestedYcbcrRange; - VkChromaLocation suggestedXChromaOffset; - VkChromaLocation suggestedYChromaOffset; -} VkScreenBufferFormatPropertiesQNX; - -typedef struct VkImportScreenBufferInfoQNX { - VkStructureType sType; - const void* pNext; - struct _screen_buffer* buffer; -} VkImportScreenBufferInfoQNX; - -typedef struct VkExternalFormatQNX { - VkStructureType sType; - void* pNext; - uint64_t externalFormat; -} VkExternalFormatQNX; - -typedef struct VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX { - VkStructureType sType; - void* pNext; - VkBool32 screenBufferImport; -} VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX; - -typedef VkResult (VKAPI_PTR *PFN_vkGetScreenBufferPropertiesQNX)(VkDevice device, const struct _screen_buffer* buffer, VkScreenBufferPropertiesQNX* pProperties); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkGetScreenBufferPropertiesQNX( - VkDevice device, - const struct _screen_buffer* buffer, - VkScreenBufferPropertiesQNX* pProperties); -#endif - #ifdef __cplusplus } #endif diff --git a/ext/vulkan/vulkan_vi.h b/ext/vulkan/vulkan_vi.h index c9227e822..0355e7a16 100644 --- a/ext/vulkan/vulkan_vi.h +++ b/ext/vulkan/vulkan_vi.h @@ -2,7 +2,7 @@ #define VULKAN_VI_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_NN_vi_surface is a preprocessor guard. Do not pass it to API calls. #define VK_NN_vi_surface 1 #define VK_NN_VI_SURFACE_SPEC_VERSION 1 #define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface" diff --git a/ext/vulkan/vulkan_wayland.h b/ext/vulkan/vulkan_wayland.h index c93b21787..9afd0b76d 100644 --- a/ext/vulkan/vulkan_wayland.h +++ b/ext/vulkan/vulkan_wayland.h @@ -2,7 +2,7 @@ #define VULKAN_WAYLAND_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_KHR_wayland_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_wayland_surface 1 #define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 #define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" diff --git a/ext/vulkan/vulkan_win32.h b/ext/vulkan/vulkan_win32.h index fae3b8532..a8e46c89b 100644 --- a/ext/vulkan/vulkan_win32.h +++ b/ext/vulkan/vulkan_win32.h @@ -2,7 +2,7 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_KHR_win32_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_win32_surface 1 #define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 #define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" @@ -48,7 +47,6 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( #endif -// VK_KHR_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_memory_win32 1 #define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" @@ -98,7 +96,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( #endif -// VK_KHR_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_win32_keyed_mutex 1 #define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 #define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" @@ -116,7 +113,6 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { -// VK_KHR_external_semaphore_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_semaphore_win32 1 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" @@ -169,7 +165,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( #endif -// VK_KHR_external_fence_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_external_fence_win32 1 #define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" @@ -213,7 +208,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( #endif -// VK_NV_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. #define VK_NV_external_memory_win32 1 #define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" @@ -242,7 +236,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( #endif -// VK_NV_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. #define VK_NV_win32_keyed_mutex 1 #define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2 #define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" @@ -260,7 +253,6 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { -// VK_EXT_full_screen_exclusive is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_full_screen_exclusive 1 #define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4 #define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive" @@ -317,7 +309,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT( #endif -// VK_NV_acquire_winrt_display is a preprocessor guard. Do not pass it to API calls. #define VK_NV_acquire_winrt_display 1 #define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 #define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" diff --git a/ext/vulkan/vulkan_xcb.h b/ext/vulkan/vulkan_xcb.h index de7405524..68e61b88f 100644 --- a/ext/vulkan/vulkan_xcb.h +++ b/ext/vulkan/vulkan_xcb.h @@ -2,7 +2,7 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_KHR_xcb_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_xcb_surface 1 #define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 #define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" diff --git a/ext/vulkan/vulkan_xlib.h b/ext/vulkan/vulkan_xlib.h index 1aa632f2e..ea5360ab6 100644 --- a/ext/vulkan/vulkan_xlib.h +++ b/ext/vulkan/vulkan_xlib.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_KHR_xlib_surface is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_xlib_surface 1 #define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 #define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" diff --git a/ext/vulkan/vulkan_xlib_xrandr.h b/ext/vulkan/vulkan_xlib_xrandr.h index e164ffc91..8fc35cfc5 100644 --- a/ext/vulkan/vulkan_xlib_xrandr.h +++ b/ext/vulkan/vulkan_xlib_xrandr.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_XRANDR_H_ 1 /* -** Copyright 2015-2023 The Khronos Group Inc. +** Copyright 2015-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,6 @@ extern "C" { -// VK_EXT_acquire_xlib_display is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_acquire_xlib_display 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display" diff --git a/ffmpeg b/ffmpeg index 82049cca2..98973e62e 160000 --- a/ffmpeg +++ b/ffmpeg @@ -1 +1 @@ -Subproject commit 82049cca2e4c1516ed00a77b502a21f91b7843f4 +Subproject commit 98973e62e0653fcac12f277838ff3d76e786722b diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 551176cbc..44b7bb81f 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -70,22 +70,22 @@ class PrintfLogger : public LogListener { public: void Log(const LogMessage &message) override { switch (message.level) { - case LogLevel::LVERBOSE: + case LogTypes::LVERBOSE: fprintf(stderr, "V %s", message.msg.c_str()); break; - case LogLevel::LDEBUG: + case LogTypes::LDEBUG: fprintf(stderr, "D %s", message.msg.c_str()); break; - case LogLevel::LINFO: + case LogTypes::LINFO: fprintf(stderr, "I %s", message.msg.c_str()); break; - case LogLevel::LERROR: + case LogTypes::LERROR: fprintf(stderr, "E %s", message.msg.c_str()); break; - case LogLevel::LWARNING: + case LogTypes::LWARNING: fprintf(stderr, "W %s", message.msg.c_str()); break; - case LogLevel::LNOTICE: + case LogTypes::LNOTICE: default: fprintf(stderr, "N %s", message.msg.c_str()); break; @@ -94,7 +94,8 @@ public: }; // Temporary hacks around annoying linking errors. -void NativeFrame(GraphicsContext *graphicsContext) { } +void NativeUpdate() { } +void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } std::string System_GetProperty(SystemProperty prop) { return ""; } @@ -116,7 +117,8 @@ bool System_GetPropertyBool(SystemProperty prop) { } } void System_Notify(SystemNotification notification) {} -void System_PostUIMessage(UIMessage message, const std::string ¶m) {} +void System_PostUIMessage(const std::string &message, const std::string ¶m) {} +void System_NotifyUserMessage(const std::string &message, float duration, u32 color, const char *id) {} bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::SEND_DEBUG_OUTPUT: @@ -131,9 +133,8 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return true; } return false; - default: - return false; } + return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} @@ -142,12 +143,6 @@ void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\ void System_AudioClear() {} void System_AudioPushSamples(const s32 *audio, int numSamples) {} -// TODO: To avoid having to define these here, these should probably be turned into system "requests". -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; } -std::string NativeLoadSecret(const char *nameOfSecret) { - return ""; -} - int printUsage(const char *progname, const char *reason) { if (reason != NULL) @@ -233,12 +228,12 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const System_Notify(SystemNotification::BOOT_DONE); - Core_UpdateDebugStats((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS || g_Config.bLogFrameDrops); + Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops); PSP_BeginHostFrame(); Draw::DrawContext *draw = coreParameter.graphicsContext ? coreParameter.graphicsContext->GetDrawContext() : nullptr; if (draw) - draw->BeginFrame(Draw::DebugFlags::NONE); + draw->BeginFrame(); bool passed = true; double deadline = time_now_d() + opt.timeout; @@ -365,10 +360,8 @@ int main(int argc, const char* argv[]) cpuCore = CPUCore::INTERPRETER; else if (!strcmp(argv[i], "-j")) cpuCore = CPUCore::JIT; - else if (!strcmp(argv[i], "--jit-ir")) - cpuCore = CPUCore::JIT_IR; else if (!strcmp(argv[i], "--ir")) - cpuCore = CPUCore::IR_INTERPRETER; + cpuCore = CPUCore::IR_JIT; else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) testOptions.compare = true; else if (!strcmp(argv[i], "--bench")) @@ -428,10 +421,10 @@ int main(int argc, const char* argv[]) PrintfLogger *printfLogger = new PrintfLogger(); - for (int i = 0; i < (int)LogType::NUMBER_OF_LOGS; i++) { - LogType type = (LogType)i; + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { + LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; logman->SetEnabled(type, fullLog); - logman->SetLogLevel(type, LogLevel::LDEBUG); + logman->SetLogLevel(type, LogTypes::LDEBUG); } logman->AddListener(printfLogger); @@ -472,6 +465,7 @@ int main(int argc, const char* argv[]) g_Config.bHardwareTransform = true; g_Config.iAnisotropyLevel = 0; // When testing mipmapping we really don't want this. g_Config.iMultiSampleLevel = 0; + g_Config.bVertexCache = false; g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; g_Config.iTimeFormat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; g_Config.bEncryptSave = true; @@ -497,22 +491,20 @@ int main(int argc, const char* argv[]) g_Config.iPSPModel = PSP_MODEL_SLIM; g_Config.iGlobalVolume = VOLUME_FULL; g_Config.iReverbVolume = VOLUME_FULL; - g_Config.internalDataDirectory.clear(); - - Path exePath = File::GetExeDirectory(); - g_Config.flash0Directory = exePath / "assets/flash0"; #if PPSSPP_PLATFORM(WINDOWS) - // Mount a filesystem - g_Config.memStickDirectory = exePath / "memstick"; - File::CreateDir(g_Config.memStickDirectory); - CreateSysDirectories(); -#elif !PPSSPP_PLATFORM(ANDROID) + g_Config.internalDataDirectory.clear(); + InitSysDirectories(); +#endif + + Path executablePath = File::GetExeDirectory(); +#if !PPSSPP_PLATFORM(ANDROID) && !PPSSPP_PLATFORM(WINDOWS) g_Config.memStickDirectory = Path(std::string(getenv("HOME"))) / ".ppsspp"; + g_Config.flash0Directory = executablePath / "assets/flash0"; #endif // Try to find the flash0 directory. Often this is from a subdirectory. - Path nextPath = exePath; + Path nextPath = executablePath; for (int i = 0; i < 5; ++i) { if (File::Exists(nextPath / "assets/flash0")) { g_Config.flash0Directory = nextPath / "assets/flash0"; diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index b500d26de..7329860ba 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -191,7 +191,7 @@ Console true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -225,7 +225,7 @@ Console true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9d.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -258,7 +258,7 @@ Console true - winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib @@ -289,7 +289,7 @@ Console true - winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib @@ -323,7 +323,7 @@ true true true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -362,7 +362,7 @@ true true true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;d3dx9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) 0x00400000 false true @@ -400,7 +400,7 @@ true true true - winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib;%(AdditionalLibraryDirectories) @@ -435,7 +435,7 @@ true true true - winhttp.lib;ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) + ole32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;shell32.lib;advapi32.lib;gdi32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib;%(AdditionalLibraryDirectories) @@ -502,18 +502,12 @@ {edfa2e87-8ac1-4853-95d4-d7594ff81947} - - {956f1f48-b612-46d8-89ee-96996dcd9383} - {3baae095-e0ab-4b0e-b5df-ce39c8ae31de} {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} - - {31694510-a8c0-40f6-b09b-e8df825adefa} - {457f45d2-556f-47bc-a31d-aff0d15beaed} diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index df2218587..7333e4646 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -95,6 +95,8 @@ public: void Shutdown() override {} void Resize() override {} + void SwapInterval(int interval) override {} + void SwapBuffers() override {} private: Draw::DrawContext *draw_ = nullptr; @@ -156,7 +158,7 @@ bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) { #endif CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(false); + draw_ = Draw::T3DCreateGLContext(); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); @@ -164,7 +166,8 @@ bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) { _assert_(success); renderManager_->SetSwapFunction([&]() { SDL_GL_SwapWindow(screen_); - }); + }, false); + return success; } @@ -190,6 +193,7 @@ bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext * if (!gfx_->ThreadFrame()) { break; } + gfx_->SwapBuffers(); } threadState_ = RenderThreadState::STOPPING; @@ -217,6 +221,7 @@ void SDLHeadlessHost::ShutdownGraphics() { } void SDLHeadlessHost::SwapBuffers() { + gfx_->SwapBuffers(); } #endif diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index a4da9eed6..3aef27028 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -132,6 +132,7 @@ bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsConte if (!gfx_->ThreadFrame()) { break; } + gfx_->SwapBuffers(); } threadState_ = RenderThreadState::STOPPING; @@ -172,4 +173,5 @@ void WindowsHeadlessHost::SwapBuffers() { TranslateMessage(&msg); DispatchMessage(&msg); } + gfx_->SwapBuffers(); } diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index 5d5bd0d95..daa380b74 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -25,6 +25,7 @@ #include "Common/CommonWindows.h" +// TODO: Get rid of this junk class WindowsHeadlessHost : public HeadlessHost { public: diff --git a/history.md b/history.md index d09829cdc..153f8f96b 100644 --- a/history.md +++ b/history.md @@ -1,142 +1,5 @@ This is history moved out from README.md, which was getting a bit long. -What's new in 1.14.4 -==================== -* Multiple shader compatibility fixes for older devices/drivers: ([#16710], [#16709], [#16708]) -* A few other minor fixes: ([#16703], [#16706]) - -What's new in 1.14.3 -==================== -* Several crash/hang fixes ([#16690], [#16689], [#16683], [#16685], [#16680], [#16697], [#16681], more) -* Minor UI fixes ([#16698], [#16684], [#16674], [#16677]) -* Fix confirm/cancel button reversal ([#16692]) - -What's new in 1.14.2 -==================== -* Fix Toca/DTM and others (culling) on Mali again ([#16645]) -* Fix line rendering bugs in the homebrew Tempest clone Webfest ([#16656]) -* Assorted cleanup and bugfixes ([#16673], [#16662], [#16655], [#16644], [#16636], [#16639] etc) - -What's new in 1.14.1 -==================== -* Fix black screen in Vulkan on some older Android devices (Android version 7) ([#16599]) -* Fix error message in Medal of Honor ([#16614]) -* Various minor bugfixes ([#16617], [#16609], [#16608], [#16615], [#16619]) -* Add an option to turn off the new transparent menu background ([#16595]) - -What's new in 1.14 -================== -* Massive number of rendering fixes - - Water in Outrun 2006 and DiRT 2 now renders correctly (logic op fixes) ([#15960], [#16208], [#16032], [#16024], [#15967]) - - Split/Second now renders all effects correctly - - Multiple fixes workarounds for clipping/culling, both through clip planes and geometry shaders, fixing - graphical issues in many, many games and getting rid of hacks ([#16142], [#16504], [#16442], [#16383], [#16165], [#16162], [#16049], others) - - Killzone color effect now renders efficiently and correctly (in-game only, not title screen) ([#15934]) - - Ridge Racer speedometers and lens flares fixed ([#16084], [#16188], [#16115]) - - Lens flare effect fixed in Burnout Dominator, Ridge Racer, Colin McRae, several others ([#16014], [#16081], [#16076], [#16073]) - - Shadows in Colin McRae are no longer flickering (side effect of other fixes) - - Spongebob: Yellow Avenger renders correctly (previously very broken) ([#15907], [#15903]) - - Cars: Race-o-Rama, and MX vs ATV Reflex render correctly (at 1x resolution only) ([#15898], [#15907]) - - Asphalt 2 depth occlusion problems fixed ([#15854], [#15853]) - - Fix performance regression in Juiced 2 while also fixing the graphics ([#15888]) - - Silent Hill games are less broken ([#16127]) - - Depth occlusion and other problems fixed in Kurohyou (both games) and Ratchet & Clank ([#16454], [#15772], [#15728], [#15859]) - - Misshitsu no Sacrifice intro animation and Macross water rendering fixed (3D texture) ([#15727]) - - Tekken 6 Nancy laser beam fixed, plus line rendering fixes in rRootage and other games ([#16067]) - - Tiger & Bunny, Yu-Gi-Oh, GEB, and PlayView games - JPEG image display issues ([#16179], [#16184], [#15924]) - - Many, many others like Hunter x Hunter, Crash: Mind over Mutant, Boundless Trails, etc. ([#16265], [#16043], [#16379], [#15822], [#16358]) -* Software renderer performance and accuracy improvements - - Better performance ([#15998], [#16001], [#16011], [#16039], [#16054], [#16080], [#16085], [#16094], [#16102], [#16387], [#16486], [#16502], [#16518]) - - Improved accuracy, clipping ([#15999], [#16005], [#16042], [#16086], [#16117], [#16231], [#16241], [#16265], [#16274], [#16469], [#16470], [#16478], [#16480], [#16485]) -* New features - - Initial VR support added (Quest and PICO only for now, PC in the future) ([#15659], [#15901], [#16246], [#16262], [#16273]) - - MSAA antialiasing added to the Vulkan backend (desktop only) ([#16458]) - - New API for plugins to access aspect ratio, scaling and fast-forward ([#16441]), other new APIs & improvements ([#15748], [#16121], [#16187], [#16198], [#16389]) - - Read texture replacement packs directly from ZIP files ([#16304]) -* UI improvements - - New interactive Display Layout & Effects screen, replacing the old Display Layout Editor ([#16409], [#16415], [#16417], [#16445]) - - Add default shader for LCD persistence simulation ([#16531]) - - Game being played can now be seen as a background in most menus ([#16404], more) - - Reorganize speed hack settings ([#16346], [#16347], [#16348], [#16432]) -* Stability fixes - - Workaround for hangs on older Adreno GPUs ([#16422]) - - Input handling fixes for deadzones and touch controls ([#16419], [#16450]) - - Avoid game bugs in Twinbee Portable ([#16388]) and Shining Ark ([#16449]) - - Fixes to D3D9 backend issues ([#15723], [#15815], [#15926], [#16100], [#16232], [#16550]) -* IR interpreter (iOS, etc.) bug fixes - - Metal Gear Solid - Peace Walker no longer bugged out ([#16396]) - - VFPU fixes for Dissidia, others ([#16302], [#16305], [#16306]) -* Performance improvements - - Vulkan bandwidth and synchronization optimizations ([#16434], [#16099], [#16090], [#16072], [#16061], [#16060], [#16035], [#15917]) - - Lighting "ubershader" optimization to prevent hitches ([#16104], [#16111]) - - Assorted minor other improvements ([#15589], [#15843], [#16190]) - - Improve texture replacement memory usage ([#15884], [#16304], [#16314]) - - Texture upscaling speedup and fixes ([#15803], [#16125]) -* Other - - HLE/CPU accuracy improvements helping Brooktown High, Frontier Gate, Madoka Magicka, some language patches ([#16413], [#16070], [#16052], [#15952], [#15957], more) - - Many GE debugger improvements ([#15839], [#15851], [#15894], [#15925], [#15974], [#16007], [#16047], [#16096], [#16201]) - - Optional memory alignment validation in IR mode ([#15879], [#15880]) - - Fix netplay assertion in Cars ([#16089]) - -What's new in 1.13.2 -==================== -* Crashfix on Android 12 when playing certain background music ([#15990]) -* Fix Star Ocean battles in D3D backends ([#15889]) -* Minor fixes that might fix some other crashes - -What's new in 1.13.1 -==================== - -* Confirmation dialog added before change of MAC address ([#15738]) -* IR interpreter regression fixed ([#15739]) -* Fix clearing of replacement texture cache ([#15740]) -* Improved Portuguese-pt translation ([#15734]) -* Fix graphical regression in Split/Second ([#15733]) -* Couple of minor crash fixes - -What's new in 1.13 -================== - -General - -* Fix assorted Android "scoped storage"-related bugs and performance issues ([#15237], [#15487]), etc. -* Analog mapping for fast-forward ([#15645]) -* Major softgpu accuracy fixes and speedups, including a JIT ([#15163], [#15345], [#15389], [#15529], [#15440], [#15410], [#15405], [#15400]) and many, many more -* Fixed some NEON code paths ([#15481]) -* Fix performance of texture uploads with Vulkan ([#15474]) -* Don't include the large font atlas when we don't need it -* Improved upscaling shaders ([#15566]) -* Vulkan texture upscaling performance improvements ([#15238]), etc. -* Vulkan correctness fixes ([#15217], [#15211]), use the VMA allocator ([#15162]), etc. -* Fixes to depth culling ([#15106]), many more -* Background loading of texture replacement ([#15025]) -* Threading manager improvements and fixes ([#15470]), etc. -* Added search in settings ([#14414]) -* Added fast button repeats on custom touch buttons ([#15613]) -* Two new bicubic upscaling shader: Catmull-Rom and Mitchell-Netravali ([#15569]) -* Allow to change screen rotation per game and to bind a key to change it ([#15494], [#15510]) -* Re-enabled software rendering option on Android ([#12958]) - -Game fixes - -* Add more workarounds for Mali driver bugs ([#15016]) -* Vortex in God of War: Ghost of Sparta can now be passed ([#15640]) -* Various proAdhoc fixes ([#15213], [#15215]), and many more -* Correct flickering text in Sol Trigger and Last Ranker. ([#15549]) -* Fix and improve line drawing in Echochrome ([#15583]), after line refactoring ([#15073], [#15075]) -* Fix HUD graphics in Split/Second ([#15500], [#15501]) -* Fix bad screen overlay issues in Clone Wars and Force Unleashed ([#15691], [#15696], [#12949], [#9572]) -* Zettai Zetsumei Toshi 3 no longer hangs on character select screen ([#15687]) -* Juiced 2: Bloom effect no longer covering the screen ([#7295], [#15717]) -* Fix keyboard shift issue in a few games ([#15698]) - -UI - -* Windows/Xbox UWP directory navigation improvements ([#15652]) -* Color change and basic theme support ([#15396], [#15394]) -* Fix input focus bug ([#15560]) -* New GE debugger features and other UI fixes ([#15393], [#15324], [#15377], [#15424], [#15402], [#15378], [#15338]), etc. - What's new in 1.12.3 ==================== * Fix background music speed. A couple translation fixes. @@ -1064,239 +927,4 @@ go to see there http://forums.ppsspp.org/showthread.php?tid=3595&pid=59241#pid59 [#14492]: https://github.com/hrydgard/ppsspp/issues/14492 "[AdhocGameMode] Create GameMode's socket after Master and all Replicas have been created" [#14513]: https://github.com/hrydgard/ppsspp/issues/14513 "[Adhoc] Reducing HLE delays due to Mutiplayer performance regressions" [#14849]: https://github.com/hrydgard/ppsspp/issues/14849 "[Adhoc] Fix Socket error 10014 on Windows when hosting a game of Vulcanus Seek and Destroy" -[#11974]: https://github.com/hrydgard/ppsspp/issues/11974 "[Linux] [Vulkan] Toggle fullscreen doesn't update display properly" -[#16710]: https://github.com/hrydgard/ppsspp/issues/16710 "GLES: Use uint for uint shift amounts" -[#16709]: https://github.com/hrydgard/ppsspp/issues/16709 "Correct some shader errors in reporting" -[#16708]: https://github.com/hrydgard/ppsspp/issues/16708 "Additional fixes from both our reports and Play reports" -[#16703]: https://github.com/hrydgard/ppsspp/issues/16703 "Minor fixes based on the latest Google Play report" -[#16706]: https://github.com/hrydgard/ppsspp/issues/16706 "softgpu: Fix lighting with 0 exp" -[#16690]: https://github.com/hrydgard/ppsspp/issues/16690 "softgpu: Detect binner alloc fail and bail" -[#16689]: https://github.com/hrydgard/ppsspp/issues/16689 "Vulkan: Avoid race in compile thread exit" -[#16683]: https://github.com/hrydgard/ppsspp/issues/16683 "Assorted fixes after looking at crash data" -[#16685]: https://github.com/hrydgard/ppsspp/issues/16685 "Replacement: Verify out stride" -[#16680]: https://github.com/hrydgard/ppsspp/issues/16680 "Make sure we don't multithread libzip access" -[#16697]: https://github.com/hrydgard/ppsspp/issues/16697 "Check for valid memory range when doing fast bone matrix loads" -[#16681]: https://github.com/hrydgard/ppsspp/issues/16681 "Cleanup some mic data reading" -[#16698]: https://github.com/hrydgard/ppsspp/issues/16698 "Screen background fixes" -[#16684]: https://github.com/hrydgard/ppsspp/issues/16684 "Enabled CPU breakpoints unchecked" -[#16674]: https://github.com/hrydgard/ppsspp/issues/16674 "Broken menus after using Break on Load" -[#16677]: https://github.com/hrydgard/ppsspp/issues/16677 "D3D11: Fix Draw state issues on pause screen" -[#16692]: https://github.com/hrydgard/ppsspp/issues/16692 "Dialog: Fix confirm/cancel button reversal" -[#16645]: https://github.com/hrydgard/ppsspp/issues/16645 "Fix vertex shader range culling - the driver bug check was wrong." -[#16656]: https://github.com/hrydgard/ppsspp/issues/16656 "Fix rendering of lines with the same x/y but different z." -[#16673]: https://github.com/hrydgard/ppsspp/issues/16673 "Show bluescreen properly on memory errors that we failed to ignore." -[#16662]: https://github.com/hrydgard/ppsspp/issues/16662 "Correct some reversed dependencies, minor other cleanup" -[#16655]: https://github.com/hrydgard/ppsspp/issues/16655 "OpenXR - Force flat mode for Madden NFL games" -[#16644]: https://github.com/hrydgard/ppsspp/issues/16644 "Additional Android cleanup" -[#16636]: https://github.com/hrydgard/ppsspp/issues/16636 "Crash: Ensure we never handle faults in faults" -[#16639]: https://github.com/hrydgard/ppsspp/issues/16639 "Minor initialization cleanup, setup for Vulkan validation layers on Android" -[#16599]: https://github.com/hrydgard/ppsspp/issues/16599 "Vulkan: Remove the new 0th descriptor set, move everything else back to desc set 0" -[#16614]: https://github.com/hrydgard/ppsspp/issues/16614 "GPU: Keep prevPrim_ set on flush" -[#16617]: https://github.com/hrydgard/ppsspp/issues/16617 "GE Debugger: Prevent double init" -[#16609]: https://github.com/hrydgard/ppsspp/issues/16609 "OpenXR - Rendering fixes for a few games" -[#16608]: https://github.com/hrydgard/ppsspp/issues/16608 "Cleanup value corrections in config load/save" -[#16615]: https://github.com/hrydgard/ppsspp/issues/16615 "D3D9: Support old-style user clip planes" -[#16619]: https://github.com/hrydgard/ppsspp/issues/16619 "Debugger: Don't hang memory dump if stepping in GE" -[#16595]: https://github.com/hrydgard/ppsspp/issues/16595 "Transparent background option" -[#15960]: https://github.com/hrydgard/ppsspp/issues/15960 "Enable logic op emulation in-shader" -[#16208]: https://github.com/hrydgard/ppsspp/issues/16208 "GPU: Respect stencil state in shader blend" -[#16032]: https://github.com/hrydgard/ppsspp/issues/16032 "Fix the water in Outrun when no logic ops" -[#16024]: https://github.com/hrydgard/ppsspp/issues/16024 "GPU: Fix simulating logicop with blend and shader" -[#15967]: https://github.com/hrydgard/ppsspp/issues/15967 "Fix BlueToAlpha mode, re-enable it for Outrun and DiRT" -[#16142]: https://github.com/hrydgard/ppsspp/issues/16142 "Implement geometry shader for range culling" -[#16504]: https://github.com/hrydgard/ppsspp/issues/16504 "GPU: Use accurate depth for depth range hack" -[#16442]: https://github.com/hrydgard/ppsspp/issues/16442 "Vulkan: Only use geometry shaders with accurate depth" -[#16383]: https://github.com/hrydgard/ppsspp/issues/16383 "GPU: Automatically reduce depth range on == test" -[#16165]: https://github.com/hrydgard/ppsspp/issues/16165 "Vulkan: Clip clamped depth in geometry shader" -[#16162]: https://github.com/hrydgard/ppsspp/issues/16162 "Implement negative Z clipping in geometry shader" -[#16049]: https://github.com/hrydgard/ppsspp/issues/16049 "GPU: Clip depth properly when also clamping" -[#15934]: https://github.com/hrydgard/ppsspp/issues/15934 "Split the main framebuffer in Killzone, to avoid texturing-from-current-rendertarget" -[#16084]: https://github.com/hrydgard/ppsspp/issues/16084 "Fix Ridge Racer lens flares - ignore stride if texHeight == 1, when matching tex/fb" -[#16188]: https://github.com/hrydgard/ppsspp/issues/16188 "Fix depal bounds with dynamic CLUT. Fixes lens flare glitches in Ridge Racer" -[#16115]: https://github.com/hrydgard/ppsspp/issues/16115 "Add compatibility flag for loading pixels on framebuffer create using nearest filtering" -[#16014]: https://github.com/hrydgard/ppsspp/issues/16014 "Texture depal using CLUT loaded from framebuffers, and more. Fixes Burnout Dominator lens flare" -[#16081]: https://github.com/hrydgard/ppsspp/issues/16081 "Fix green flashes with Burnout Dominator lens flare" -[#16076]: https://github.com/hrydgard/ppsspp/issues/16076 "Don't try to replace or scale CLUT8-on-GPU textures." -[#16073]: https://github.com/hrydgard/ppsspp/issues/16073 "CLUTs can be loaded from small rectangular textures. Need to linearize." -[#15907]: https://github.com/hrydgard/ppsspp/issues/15907 "Reinterpret between 32 and 16 bit texture formats" -[#15903]: https://github.com/hrydgard/ppsspp/issues/15903 "Remove support for framebuffers changing stride (already unreachable)." -[#15898]: https://github.com/hrydgard/ppsspp/issues/15898 "Rendering issues in Tantalus Media games (Spongebob, MX ATV, etc)" -[#15854]: https://github.com/hrydgard/ppsspp/issues/15854 "Use sequence numbers instead of a tracking array for depth buffers" -[#15853]: https://github.com/hrydgard/ppsspp/issues/15853 "Framebuffer-bind sequence numbers" -[#15888]: https://github.com/hrydgard/ppsspp/issues/15888 "Copy color from overlapping framebuffers on bind, under certain conditions" -[#16127]: https://github.com/hrydgard/ppsspp/issues/16127 "Fixes for Silent Hill: Origins (depth buffer reassignment, eliminate readback)" -[#16454]: https://github.com/hrydgard/ppsspp/issues/16454 "GPU: Support framebuf depal from rendered CLUT" -[#15772]: https://github.com/hrydgard/ppsspp/issues/15772 "Add support for binding the depth buffer as a color target. Fixes Kurohyo depth sorting" -[#15728]: https://github.com/hrydgard/ppsspp/issues/15728 "Better ways to deal with overlapping render targets" -[#15859]: https://github.com/hrydgard/ppsspp/issues/15859 "Allow binding depth as 565" -[#15727]: https://github.com/hrydgard/ppsspp/issues/15727 "Implement the PSP's equal-size mips \"3D texturing\"" -[#16067]: https://github.com/hrydgard/ppsspp/issues/16067 "GPU: Account for w properly in lines, fixing width" -[#16179]: https://github.com/hrydgard/ppsspp/issues/16179 "Correct size and YUV order for jpeg decoding" -[#16184]: https://github.com/hrydgard/ppsspp/issues/16184 "GPU: Hook Gods Eater Burst avatar read" -[#15924]: https://github.com/hrydgard/ppsspp/issues/15924 "Add support for reading depth buffers to the PackFramebufferSync function" -[#16265]: https://github.com/hrydgard/ppsspp/issues/16265 "GPU: Respect world matrix and reverse flag w/o normals" -[#16043]: https://github.com/hrydgard/ppsspp/issues/16043 "Consider the Adreno and Mali stencil-discard bugs the same." -[#16379]: https://github.com/hrydgard/ppsspp/issues/16379 "Fix alpha/stencil replace on Adreno when color masked" -[#15822]: https://github.com/hrydgard/ppsspp/issues/15822 "GPU: Write stencil fail to alpha is RGB masked" -[#16358]: https://github.com/hrydgard/ppsspp/issues/16358 "TexCache: Fix 16->32 colors with CLUT start pos" -[#15998]: https://github.com/hrydgard/ppsspp/issues/15998 "softgpu: Allow almost flat rectangles to go fast" -[#16001]: https://github.com/hrydgard/ppsspp/issues/16001 "softgpu: Check depth test early on simple stencil" -[#16011]: https://github.com/hrydgard/ppsspp/issues/16011 "Detect more triangles as rectangles in softgpu" -[#16039]: https://github.com/hrydgard/ppsspp/issues/16039 "softgpu: Run early Z tests in fast rect path" -[#16054]: https://github.com/hrydgard/ppsspp/issues/16054 "softgpu: Reduce some flushing / flushing cost" -[#16080]: https://github.com/hrydgard/ppsspp/issues/16080 "softgpu: Avoid unnecessary flushing for curves" -[#16085]: https://github.com/hrydgard/ppsspp/issues/16085 "softgpu: Cache reused indexed verts" -[#16094]: https://github.com/hrydgard/ppsspp/issues/16094 "softgpu: Optimize rectangle sampling/blending used in bloom" -[#16102]: https://github.com/hrydgard/ppsspp/issues/16102 "softgpu: Avoid waiting for a thread to drain" -[#16387]: https://github.com/hrydgard/ppsspp/issues/16387 "softgpu: Use threads on self-render if safe" -[#16486]: https://github.com/hrydgard/ppsspp/issues/16486 "softgpu: Apply optimizations to states generically" -[#16502]: https://github.com/hrydgard/ppsspp/issues/16502 "A few more softgpu optimizations for alpha blend/test" -[#16518]: https://github.com/hrydgard/ppsspp/issues/16518 "softgpu: Expand fast path to all fb formats" -[#15999]: https://github.com/hrydgard/ppsspp/issues/15999 "softgpu: Clamp/wrap textures at 512 pixels" -[#16005]: https://github.com/hrydgard/ppsspp/issues/16005 "softgpu: Correct accuracy of fog calculation" -[#16042]: https://github.com/hrydgard/ppsspp/issues/16042 "softgpu: Refactor imm prim handling to support fog/color1" -[#16086]: https://github.com/hrydgard/ppsspp/issues/16086 "softgpu: Fix self-render detect in Ridge Racer" -[#16117]: https://github.com/hrydgard/ppsspp/issues/16117 "Correct texture projection issues, mainly in softgpu" -[#16231]: https://github.com/hrydgard/ppsspp/issues/16231 "softgpu: Cull a triangle with all negative w" -[#16241]: https://github.com/hrydgard/ppsspp/issues/16241 "softgpu: Correct linear interp for uneven positions" -[#16274]: https://github.com/hrydgard/ppsspp/issues/16274 "Correct accuracy of bounding box test" -[#16469]: https://github.com/hrydgard/ppsspp/issues/16469 "Correct block transfer overlap and wrapping behavior" -[#16470]: https://github.com/hrydgard/ppsspp/issues/16470 "softgpu: Correctly fix inversions, matching tests" -[#16478]: https://github.com/hrydgard/ppsspp/issues/16478 "softgpu: Interpolate Z for 3D lines" -[#16480]: https://github.com/hrydgard/ppsspp/issues/16480 "softgpu: Cull verts outside post-viewport Z" -[#16485]: https://github.com/hrydgard/ppsspp/issues/16485 "softgpu: Handle infnan fog coefficients better" -[#15659]: https://github.com/hrydgard/ppsspp/issues/15659 "Oculus Quest native support" -[#15901]: https://github.com/hrydgard/ppsspp/issues/15901 "OpenXR - Stereoscopic rendering" -[#16246]: https://github.com/hrydgard/ppsspp/issues/16246 "VR: Add the VR code to all builds. Remove IsVRBuild calls from the renderer." -[#16262]: https://github.com/hrydgard/ppsspp/issues/16262 "OpenXR - Add an option to adjust camera distance" -[#16273]: https://github.com/hrydgard/ppsspp/issues/16273 "Vulkan multiview rendering" -[#16458]: https://github.com/hrydgard/ppsspp/issues/16458 "Implement MSAA support for desktop GPUs in Vulkan" -[#16441]: https://github.com/hrydgard/ppsspp/issues/16441 "Exposed more emulator things to devctl api" -[#15748]: https://github.com/hrydgard/ppsspp/issues/15748 "Windows: Add a simple window message to get the base pointer." -[#16121]: https://github.com/hrydgard/ppsspp/issues/16121 "Debugger: Add API to scan memory for funcs" -[#16187]: https://github.com/hrydgard/ppsspp/issues/16187 "Remote API: hle.func.removeRange added" -[#16198]: https://github.com/hrydgard/ppsspp/issues/16198 "Readback stencil buffer for debugger on GLES" -[#16389]: https://github.com/hrydgard/ppsspp/issues/16389 "Make breakpoints work better in interpreter" -[#16304]: https://github.com/hrydgard/ppsspp/issues/16304 "Improve texture replacement cache and allow read from zip" -[#16409]: https://github.com/hrydgard/ppsspp/issues/16409 "Preserve framebuffer on pause screen even if render resolution is changed" -[#16415]: https://github.com/hrydgard/ppsspp/issues/16415 "Display layout editor - Remove editing widget, just use the background directly" -[#16417]: https://github.com/hrydgard/ppsspp/issues/16417 "Move post processing settings to the Display Layout Editor" -[#16445]: https://github.com/hrydgard/ppsspp/issues/16445 "New screen size controls on Display Layout & Effects screen" -[#16531]: https://github.com/hrydgard/ppsspp/issues/16531 "iota97's \"Motion blur\" - LCD persistence shader, plus fixes to make it work with OpenGL" -[#16404]: https://github.com/hrydgard/ppsspp/issues/16404 "Make the pause screen \"transparent\"" -[#16346]: https://github.com/hrydgard/ppsspp/issues/16346 "Change the \"Retain changed textures\" option into a compat.ini option." -[#16347]: https://github.com/hrydgard/ppsspp/issues/16347 "Always skin in decode for software transform and rendering" -[#16348]: https://github.com/hrydgard/ppsspp/issues/16348 "Speed hack setting reorganization" -[#16432]: https://github.com/hrydgard/ppsspp/issues/16432 "Cleanup graphics settings list" -[#16422]: https://github.com/hrydgard/ppsspp/issues/16422 "Add compat flag / bug check for games on old Adreno/GL affected" -[#16419]: https://github.com/hrydgard/ppsspp/issues/16419 "Stick input: Fix issue where deadzone noise from one device could drown out signal from another." -[#16450]: https://github.com/hrydgard/ppsspp/issues/16450 "UI: Fix right analog with single button" -[#16388]: https://github.com/hrydgard/ppsspp/issues/16388 "Twinbee Portable: Add compat flag to avoid game bug with some languages" -[#16449]: https://github.com/hrydgard/ppsspp/issues/16449 "Blind workaround for Shining Ark circle button problem" -[#15723]: https://github.com/hrydgard/ppsspp/issues/15723 "D3D9 state cache cleanup" -[#15815]: https://github.com/hrydgard/ppsspp/issues/15815 "Depth blit using raster" -[#15926]: https://github.com/hrydgard/ppsspp/issues/15926 "Implement shader blending for D3D9" -[#16100]: https://github.com/hrydgard/ppsspp/issues/16100 "D3D9: Allow INTZ depth buffers more correctly" -[#16232]: https://github.com/hrydgard/ppsspp/issues/16232 "D3D9: Correct scissor state cache in Draw" -[#16550]: https://github.com/hrydgard/ppsspp/issues/16550 "Hide the D3D9 option on Intel Xe graphics." -[#16396]: https://github.com/hrydgard/ppsspp/issues/16396 "Correct misbehavior on uninitialized values in IR" -[#16302]: https://github.com/hrydgard/ppsspp/issues/16302 "Handle vrot overlap and vscl/vmscl prefixes more accurately" -[#16305]: https://github.com/hrydgard/ppsspp/issues/16305 "irjit: Fix unordered float compares" -[#16306]: https://github.com/hrydgard/ppsspp/issues/16306 "irjit: Correct prefix validation" -[#16434]: https://github.com/hrydgard/ppsspp/issues/16434 "Vulkan: Use stencil export when available" -[#16099]: https://github.com/hrydgard/ppsspp/issues/16099 "Vulkan: Avoid allocating depth images for stuff like temp copies, depal buffers etc." -[#16090]: https://github.com/hrydgard/ppsspp/issues/16090 "Simplify synchronization in VulkanRenderManager" -[#16072]: https://github.com/hrydgard/ppsspp/issues/16072 "Vulkan: Don't have renderpasses store/load depth buffers when we don't use them" -[#16061]: https://github.com/hrydgard/ppsspp/issues/16061 "Vulkan: Submit main command buffer before acquiring the swapchain image" -[#16060]: https://github.com/hrydgard/ppsspp/issues/16060 "Vulkan FrameData refactor" -[#16035]: https://github.com/hrydgard/ppsspp/issues/16035 "Vulkan: \"Acquire\" the image from the swapchain as late as possible in the frame" -[#15917]: https://github.com/hrydgard/ppsspp/issues/15917 "Vulkan bandwidth optimizations (configure renderpass load/store better)" -[#16104]: https://github.com/hrydgard/ppsspp/issues/16104 "Generate \"Ubershaders\" that can handle all lighting configurations" -[#16111]: https://github.com/hrydgard/ppsspp/issues/16111 "Always do the vertex shader part of the fog computation." -[#15589]: https://github.com/hrydgard/ppsspp/issues/15589 "Vulkan: Parallelize GLSL compilation" -[#15843]: https://github.com/hrydgard/ppsspp/issues/15843 "GPU: Skip fb create upload when clearing" -[#16190]: https://github.com/hrydgard/ppsspp/issues/16190 "Reduce IO primarily during save operations" -[#15884]: https://github.com/hrydgard/ppsspp/issues/15884 "Replacement: Read files only within time budget" -[#16314]: https://github.com/hrydgard/ppsspp/issues/16314 "UI: Install textures as a zip if supported" -[#15803]: https://github.com/hrydgard/ppsspp/issues/15803 "Reimplement bicubic upscaling." -[#16125]: https://github.com/hrydgard/ppsspp/issues/16125 "Remove alpha ignore in xbrz texture shaders." -[#16413]: https://github.com/hrydgard/ppsspp/issues/16413 "Kernel: Respect partition param in heap funcs" -[#16070]: https://github.com/hrydgard/ppsspp/issues/16070 "Kernel: Match index lookup behavior for tls" -[#16052]: https://github.com/hrydgard/ppsspp/issues/16052 "HLE: sceKernelAllocPartitionMemory volatile memory support (partition 5)" -[#15952]: https://github.com/hrydgard/ppsspp/issues/15952 "interp: Handle jumps in branch delay slots better" -[#15957]: https://github.com/hrydgard/ppsspp/issues/15957 "Handle branch/jump in branch delay slots more accurately" -[#15839]: https://github.com/hrydgard/ppsspp/issues/15839 "GE debugger: Allow displaying two tabs at once, separate DL view" -[#15851]: https://github.com/hrydgard/ppsspp/issues/15851 "After recording a GE dump, open an explorer window pointing at the file" -[#15894]: https://github.com/hrydgard/ppsspp/issues/15894 "GE Debugger: Record only one flip if display framebuf not changed, step on vsync" -[#15925]: https://github.com/hrydgard/ppsspp/issues/15925 "GE Debugger: Improve display list disasm" -[#15974]: https://github.com/hrydgard/ppsspp/issues/15974 "Add breakpoint conditions to GE debugger" -[#16007]: https://github.com/hrydgard/ppsspp/issues/16007 "GE Debugger: Add fields to register expressions" -[#16047]: https://github.com/hrydgard/ppsspp/issues/16047 "GE Debugger: Allow search" -[#16096]: https://github.com/hrydgard/ppsspp/issues/16096 "GE Debugger: Add option to track pixel in preview" -[#16201]: https://github.com/hrydgard/ppsspp/issues/16201 "GE Debugger: Normalize framebuffer texture preview" -[#15879]: https://github.com/hrydgard/ppsspp/issues/15879 "irjit: Validate alignment in slow memory mode" -[#15880]: https://github.com/hrydgard/ppsspp/issues/15880 "Core: Show exception on misaligned jump" -[#16089]: https://github.com/hrydgard/ppsspp/issues/16089 "[AdhocMatching] Fix assertion issue when playing Cars over public adhoc server." -[#15990]: https://github.com/hrydgard/ppsspp/issues/15990 "Atrac3+: Allocate some extra" -[#15889]: https://github.com/hrydgard/ppsspp/issues/15889 "Correct D3D viewport offset sign in sw transform" -[#15738]: https://github.com/hrydgard/ppsspp/issues/15738 "Add confirmation dialog when generating a new Mac address" -[#15739]: https://github.com/hrydgard/ppsspp/issues/15739 "irjit: Correct another PurgeTemps case" -[#15740]: https://github.com/hrydgard/ppsspp/issues/15740 "Replacement: Clear cache on disable" -[#15734]: https://github.com/hrydgard/ppsspp/issues/15734 "Better pt-pt translation" -[#15733]: https://github.com/hrydgard/ppsspp/issues/15733 "Fix bug in blue-to-alpha - alpha blending could be on when it shouldn't be." -[#15237]: https://github.com/hrydgard/ppsspp/issues/15237 "Path: Check for PSP case insensitively" -[#15487]: https://github.com/hrydgard/ppsspp/issues/15487 "Save textures on background tasks when texture dumping is enabled." -[#15645]: https://github.com/hrydgard/ppsspp/issues/15645 "UI: Add analog speed limit mapping" -[#15163]: https://github.com/hrydgard/ppsspp/issues/15163 "Implement a jit for drawing pixels in the software renderer" -[#15345]: https://github.com/hrydgard/ppsspp/issues/15345 "Fix some minor softgpu blending bugs" -[#15389]: https://github.com/hrydgard/ppsspp/issues/15389 "Draw rectangles always using a specialized path in softgpu" -[#15529]: https://github.com/hrydgard/ppsspp/issues/15529 "softgpu: Fix viewport flag clean/dirty" -[#15440]: https://github.com/hrydgard/ppsspp/issues/15440 "softgpu: Plug bad leak of bin queue data" -[#15410]: https://github.com/hrydgard/ppsspp/issues/15410 "softgpu: Remove offset from screenpos, adjust filtering coords" -[#15405]: https://github.com/hrydgard/ppsspp/issues/15405 "Fix some samplerjit issues without SSE4 or AVX" -[#15400]: https://github.com/hrydgard/ppsspp/issues/15400 "softgpu: Track dirty vs really dirty per buffer" -[#15481]: https://github.com/hrydgard/ppsspp/issues/15481 "Fix some NEON code that had bad compile-time checks" -[#15474]: https://github.com/hrydgard/ppsspp/issues/15474 "Merge CheckAlpha into texture decoding" -[#15566]: https://github.com/hrydgard/ppsspp/issues/15566 "Screen upscaling shaders improvements" -[#15238]: https://github.com/hrydgard/ppsspp/issues/15238 "Vulkan: Be more restrictive about hardware texture upscaling on \"slow\" GPUs" -[#15217]: https://github.com/hrydgard/ppsspp/issues/15217 "Vulkan is strict about scissor rect, so let's clamp centrally." -[#15211]: https://github.com/hrydgard/ppsspp/issues/15211 "Vulkan: Specify Vulkan version, fix mip level generation calculation" -[#15162]: https://github.com/hrydgard/ppsspp/issues/15162 "Integrate VMA (Vulkan Memory Allocator)" -[#15106]: https://github.com/hrydgard/ppsspp/issues/15106 "GLES: Explicitly enable ARB_cull_distance" -[#15025]: https://github.com/hrydgard/ppsspp/issues/15025 "Allow delayed loading of texture replacements" -[#15470]: https://github.com/hrydgard/ppsspp/issues/15470 "Threading manager stresstest and fixes" -[#14414]: https://github.com/hrydgard/ppsspp/issues/14414 "Add search for settings" -[#15613]: https://github.com/hrydgard/ppsspp/issues/15613 "Allow to repeat a \"single\" button" -[#15569]: https://github.com/hrydgard/ppsspp/issues/15569 "Upscaling shaders" -[#15494]: https://github.com/hrydgard/ppsspp/issues/15494 "Add key bind to hotswap internal screen rotation" -[#15510]: https://github.com/hrydgard/ppsspp/issues/15510 "Allow to set InternalScreenRotation per game" -[#12958]: https://github.com/hrydgard/ppsspp/issues/12958 "Feature Request: restore software rendering ui setting on android" -[#15016]: https://github.com/hrydgard/ppsspp/issues/15016 "List of games with graphics rendering issues using mali gpu with vulkan backend" -[#15640]: https://github.com/hrydgard/ppsspp/issues/15640 "Disable ForceMax60FPS for GOW games and replace it with fixed 60 fps" -[#15213]: https://github.com/hrydgard/ppsspp/issues/15213 "[Adhoc] Updated PdpCreate, PdpSend, PdpRecv, GetPdpStat, GetPtpStat" -[#15215]: https://github.com/hrydgard/ppsspp/issues/15215 "[Adhocctl] Fix Tekken 5 Dark Resurrection Multiplayer" -[#15549]: https://github.com/hrydgard/ppsspp/issues/15549 "GPU: Hook Sol Trigger func to flush texture" -[#15583]: https://github.com/hrydgard/ppsspp/issues/15583 "Fix and further improve line drawing in Echochrome" -[#15073]: https://github.com/hrydgard/ppsspp/issues/15073 "Cleanup line/point handling and refactor a bit" -[#15075]: https://github.com/hrydgard/ppsspp/issues/15075 "Draw points using triangles" -[#15500]: https://github.com/hrydgard/ppsspp/issues/15500 "Add BlueToAlpha compat.ini workaround, fixes Split/Second graphics" -[#15501]: https://github.com/hrydgard/ppsspp/issues/15501 "Make the existing ReinterpretFramebuffers/ShaderColorBitmask path work for Split/Second" -[#15691]: https://github.com/hrydgard/ppsspp/issues/15691 "Add a simple compat flag to workaround the Clone Wars issue, #12949" -[#15696]: https://github.com/hrydgard/ppsspp/issues/15696 "Use the recent Clone Wars fix for Star Wars: Force Unleashed too" -[#12949]: https://github.com/hrydgard/ppsspp/issues/12949 "Star Wars: The Clone Wars - Graphic glitch [Android/Windows]" -[#9572]: https://github.com/hrydgard/ppsspp/issues/9572 "Star Wars force unleashed [Screen Overlay problem]" -[#15687]: https://github.com/hrydgard/ppsspp/issues/15687 "Add Zettai Zetsumei Toshi 3" -[#7295]: https://github.com/hrydgard/ppsspp/issues/7295 "Juiced 2: Hot Import Nights, screen artifacts and missing half of race tracks" -[#15717]: https://github.com/hrydgard/ppsspp/issues/15717 "Allows \"merging\" render targets that overlap on the Y axis. Fixes Juiced 2" -[#15698]: https://github.com/hrydgard/ppsspp/issues/15698 "Osk: Allow upper/lower for all keyboards" -[#15652]: https://github.com/hrydgard/ppsspp/issues/15652 "Replace Win32 file IO with UWP safe variants and add support for getting drives to UWP build" -[#15396]: https://github.com/hrydgard/ppsspp/issues/15396 "Add UI Tint/Saturation settings" -[#15394]: https://github.com/hrydgard/ppsspp/issues/15394 "Allow custom UI themes" -[#15560]: https://github.com/hrydgard/ppsspp/issues/15560 "UI: Abandon focus movement on returning from pause" -[#15393]: https://github.com/hrydgard/ppsspp/issues/15393 "GE Debugger: Avoid crash on Step Draw with flush" -[#15324]: https://github.com/hrydgard/ppsspp/issues/15324 "UI: Reset ZIP install errors for new ZIPs" -[#15377]: https://github.com/hrydgard/ppsspp/issues/15377 "Debugger: Avoid mem write tag lookup on small alloc" -[#15424]: https://github.com/hrydgard/ppsspp/issues/15424 "Windows: Create SYSTEM directory early" -[#15402]: https://github.com/hrydgard/ppsspp/issues/15402 "GE Debugger: Highlight changed state values" -[#15378]: https://github.com/hrydgard/ppsspp/issues/15378 "GE Debugger: Add filter to skip prim calls" -[#15338]: https://github.com/hrydgard/ppsspp/issues/15338 "Alow flushing at will via the GE debugger" \ No newline at end of file +[#11974]: https://github.com/hrydgard/ppsspp/issues/11974 "[Linux] [Vulkan] Toggle fullscreen doesn't update display properly" \ No newline at end of file diff --git a/ios/AppDelegate.mm b/ios/AppDelegate.mm index 5308edfeb..9f543a55f 100644 --- a/ios/AppDelegate.mm +++ b/ios/AppDelegate.mm @@ -112,7 +112,7 @@ iOSCoreAudioShutdown(); } - System_PostUIMessage(UIMessage::LOST_FOCUS); + NativeMessageReceived("lost_focus", ""); } -(void) applicationDidBecomeActive:(UIApplication *)application { @@ -120,7 +120,7 @@ iOSCoreAudioInit(); } - System_PostUIMessage(UIMessage::GOT_FOCUS); + NativeMessageReceived("got_focus", ""); } - (void)applicationWillTerminate:(UIApplication *)application { diff --git a/ios/SmartKeyboardMap.cpp b/ios/SmartKeyboardMap.cpp index a61fc7da3..43d8e5b46 100644 --- a/ios/SmartKeyboardMap.cpp +++ b/ios/SmartKeyboardMap.cpp @@ -9,7 +9,7 @@ #include "SmartKeyboardMap.hpp" #include "Common/Input/KeyCodes.h" -InputKeyCode getSmartKeyboardMap(int keycode) { +int getSmartKeyboardMap(int keycode) { switch(keycode) { case 4: return NKCODE_A; case 5: return NKCODE_B; @@ -73,6 +73,6 @@ InputKeyCode getSmartKeyboardMap(int keycode) { case 229: return NKCODE_SHIFT_RIGHT; case 230: return NKCODE_META_RIGHT; case 231: return NKCODE_ALT_RIGHT; - default: return NKCODE_UNKNOWN; + default: return 0; } } diff --git a/ios/SmartKeyboardMap.hpp b/ios/SmartKeyboardMap.hpp index fcaa22d96..bf6a3654a 100644 --- a/ios/SmartKeyboardMap.hpp +++ b/ios/SmartKeyboardMap.hpp @@ -6,8 +6,9 @@ // // -#pragma once +#ifndef SmartKeyboardMap_hpp +#define SmartKeyboardMap_hpp -#include "Common/Input/KeyCodes.h" +int getSmartKeyboardMap(int keycode); -InputKeyCode getSmartKeyboardMap(int keycode); +#endif /* SmartKeyboardMap_hpp */ diff --git a/ios/ViewController.mm b/ios/ViewController.mm index c85b8b5ef..359eda075 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -22,7 +22,6 @@ #include "Common/System/Display.h" #include "Common/System/System.h" -#include "Common/System/OSD.h" #include "Common/System/NativeApp.h" #include "Common/File/VFS/VFS.h" #include "Common/Log.h" @@ -49,7 +48,7 @@ class IOSGraphicsContext : public GraphicsContext { public: IOSGraphicsContext() { CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(false); + draw_ = Draw::T3DCreateGLContext(); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); @@ -63,6 +62,8 @@ public: return draw_; } + void SwapInterval(int interval) override {} + void SwapBuffers() override {} void Resize() override {} void Shutdown() override {} @@ -104,7 +105,7 @@ static CameraHelper *cameraHelper; static LocationHelper *locationHelper; @interface ViewController () { - std::map iCadeToKeyMap; + std::map iCadeToKeyMap; } @property (nonatomic, strong) EAGLContext* context; @@ -150,10 +151,6 @@ static LocationHelper *locationHelper; return self; } -- (BOOL)prefersHomeIndicatorAutoHidden { - return YES; -} - - (void)shareText:(NSString *)text { NSArray *items = @[text]; UIActivityViewController * viewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; @@ -204,7 +201,7 @@ extern float g_safeInsetBottom; graphicsContext = new IOSGraphicsContext(); graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) { - g_OSD.Show(OSDType::MESSAGE_ERROR, details, 0.0f, "error_callback"); + System_NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback"); }, nullptr); graphicsContext->ThreadStart(); @@ -236,7 +233,8 @@ extern float g_safeInsetBottom; INFO_LOG(SYSTEM, "Emulation thread starting\n"); while (threadEnabled) { - NativeFrame(graphicsContext); + NativeUpdate(); + NativeRender(graphicsContext); } @@ -462,7 +460,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { break; } axis.deviceId = DEVICE_ID_PAD_0; - NativeAxis(&axis, 1); + NativeAxis(axis); } else { KeyInput key; key.flags = KEY_DOWN; @@ -531,7 +529,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { break; } axis.deviceId = DEVICE_ID_PAD_0; - NativeAxis(&axis, 1); + NativeAxis(axis); } else { KeyInput key; key.flags = KEY_UP; @@ -565,7 +563,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { } } -- (void)controllerButtonPressed:(BOOL)pressed keyCode:(InputKeyCode)keyCode +- (void)controllerButtonPressed:(BOOL)pressed keyCode:(keycode_t)keyCode { KeyInput key; key.deviceId = DEVICE_ID_PAD_0; @@ -689,7 +687,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.deviceId = DEVICE_ID_PAD_0; axisInput.axisId = JOYSTICK_AXIS_X; axisInput.value = value; - NativeAxis(&axisInput, 1); + NativeAxis(axisInput); }; extendedProfile.leftThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *axis, float value) { @@ -697,7 +695,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.deviceId = DEVICE_ID_PAD_0; axisInput.axisId = JOYSTICK_AXIS_Y; axisInput.value = -value; - NativeAxis(&axisInput, 1); + NativeAxis(axisInput); }; // Map right thumbstick as another analog stick, particularly useful for controllers like the DualShock 3/4 when connected to an iOS device @@ -706,7 +704,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.deviceId = DEVICE_ID_PAD_0; axisInput.axisId = JOYSTICK_AXIS_Z; axisInput.value = value; - NativeAxis(&axisInput, 1); + NativeAxis(axisInput); }; extendedProfile.rightThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *axis, float value) { @@ -714,7 +712,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.deviceId = DEVICE_ID_PAD_0; axisInput.axisId = JOYSTICK_AXIS_RZ; axisInput.value = -value; - NativeAxis(&axisInput, 1); + NativeAxis(axisInput); }; } #endif @@ -754,6 +752,10 @@ void stopLocation() { @end +void System_ShowFileInFolder(const char *path) { + // Unsupported +} + void System_LaunchUrl(LaunchUrlType urlType, char const* url) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithCString:url encoding:NSStringEncodingConversionAllowLossy]]]; diff --git a/ios/main.mm b/ios/main.mm index c111208ab..e90b60e8a 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -21,7 +21,6 @@ #include "Common/System/Request.h" #include "Common/StringUtils.h" #include "Common/Profiler/Profiler.h" -#include "Core/Config.h" #include "UI/DarwinFileSystemServices.h" static int (*csops)(pid_t pid, unsigned int ops, void * useraddr, size_t usersize); @@ -109,8 +108,6 @@ std::string System_GetProperty(SystemProperty prop) { return StringFromFormat("iOS %s", version.c_str()); case SYSPROP_LANGREGION: return [[[NSLocale currentLocale] objectForKey:NSLocaleIdentifier] UTF8String]; - case SYSPROP_BUILD_VERSION: - return PPSSPP_GIT_VERSION; default: return ""; } @@ -160,8 +157,6 @@ bool System_GetPropertyBool(SystemProperty prop) { return false; case SYSPROP_HAS_BACK_BUTTON: return false; - case SYSPROP_HAS_ACCELEROMETER: - return true; case SYSPROP_APP_GOLD: #ifdef GOLD return true; @@ -170,10 +165,7 @@ bool System_GetPropertyBool(SystemProperty prop) { #endif case SYSPROP_CAN_JIT: return get_debugged(); -#ifndef HTTPS_NOT_AVAILABLE - case SYSPROP_SUPPORTS_HTTPS: - return true; -#endif + default: return false; } diff --git a/libretro/CMakeLists.txt b/libretro/CMakeLists.txt index 7ebc7a6e1..da76ff3e0 100644 --- a/libretro/CMakeLists.txt +++ b/libretro/CMakeLists.txt @@ -23,7 +23,7 @@ endif() if(NOT MSVC) if (APPLE OR IOS) - target_link_libraries(ppsspp_libretro objc "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libretro.osx.def") + target_link_libraries(ppsspp_libretro "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libretro.osx.def") else() target_link_libraries(ppsspp_libretro "-Wl,-Bsymbolic") endif() diff --git a/libretro/LibretroD3D11Context.cpp b/libretro/LibretroD3D11Context.cpp index 2a9da24dc..82661ab2d 100644 --- a/libretro/LibretroD3D11Context.cpp +++ b/libretro/LibretroD3D11Context.cpp @@ -46,7 +46,7 @@ void LibretroD3D11Context::CreateDrawContext() { ID3D11DeviceContext1 *context1 = nullptr; d3d11_->context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&context1); - draw_ = Draw::T3DCreateD3D11Context(d3d11_->device, d3d11_->context, device1, context1, nullptr, d3d11_->featureLevel, NULL, adapterNames, 3); + draw_ = Draw::T3DCreateD3D11Context(d3d11_->device, d3d11_->context, device1, context1, d3d11_->featureLevel, NULL, adapterNames); } void LibretroD3D11Context::DestroyDrawContext() { diff --git a/libretro/LibretroGLContext.cpp b/libretro/LibretroGLContext.cpp index 240b3e1e1..c820f6675 100644 --- a/libretro/LibretroGLContext.cpp +++ b/libretro/LibretroGLContext.cpp @@ -31,7 +31,7 @@ void LibretroGLContext::CreateDrawContext() { #endif CheckGLExtensions(); - draw_ = Draw::T3DCreateGLContext(false); + draw_ = Draw::T3DCreateGLContext(); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); diff --git a/libretro/LibretroGLCoreContext.cpp b/libretro/LibretroGLCoreContext.cpp index 54e324c4c..66261dea8 100644 --- a/libretro/LibretroGLCoreContext.cpp +++ b/libretro/LibretroGLCoreContext.cpp @@ -26,7 +26,7 @@ void LibretroGLCoreContext::CreateDrawContext() { glewInitDone = true; CheckGLExtensions(); } - draw_ = Draw::T3DCreateGLContext(false); + draw_ = Draw::T3DCreateGLContext(); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); diff --git a/libretro/LibretroGraphicsContext.h b/libretro/LibretroGraphicsContext.h index 958c5218a..ee15e5a1a 100644 --- a/libretro/LibretroGraphicsContext.h +++ b/libretro/LibretroGraphicsContext.h @@ -21,7 +21,7 @@ public: void Shutdown() override { DestroyDrawContext(); } - virtual void SwapBuffers() = 0; + void SwapInterval(int interval) override {} void Resize() override {} virtual void GotBackbuffer(); diff --git a/libretro/LibretroVulkanContext.cpp b/libretro/LibretroVulkanContext.cpp index ccce6c9ad..c7072df17 100644 --- a/libretro/LibretroVulkanContext.cpp +++ b/libretro/LibretroVulkanContext.cpp @@ -139,11 +139,7 @@ void LibretroVulkanContext::CreateDrawContext() { return; } - bool useMultiThreading = g_Config.bRenderMultiThreading; - if (g_Config.iInflightFrames == 1) { - useMultiThreading = false; - } - draw_ = Draw::T3DCreateVulkanContext(vk, useMultiThreading); + draw_ = Draw::T3DCreateVulkanContext(vk); ((VulkanRenderManager*)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER))->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::VULKAN); } diff --git a/libretro/Makefile b/libretro/Makefile index 4625c9da0..4eb5be6e8 100644 --- a/libretro/Makefile +++ b/libretro/Makefile @@ -300,12 +300,16 @@ else ifneq (,$(findstring armv,$(platform))) # emscripten else ifeq ($(platform), emscripten) - TARGET_ARCH = wasm32 - GLES = 1 TARGET := $(TARGET_NAME)_libretro_emscripten.bc - PLATCFLAGS += -msimd128 -msse3 -mssse3 -msse4.1 -pthread -D__EMSCRIPTEN__ -DNO_MMAP - PLATFORM_EXT = emscripten - STATIC_LINKING = 1 + GLES := 1 + CPUFLAGS += + PLATCFLAGS += -DCC_resampler=mupen_CC_resampler -Dsinc_resampler=mupen_sinc_resampler \ + -Drglgen_symbol_map=mupen_rglgen_symbol_map -Dmain_exit=mupen_main_exit \ + -Dadler32=mupen_adler32 -Drarch_resampler_realloc=mupen_rarch_resampler_realloc \ + -Daudio_convert_s16_to_float_C=mupen_audio_convert_s16_to_float_C -Daudio_convert_float_to_s16_C=mupen_audio_convert_float_to_s16_C \ + -Daudio_convert_init_simd=mupen_audio_convert_init_simd -Drglgen_resolve_symbols_custom=mupen_rglgen_resolve_symbols_custom \ + -Drglgen_resolve_symbols=mupen_rglgen_resolve_symbols + PLATFORM_EXT = unix # Windows MSVC all architectures else ifneq (,$(findstring windows_msvc2019,$(platform))) @@ -431,11 +435,7 @@ else GLFLAGS += -DHAVE_OPENGL endif -COREFLAGS += -D__LIBRETRO__ -DPPSSPP -DWITH_UPNP -DGLEW_STATIC -DGLEW_NO_GLU -DMINIUPNP_STATICLIB -ifneq ($(platform), emscripten) - # ffmpeg does not work with emscripten - COREFLAGS += -DUSE_FFMPEG -endif +COREFLAGS += -D__LIBRETRO__ -DPPSSPP -DUSE_FFMPEG -DWITH_UPNP -DGLEW_STATIC -DGLEW_NO_GLU -DMINIUPNP_STATICLIB ifeq ($(DEBUG), 1) ifneq (,$(findstring msvc,$(platform))) @@ -445,8 +445,6 @@ ifeq ($(DEBUG), 1) CPUOPTS += -O0 -g endif CPUOPTS += -D_DEBUG -else ifeq ($(platform), emscripten) - CPUOPTS += -O3 -DNDEBUG else CPUOPTS += -O2 -DNDEBUG endif @@ -496,7 +494,7 @@ all: $(TARGET) $(TARGET): $(OBJECTS) ifeq ($(STATIC_LINKING), 1) - $(AR) rcs $(TARGET) $(OBJECTS) + $(AR) rcs $A $(OBJECTS) else $(LD) $(LINKOUT)$@ $(OBJECTS) $(LDFLAGS) $(GL_LIB) endif diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 90c21ce9e..05754192e 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -193,69 +193,7 @@ SOURCES_C += \ $(EXTDIR)/libpng17/pngwtran.c \ $(EXTDIR)/libpng17/pngwutil.c -INCFLAGS += -I$(EXTDIR)/rcheevos/include - -COREFLAGS += -DRC_DISABLE_LUA - -SOURCES_C += \ - $(EXTDIR)/rcheevos/src/rapi/rc_api_common.c \ - $(EXTDIR)/rcheevos/src/rapi/rc_api_editor.c \ - $(EXTDIR)/rcheevos/src/rapi/rc_api_info.c \ - $(EXTDIR)/rcheevos/src/rapi/rc_api_runtime.c \ - $(EXTDIR)/rcheevos/src/rapi/rc_api_user.c \ - $(EXTDIR)/rcheevos/src/rcheevos/alloc.c \ - $(EXTDIR)/rcheevos/src/rcheevos/condition.c \ - $(EXTDIR)/rcheevos/src/rcheevos/condset.c \ - $(EXTDIR)/rcheevos/src/rcheevos/consoleinfo.c \ - $(EXTDIR)/rcheevos/src/rcheevos/format.c \ - $(EXTDIR)/rcheevos/src/rcheevos/lboard.c \ - $(EXTDIR)/rcheevos/src/rcheevos/memref.c \ - $(EXTDIR)/rcheevos/src/rcheevos/operand.c \ - $(EXTDIR)/rcheevos/src/rc_client.c \ - $(EXTDIR)/rcheevos/src/rc_util.c \ - $(EXTDIR)/rcheevos/src/rc_compat.c \ - $(EXTDIR)/rcheevos/src/rcheevos/rc_validate.c \ - $(EXTDIR)/rcheevos/src/rcheevos/richpresence.c \ - $(EXTDIR)/rcheevos/src/rcheevos/runtime.c \ - $(EXTDIR)/rcheevos/src/rcheevos/runtime_progress.c \ - $(EXTDIR)/rcheevos/src/rcheevos/trigger.c \ - $(EXTDIR)/rcheevos/src/rcheevos/value.c \ - $(EXTDIR)/rcheevos/src/rhash/cdreader.c \ - $(EXTDIR)/rcheevos/src/rhash/hash.c \ - $(EXTDIR)/rcheevos/src/rhash/md5.c - COREFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 -COREFLAGS += -DHTTPS_NOT_AVAILABLE - -COREFLAGS += -D_7ZIP_ST -INCFLAGS += -I$(EXTDIR)/libchdr/deps/lzma-22.01/include - -SOURCES_C += \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Alloc.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bcj2.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bcj2Enc.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bra.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Bra86.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/CpuArch.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Delta.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzFind.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzFindOpt.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzmaDec.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzmaEnc.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Lzma86Dec.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Lzma86Enc.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/LzmaLib.c \ - $(EXTDIR)/libchdr/deps/lzma-22.01/src/Sort.c - -INCFLAGS += -I$(EXTDIR)/libchdr/include - -SOURCES_C += \ - $(EXTDIR)/libchdr/src/libchdr_bitstream.c \ - $(EXTDIR)/libchdr/src/libchdr_cdrom.c \ - $(EXTDIR)/libchdr/src/libchdr_chd.c \ - $(EXTDIR)/libchdr/src/libchdr_flac.c \ - $(EXTDIR)/libchdr/src/libchdr_huffman.c - ifeq ($(PLATFORM_EXT), android) COREFLAGS += -DHAVE_DLFCN_H else ifneq ($(PLATFORM_EXT), win32) @@ -269,7 +207,6 @@ endif SOURCES_C += \ $(EXTDIR)/cpu_features/src/filesystem.c \ $(EXTDIR)/cpu_features/src/impl_aarch64_linux_or_android.c \ - $(EXTDIR)/cpu_features/src/impl_aarch64_windows.c \ $(EXTDIR)/cpu_features/src/impl_arm_linux_or_android.c \ $(EXTDIR)/cpu_features/src/impl_mips_linux_or_android.c \ $(EXTDIR)/cpu_features/src/impl_ppc_linux.c \ @@ -348,7 +285,6 @@ SOURCES_CXX += \ $(COMMONDIR)/File/DirListing.cpp \ $(COMMONDIR)/GPU/thin3d.cpp \ $(COMMONDIR)/GPU/Shader.cpp \ - $(COMMONDIR)/GPU/GPUBackendCommon.cpp \ $(COMMONDIR)/GPU/ShaderWriter.cpp \ $(COMMONDIR)/GPU/ShaderTranslation.cpp \ $(COMMONDIR)/GPU/OpenGL/thin3d_gl.cpp \ @@ -357,7 +293,6 @@ SOURCES_CXX += \ $(COMMONDIR)/GPU/OpenGL/GLFeatures.cpp \ $(COMMONDIR)/GPU/OpenGL/GLFrameData.cpp \ $(COMMONDIR)/GPU/OpenGL/GLRenderManager.cpp \ - $(COMMONDIR)/GPU/OpenGL/GLMemory.cpp \ $(COMMONDIR)/GPU/OpenGL/GLQueueRunner.cpp \ $(COMMONDIR)/GPU/OpenGL/DataFormatGL.cpp \ $(COMMONDIR)/GPU/Vulkan/thin3d_vulkan.cpp \ @@ -370,7 +305,6 @@ SOURCES_CXX += \ $(COMMONDIR)/GPU/Vulkan/VulkanImage.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanFramebuffer.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanMemory.cpp \ - $(COMMONDIR)/GPU/Vulkan/VulkanDescSet.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanProfiler.cpp \ $(COMMONDIR)/GPU/Vulkan/VulkanBarrier.cpp \ $(COMMONDIR)/Input/GestureDetector.cpp \ @@ -384,8 +318,6 @@ SOURCES_CXX += \ $(COMMONDIR)/Net/HTTPClient.cpp \ $(COMMONDIR)/Net/HTTPHeaders.cpp \ $(COMMONDIR)/Net/HTTPServer.cpp \ - $(COMMONDIR)/Net/HTTPRequest.cpp \ - $(COMMONDIR)/Net/HTTPNaettRequest.cpp \ $(COMMONDIR)/Net/NetBuffer.cpp \ $(COMMONDIR)/Net/Resolve.cpp \ $(COMMONDIR)/Net/Sinks.cpp \ @@ -405,14 +337,12 @@ SOURCES_CXX += \ $(COMMONDIR)/UI/Context.cpp \ $(COMMONDIR)/UI/UIScreen.cpp \ $(COMMONDIR)/UI/Tween.cpp \ - $(COMMONDIR)/UI/IconCache.cpp \ $(COMMONDIR)/UI/View.cpp \ $(COMMONDIR)/UI/ViewGroup.cpp \ $(COMMONDIR)/UI/ScrollView.cpp \ $(COMMONDIR)/UI/PopupScreens.cpp \ $(COMMONDIR)/System/Display.cpp \ $(COMMONDIR)/System/Request.cpp \ - $(COMMONDIR)/System/OSD.cpp \ $(COMMONDIR)/ArmCPUDetect.cpp \ $(COMMONDIR)/CPUDetect.cpp \ $(COMMONDIR)/Buffer.cpp \ @@ -698,21 +628,18 @@ SOURCES_CXX += \ $(COREDIR)/HW/SasReverb.cpp \ $(COREDIR)/HW/StereoResampler.cpp \ $(COREDIR)/Compatibility.cpp \ - $(COREDIR)/FrameTiming.cpp \ $(COREDIR)/Loaders.cpp \ $(COREDIR)/MIPS/JitCommon/JitCommon.cpp \ $(COREDIR)/MIPS/JitCommon/JitState.cpp \ $(COREDIR)/MIPS/JitCommon/JitBlockCache.cpp \ - $(COREDIR)/MIPS/IR/IRAnalysis.cpp \ $(COREDIR)/MIPS/IR/IRCompALU.cpp \ $(COREDIR)/MIPS/IR/IRCompBranch.cpp \ $(COREDIR)/MIPS/IR/IRCompFPU.cpp \ $(COREDIR)/MIPS/IR/IRCompLoadStore.cpp \ $(COREDIR)/MIPS/IR/IRCompVFPU.cpp \ - $(COREDIR)/MIPS/IR/IRInst.cpp \ $(COREDIR)/MIPS/IR/IRInterpreter.cpp \ $(COREDIR)/MIPS/IR/IRJit.cpp \ - $(COREDIR)/MIPS/IR/IRNativeCommon.cpp \ + $(COREDIR)/MIPS/IR/IRInst.cpp \ $(COREDIR)/MIPS/IR/IRPassSimplify.cpp \ $(COREDIR)/MIPS/IR/IRRegCache.cpp \ $(COREDIR)/MIPS/IR/IRFrontend.cpp \ @@ -734,7 +661,6 @@ SOURCES_CXX += \ $(COREDIR)/PSPLoaders.cpp \ $(COREDIR)/Replay.cpp \ $(COREDIR)/Reporting.cpp \ - $(COREDIR)/RetroAchievements.cpp \ $(COREDIR)/SaveState.cpp \ $(COREDIR)/Screenshot.cpp \ $(COREDIR)/System.cpp \ @@ -788,15 +714,6 @@ ifeq ($(WITH_DYNAREC),1) $(COREDIR)/MIPS/ARM64/Arm64Jit.cpp \ $(COREDIR)/MIPS/ARM64/Arm64RegCache.cpp \ $(COREDIR)/MIPS/ARM64/Arm64RegCacheFPU.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRAsm.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRCompALU.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRCompBranch.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRCompFPU.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRCompLoadStore.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRCompSystem.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRCompVec.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRJit.cpp \ - $(COREDIR)/MIPS/ARM64/Arm64IRRegCache.cpp \ $(COREDIR)/Util/DisArm64.cpp \ $(GPUCOMMONDIR)/VertexDecoderArm64.cpp @@ -842,15 +759,6 @@ ifeq ($(WITH_DYNAREC),1) $(COREDIR)/MIPS/x86/JitSafeMem.cpp \ $(COREDIR)/MIPS/x86/RegCache.cpp \ $(COREDIR)/MIPS/x86/RegCacheFPU.cpp \ - $(COREDIR)/MIPS/x86/X64IRAsm.cpp \ - $(COREDIR)/MIPS/x86/X64IRCompALU.cpp \ - $(COREDIR)/MIPS/x86/X64IRCompBranch.cpp \ - $(COREDIR)/MIPS/x86/X64IRCompFPU.cpp \ - $(COREDIR)/MIPS/x86/X64IRCompLoadStore.cpp \ - $(COREDIR)/MIPS/x86/X64IRCompSystem.cpp \ - $(COREDIR)/MIPS/x86/X64IRCompVec.cpp \ - $(COREDIR)/MIPS/x86/X64IRJit.cpp \ - $(COREDIR)/MIPS/x86/X64IRRegCache.cpp \ $(GPUDIR)/Common/VertexDecoderX86.cpp endif endif diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index de6792012..e60c07370 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -239,22 +239,22 @@ class PrintfLogger : public LogListener { switch (message.level) { - case LogLevel::LVERBOSE: - case LogLevel::LDEBUG: + case LogTypes::LVERBOSE: + case LogTypes::LDEBUG: log_(RETRO_LOG_DEBUG, "[%s] %s", message.log, message.msg.c_str()); break; - case LogLevel::LERROR: + case LogTypes::LERROR: log_(RETRO_LOG_ERROR, "[%s] %s", message.log, message.msg.c_str()); break; - case LogLevel::LNOTICE: - case LogLevel::LWARNING: + case LogTypes::LNOTICE: + case LogTypes::LWARNING: log_(RETRO_LOG_WARN, "[%s] %s", message.log, message.msg.c_str()); break; - case LogLevel::LINFO: + case LogTypes::LINFO: default: log_(RETRO_LOG_INFO, "[%s] %s", message.log, message.msg.c_str()); @@ -425,10 +425,6 @@ static std::string map_psp_language_to_i18n_locale(int val) static void check_variables(CoreParameter &coreParam) { - bool isFastForwarding; - if (environ_cb(RETRO_ENVIRONMENT_GET_FASTFORWARDING, &isFastForwarding)) - coreParam.fastForward = isFastForwarding; - bool updated = false; if ( coreState != CoreState::CORE_POWERUP @@ -474,14 +470,13 @@ static void check_variables(CoreParameter &coreParam) g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED; } -#ifndef __EMSCRIPTEN__ var.key = "ppsspp_cpu_core"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "JIT")) g_Config.iCpuCore = (int)CPUCore::JIT; else if (!strcmp(var.value, "IR JIT")) - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; + g_Config.iCpuCore = (int)CPUCore::IR_JIT; else if (!strcmp(var.value, "Interpreter")) g_Config.iCpuCore = (int)CPUCore::INTERPRETER; } @@ -490,11 +485,8 @@ static void check_variables(CoreParameter &coreParam) // Just gonna force it to the IR interpreter on startup. // We don't hide the option, but we make sure it's off on bootup. In case someone wants // to experiment in future iOS versions or something... - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; + g_Config.iCpuCore = (int)CPUCore::IR_JIT; } -#else - g_Config.iCpuCore = (int)CPUCore::INTERPRETER; -#endif var.key = "ppsspp_fast_memory"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -523,8 +515,6 @@ static void check_variables(CoreParameter &coreParam) g_Config.iIOTimingMethod = IOTIMING_HOST; else if (!strcmp(var.value, "Simulate UMD delays")) g_Config.iIOTimingMethod = IOTIMING_REALISTIC; - else if (!strcmp(var.value, "Simulate UMD slow reading speed")) - g_Config.iIOTimingMethod = IOTIMING_UMDSLOWREALISTIC; } var.key = "ppsspp_force_lag_sync"; @@ -613,7 +603,6 @@ static void check_variables(CoreParameter &coreParam) g_Config.iInternalResolution = 10; } -#if 0 // see issue #16786 var.key = "ppsspp_mulitsample_level"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -628,7 +617,15 @@ static void check_variables(CoreParameter &coreParam) else if (!strcmp(var.value, "x8")) g_Config.iMultiSampleLevel = 3; } -#endif + + var.key = "ppsspp_skip_buffer_effects"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bSkipBufferEffects = false; + else + g_Config.bSkipBufferEffects = true; + } var.key = "ppsspp_skip_gpu_readbacks"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -708,6 +705,15 @@ static void check_variables(CoreParameter &coreParam) g_Config.bSoftwareSkinning = true; } + var.key = "ppsspp_vertex_cache"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bVertexCache = false; + else + g_Config.bVertexCache = true; + } + var.key = "ppsspp_lazy_texture_caching"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -1009,7 +1015,6 @@ static void check_variables(CoreParameter &coreParam) } } -#if 0 // see issue #16786 if (g_Config.iMultiSampleLevel != iMultiSampleLevel_prev && PSP_IsInited()) { if (gpu) @@ -1017,7 +1022,6 @@ static void check_variables(CoreParameter &coreParam) gpu->NotifyRenderResized(); } } -#endif if (updateAvInfo) { @@ -1026,6 +1030,9 @@ static void check_variables(CoreParameter &coreParam) environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &avInfo); } + bool isFastForwarding = environ_cb(RETRO_ENVIRONMENT_GET_FASTFORWARDING, &isFastForwarding); + coreParam.fastForward = isFastForwarding; + set_variable_visibility(); } @@ -1074,7 +1081,7 @@ void retro_init(void) logman->RemoveListener(logman->GetDebuggerListener()); logman->ChangeFileLog(nullptr); logman->AddListener(printfLogger); - logman->SetAllLogLevels(LogLevel::LINFO); + logman->SetAllLogLevels(LogTypes::LINFO); } g_Config.Load("", ""); @@ -1160,7 +1167,7 @@ namespace Libretro { ctx->SetRenderTarget(); if (ctx->GetDrawContext()) - ctx->GetDrawContext()->BeginFrame(Draw::DebugFlags::NONE); + ctx->GetDrawContext()->BeginFrame(); gpu->BeginHostFrame(); @@ -1169,10 +1176,8 @@ namespace Libretro gpu->EndHostFrame(); - if (ctx->GetDrawContext()) { + if (ctx->GetDrawContext()) ctx->GetDrawContext()->EndFrame(); - ctx->GetDrawContext()->Present(Draw::PresentMode::FIFO, 1); - } } static void EmuThreadFunc() @@ -1288,23 +1293,6 @@ bool retro_load_game(const struct retro_game_info *game) return false; } - struct retro_core_option_display option_display; - - // Show/hide 'MSAA' and 'Texture Shader' options, Vulkan only - option_display.visible = (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) ? true : false; -#if 0 // see issue #16786 - option_display.key = "ppsspp_mulitsample_level"; - environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); -#endif - option_display.key = "ppsspp_texture_shader"; - environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); - - // Show/hide 'Buffered Frames' option, Vulkan/GL only - option_display.visible = (g_Config.iGPUBackend == (int)GPUBackend::VULKAN || - g_Config.iGPUBackend == (int)GPUBackend::OPENGL) ? true : false; - option_display.key = "ppsspp_inflight_frames"; - environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); - set_variable_visibility(); return true; @@ -1682,8 +1670,7 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_CAN_JIT: #if PPSSPP_PLATFORM(IOS) - bool can_jit; - return (environ_cb(RETRO_ENVIRONMENT_GET_JIT_CAPABLE, &can_jit) && can_jit); + return false; #else return true; #endif @@ -1702,8 +1689,10 @@ void System_Notify(SystemNotification notification) { } } bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } -void System_PostUIMessage(UIMessage message, const std::string ¶m) {} -void NativeFrame(GraphicsContext *graphicsContext) {} +void System_PostUIMessage(const std::string &message, const std::string ¶m) {} +void System_NotifyUserMessage(const std::string &message, float duration, u32 color, const char *id) {} +void NativeUpdate() {} +void NativeRender(GraphicsContext *graphicsContext) {} void NativeResized() {} void System_Toast(const char *str) {} @@ -1744,9 +1733,3 @@ bool System_AudioRecordingState() { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } #endif - -// TODO: To avoid having to define these here, these should probably be turned into system "requests". -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; } -std::string NativeLoadSecret(const char *nameOfSecret) { - return ""; -} diff --git a/libretro/libretro.h b/libretro/libretro.h index fe020d64a..bb114aed3 100644 --- a/libretro/libretro.h +++ b/libretro/libretro.h @@ -1765,39 +1765,6 @@ enum retro_mod * (see enum retro_savestate_context) */ -#define RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT (73 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_hw_render_context_negotiation_interface * -- - * Before calling SET_HW_RNEDER_CONTEXT_NEGOTIATION_INTERFACE, a core can query - * which version of the interface is supported. - * - * Frontend looks at interface_type and returns the maximum supported - * context negotiation interface version. - * If the interface_type is not supported or recognized by the frontend, a version of 0 - * must be returned in interface_version and true is returned by frontend. - * - * If this environment call returns true with interface_version greater than 0, - * a core can always use a negotiation interface version larger than what the frontend returns, but only - * earlier versions of the interface will be used by the frontend. - * A frontend must not reject a negotiation interface version that is larger than - * what the frontend supports. Instead, the frontend will use the older entry points that it recognizes. - * If this is incompatible with a particular core's requirements, it can error out early. - * - * Backwards compatibility note: - * This environment call was introduced after Vulkan v1 context negotiation. - * If this environment call is not supported by frontend - i.e. the environment call returns false - - * only Vulkan v1 context negotiation is supported (if Vulkan HW rendering is supported at all). - * If a core uses Vulkan negotiation interface with version > 1, negotiation may fail unexpectedly. - * All future updates to the context negotiation interface implies that frontend must support - * this environment call to query support. - */ - -#define RETRO_ENVIRONMENT_GET_JIT_CAPABLE 74 - /* bool * -- - * Result is set to true if the frontend has already verified JIT can be - * used, mainly for use iOS/tvOS. On other platforms the result is true. - */ - - /* VFS functionality */ /* File paths: diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h index 6e08fc41f..d0f7c22c7 100644 --- a/libretro/libretro_core_options.h +++ b/libretro/libretro_core_options.h @@ -293,7 +293,6 @@ struct retro_core_option_v2_definition option_defs_us[] = { }, "480x272" }, -#if 0 // see issue #16786 { "ppsspp_mulitsample_level", "MSAA Antialiasing (Vulkan Only)", @@ -310,7 +309,16 @@ struct retro_core_option_v2_definition option_defs_us[] = { }, "Disabled" }, -#endif + { + "ppsspp_skip_buffer_effects", + "Skip Buffer Effects", + NULL, + "Faster, but may cause major rendering issues.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, { "ppsspp_skip_gpu_readbacks", "Skip GPU Readbacks", diff --git a/link_readme.py b/link_readme.py index 24294453e..0927769af 100755 --- a/link_readme.py +++ b/link_readme.py @@ -79,8 +79,6 @@ def update(file_name): footer = cont[d + len(footer_delimiter):] cont = cont[0 : d] re.sub(r"\[#(\d+)\]:", already_added_id, footer) - if footer[-1] != "\n": - footer += "\n" # Add brackets if missing added_bracket = re.sub(r"([^[])#(\d+)", add_bracket, cont) diff --git a/macOS/Info.plist b/macOS/Info.plist index 03a318124..c4f448c26 100644 --- a/macOS/Info.plist +++ b/macOS/Info.plist @@ -90,8 +90,6 @@ CSResourcesFileMapped - NSHighResolutionCapable - NSHumanReadableCopyright UTExportedTypeDeclarations diff --git a/macOS/InfoGold.plist b/macOS/InfoGold.plist index 2bec2d660..cd816e250 100644 --- a/macOS/InfoGold.plist +++ b/macOS/InfoGold.plist @@ -90,8 +90,6 @@ CSResourcesFileMapped - NSHighResolutionCapable - NSHumanReadableCopyright UTExportedTypeDeclarations diff --git a/ppsspp.iss b/ppsspp.iss index 09c3936d5..20e64673f 100644 --- a/ppsspp.iss +++ b/ppsspp.iss @@ -78,7 +78,6 @@ Source: "assets\themes\*.*"; DestDir: "{app}\assets\themes" Source: "assets\debugger\*"; DestDir: "{app}\assets\debugger"; Flags: recursesubdirs Source: "assets\lang\*.ini"; DestDir: "{app}\assets\lang" Source: "assets\flash0\font\*.*"; DestDir: "{app}\assets\flash0\font" -Source: "assets\vfpu\*.*"; DestDir: "{app}\assets\vfpu" Source: "dx9sdk\8.1\Redist\D3D\x64\d3dcompiler_47.dll"; DestDir: "{app}" Source: "dx9sdk\8.1\Redist\D3D\x86\d3dcompiler_47.dll"; DestName: "d3dcompiler_47.x86.dll"; DestDir: "{app}" diff --git a/ppsspp_config.h b/ppsspp_config.h index 2861b621b..d819d137b 100644 --- a/ppsspp_config.h +++ b/ppsspp_config.h @@ -8,7 +8,7 @@ #define PPSSPP_API(PPSSPP_FEATURE) (PPSSPP_API_##PPSSPP_FEATURE) // ARCH defines -#if defined(_M_IX86) || defined(__i386__) || defined (__EMSCRIPTEN__) +#if defined(_M_IX86) || defined(__i386__) #define PPSSPP_ARCH_X86 1 #define PPSSPP_ARCH_32BIT 1 //TODO: Remove this compat define @@ -17,13 +17,9 @@ #endif #endif -#if (defined(_M_X64) || defined(__amd64__) || defined(__x86_64__)) && !defined(__EMSCRIPTEN__) +#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) #define PPSSPP_ARCH_AMD64 1 - #if defined(__ILP32__) - #define PPSSPP_ARCH_32BIT 1 - #else - #define PPSSPP_ARCH_64BIT 1 - #endif + #define PPSSPP_ARCH_64BIT 1 //TODO: Remove this compat define #ifndef _M_X64 #define _M_X64 1 @@ -57,7 +53,7 @@ #if defined(__aarch64__) || defined(_M_ARM64) #define PPSSPP_ARCH_ARM64 1 #define PPSSPP_ARCH_64BIT 1 - #define PPSSPP_ARCH_ARM_NEON 1 // Applies to both ARM32 and ARM64 + #define PPSSPP_ARCH_ARM_NEON 1 #define PPSSPP_ARCH_ARM64_NEON 1 #endif @@ -75,11 +71,6 @@ #define PPSSPP_ARCH_64BIT 1 #endif -#if defined(__loongarch64) - //https://github.com/gcc-mirror/gcc/blob/master/gcc/config/loongarch/loongarch-c.cc - #define PPSSPP_ARCH_LOONGARCH64 1 - #define PPSSPP_ARCH_64BIT 1 -#endif // PLATFORM defines #if defined(_WIN32) @@ -113,8 +104,6 @@ #define PPSSPP_PLATFORM_LINUX 1 #elif defined(__linux__) #define PPSSPP_PLATFORM_LINUX 1 -#elif defined(__OpenBSD__) - #define PPSSPP_PLATFORM_OPENBSD 1 #endif // Windows ARM/ARM64, and Windows UWP (all), are the only platform that don't do GL at all (until Apple finally removes it) diff --git a/source_assets/image/background_gold.png b/source_assets/image/background_gold.png new file mode 100644 index 000000000..af48e0817 Binary files /dev/null and b/source_assets/image/background_gold.png differ diff --git a/source_assets/image/buttons.svg b/source_assets/image/buttons.svg index b6bf625d1..68203e5e4 100644 --- a/source_assets/image/buttons.svg +++ b/source_assets/image/buttons.svg @@ -12,7 +12,7 @@ height="1052.3622047" id="svg2" version="1.1" - inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" sodipodi:docname="buttons.svg"> @@ -1688,10 +1688,10 @@ id="filter5096-3" style="color-interpolation-filters:sRGB" inkscape:label="Drop Shadow" - x="-0.17000000000000001" - y="-0.13999999999999999" - width="1.3600000000000001" - height="1.28"> + x="-0.065" + y="-0.065" + width="1.13" + height="1.13"> + inkscape:label="Drop Shadow"> - - - - - - - - - - - - - - - - - - - - - + width="399.68362" + height="362.96939" + x="-2.726912" + y="-3.7985277" /> + transform="matrix(1.009758,0,0,1.1824906,296.82679,84.989682)"> + style="fill:#ffffff;fill-opacity:0.670213;stroke:none" /> + style="fill:#ffffff;fill-opacity:0.670213;stroke:none" /> + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:0.670213;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /> 6 @@ -3138,7 +3042,7 @@ + inkscape:export-ydpi="133.41901"> @@ -3200,7 +3103,7 @@ d="m 244.23139,299.67116 c 0.04,-0.32 0.07,-0.64 0.07,-0.98 0,-0.34 -0.03,-0.66 -0.07,-0.98 l 2.11,-1.65 c 0.19,-0.15 0.24,-0.42 0.12,-0.64 l -2,-3.46 c -0.09,-0.16 -0.26,-0.25 -0.44,-0.25 -0.06,0 -0.12,0.01 -0.17,0.03 l -2.49,1 c -0.52,-0.4 -1.08,-0.73 -1.69,-0.98 l -0.38,-2.65 c -0.03,-0.24 -0.24,-0.42 -0.49,-0.42 h -4 c -0.25,0 -0.46,0.18 -0.49,0.42 l -0.38,2.65 c -0.61,0.25 -1.17,0.59 -1.69,0.98 l -2.49,-1 c -0.06,-0.02 -0.12,-0.03 -0.18,-0.03 -0.17,0 -0.34,0.09 -0.43,0.25 l -2,3.46 c -0.13,0.22 -0.07,0.49 0.12,0.64 l 2.11,1.65 c -0.04,0.32 -0.07,0.65 -0.07,0.98 0,0.33 0.03,0.66 0.07,0.98 l -2.11,1.65 c -0.19,0.15 -0.24,0.42 -0.12,0.64 l 2,3.46 c 0.09,0.16 0.26,0.25 0.44,0.25 0.06,0 0.12,-0.01 0.17,-0.03 l 2.49,-1 c 0.52,0.4 1.08,0.73 1.69,0.98 l 0.38,2.65 c 0.03,0.24 0.24,0.42 0.49,0.42 h 4 c 0.25,0 0.46,-0.18 0.49,-0.42 l 0.38,-2.65 c 0.61,-0.25 1.17,-0.59 1.69,-0.98 l 2.49,1 c 0.06,0.02 0.12,0.03 0.18,0.03 0.17,0 0.34,-0.09 0.43,-0.25 l 2,-3.46 c 0.12,-0.22 0.07,-0.49 -0.12,-0.64 z m -7.43,-4.98 c -2.21,0 -4,1.79 -4,4 0,2.21 1.79,4 4,4 2.21,0 4,-1.79 4,-4 0,-2.21 -1.79,-4 -4,-4 z" id="path1351" sodipodi:nodetypes="csccccsccccssccccsccccsccccsccccssccccsccccsssss" - transform="matrix(1.222815,0,0,1.222815,32.591717,-144.09755)" + transform="matrix(1.222815,0,0,1.222815,-53.018711,-41.061989)" inkscape:export-xdpi="135" inkscape:export-ydpi="135" /> + transform="translate(-15.419355,43.255668)"> + transform="translate(34.285714,-2.1428571)"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/source_assets/image/checkmark.png b/source_assets/image/checkmark.png deleted file mode 100644 index 4da8328ea..000000000 Binary files a/source_assets/image/checkmark.png and /dev/null differ diff --git a/source_assets/image/empty.png b/source_assets/image/empty.png deleted file mode 100644 index 5d4d81057..000000000 Binary files a/source_assets/image/empty.png and /dev/null differ diff --git a/source_assets/image/fast_forward.png b/source_assets/image/fast_forward.png deleted file mode 100644 index d7fb6ae6b..000000000 Binary files a/source_assets/image/fast_forward.png and /dev/null differ diff --git a/source_assets/image/pausepng.png b/source_assets/image/pausepng.png deleted file mode 100644 index b618a7ffd..000000000 Binary files a/source_assets/image/pausepng.png and /dev/null differ diff --git a/source_assets/image/play.png b/source_assets/image/play.png deleted file mode 100644 index d324c25b8..000000000 Binary files a/source_assets/image/play.png and /dev/null differ diff --git a/source_assets/image/record.png b/source_assets/image/record.png deleted file mode 100644 index 05008ad25..000000000 Binary files a/source_assets/image/record.png and /dev/null differ diff --git a/source_assets/image/retroachievements_logo.png b/source_assets/image/retroachievements_logo.png deleted file mode 100644 index 15bfa907a..000000000 Binary files a/source_assets/image/retroachievements_logo.png and /dev/null differ diff --git a/source_assets/image/speaker.png b/source_assets/image/speaker.png deleted file mode 100644 index b043e5e63..000000000 Binary files a/source_assets/image/speaker.png and /dev/null differ diff --git a/source_assets/image/speaker_max.png b/source_assets/image/speaker_max.png deleted file mode 100644 index 8625b2b2e..000000000 Binary files a/source_assets/image/speaker_max.png and /dev/null differ diff --git a/source_assets/image/speaker_off.png b/source_assets/image/speaker_off.png deleted file mode 100644 index b8b1e8e2b..000000000 Binary files a/source_assets/image/speaker_off.png and /dev/null differ diff --git a/source_assets/image/stop.png b/source_assets/image/stop.png deleted file mode 100644 index 3860c5b38..000000000 Binary files a/source_assets/image/stop.png and /dev/null differ diff --git a/source_assets/image/winner_cup.png b/source_assets/image/winner_cup.png deleted file mode 100644 index 27ba1ed94..000000000 Binary files a/source_assets/image/winner_cup.png and /dev/null differ diff --git a/ui_atlasscript.txt b/ui_atlasscript.txt index ded4b2314..eead48f3f 100644 --- a/ui_atlasscript.txt +++ b/ui_atlasscript.txt @@ -21,6 +21,7 @@ image I_STICK_LINE source_assets/image/stick_line.png copy image I_STICK_BG_LINE source_assets/image/stick_bg_line.png copy image I_CHECKEDBOX source_assets/image/checkedbox.png copy image I_BG source_assets/image/background2.png copy +image I_BG_GOLD source_assets/image/background_gold.png copy image I_L source_assets/image/L.png copy image I_R source_assets/image/R.png copy image I_DROP_SHADOW source_assets/image/dropshadow.png copy @@ -69,15 +70,3 @@ image I_ARROW_UP source_assets/image/arrow_up.png copy image I_ARROW_DOWN source_assets/image/arrow_down.png copy image I_SLIDERS source_assets/image/sliders.png copy image I_THREE_DOTS source_assets/image/three_dots.png copy -image I_INFO source_assets/image/info.png copy -image I_RETROACHIEVEMENTS_LOGO source_assets/image/retroachievements_logo.png copy -image I_CHECKMARK source_assets/image/checkmark.png copy -image I_PLAY source_assets/image/play.png copy -image I_STOP source_assets/image/stop.png copy -image I_FASTFORWARD source_assets/image/fast_forward.png copy -image I_RECORD source_assets/image/record.png copy -image I_SPEAKER source_assets/image/speaker.png copy -image I_SPEAKER_MAX source_assets/image/speaker_max.png copy -image I_SPEAKER_OFF source_assets/image/speaker_off.png copy -image I_WINNER_CUP source_assets/image/winner_cup.png copy -image I_EMPTY source_assets/image/empty.png copy diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index 088416e2b..f9dd036ac 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -34,11 +34,11 @@ #include "Core/MemMap.h" #include "Core/Core.h" #include "Core/CoreTiming.h" -#include "Core/Config.h" #include "Core/HLE/HLE.h" // Temporary hacks around annoying linking errors. Copied from Headless. -void NativeFrame(GraphicsContext *graphicsContext) { } +void NativeUpdate() { } +void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } @@ -56,15 +56,9 @@ HLEFunction UnitTestFakeSyscalls[] = { {0x1234BEEF, &UnitTestTerminator, "UnitTestTerminator"}, }; -double ExecCPUTest(bool clearCache = true) { +double ExecCPUTest() { int blockTicks = 1000000; int total = 0; - - if (MIPSComp::jit) { - currentMIPS->pc = PSP_GetUserMemoryBase(); - MIPSComp::JitAt(); - } - double st = time_now_d(); do { for (int j = 0; j < 1000; ++j) { @@ -80,17 +74,6 @@ double ExecCPUTest(bool clearCache = true) { while (time_now_d() - st < 0.5); double elapsed = time_now_d() - st; - if (MIPSComp::jit) { - JitBlockCacheDebugInterface *cache = MIPSComp::jit->GetBlockCacheDebugInterface(); - if (cache) { - JitBlockDebugInfo block = cache->GetBlockDebugInfo(0); - WARN_LOG(JIT, "Executed %d target instrs, %d IR, for %d orig", (int)block.targetDisasm.size(), (int)block.irDisasm.size(), (int)block.origDisasm.size()); - } - - if (clearCache) - MIPSComp::jit->ClearCache(); - } - return total / elapsed; } @@ -126,7 +109,6 @@ static void DestroyJitHarness() { bool TestJit() { SetupJitHarness(); - g_Config.bFastMemory = true; currentMIPS->pc = PSP_GetUserMemoryBase(); u32 *p = (u32 *)Memory::GetPointer(currentMIPS->pc); @@ -177,43 +159,46 @@ bool TestJit() { *p++ = MIPS_MAKE_SYSCALL("UnitTestFakeSyscalls", "UnitTestTerminator"); *p++ = MIPS_MAKE_BREAK(1); - *p++ = MIPS_MAKE_JR_RA(); // Dogfood. addr = currentMIPS->pc; for (size_t j = 0; j < ARRAY_SIZE(lines); ++j) { char line[512]; - MIPSDisAsm(Memory::Read_Instruction(addr), addr, line, sizeof(line), true); + MIPSDisAsm(Memory::Read_Instruction(addr), addr, line, true); addr += 4; printf("%s\n", line); } printf("\n"); - double jit_speed = 0.0, jit_ir_speed = 0.0, ir_speed = 0.0, interp_speed = 0.0; + double jit_speed = 0.0, interp_speed = 0.0; if (compileSuccess) { interp_speed = ExecCPUTest(); - mipsr4k.UpdateCore(CPUCore::IR_INTERPRETER); - ir_speed = ExecCPUTest(); mipsr4k.UpdateCore(CPUCore::JIT); jit_speed = ExecCPUTest(); - mipsr4k.UpdateCore(CPUCore::JIT_IR); - jit_ir_speed = ExecCPUTest(false); // Disassemble - JitBlockCacheDebugInterface *cache = MIPSComp::jit->GetBlockCacheDebugInterface(); - if (cache) { - JitBlockDebugInfo block = cache->GetBlockDebugInfo(0); // Should only be one block. - std::vector &lines = block.targetDisasm; - // Cut off at 25 due to the repetition above. Might need tweaking for large instructions. - const int cutoff = 50; - for (int i = 0; i < std::min((int)lines.size(), cutoff); i++) { - printf("%s\n", lines[i].c_str()); - } - if (lines.size() > cutoff) - printf("...\n"); + JitBlockCache *cache = MIPSComp::jit->GetBlockCache(); + JitBlock *block = cache->GetBlock(0); // Should only be one block. +#if PPSSPP_ARCH(ARM) + std::vector lines = DisassembleArm2(block->normalEntry, block->codeSize); +#elif PPSSPP_ARCH(ARM64) + std::vector lines = DisassembleArm64(block->normalEntry, block->codeSize); +#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) + std::vector lines = DisassembleX86(block->normalEntry, block->codeSize); +#elif PPSSPP_ARCH(RISCV64) + std::vector lines = DisassembleRV64(block->normalEntry, block->codeSize); +#else + std::vector lines; +#endif + // Cut off at 25 due to the repetition above. Might need tweaking for large instructions. + const int cutoff = 25; + for (int i = 0; i < std::min((int)lines.size(), cutoff); i++) { + printf("%s\n", lines[i].c_str()); } - printf("Jit was %fx faster than interp, IR was %fx faster, JIT IR %fx.\n\n", jit_speed / interp_speed, ir_speed / interp_speed, jit_ir_speed / interp_speed); + if (lines.size() > cutoff) + printf("...\n"); + printf("Jit was %fx faster than interp.\n\n", jit_speed / interp_speed); } printf("\n"); diff --git a/unittest/TestArmEmitter.cpp b/unittest/TestArmEmitter.cpp index 96d96cf66..848655058 100644 --- a/unittest/TestArmEmitter.cpp +++ b/unittest/TestArmEmitter.cpp @@ -243,8 +243,8 @@ bool TestArmEmitter() { int R001 = GetRowName(0, M_4x4, 1, 0); int R002 = GetRowName(0, M_4x4, 2, 0); int R003 = GetRowName(0, M_4x4, 3, 0); - printf("Col 010: %s\n", GetVectorNotation(C010, V_Quad).c_str()); - printf("Row 003: %s\n", GetVectorNotation(R003, V_Quad).c_str()); + printf("Col 010: %s\n", GetVectorNotation(C010, V_Quad)); + printf("Row 003: %s\n", GetVectorNotation(R003, V_Quad)); MIPSAnalyst::AnalysisResults results; memset(&results, 0, sizeof(results)); diff --git a/unittest/TestThreadManager.cpp b/unittest/TestThreadManager.cpp index 10a8b581b..f6a11f2fa 100644 --- a/unittest/TestThreadManager.cpp +++ b/unittest/TestThreadManager.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "Common/Log.h" #include "Common/TimeUtil.h" diff --git a/unittest/TestVertexJit.cpp b/unittest/TestVertexJit.cpp index f5561c0fa..e759d6444 100644 --- a/unittest/TestVertexJit.cpp +++ b/unittest/TestVertexJit.cpp @@ -78,7 +78,7 @@ public: void Execute(int vtype, int indexUpperBound, bool useJit) { SetupExecute(vtype, useJit); - dec_->DecodeVerts(dst_, src_, &gstate_c.uv, indexLowerBound_, indexUpperBound); + dec_->DecodeVerts(dst_, src_, indexLowerBound_, indexUpperBound); } double ExecuteTimed(int vtype, int indexUpperBound, bool useJit) { @@ -88,7 +88,7 @@ public: double st = time_now_d(); do { for (int j = 0; j < ROUNDS; ++j) { - dec_->DecodeVerts(dst_, src_, &gstate_c.uv, indexLowerBound_, indexUpperBound); + dec_->DecodeVerts(dst_, src_, indexLowerBound_, indexUpperBound); ++total; } } while (time_now_d() - st < 0.5); diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 8cea9a532..88de9eab7 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -47,7 +47,6 @@ #endif #include "Common/Data/Collections/TinySet.h" -#include "Common/Data/Collections/FastVec.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Data/Text/Parsers.h" #include "Common/Data/Text/WrapText.h" @@ -58,8 +57,6 @@ #include "Common/Render/DrawBuffer.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" -#include "Common/Thread/ThreadUtil.h" -#include "Common/Data/Format/IniFile.h" #include "Common/ArmEmitter.h" #include "Common/BitScan.h" @@ -100,17 +97,12 @@ bool System_GetPropertyBool(SystemProperty prop) { } } void System_Notify(SystemNotification notification) {} -void System_PostUIMessage(UIMessage message, const std::string ¶m) {} +void System_PostUIMessage(const std::string &message, const std::string ¶m) {} +void System_NotifyUserMessage(const std::string &message, float duration, u32 color, const char *id) {} void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\0'; } void System_AudioClear() {} void System_AudioPushSamples(const s32 *audio, int numSamples) {} -// TODO: To avoid having to define these here, these should probably be turned into system "requests". -bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; } -std::string NativeLoadSecret(const char *nameOfSecret) { - return ""; -} - #if PPSSPP_PLATFORM(ANDROID) JNIEnv *getEnv() { return nullptr; @@ -373,45 +365,6 @@ bool TestTinySet() { return true; } -bool TestFastVec() { - FastVec a; - EXPECT_EQ_INT((int)a.size(), 0); - a.push_back(1); - EXPECT_EQ_INT((int)a.size(), 1); - a.push_back(2); - EXPECT_EQ_INT((int)a.size(), 2); - FastVec b; - b.push_back(8); - b.push_back(9); - b.push_back(10); - EXPECT_EQ_INT((int)b.size(), 3); - for (int i = 0; i < 100; i++) { - b.push_back(33); - } - EXPECT_EQ_INT((int)b.size(), 103); - - int items[4] = { 50, 60, 70, 80 }; - b.insert(b.begin() + 1, items, items + 4); - EXPECT_EQ_INT(b[0], 8); - EXPECT_EQ_INT(b[1], 50); - EXPECT_EQ_INT(b[2], 60); - EXPECT_EQ_INT(b[3], 70); - EXPECT_EQ_INT(b[4], 80); - EXPECT_EQ_INT(b[5], 9); - - b.resize(2); - b.insert(b.end(), items, items + 4); - EXPECT_EQ_INT(b[0], 8); - EXPECT_EQ_INT(b[1], 50); - EXPECT_EQ_INT(b[2], 50); - EXPECT_EQ_INT(b[3], 60); - EXPECT_EQ_INT(b[4], 70); - EXPECT_EQ_INT(b[5], 80); - - - return true; -} - bool TestVFPUSinCos() { float sine, cosine; // Needed for VFPU tables. @@ -478,7 +431,7 @@ bool TestMatrixTranspose() { } void TestGetMatrix(int matrix, MatrixSize sz) { - INFO_LOG(SYSTEM, "Testing matrix %s", GetMatrixNotation(matrix, sz).c_str()); + INFO_LOG(SYSTEM, "Testing matrix %s", GetMatrixNotation(matrix, sz)); u8 fullMatrix[16]; u8 cols[4]; @@ -496,8 +449,8 @@ void TestGetMatrix(int matrix, MatrixSize sz) { // int rowName = GetRowName(matrix, sz, i, 0); int colName = cols[i]; int rowName = rows[i]; - INFO_LOG(SYSTEM, "Column %i: %s", i, GetVectorNotation(colName, vsz).c_str()); - INFO_LOG(SYSTEM, "Row %i: %s", i, GetVectorNotation(rowName, vsz).c_str()); + INFO_LOG(SYSTEM, "Column %i: %s", i, GetVectorNotation(colName, vsz)); + INFO_LOG(SYSTEM, "Row %i: %s", i, GetVectorNotation(rowName, vsz)); u8 colRegs[4]; u8 rowRegs[4]; @@ -917,10 +870,10 @@ static bool TestDepthMath() { bool TestInputMapping() { InputMapping mapping; - mapping.deviceId = DEVICE_ID_PAD_0; + mapping.deviceId = 10; mapping.keyCode = 20; InputMapping mapping2; - mapping2.deviceId = DEVICE_ID_PAD_8; + mapping2.deviceId = 18; mapping2.keyCode = 38; std::string cfg = mapping.ToConfigString(); @@ -973,30 +926,6 @@ bool TestEscapeMenuString() { return true; } -bool TestSubstitutions() { - std::string output = ApplySafeSubstitutions("%3 %2 %1", "a", "b", "c"); - EXPECT_EQ_STR(output, std::string("c b a")); - return true; -} - -bool TestIniFile() { - const std::string testLine = "adsf\\#asdf = jkl\\# # comment"; - const std::string testLine2 = "# Just a comment"; - - std::string temp; - ParsedIniLine line; - line.ParseFrom(testLine); - line.Reconstruct(&temp); - EXPECT_EQ_STR(testLine, temp); - - temp.clear(); - line.ParseFrom(testLine2); - line.Reconstruct(&temp); - - EXPECT_EQ_STR(testLine2, temp); - return true; -} - typedef bool (*TestFunc)(); struct TestItem { const char *name; @@ -1048,19 +977,14 @@ TestItem availableTests[] = { TEST_ITEM(ThreadManager), TEST_ITEM(WrapText), TEST_ITEM(TinySet), - TEST_ITEM(FastVec), TEST_ITEM(SmallDataConvert), TEST_ITEM(DepthMath), TEST_ITEM(InputMapping), TEST_ITEM(EscapeMenuString), TEST_ITEM(VFS), - TEST_ITEM(Substitutions), - TEST_ITEM(IniFile), }; int main(int argc, const char *argv[]) { - SetCurrentThreadName("UnitTest"); - cpu_info.bNEON = true; cpu_info.bVFP = true; cpu_info.bVFPv3 = true; diff --git a/unittest/UnitTests.vcxproj b/unittest/UnitTests.vcxproj index 76ce39678..687314e43 100644 --- a/unittest/UnitTests.vcxproj +++ b/unittest/UnitTests.vcxproj @@ -181,7 +181,7 @@ Console true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86/lib @@ -205,7 +205,7 @@ Console true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86_64/lib @@ -229,7 +229,7 @@ Console true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib @@ -254,7 +254,7 @@ Console true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib @@ -283,7 +283,7 @@ true true true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86/lib @@ -313,7 +313,7 @@ true true true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/x86_64/lib @@ -343,7 +343,7 @@ true true true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/aarch64/lib @@ -373,7 +373,7 @@ true true true - winhttp.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) + mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dsound.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies) /ignore:4049 /ignore:4217 %(AdditionalOptions) ../ffmpeg/Windows/arm/lib @@ -420,24 +420,21 @@ {edfa2e87-8ac1-4853-95d4-d7594ff81947} - - {956f1f48-b612-46d8-89ee-96996dcd9383} - {3baae095-e0ab-4b0e-b5df-ce39c8ae31de} {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} - - {31694510-a8c0-40f6-b09b-e8df825adefa} - {f761046e-6c38-4428-a5f1-38391a37bb34} {457f45d2-556f-47bc-a31d-aff0d15beaed} + + {004b8d11-2be3-4bd9-ab40-2be04cf2096f} +