diff --git a/.gitignore b/.gitignore
index ead94a875f..ad32797a1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,8 +28,6 @@ Windows/ARM64
Windows/ipch
Windows/bin-release
Windows/win-version.h
-ui_atlas.zim.png
-ui_atlas_high.zim.png
android/assets
ext/_Output
android/lint.xml
@@ -87,10 +85,10 @@ __testfinish.txt
__testfailure.bmp
GameLogNotes.txt
screenshots
-android/ui_atlas_luna.zim
android/assets/lang
android/assets/flash0
-ppge_atlas.zim.png
+ui_atlas_luna.zim.png
+ppge_atlas_luna.zim.png
local.properties
r.sh
diff --git a/.gitmodules b/.gitmodules
index a6bbcdb0c4..04a3791ff2 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,3 +28,6 @@
[submodule "ext/rapidjson"]
path = ext/rapidjson
url = https://github.com/Tencent/rapidjson.git
+[submodule "ext/native/tools/prebuilt"]
+ path = ext/native/tools/prebuilt
+ url = https://github.com/hrydgard/ppsspp-freetype.git
diff --git a/.travis.yml b/.travis.yml
index 64aff24a17..da4efe94a4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -86,11 +86,11 @@ matrix:
env: PPSSPP_BUILD_TYPE=Linux
LIBRETRO=TRUE
- os: osx
- osx_image: xcode8.3
+ osx_image: xcode9
compiler: "clang"
env: PPSSPP_BUILD_TYPE=macOS
- os: osx
- osx_image: xcode8.3
+ osx_image: xcode9
compiler: "clang"
env: PPSSPP_BUILD_TYPE=iOS
- os: windows
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 70ae3ef945..5a4520f966 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -166,6 +166,10 @@ endif()
include_directories(ext/native)
+# Work around for some misfeature of the current glslang build system
+include_directories(ext/glslang)
+
+
if(NOT OPENGL_LIBRARIES AND USING_GLES2)
set(OPENGL_LIBRARIES GLESv2 EGL)
endif()
@@ -268,6 +272,7 @@ if(NOT MSVC)
# Disable some warnings
add_definitions(-Wno-multichar)
add_definitions(-Wno-deprecated-register)
+ add_definitions(-Wno-tautological-pointer-compare)
# Don't compile with strict aliasing, we're not 100% aliasing-safe
add_compile_options(-fno-strict-aliasing)
@@ -485,12 +490,6 @@ add_library(gason STATIC
ext/native/ext/gason/gason.h
)
-add_library(rg_etc1 STATIC
- ext/native/ext/rg_etc1/rg_etc1.cpp
- ext/native/ext/rg_etc1/rg_etc1.h
-)
-include_directories(ext/native/ext/rg_etc1)
-
if(USE_FFMPEG)
if(NOT FFMPEG_DIR)
if(NOT USE_SYSTEM_FFMPEG)
@@ -661,13 +660,16 @@ else()
set(LIBZIP_LIBRARY libzip)
endif()
-# FindPNG does a few things we don't want. So do it ourselves. Fixed to libpng17
-find_path(PNG_PNG_INCLUDE_DIR NAMES "libpng17/png.h")
-find_library(PNG_LIBRARY NAMES png17 libpng17)
-find_package(PackageHandleStandardArgs)
-find_package_handle_standard_args(PNG REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR)
+# Arm platforms require at least libpng17.
+if(ANDROID OR ARMV7 OR ARM64 OR ARM OR IOS)
+ set(PNG_REQUIRED_VERSION 1.7)
+else()
+ set(PNG_REQUIRED_VERSION 1.6)
+endif()
+
+find_package(PNG ${PNG_REQUIRED_VERSION})
if(PNG_FOUND)
- include_directories(${PNG_PNG_INCLUDE_DIR})
+ include_directories(${PNG_INCLUDE_DIRS})
else()
if(ARM)
set(PNG_ARM_INCLUDES
@@ -701,8 +703,8 @@ else()
ext/native/ext/libpng17/pngwutil.c
${PNG_ARM_INCLUDES}
)
- set(PNG_LIBRARY png17)
- include_directories(ext/native/ext)
+ set(PNG_LIBRARIES png17)
+ include_directories(ext/native/ext/libpng17)
endif()
set(nativeExtra)
@@ -844,6 +846,7 @@ list(APPEND NativeAppSource
UI/DiscordIntegration.cpp
UI/NativeApp.cpp
UI/BackgroundAudio.cpp
+ UI/ChatScreen.cpp
UI/DevScreens.cpp
UI/DisplayLayoutEditor.cpp
UI/DisplayLayoutScreen.cpp
@@ -869,7 +872,6 @@ list(APPEND NativeAppSource
UI/CwCheatScreen.cpp
UI/InstallZipScreen.cpp
UI/ProfilerDraw.cpp
- UI/ui_atlas.cpp
UI/TextureUtil.cpp
UI/ComboKeyMappingScreen.cpp
)
@@ -1042,6 +1044,8 @@ add_library(native STATIC
ext/native/thread/threadutil.h
ext/native/thread/threadpool.cpp
ext/native/thread/threadpool.h
+ ext/native/ui/root.cpp
+ ext/native/ui/root.h
ext/native/ui/screen.cpp
ext/native/ui/screen.h
ext/native/ui/ui.cpp
@@ -1082,7 +1086,7 @@ if(ANDROID)
set(ATOMIC_LIB atomic)
endif()
-target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARY} ${ZLIB_LIBRARY} rg_etc1 gason udis86 ${RT_LIB} ${nativeExtraLibs} ${ATOMIC_LIB})
+target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARIES} ${ZLIB_LIBRARY} gason udis86 ${RT_LIB} ${nativeExtraLibs} ${ATOMIC_LIB})
if(TARGET Ext::GLEW)
target_link_libraries(native Ext::GLEW)
endif()
@@ -1760,8 +1764,6 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/Util/BlockAllocator.h
Core/Util/PPGeDraw.cpp
Core/Util/PPGeDraw.h
- Core/Util/ppge_atlas.cpp
- Core/Util/ppge_atlas.h
${CORE_NEON}
${GPU_SOURCES}
ext/disarm.cpp
@@ -1805,7 +1807,7 @@ if(FFmpeg_FOUND)
endif()
# Discord integration
-if(USE_DISCORD AND NOT IOS)
+if(USE_DISCORD AND NOT IOS AND NOT LIBRETRO)
add_definitions(-DUSE_DISCORD=1)
target_link_libraries(${CoreLibName} discord-rpc)
endif()
@@ -1933,6 +1935,7 @@ endif()
set(NativeAssets
android/assets/ui_atlas_luna.zim
+ android/assets/ui_atlas_luna.meta
assets/lang
assets/shaders
assets/scalers
@@ -1941,7 +1944,8 @@ set(NativeAssets
assets/compat.ini
assets/gamecontrollerdb.txt
assets/langregion.ini
- assets/ppge_atlas.zim
+ assets/ppge_atlas_luna.zim
+ assets/ppge_atlas_luna.meta
assets/rargray.png
assets/unknown.png
assets/zip.png
diff --git a/Common/ChunkFile.cpp b/Common/ChunkFile.cpp
index 22327a7575..8334e9b5a7 100644
--- a/Common/ChunkFile.cpp
+++ b/Common/ChunkFile.cpp
@@ -117,6 +117,19 @@ void PointerWrap::Do(std::wstring &x) {
(*ptr) += stringLen;
}
+void PointerWrap::Do(std::u16string &x) {
+ int stringLen = sizeof(char16_t) * ((int)x.length() + 1);
+ Do(stringLen);
+
+ switch (mode) {
+ case MODE_READ: x = (char16_t*)*ptr; break;
+ case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
+ case MODE_MEASURE: break;
+ case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (char16_t*)*ptr, "Savestate verification failure: (at %p).\n", x.c_str()); break;
+ }
+ (*ptr) += stringLen;
+}
+
struct standard_tm {
int tm_sec;
int tm_min;
diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h
index dba69b0da0..42d5b38675 100644
--- a/Common/ChunkFile.h
+++ b/Common/ChunkFile.h
@@ -459,7 +459,8 @@ public:
// Store strings.
void Do(std::string &x);
- void Do(std::wstring &x);
+ void Do(std::wstring &x); // DEPRECATED, do not save wstrings
+ void Do(std::u16string &x);
void Do(tm &t);
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index 49eeb14169..037f4258ea 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -137,7 +137,7 @@
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
stdafx.h;Common/DbgNew.h
MultiThreadedDebug
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
StreamingSIMDExtensions2
Precise
true
@@ -164,7 +164,7 @@
stdafx.h;Common/DbgNew.h
MultiThreadedDebug
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
NotSet
Precise
false
@@ -192,7 +192,7 @@
stdafx.h;Common/DbgNew.h
MultiThreadedDebug
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
NotSet
Precise
false
@@ -220,7 +220,7 @@
stdafx.h
MultiThreadedDebug
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
NotSet
Precise
false
@@ -253,7 +253,7 @@
false
StreamingSIMDExtensions2
Precise
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
Speed
true
false
@@ -283,7 +283,7 @@
true
USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
stdafx.h
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
false
NotSet
Precise
@@ -318,7 +318,7 @@
true
USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
stdafx.h
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
false
NotSet
Precise
@@ -353,7 +353,7 @@
true
USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
stdafx.h
- ../ext/native;../ext/snappy;..
+ ../ext/native;../ext/snappy;../ext/glslang;..
false
NotSet
Precise
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 68e7c01282..65547b8502 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -74,6 +74,7 @@
+
diff --git a/Common/ConsoleListener.cpp b/Common/ConsoleListener.cpp
index 6b50ae0742..2d2851d905 100644
--- a/Common/ConsoleListener.cpp
+++ b/Common/ConsoleListener.cpp
@@ -64,11 +64,7 @@ ConsoleListener::ConsoleListener() : bHidden(true)
logPending = new char[LOG_PENDING_MAX];
}
++refCount;
-#elif defined(ANDROID)
- bUseColor = false;
-#elif defined(IOS)
- bUseColor = false;
-#elif PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(SWITCH)
+#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(SWITCH)
bUseColor = false;
#elif defined(_MSC_VER)
bUseColor = false;
diff --git a/Common/GL/GLInterface/EGLSwitch.cpp b/Common/GL/GLInterface/EGLSwitch.cpp
new file mode 100644
index 0000000000..4cd670c678
--- /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 0000000000..b313158429
--- /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
index 6a8202aaf1..389f650ae7 100644
--- a/Common/GL/GLInterface/GLInterface.cpp
+++ b/Common/GL/GLInterface/GLInterface.cpp
@@ -2,10 +2,13 @@
// 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)
@@ -23,6 +26,8 @@
cInterfaceBase* HostGL_CreateGLInterface(){
#ifdef __ANDROID__
return new cInterfaceEGLAndroid;
+ #elif if PPSSPP_PLATFORM(SWITCH)
+ return new cInterfaceEGLSwitch;
#elif defined(__APPLE__)
return new cInterfaceAGL;
#elif defined(_WIN32)
diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp
index 99be29b104..e4f5f47f9a 100644
--- a/Common/KeyMap.cpp
+++ b/Common/KeyMap.cpp
@@ -343,6 +343,7 @@ void UpdateNativeMenuKeys() {
KeyDef(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE),
KeyDef(DEVICE_ID_ANY, NKCODE_BACK),
KeyDef(DEVICE_ID_ANY, NKCODE_BUTTON_B),
+ KeyDef(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_4),
};
for (size_t i = 0; i < ARRAY_SIZE(hardcodedCancelKeys); i++) {
@@ -696,12 +697,16 @@ const KeyMap_IntStrPair psp_button_names[] = {
{VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"},
{VIRTKEY_AXIS_RIGHT_X_MIN, "RightAn.Left"},
{VIRTKEY_AXIS_RIGHT_X_MAX, "RightAn.Right"},
+ {VIRTKEY_OPENCHAT, "OpenChat" },
{VIRTKEY_AXIS_SWAP, "AxisSwap"},
{VIRTKEY_DEVMENU, "DevMenu"},
{VIRTKEY_TEXTURE_DUMP, "Texture Dumping"},
{VIRTKEY_TEXTURE_REPLACE, "Texture Replacement"},
{VIRTKEY_SCREENSHOT, "Screenshot"},
+ {VIRTKEY_MUTE_TOGGLE, "Mute toggle"},
+ {VIRTKEY_ANALOG_ROTATE_CW, "Rotate Analog (CW)"},
+ {VIRTKEY_ANALOG_ROTATE_CCW, "Rotate Analog (CCW)"},
{CTRL_HOME, "Home"},
{CTRL_HOLD, "Hold"},
diff --git a/Common/KeyMap.h b/Common/KeyMap.h
index 6b39cbd4de..ce2f499f47 100644
--- a/Common/KeyMap.h
+++ b/Common/KeyMap.h
@@ -57,6 +57,10 @@ enum {
VIRTKEY_TEXTURE_DUMP = 0x40000019,
VIRTKEY_TEXTURE_REPLACE = 0x4000001A,
VIRTKEY_SCREENSHOT = 0x4000001B,
+ VIRTKEY_MUTE_TOGGLE = 0x4000001C,
+ VIRTKEY_OPENCHAT = 0x4000001D,
+ VIRTKEY_ANALOG_ROTATE_CW = 0x4000001E,
+ VIRTKEY_ANALOG_ROTATE_CCW = 0x4000001F,
VIRTKEY_LAST,
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
};
diff --git a/Common/Log.h b/Common/Log.h
index 76f867923e..1e463acadc 100644
--- a/Common/Log.h
+++ b/Common/Log.h
@@ -122,7 +122,7 @@ void AndroidAssertLog(const char *func, const char *file, int line, const char *
#if MAX_LOGLEVEL >= DEBUG_LEVEL
#define _dbg_assert_(_t_, _a_) \
if (!(_a_)) {\
- ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n\nIgnore and continue?", \
+ ERROR_LOG(_t_, #_a_ "\n\nError...\n\n Line: %d\n File: %s\n\nIgnore and continue?", \
__LINE__, __FILE__); \
if (!PanicYesNo("*** Assertion ***\n")) { Crash(); } \
}
@@ -184,4 +184,4 @@ void AndroidAssertLog(const char *func, const char *file, int line, const char *
Crash(); \
}
-#endif // __ANDROID__
\ No newline at end of file
+#endif // __ANDROID__
diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp
index 4fef8c6f3e..519bfc6bd5 100644
--- a/Common/MemoryUtil.cpp
+++ b/Common/MemoryUtil.cpp
@@ -50,7 +50,7 @@ static SYSTEM_INFO sys_info;
#endif
#define MEM_PAGE_MASK ((MEM_PAGE_SIZE)-1)
-#define round_page(x) ((((uintptr_t)(x)) + MEM_PAGE_MASK) & ~(MEM_PAGE_MASK))
+#define ppsspp_round_page(x) ((((uintptr_t)(x)) + MEM_PAGE_MASK) & ~(MEM_PAGE_MASK))
#ifdef _WIN32
// Win32 flags are odd...
@@ -127,7 +127,7 @@ void *AllocateExecutableMemory(size_t size) {
GetSystemInfo(&sys_info);
#if defined(_M_X64)
if ((uintptr_t)&hint_location > 0xFFFFFFFFULL) {
- size_t aligned_size = round_page(size);
+ size_t aligned_size = ppsspp_round_page(size);
#if 1 // Turn off to hunt for RIP bugs on x86-64.
ptr = SearchForFreeMem(aligned_size);
if (!ptr) {
@@ -161,11 +161,11 @@ void *AllocateExecutableMemory(size_t size) {
// We use a dummy global variable to give us a good location to start from.
if (!map_hint) {
if ((uintptr_t) &hint_location > 0xFFFFFFFFULL)
- map_hint = (char*)round_page(&hint_location) - 0x20000000; // 0.5gb lower than our approximate location
+ map_hint = (char*)ppsspp_round_page(&hint_location) - 0x20000000; // 0.5gb lower than our approximate location
else
map_hint = (char*)0x20000000; // 0.5GB mark in memory
} else if ((uintptr_t) map_hint > 0xFFFFFFFFULL) {
- map_hint -= round_page(size); /* round down to the next page if we're in high memory */
+ map_hint -= ppsspp_round_page(size); /* round down to the next page if we're in high memory */
}
#endif
@@ -191,7 +191,7 @@ void *AllocateExecutableMemory(size_t size) {
#if defined(_M_X64) && !defined(_WIN32)
else if ((uintptr_t)map_hint <= 0xFFFFFFFF) {
// Round up if we're below 32-bit mark, probably allocating sequentially.
- map_hint += round_page(size);
+ map_hint += ppsspp_round_page(size);
// If we moved ahead too far, skip backwards and recalculate.
// When we free, we keep moving forward and eventually move too far.
@@ -204,7 +204,7 @@ void *AllocateExecutableMemory(size_t size) {
}
void *AllocateMemoryPages(size_t size, uint32_t memProtFlags) {
- size = round_page(size);
+ size = ppsspp_round_page(size);
#ifdef _WIN32
if (sys_info.dwPageSize == 0)
GetSystemInfo(&sys_info);
diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp
index cb4dc0b33a..501690e861 100644
--- a/Common/Vulkan/VulkanContext.cpp
+++ b/Common/Vulkan/VulkanContext.cpp
@@ -285,6 +285,14 @@ void VulkanContext::EndFrame() {
}
}
+void VulkanContext::UpdateInflightFrames(int n) {
+ assert(n >= 1 && n <= MAX_INFLIGHT_FRAMES);
+ inflightFrames_ = n;
+ if (curFrame_ >= inflightFrames_) {
+ curFrame_ = 0;
+ }
+}
+
void VulkanContext::WaitUntilQueueIdle() {
// Should almost never be used
vkQueueWaitIdle(gfx_queue_);
@@ -949,20 +957,17 @@ bool VulkanContext::InitSwapchain() {
ILOG("Supported present mode: %d (%s)", presentModes[i], PresentModeString(presentModes[i]));
}
for (size_t i = 0; i < presentModeCount; i++) {
- if (swapchainPresentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) {
- // Default to the first present mode from the list.
+ bool match = false;
+ match = match || ((flags_ & VULKAN_FLAG_PRESENT_MAILBOX) && presentModes[i] == VK_PRESENT_MODE_MAILBOX_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) {
swapchainPresentMode = presentModes[i];
}
- if ((flags_ & VULKAN_FLAG_PRESENT_MAILBOX) && presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
- swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
- break;
- }
- if ((flags_ & VULKAN_FLAG_PRESENT_FIFO_RELAXED) && presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) {
- swapchainPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
- break;
- }
- if ((flags_ & VULKAN_FLAG_PRESENT_IMMEDIATE) && presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
- swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+ if (match) {
break;
}
}
diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h
index fccc3dc98e..7a5e515265 100644
--- a/Common/Vulkan/VulkanContext.h
+++ b/Common/Vulkan/VulkanContext.h
@@ -13,6 +13,7 @@ enum {
VULKAN_FLAG_PRESENT_MAILBOX = 2,
VULKAN_FLAG_PRESENT_IMMEDIATE = 4,
VULKAN_FLAG_PRESENT_FIFO_RELAXED = 8,
+ VULKAN_FLAG_PRESENT_FIFO = 16,
};
enum {
@@ -136,6 +137,7 @@ public:
VkDevice GetDevice() const { return device_; }
VkInstance GetInstance() const { return instance_; }
uint32_t GetFlags() const { return flags_; }
+ void UpdateFlags(uint32_t flags) { flags_ = flags; }
VulkanDeleteList &Delete() { return globalDeleteList_; }
@@ -174,10 +176,13 @@ public:
VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata);
void DestroyDebugMsgCallback();
- VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
+ VkPhysicalDevice GetPhysicalDevice(int n) const {
return physical_devices_[n];
}
- int GetCurrentPhysicalDevice() const {
+ VkPhysicalDevice GetCurrentPhysicalDevice() const {
+ return physical_devices_[physical_device_];
+ }
+ int GetCurrentPhysicalDeviceIndex() const {
return physical_device_;
}
int GetNumPhysicalDevices() const {
@@ -200,7 +205,7 @@ public:
const PhysicalDeviceProps &GetPhysicalDeviceProperties(int i = -1) const {
if (i < 0)
- i = GetCurrentPhysicalDevice();
+ i = GetCurrentPhysicalDeviceIndex();
return physicalDeviceProperties_[i];
}
@@ -249,6 +254,8 @@ public:
int GetInflightFrames() const {
return inflightFrames_;
}
+ // Don't call while a frame is in progress.
+ void UpdateInflightFrames(int n);
int GetCurFrame() const {
return curFrame_;
diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp
index a523ab4968..c748696c2c 100644
--- a/Common/Vulkan/VulkanLoader.cpp
+++ b/Common/Vulkan/VulkanLoader.cpp
@@ -236,6 +236,7 @@ bool g_vulkanMayBeAvailable = false;
static const char *device_name_blacklist[] = {
"NVIDIA:SHIELD Tablet K1",
+ "SDL:Horizon",
};
static const char *so_names[] = {
diff --git a/Core/Config.cpp b/Core/Config.cpp
index 30d765404b..21f22a6c29 100644
--- a/Core/Config.cpp
+++ b/Core/Config.cpp
@@ -441,6 +441,7 @@ static ConfigSetting generalSettings[] = {
ConfigSetting("AutoLoadSaveState", &g_Config.iAutoLoadSaveState, 0, true, true),
ReportedConfigSetting("EnableCheats", &g_Config.bEnableCheats, true, true, true),
ConfigSetting("CwCheatRefreshRate", &g_Config.iCwCheatRefreshRate, 77, true, true),
+ ConfigSetting("CwCheatScrollPosition", &g_Config.fCwCheatScrollPosition, 0.0f, true, true),
ConfigSetting("ScreenshotsAsPNG", &g_Config.bScreenshotsAsPNG, false, true, true),
ConfigSetting("ScreenshotsAtRenderRes", &g_Config.bScreenshotsAtRenderRes, false, true, true),
@@ -454,6 +455,9 @@ static ConfigSetting generalSettings[] = {
ConfigSetting("EnableStateUndo", &g_Config.bEnableStateUndo, false/*&DefaultEnableStateUndo*/, true, true),
ConfigSetting("RewindFlipFrequency", &g_Config.iRewindFlipFrequency, 0, true, true),
+ ConfigSetting("ShowRegionOnGameIcon", &g_Config.bShowRegionOnGameIcon, false, true, true),
+ ConfigSetting("ShowIDOnGameIcon", &g_Config.bShowIDOnGameIcon, false, true, true),
+ ConfigSetting("GameGridScale", &g_Config.fGameGridScale, 1.0, true, true),
ConfigSetting("GridView1", &g_Config.bGridView1, true),
ConfigSetting("GridView2", &g_Config.bGridView2, true),
ConfigSetting("GridView3", &g_Config.bGridView3, false),
@@ -786,6 +790,9 @@ static ConfigSetting graphicsSettings[] = {
ConfigSetting("GfxDebugSplitSubmit", &g_Config.bGfxDebugSplitSubmit, false, false, false),
ConfigSetting("LogFrameDrops", &g_Config.bLogFrameDrops, false, true, false),
+ ConfigSetting("InflightFrames", &g_Config.iInflightFrames, 3, true, false),
+ ConfigSetting("RenderDuplicateFrames", &g_Config.bRenderDuplicateFrames, false, true, true),
+
ConfigSetting(false),
};
@@ -840,6 +847,12 @@ static ConfigSetting controlSettings[] = {
ConfigSetting("ComboKey3Mapping", &g_Config.iCombokey3, 0, true, true),
ConfigSetting("ComboKey4Mapping", &g_Config.iCombokey4, 0, true, true),
+ ConfigSetting("ComboKey0Toggle", &g_Config.bComboToggle0, false, true, true),
+ ConfigSetting("ComboKey1Toggle", &g_Config.bComboToggle1, false, true, true),
+ ConfigSetting("ComboKey2Toggle", &g_Config.bComboToggle2, false, true, true),
+ ConfigSetting("ComboKey3Toggle", &g_Config.bComboToggle3, false, true, true),
+ ConfigSetting("ComboKey4Toggle", &g_Config.bComboToggle4, false, true, true),
+
#if defined(_WIN32)
// A win32 user seeing touch controls is likely using PPSSPP on a tablet. There it makes
// sense to default this to on.
@@ -861,6 +874,7 @@ static ConfigSetting controlSettings[] = {
ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 100, true, true),
ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 100, true, true),
ConfigSetting("DeadzoneRadius", &g_Config.fDeadzoneRadius, 0.2f, true, true),
+ ConfigSetting("TiltDeadzoneSkip", &g_Config.fTiltDeadzoneSkip, 0.0f, true, true),
ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, true, true),
#endif
@@ -870,6 +884,7 @@ static ConfigSetting controlSettings[] = {
ConfigSetting("TouchButtonOpacity", &g_Config.iTouchButtonOpacity, 65, true, true),
ConfigSetting("TouchButtonHideSeconds", &g_Config.iTouchButtonHideSeconds, 20, true, true),
ConfigSetting("AutoCenterTouchAnalog", &g_Config.bAutoCenterTouchAnalog, false, true, true),
+ ConfigSetting("AnalogAutoRotSpeed", &g_Config.fAnalogAutoRotSpeed, 15.0f, true, true),
// Snap touch control position
ConfigSetting("TouchSnapToGrid", &g_Config.bTouchSnapToGrid, false, true, true),
@@ -898,6 +913,8 @@ static ConfigSetting controlSettings[] = {
ConfigSetting("Speed1KeyX", "Speed1KeyY", "Speed1KeyScale", "ShowSpeed1Key", &g_Config.touchSpeed1Key, defaultTouchPosHide, true, true),
ConfigSetting("Speed2KeyX", "Speed2KeyY", "Speed2KeyScale", "ShowSpeed2Key", &g_Config.touchSpeed2Key, defaultTouchPosHide, true, true),
ConfigSetting("RapidFireKeyX", "RapidFireKeyY", "RapidFireKeyScale", "ShowRapidFireKey", &g_Config.touchRapidFireKey, defaultTouchPosHide, true, true),
+ ConfigSetting("AnalogRotationCWKeyX", "AnalogRotationKeyCWY", "AnalogRotationKeyCWScale", "ShowAnalogRotationCWKey", &g_Config.touchAnalogRotationCWKey, defaultTouchPosHide, true, true),
+ ConfigSetting("AnalogRotationCCWKeyX", "AnalogRotationKeyCCWY", "AnalogRotationKeyCCWScale", "ShowAnalogRotationCCWKey", &g_Config.touchAnalogRotationCCWKey, defaultTouchPosHide, true, true),
#ifdef _WIN32
ConfigSetting("DInputAnalogDeadzone", &g_Config.fDInputAnalogDeadzone, 0.1f, true, true),
@@ -927,7 +944,15 @@ static ConfigSetting controlSettings[] = {
static ConfigSetting networkSettings[] = {
ConfigSetting("EnableWlan", &g_Config.bEnableWlan, false, true, true),
ConfigSetting("EnableAdhocServer", &g_Config.bEnableAdhocServer, false, true, true),
-
+ ConfigSetting("EnableNetworkChat", &g_Config.bEnableNetworkChat, false, true, true),
+ ConfigSetting("ChatButtonPosition",&g_Config.iChatButtonPosition,BOTTOM_LEFT,true,true),
+ ConfigSetting("ChatScreenPosition",&g_Config.iChatScreenPosition,BOTTOM_LEFT,true,true),
+ ConfigSetting("EnableQuickChat", &g_Config.bEnableQuickChat, true, true, true),
+ ConfigSetting("QuickChat1", &g_Config.sQuickChat0, "Quick Chat 1", true, true),
+ ConfigSetting("QuickChat2", &g_Config.sQuickChat1, "Quick Chat 2", true, true),
+ ConfigSetting("QuickChat3", &g_Config.sQuickChat2, "Quick Chat 3", true, true),
+ ConfigSetting("QuickChat4", &g_Config.sQuickChat3, "Quick Chat 4", true, true),
+ ConfigSetting("QuickChat5", &g_Config.sQuickChat4, "Quick Chat 5", true, true),
ConfigSetting(false),
};
@@ -968,7 +993,7 @@ static ConfigSetting systemParamSettings[] = {
ReportedConfigSetting("ButtonPreference", &g_Config.iButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS, true, true),
ConfigSetting("LockParentalLevel", &g_Config.iLockParentalLevel, 0, true, true),
ConfigSetting("WlanAdhocChannel", &g_Config.iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC, true, true),
-#if defined(USING_WIN_UI)
+#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID)
ConfigSetting("BypassOSKWithKeyboard", &g_Config.bBypassOSKWithKeyboard, false, true, true),
ConfigSetting("DisableWinMenu", &g_Config.bDisableWinMenu, false, true, true),
ConfigSetting("DisableWinBorders", &g_Config.bDisableWinBorders, false, true, true),
@@ -1116,6 +1141,12 @@ std::map> GetLangValuesMapping() {
return langValuesMapping;
}
+void Config::Reload() {
+ reload_ = true;
+ Load();
+ reload_ = false;
+}
+
void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0;
iniFilename_ = FindConfigFile(useIniFilename ? iniFileName : "ppsspp.ini");
@@ -1492,7 +1523,8 @@ bool Config::hasGameConfig(const std::string &pGameId) {
}
void Config::changeGameSpecific(const std::string &pGameId, const std::string &title) {
- Save("changeGameSpecific");
+ if (!reload_)
+ Save("changeGameSpecific");
gameId_ = pGameId;
gameIdTitle_ = title;
bGameSpecific = !pGameId.empty();
@@ -1571,7 +1603,7 @@ bool Config::loadGameConfig(const std::string &pGameId, const std::string &title
}
void Config::unloadGameConfig() {
- if (bGameSpecific){
+ if (bGameSpecific) {
changeGameSpecific();
IniFile iniFile;
@@ -1624,6 +1656,8 @@ void Config::ResetControlLayout() {
reset(g_Config.touchSpeed1Key);
reset(g_Config.touchSpeed2Key);
reset(g_Config.touchRapidFireKey);
+ reset(g_Config.touchAnalogRotationCWKey);
+ reset(g_Config.touchAnalogRotationCCWKey);
}
void Config::GetReportingInfo(UrlEncoder &data) {
diff --git a/Core/Config.h b/Core/Config.h
index 0c08473b07..536c940c30 100644
--- a/Core/Config.h
+++ b/Core/Config.h
@@ -28,6 +28,17 @@
extern const char *PPSSPP_GIT_VERSION;
const int MAX_CONFIG_VOLUME = 8;
+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 Download;
class Downloader;
@@ -196,6 +207,7 @@ public:
bool bEnableCheats;
bool bReloadCheats;
int iCwCheatRefreshRate;
+ float fCwCheatScrollPosition;
int iBloomHack; //0 = off, 1 = safe, 2 = balanced, 3 = aggressive
bool bBlockTransferGPU;
bool bDisableSlowFramebufEffects;
@@ -205,6 +217,8 @@ public:
std::string sPostShaderName; // Off for off.
bool bGfxDebugOutput;
bool bGfxDebugSplitSubmit;
+ int iInflightFrames;
+ bool bRenderDuplicateFrames;
// Sound
bool bEnableSound;
@@ -219,6 +233,9 @@ public:
// UI
bool bShowDebuggerOnLoad;
int iShowFPSCounter;
+ bool bShowRegionOnGameIcon;
+ bool bShowIDOnGameIcon;
+ float fGameGridScale;
// TODO: Maybe move to a separate theme system.
uint32_t uItemStyleFg;
@@ -268,6 +285,8 @@ public:
int iTiltSensitivityY;
//the deadzone radius of the tilt
float fDeadzoneRadius;
+ // deadzone skip
+ float fTiltDeadzoneSkip;
//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;
@@ -286,6 +305,8 @@ public:
int iTouchButtonStyle;
int iTouchButtonOpacity;
int iTouchButtonHideSeconds;
+ // Auto rotation speed
+ float fAnalogAutoRotSpeed;
// Snap touch control position
bool bTouchSnapToGrid;
@@ -319,6 +340,8 @@ public:
ConfigTouchPos touchSpeed1Key;
ConfigTouchPos touchSpeed2Key;
ConfigTouchPos touchRapidFireKey;
+ ConfigTouchPos touchAnalogRotationCWKey;
+ ConfigTouchPos touchAnalogRotationCCWKey;
// Controls Visibility
bool bShowTouchControls;
@@ -335,6 +358,12 @@ public:
int iCombokey3;
int iCombokey4;
+ bool bComboToggle0;
+ bool bComboToggle1;
+ bool bComboToggle2;
+ bool bComboToggle3;
+ bool bComboToggle4;
+
// Ignored on iOS and other platforms that lack pause.
bool bShowTouchPause;
@@ -388,10 +417,20 @@ public:
bool bEnableAdhocServer;
int iWlanAdhocChannel;
bool bWlanPowerSave;
+ bool bEnableNetworkChat;
+ //for chat position , moveable buttons is better than this
+ int iChatButtonPosition;
+ int iChatScreenPosition;
+
+ bool bEnableQuickChat;
+ std::string sQuickChat0;
+ std::string sQuickChat1;
+ std::string sQuickChat2;
+ std::string sQuickChat3;
+ std::string sQuickChat4;
int iPSPModel;
int iFirmwareVersion;
- // TODO: Make this work with your platform, too!
bool bBypassOSKWithKeyboard;
#if defined(USING_WIN_UI)
bool bDisableWinMenu;
@@ -438,6 +477,7 @@ public:
void Load(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr);
void Save(const char *saveReason);
+ void Reload();
void RestoreDefaults();
//per game config managment, should maybe be in it's own class
@@ -476,6 +516,7 @@ protected:
void LoadStandardControllerIni();
private:
+ bool reload_ = false;
std::string gameId_;
std::string gameIdTitle_;
std::string iniFilename_;
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 021cbfb153..1c422c1593 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -71,7 +71,6 @@
-
StaticLibrary
@@ -134,7 +133,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
StreamingSIMDExtensions2
Precise
@@ -156,7 +155,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
NotSet
Precise
@@ -179,7 +178,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
NotSet
Precise
@@ -202,7 +201,7 @@
Level3
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)
NotSet
Precise
@@ -229,7 +228,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
false
StreamingSIMDExtensions2
Precise
@@ -260,7 +259,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
NotSet
Precise
false
@@ -290,7 +289,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
NotSet
Precise
false
@@ -320,7 +319,7 @@
MaxSpeed
true
true
- ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext
+ ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext
NotSet
Precise
false
@@ -834,7 +833,6 @@
-
MaxSpeed
true
@@ -1166,7 +1164,6 @@
-
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index d1257aa716..19698164c2 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -336,9 +336,6 @@
Util
-
- Util
-
HLE\Libraries
@@ -1000,9 +997,6 @@
Util
-
- Util
-
HLE\Libraries
diff --git a/Core/Debugger/WebSocket/GPUBufferSubscriber.cpp b/Core/Debugger/WebSocket/GPUBufferSubscriber.cpp
index 67b13d85b2..aff77aae30 100644
--- a/Core/Debugger/WebSocket/GPUBufferSubscriber.cpp
+++ b/Core/Debugger/WebSocket/GPUBufferSubscriber.cpp
@@ -17,7 +17,7 @@
#include
#ifndef USING_QT_UI
-#include
+#include
#include
#endif
#include "data/base64.h"
diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp
index 64b5d6197d..9ddc44f630 100644
--- a/Core/Dialog/PSPDialog.cpp
+++ b/Core/Dialog/PSPDialog.cpp
@@ -144,8 +144,13 @@ void PSPDialog::DoState(PointerWrap &p)
p.Do(isFading);
p.Do(fadeIn);
p.Do(fadeValue);
+
+ // I don't think we should save these two... Let's just ignore them for now for compat.
+ int okButtonImg = 0;
p.Do(okButtonImg);
+ int cancelButtonImg = 0;
p.Do(cancelButtonImg);
+
p.Do(okButtonFlag);
p.Do(cancelButtonFlag);
diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h
index d7875078c3..4de49d27f0 100644
--- a/Core/Dialog/PSPDialog.h
+++ b/Core/Dialog/PSPDialog.h
@@ -17,6 +17,8 @@
#pragma once
+#include "gfx/texture_atlas.h"
+
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Common/Swap.h"
@@ -112,8 +114,8 @@ protected:
bool fadeIn;
u32 fadeValue;
- int okButtonImg;
- int cancelButtonImg;
+ ImageID okButtonImg;
+ ImageID cancelButtonImg;
int okButtonFlag;
int cancelButtonFlag;
};
diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp
index a51d8ccefb..5210914309 100644
--- a/Core/Dialog/PSPGamedataInstallDialog.cpp
+++ b/Core/Dialog/PSPGamedataInstallDialog.cpp
@@ -211,7 +211,7 @@ void PSPGamedataInstallDialog::WriteSfoFile() {
size_t sfoSize;
sfoFile.WriteSFO(&sfoData,&sfoSize);
- u32 handle = pspFileSystem.OpenFile(sfopath, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE));
+ int handle = pspFileSystem.OpenFile(sfopath, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE));
if (handle >= 0) {
pspFileSystem.WriteFile(handle, sfoData, sfoSize);
pspFileSystem.CloseFile(handle);
diff --git a/Core/Dialog/PSPGamedataInstallDialog.h b/Core/Dialog/PSPGamedataInstallDialog.h
index 85d0c33fc4..5c9662e24e 100644
--- a/Core/Dialog/PSPGamedataInstallDialog.h
+++ b/Core/Dialog/PSPGamedataInstallDialog.h
@@ -62,7 +62,7 @@ private:
u64 allReadSize; // use this to calculate progress value.
int progressValue;
- u32 currentInputFile;
+ int currentInputFile;
u32 currentInputBytesLeft;
- u32 currentOutputFile;
+ int currentOutputFile;
};
diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp
index 7ef30d7691..20b3fb84a3 100755
--- a/Core/Dialog/PSPMsgDialog.cpp
+++ b/Core/Dialog/PSPMsgDialog.cpp
@@ -45,7 +45,7 @@ int PSPMsgDialog::Init(unsigned int paramAddr) {
// Ignore if already running
if (GetStatus() != SCE_UTILITY_STATUS_NONE) {
ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityMsgDialogInitStart: invalid status");
- return 0;
+ return SCE_ERROR_UTILITY_INVALID_STATUS;
}
messageDialogAddr = paramAddr;
@@ -148,10 +148,9 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK)
WRAP_WIDTH = 372.0f;
float y = 140.0f;
- float h, sy ,ey;
- int n;
- PPGeMeasureText(0, &h, &n, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
- float h2 = h * n / 2.0f;
+ float h, sy, ey;
+ PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
+ float h2 = h / 2.0f;
ey = y + h2 + 20.0f;
if (hasYesNo)
@@ -172,7 +171,7 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK)
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
}
- PPGeMeasureText(&w, &h, 0, choiceText, FONT_SCALE);
+ PPGeMeasureText(&w, &h, choiceText, FONT_SCALE);
w = 15.0f;
h = 8.0f;
float y2 = y + h2 + 8.0f;
@@ -225,14 +224,14 @@ int PSPMsgDialog::Update(int animSpeed) {
UpdateButtons();
UpdateFade(animSpeed);
- okButtonImg = I_CIRCLE;
- cancelButtonImg = I_CROSS;
+ okButtonImg = ImageID("I_CIRCLE");
+ cancelButtonImg = ImageID("I_CROSS");
okButtonFlag = CTRL_CIRCLE;
cancelButtonFlag = CTRL_CROSS;
if (messageDialog.common.buttonSwap == 1)
{
- okButtonImg = I_CROSS;
- cancelButtonImg = I_CIRCLE;
+ okButtonImg = ImageID("I_CROSS");
+ cancelButtonImg = ImageID("I_CIRCLE");
okButtonFlag = CTRL_CROSS;
cancelButtonFlag = CTRL_CIRCLE;
}
diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp
index a4f4df8083..a5c278bf06 100644
--- a/Core/Dialog/PSPNetconfDialog.cpp
+++ b/Core/Dialog/PSPNetconfDialog.cpp
@@ -28,9 +28,14 @@
#define NETCONF_CONNECT_APNET 0
#define NETCONF_STATUS_APNET 1
#define NETCONF_CONNECT_ADHOC 2
+#define NETCONF_CONNECT_APNET_LAST 3
#define NETCONF_CREATE_ADHOC 4
#define NETCONF_JOIN_ADHOC 5
+// Needs testing.
+const static int NET_INIT_DELAY_US = 300000;
+const static int NET_SHUTDOWN_DELAY_US = 26000;
+
PSPNetconfDialog::PSPNetconfDialog() {
}
@@ -39,7 +44,7 @@ PSPNetconfDialog::~PSPNetconfDialog() {
int PSPNetconfDialog::Init(u32 paramAddr) {
// Already running
- if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN)
+ if (status != SCE_UTILITY_STATUS_NONE)
return SCE_ERROR_UTILITY_INVALID_STATUS;
int size = Memory::Read_U32(paramAddr);
@@ -47,7 +52,7 @@ int PSPNetconfDialog::Init(u32 paramAddr) {
// Only copy the right size to support different request format
Memory::Memcpy(&request, paramAddr, size);
- status = SCE_UTILITY_STATUS_INITIALIZE;
+ ChangeStatusInit(NET_INIT_DELAY_US);
// Eat any keys pressed before the dialog inited.
UpdateButtons();
@@ -67,16 +72,18 @@ void PSPNetconfDialog::DrawBanner() {
}
int PSPNetconfDialog::Update(int animSpeed) {
+ if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) {
+ return SCE_ERROR_UTILITY_INVALID_STATUS;
+ }
+
UpdateButtons();
auto di = GetI18NCategory("Dialog");
auto err = GetI18NCategory("Error");
const float WRAP_WIDTH = 254.0f;
- const int confirmBtnImage = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? I_CROSS : I_CIRCLE;
+ const ImageID confirmBtnImage = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? ImageID("I_CROSS") : ImageID("I_CIRCLE");
const int confirmBtn = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CROSS : CTRL_CIRCLE;
- if (status == SCE_UTILITY_STATUS_INITIALIZE) {
- status = SCE_UTILITY_STATUS_RUNNING;
- } else if (status == SCE_UTILITY_STATUS_RUNNING && (request.netAction == NETCONF_CONNECT_APNET || request.netAction == NETCONF_STATUS_APNET)) {
+ if (request.netAction == NETCONF_CONNECT_APNET || request.netAction == NETCONF_STATUS_APNET || request.netAction == NETCONF_CONNECT_APNET_LAST) {
UpdateFade(animSpeed);
StartDraw();
DrawBanner();
@@ -87,26 +94,24 @@ int PSPNetconfDialog::Update(int animSpeed) {
if (IsButtonPressed(confirmBtn)) {
StartFade(false);
- status = SCE_UTILITY_STATUS_FINISHED;
+ ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
// TODO: When the dialog is aborted, does it really set the result to this?
// It seems to make Phantasy Star Portable 2 happy, so it should be okay for now.
request.common.result = SCE_UTILITY_DIALOG_RESULT_ABORT;
}
-
- } else if (status == SCE_UTILITY_STATUS_RUNNING && (request.netAction == NETCONF_CONNECT_ADHOC || request.netAction == NETCONF_CREATE_ADHOC || request.netAction == NETCONF_JOIN_ADHOC)) {
- if (request.NetconfData != NULL) {
+
+ EndDraw();
+ } else if (request.netAction == NETCONF_CONNECT_ADHOC || request.netAction == NETCONF_CREATE_ADHOC || request.netAction == NETCONF_JOIN_ADHOC) {
+ if (request.NetconfData.IsValid()) {
Shutdown(true);
if (sceNetAdhocctlCreate(request.NetconfData->groupName) == 0) {
- status = SCE_UTILITY_STATUS_FINISHED;
+ ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
return 0;
}
return -1;
}
- } else if (status == SCE_UTILITY_STATUS_FINISHED) {
- status = SCE_UTILITY_STATUS_SHUTDOWN;
}
- EndDraw();
return 0;
}
@@ -114,7 +119,12 @@ int PSPNetconfDialog::Shutdown(bool force) {
if (status != SCE_UTILITY_STATUS_FINISHED && !force)
return SCE_ERROR_UTILITY_INVALID_STATUS;
- return PSPDialog::Shutdown(force);
+ PSPDialog::Shutdown(force);
+ if (!force) {
+ ChangeStatusShutdown(NET_SHUTDOWN_DELAY_US);
+ }
+
+ return 0;
}
void PSPNetconfDialog::DoState(PointerWrap &p) {
diff --git a/Core/Dialog/PSPNetconfDialog.h b/Core/Dialog/PSPNetconfDialog.h
index cdb0e5686e..c3f891efd2 100644
--- a/Core/Dialog/PSPNetconfDialog.h
+++ b/Core/Dialog/PSPNetconfDialog.h
@@ -44,6 +44,11 @@ public:
virtual int Shutdown(bool force = false) override;
virtual void DoState(PointerWrap &p) override;
+protected:
+ bool UseAutoStatus() override {
+ return false;
+ }
+
private:
void DrawBanner();
SceUtilityNetconfParam request;
diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp
index b1b7cde8af..958e0cb240 100755
--- a/Core/Dialog/PSPOskDialog.cpp
+++ b/Core/Dialog/PSPOskDialog.cpp
@@ -15,9 +15,11 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+#include
+#include "base/NativeApp.h"
#include "i18n/i18n.h"
#include "math/math_util.h"
-#include
+#include "util/text/utf8.h"
#include "Core/Dialog/PSPOskDialog.h"
#include "Core/Util/PPGeDraw.h"
@@ -29,10 +31,6 @@
#include "Common/ChunkFile.h"
#include "GPU/GPUState.h"
-#if defined(USING_WIN_UI)
-#include "base/NativeApp.h"
-#endif
-
#ifndef _WIN32
#include
#include
@@ -73,73 +71,73 @@ const int kor_lconsCom[] = {18,0,2,21,3,4,26,3,5,0,7,8,15,7,9,16,7,10,18,7,11,24
// Korean (Hangul) last consonant Separation key
const int kor_lconsSpr[] = {2,1,9,4,4,12,5,4,18,8,8,0,9,8,6,10,8,7,11,8,9,12,8,16,13,8,17,14,8,18,17,17,9};
-static const wchar_t oskKeys[OSK_KEYBOARD_COUNT][5][14] =
+static const char16_t oskKeys[OSK_KEYBOARD_COUNT][5][14] =
{
{
// Latin Lowercase
- {L"1234567890-+"},
- {L"qwertyuiop[]"},
- {L"asdfghjkl;@~"},
- {L"zxcvbnm,./?\\"},
+ {u"1234567890-+"},
+ {u"qwertyuiop[]"},
+ {u"asdfghjkl;@~"},
+ {u"zxcvbnm,./?\\"},
},
{
// Latin Uppercase
- {L"!@#$%^&*()_+"},
- {L"QWERTYUIOP{}"},
- {L"ASDFGHJKL:\"`"},
- {L"ZXCVBNM<>/?|"},
+ {u"!@#$%^&*()_+"},
+ {u"QWERTYUIOP{}"},
+ {u"ASDFGHJKL:\"`"},
+ {u"ZXCVBNM<>/?|"},
},
{
// Hiragana
- {L"あかさたなはまやらわぁゃっ"},
- {L"いきしちにひみ り ぃ "},
- {L"うくすつぬふむゆるをぅゅ゛"},
- {L"えけせてねへめ れ ぇ ゜"},
- {L"おこそとのほもよろんぉょー"},
+ {u"あかさたなはまやらわぁゃっ"},
+ {u"いきしちにひみ り ぃ "},
+ {u"うくすつぬふむゆるをぅゅ゛"},
+ {u"えけせてねへめ れ ぇ ゜"},
+ {u"おこそとのほもよろんぉょー"},
},
{
// Katakana
- {L"アカサタナハマヤラワァャッ"},
- {L"イキシチニヒミ リ ィ "},
- {L"ウクスツヌフムユルヲゥュ゛"},
- {L"エケセテネヘメ レ ェ ゜"},
- {L"オコソトノホモヨロンォョー"},
+ {u"アカサタナハマヤラワァャッ"},
+ {u"イキシチニヒミ リ ィ "},
+ {u"ウクスツヌフムユルヲゥュ゛"},
+ {u"エケセテネヘメ レ ェ ゜"},
+ {u"オコソトノホモヨロンォョー"},
},
{
// Korean(Hangul)
- {L"1234567890-+"},
- {L"ㅃㅉㄸㄲㅆ!@#$%^&"},
- {L"ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ[]"},
- {L"ㅁㄴㅇㄹㅎㅗㅓㅏㅣ;@~"},
- {L"ㅋㅌㅊㅍㅠㅜㅡ<>/?|"},
+ {u"1234567890-+"},
+ {u"ㅃㅉㄸㄲㅆ!@#$%^&"},
+ {u"ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ[]"},
+ {u"ㅁㄴㅇㄹㅎㅗㅓㅏㅣ;@~"},
+ {u"ㅋㅌㅊㅍㅠㅜㅡ<>/?|"},
},
{
// Russian Lowercase
- {L"1234567890-+"},
- {L"йцукенгшщзхъ"},
- {L"фывапролджэё"},
- {L"ячсмитьбю/?|"},
+ {u"1234567890-+"},
+ {u"йцукенгшщзхъ"},
+ {u"фывапролджэё"},
+ {u"ячсмитьбю/?|"},
},
{
// Russian Uppercase
- {L"!@#$%^&*()_+"},
- {L"ЙЦУКЕНГШЩЗХЪ"},
- {L"ФЫВАПРОЛДЖЭЁ"},
- {L"ЯЧСМИТЬБЮ/?|"},
+ {u"!@#$%^&*()_+"},
+ {u"ЙЦУКЕНГШЩЗХЪ"},
+ {u"ФЫВАПРОЛДЖЭЁ"},
+ {u"ЯЧСМИТЬБЮ/?|"},
},
{
// Latin Full-width Lowercase
- { L"1234567890-+" },
- { L"qwertyuiop[]" },
- { L"asdfghjkl;@~" },
- { L"zxcvbnm,./?¥¥" },
+ { u"1234567890-+" },
+ { u"qwertyuiop[]" },
+ { u"asdfghjkl;@~" },
+ { u"zxcvbnm,./?¥¥" },
},
{
// Latin Full-width Uppercase
- { L"!@#$%^&*()_+" },
- { L"QWERTYUIOP{}" },
- { L"ASDFGHJKL:¥”‘" },
- { L"ZXCVBNM<>/?|" },
+ { u"!@#$%^&*()_+" },
+ { u"QWERTYUIOP{}" },
+ { u"ASDFGHJKL:¥”‘" },
+ { u"ZXCVBNM<>/?|" },
},
};
@@ -169,7 +167,7 @@ void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const PSPPointer& em_address)
+void GetWideStringFromPSPPointer(std::u16string& _string, const PSPPointer& em_address)
{
if (!em_address.IsValid())
{
- _string = L"";
+ _string.clear();
return;
}
const size_t maxLength = 2047;
- wchar_t stringBuffer[maxLength + 1];
- wchar_t *string = stringBuffer;
+ char16_t stringBuffer[maxLength + 1];
+ char16_t *string = stringBuffer;
u16_le *input = &em_address[0];
int c;
@@ -216,7 +214,7 @@ void GetWideStringFromPSPPointer(std::wstring& _string, const PSPPointer
_string = stringBuffer;
}
-void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const wchar_t *input)
+void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const char16_t *input)
{
char stringBuffer[2048];
char *string = stringBuffer;
@@ -317,7 +315,7 @@ int PSPOskDialog::Init(u32 oskPtr) {
i_level = 0;
- inputChars = L"";
+ inputChars.clear();
if (oskParams->fields[0].intext.IsValid()) {
auto src = oskParams->fields[0].intext;
@@ -331,13 +329,16 @@ int PSPOskDialog::Init(u32 oskPtr) {
// Eat any keys pressed before the dialog inited.
UpdateButtons();
+ std::lock_guard guard(nativeMutex_);
+ nativeStatus_ = PSPOskNativeStatus::IDLE;
+
StartFade(true);
return 0;
}
-std::wstring PSPOskDialog::CombinationKorean(bool isInput)
+std::u16string PSPOskDialog::CombinationKorean(bool isInput)
{
- std::wstring string;
+ std::u16string string;
isCombinated = true;
@@ -577,9 +578,9 @@ std::wstring PSPOskDialog::CombinationKorean(bool isInput)
return string;
}
-std::wstring PSPOskDialog::CombinationString(bool isInput)
+std::u16string PSPOskDialog::CombinationString(bool isInput)
{
- std::wstring string;
+ std::u16string string;
isCombinated = false;
@@ -658,7 +659,7 @@ std::wstring PSPOskDialog::CombinationString(bool isInput)
string += inputChars[i];
}
- if (string.size() <= FieldMaxLength())
+ if (string.size() < FieldMaxLength())
{
string += oskKeys[currentKeyboard][selectedRow][selectedCol];
}
@@ -751,7 +752,7 @@ void PSPOskDialog::RenderKeyboard()
int selectedRow = selectedChar / numKeyCols[currentKeyboard];
int selectedCol = selectedChar % numKeyCols[currentKeyboard];
- wchar_t temp[2];
+ char16_t temp[2];
temp[1] = '\0';
std::string buffer;
@@ -768,7 +769,7 @@ void PSPOskDialog::RenderKeyboard()
PPGeDrawText(oskDesc.c_str(), title , 20, PPGE_ALIGN_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF));
- std::wstring result;
+ std::u16string result;
result = CombinationString(false);
@@ -836,7 +837,6 @@ void PSPOskDialog::RenderKeyboard()
}
}
-#if defined(USING_WIN_UI)
// TODO: Why does this have a 2 button press lag/delay when
// re-opening the dialog box? I don't get it.
int PSPOskDialog::NativeKeyboard() {
@@ -844,23 +844,52 @@ int PSPOskDialog::NativeKeyboard() {
return SCE_ERROR_UTILITY_INVALID_STATUS;
}
- std::wstring titleText;
- GetWideStringFromPSPPointer(titleText, oskParams->fields[0].desc);
+#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID)
+ bool beginInputBox = false;
+ if (nativeStatus_ == PSPOskNativeStatus::IDLE) {
+ std::lock_guard guard(nativeMutex_);
+ if (nativeStatus_ == PSPOskNativeStatus::IDLE) {
+ nativeStatus_ = PSPOskNativeStatus::WAITING;
+ beginInputBox = true;
+ }
+ }
- std::wstring defaultText;
- GetWideStringFromPSPPointer(defaultText, oskParams->fields[0].intext);
+ if (beginInputBox) {
+ std::u16string titleText;
+ GetWideStringFromPSPPointer(titleText, oskParams->fields[0].desc);
- if (defaultText.empty())
- defaultText.assign(L"VALUE");
+ std::u16string defaultText;
+ GetWideStringFromPSPPointer(defaultText, oskParams->fields[0].intext);
+
+ if (defaultText.empty())
+ defaultText.assign(u"VALUE");
+
+ // There's already ConvertUCS2ToUTF8 in this file. Should we use that instead of the global ones?
+ System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), [&](bool result, const std::string &value) {
+ std::lock_guard guard(nativeMutex_);
+ if (nativeStatus_ != PSPOskNativeStatus::WAITING) {
+ return;
+ }
+
+ nativeValue_ = value;
+ nativeStatus_ = result ? PSPOskNativeStatus::SUCCESS : PSPOskNativeStatus::FAILURE;
+ });
+ } else if (nativeStatus_ == PSPOskNativeStatus::SUCCESS) {
+ inputChars = ConvertUTF8ToUCS2(nativeValue_);
+ nativeValue_.clear();
- if (System_InputBoxGetWString(titleText.c_str(), defaultText, inputChars)) {
u32 maxLength = FieldMaxLength();
if (inputChars.length() > maxLength) {
ERROR_LOG(SCEUTILITY, "NativeKeyboard: input text too long(%d characters/glyphs max), truncating to game-requested length.", maxLength);
inputChars.erase(maxLength, std::string::npos);
}
+ ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
+ nativeStatus_ = PSPOskNativeStatus::DONE;
+ } else if (nativeStatus_ == PSPOskNativeStatus::FAILURE) {
+ ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
+ nativeStatus_ = PSPOskNativeStatus::DONE;
}
- ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
+#endif
u16_le *outText = oskParams->fields[0].outtext;
@@ -870,7 +899,7 @@ int PSPOskDialog::NativeKeyboard() {
// Only write the bytes of the output and the null terminator, don't write the rest.
for (size_t i = 0; i < end; ++i) {
u16 value = 0;
- if (i < FieldMaxLength())
+ if (i < FieldMaxLength() && i < inputChars.size())
value = inputChars[i];
outText[i] = value;
}
@@ -880,7 +909,6 @@ int PSPOskDialog::NativeKeyboard() {
return 0;
}
-#endif
int PSPOskDialog::Update(int animSpeed) {
if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) {
@@ -902,12 +930,10 @@ int PSPOskDialog::Update(int animSpeed) {
int selectedRow = selectedChar / numKeyCols[currentKeyboard];
int selectedExtra = selectedChar % numKeyCols[currentKeyboard];
- // TODO: Add your platforms here when you have a NativeKeyboard func.
-
-#if defined(USING_WIN_UI)
+#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(g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen)
+ if (g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen)
return NativeKeyboard();
#endif
@@ -919,15 +945,15 @@ int PSPOskDialog::Update(int animSpeed) {
auto di = GetI18NCategory("Dialog");
- PPGeDrawImage(I_SQUARE, 365, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
+ PPGeDrawImage(ImageID("I_SQUARE"), 365, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText(di->T("Space"), 390, 222, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
if (g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE) {
- PPGeDrawImage(I_CROSS, 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
- PPGeDrawImage(I_CIRCLE, 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
+ PPGeDrawImage(ImageID("I_CROSS"), 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
+ PPGeDrawImage(ImageID("I_CIRCLE"), 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
} else {
- PPGeDrawImage(I_CIRCLE, 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
- PPGeDrawImage(I_CROSS, 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
+ PPGeDrawImage(ImageID("I_CIRCLE"), 45, 222, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
+ PPGeDrawImage(ImageID("I_CROSS"), 45, 247, 16, 16, 0, CalcFadedColor(0xFFFFFFFF));
}
PPGeDrawText(di->T("Select"), 75, 222, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
@@ -1055,9 +1081,9 @@ int PSPOskDialog::Update(int animSpeed) {
} else if (IsButtonPressed(CTRL_SQUARE) && inputChars.size() < FieldMaxLength()) {
// Use a regular space if the current keyboard isn't Japanese nor full-width English
if (currentKeyboardLanguage != OSK_LANGUAGE_JAPANESE && currentKeyboardLanguage != OSK_LANGUAGE_ENGLISH_FW)
- inputChars += L" ";
+ inputChars += u" ";
else
- inputChars += L" ";
+ inputChars += u" ";
}
EndDraw();
@@ -1070,7 +1096,7 @@ int PSPOskDialog::Update(int animSpeed) {
for (size_t i = 0; i < end; ++i)
{
u16 value = 0;
- if (i < inputChars.size())
+ if (i < FieldMaxLength() && i < inputChars.size())
value = inputChars[i];
outText[i] = value;
}
@@ -1089,6 +1115,7 @@ int PSPOskDialog::Shutdown(bool force)
if (!force) {
ChangeStatusShutdown(OSK_SHUTDOWN_DELAY_US);
}
+ nativeStatus_ = PSPOskNativeStatus::IDLE;
return 0;
}
@@ -1097,7 +1124,7 @@ void PSPOskDialog::DoState(PointerWrap &p)
{
PSPDialog::DoState(p);
- auto s = p.Section("PSPOskDialog", 1);
+ auto s = p.Section("PSPOskDialog", 1, 2);
if (!s)
return;
@@ -1106,7 +1133,14 @@ void PSPOskDialog::DoState(PointerWrap &p)
p.Do(oskIntext);
p.Do(oskOuttext);
p.Do(selectedChar);
- p.Do(inputChars);
+ if (s >= 2) {
+ p.Do(inputChars);
+ } else {
+ // Discard the wstring.
+ std::wstring wstr;
+ p.Do(wstr);
+ }
+ // Don't need to save state native status or value.
}
pspUtilityDialogCommon *PSPOskDialog::GetCommonParam()
diff --git a/Core/Dialog/PSPOskDialog.h b/Core/Dialog/PSPOskDialog.h
index cac1358f71..a244fd419a 100644
--- a/Core/Dialog/PSPOskDialog.h
+++ b/Core/Dialog/PSPOskDialog.h
@@ -17,6 +17,7 @@
#pragma once
+#include
#include
#include "Core/Dialog/PSPDialog.h"
@@ -202,6 +203,14 @@ static const std::string OskKeyboardNames[] =
"English Full-width",
};
+enum class PSPOskNativeStatus {
+ IDLE,
+ DONE,
+ WAITING,
+ SUCCESS,
+ FAILURE,
+};
+
class PSPOskDialog: public PSPDialog {
public:
PSPOskDialog();
@@ -220,14 +229,12 @@ protected:
private:
void ConvertUCS2ToUTF8(std::string& _string, const PSPPointer& em_address);
- void ConvertUCS2ToUTF8(std::string& _string, const wchar_t *input);
+ void ConvertUCS2ToUTF8(std::string& _string, const char16_t *input);
void RenderKeyboard();
-#if defined(USING_WIN_UI)
int NativeKeyboard();
-#endif
- std::wstring CombinationString(bool isInput); // for Japanese, Korean
- std::wstring CombinationKorean(bool isInput); // for Korea
+ std::u16string CombinationString(bool isInput); // for Japanese, Korean
+ std::u16string CombinationKorean(bool isInput); // for Korea
void RemoveKorean(); // for Korean character removal
u32 FieldMaxLength();
@@ -239,11 +246,15 @@ private:
std::string oskOuttext;
int selectedChar;
- std::wstring inputChars;
+ std::u16string inputChars;
OskKeyboardDisplay currentKeyboard;
OskKeyboardLanguage currentKeyboardLanguage;
bool isCombinated;
+ std::mutex nativeMutex_;
+ PSPOskNativeStatus nativeStatus_ = PSPOskNativeStatus::IDLE;
+ std::string nativeValue_;
+
int i_level; // for Korean Keyboard support
int i_value[3]; // for Korean Keyboard support
};
diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp
index e0a27decaf..4e0de7f909 100755
--- a/Core/Dialog/PSPSaveDialog.cpp
+++ b/Core/Dialog/PSPSaveDialog.cpp
@@ -534,9 +534,8 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
{
const float WRAP_WIDTH = 254.0f;
float y = 136.0f, h;
- int n;
- PPGeMeasureText(0, &h, &n, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
- float h2 = h * (float)n / 2.0f;
+ PPGeMeasureText(nullptr, &h, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
+ float h2 = h / 2.0f;
if (hasYesNo)
{
auto di = GetI18NCategory("Dialog");
@@ -555,7 +554,7 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
}
- PPGeMeasureText(&w, &h, 0, choiceText, FONT_SCALE);
+ PPGeMeasureText(&w, &h, choiceText, FONT_SCALE);
w = w / 2.0f + 5.5f;
h /= 2.0f;
float y2 = y + h2 + 4.0f;
@@ -610,13 +609,13 @@ int PSPSaveDialog::Update(int animSpeed)
UpdateButtons();
UpdateFade(animSpeed);
- okButtonImg = I_CIRCLE;
- cancelButtonImg = I_CROSS;
+ okButtonImg = ImageID("I_CIRCLE");
+ cancelButtonImg = ImageID("I_CROSS");
okButtonFlag = CTRL_CIRCLE;
cancelButtonFlag = CTRL_CROSS;
if (param.GetPspParam()->common.buttonSwap == 1) {
- okButtonImg = I_CROSS;
- cancelButtonImg = I_CIRCLE;
+ okButtonImg = ImageID("I_CROSS");
+ cancelButtonImg = ImageID("I_CIRCLE");
okButtonFlag = CTRL_CROSS;
cancelButtonFlag = CTRL_CIRCLE;
}
diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp
index c014d0ca3f..484bb6e910 100644
--- a/Core/Dialog/SavedataParam.cpp
+++ b/Core/Dialog/SavedataParam.cpp
@@ -61,7 +61,7 @@ namespace
bool ReadPSPFile(std::string filename, u8 **data, s64 dataSize, s64 *readSize)
{
- u32 handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ);
+ int handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ);
if (handle < 0)
return false;
@@ -81,7 +81,7 @@ namespace
bool WritePSPFile(std::string filename, u8 *data, SceSize dataSize)
{
- u32 handle = pspFileSystem.OpenFile(filename, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE));
+ int handle = pspFileSystem.OpenFile(filename, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE | FILEACCESS_TRUNCATE));
if (handle < 0)
return false;
diff --git a/Core/FileLoaders/DiskCachingFileLoader.cpp b/Core/FileLoaders/DiskCachingFileLoader.cpp
index bb48ad3dbf..62f733dc89 100644
--- a/Core/FileLoaders/DiskCachingFileLoader.cpp
+++ b/Core/FileLoaders/DiskCachingFileLoader.cpp
@@ -21,6 +21,7 @@
#include
#include
+#include "ppsspp_config.h"
#include "file/file_util.h"
#include "file/free.h"
#include "util/text/utf8.h"
@@ -29,6 +30,11 @@
#include "Core/FileLoaders/DiskCachingFileLoader.h"
#include "Core/System.h"
+#if PPSSPP_PLATFORM(SWITCH)
+// Far from optimal, but I guess it works...
+#define fseeko fseek
+#endif
+
static const char *CACHEFILE_MAGIC = "ppssppDC";
static const s64 SAFETY_FREE_DISK_SPACE = 768 * 1024 * 1024; // 768 MB
// Aim to allow this many files cached at once.
diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp
index c373e4dac6..8e757b3315 100644
--- a/Core/FileLoaders/LocalFileLoader.cpp
+++ b/Core/FileLoaders/LocalFileLoader.cpp
@@ -117,7 +117,12 @@ std::string LocalFileLoader::Path() const {
}
size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) {
-#if PPSSPP_PLATFORM(ANDROID)
+#if PPSSPP_PLATFORM(SWITCH)
+ // Toolchain has no fancy IO API. We must lock.
+ std::lock_guard guard(readLock_);
+ lseek(fd_, absolutePos, SEEK_SET);
+ return read(fd_, data, bytes * count) / bytes;
+#elif PPSSPP_PLATFORM(ANDROID)
// pread64 doesn't appear to actually be 64-bit safe, though such ISOs are uncommon. See #10862.
if (absolutePos <= 0x7FFFFFFF) {
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64
diff --git a/Core/FileLoaders/RamCachingFileLoader.cpp b/Core/FileLoaders/RamCachingFileLoader.cpp
index 9ea0c2e61f..bc99ad80f0 100644
--- a/Core/FileLoaders/RamCachingFileLoader.cpp
+++ b/Core/FileLoaders/RamCachingFileLoader.cpp
@@ -78,7 +78,7 @@ size_t RamCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, F
size_t bytesFromCache = ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
readSize += bytesFromCache;
if (bytesFromCache == 0) {
- // We can't read any more.
+ // We can't read any more.
break;
}
}
diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp
index 0131abdeb1..b8f2b4432b 100644
--- a/Core/FileSystems/BlockDevices.cpp
+++ b/Core/FileSystems/BlockDevices.cpp
@@ -197,7 +197,8 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
u64 lastIndexPos = index[indexSize - 1] & 0x7FFFFFFF;
u64 expectedFileSize = lastIndexPos << indexShift;
if (expectedFileSize > fileSize) {
- ERROR_LOG(LOADER, "Expected CSO to at least be %lld bytes, but file is %lld bytes", expectedFileSize, fileSize);
+ ERROR_LOG(LOADER, "Expected CSO to at least be %lld bytes, but file is %lld bytes. File: '%s'",
+ expectedFileSize, fileSize, fileLoader->Path().c_str());
NotifyReadError();
}
}
diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp
index 972c1c5d03..f5bbf8e03b 100644
--- a/Core/FileSystems/DirectoryFileSystem.cpp
+++ b/Core/FileSystems/DirectoryFileSystem.cpp
@@ -442,7 +442,8 @@ void DirectoryFileHandle::Close()
if (SetEndOfFile(hFile) == 0) {
ERROR_LOG_REPORT(FILESYS, "Failed to truncate file.");
}
-#else
+#elif !PPSSPP_PLATFORM(SWITCH)
+ // Note: it's not great that Switch cannot truncate appropriately...
if (ftruncate(hFile, (off_t)needsTrunc_) != 0) {
ERROR_LOG_REPORT(FILESYS, "Failed to truncate file.");
}
@@ -794,10 +795,17 @@ static std::string SimulateVFATBug(std::string filename) {
// These are the characters allowed in DOS filenames.
static const char *FAT_UPPER_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&'(){}-_`~";
static const char *FAT_LOWER_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&'(){}-_`~";
+ static const char *LOWER_CHARS = "abcdefghijklmnopqrstuvwxyz";
+
+ // To avoid logging/comparing, skip all this if it has no lowercase chars to begin with.
+ size_t lowerchar = filename.find_first_of(LOWER_CHARS);
+ if (lowerchar == filename.npos) {
+ return filename;
+ }
bool apply_hack = false;
size_t dot_pos = filename.find('.');
- if (dot_pos == filename.npos) {
+ if (dot_pos == filename.npos && filename.length() <= 8) {
size_t badchar = filename.find_first_not_of(FAT_LOWER_CHARS);
if (badchar == filename.npos) {
// It's all lowercase. Convert to upper.
@@ -824,6 +832,7 @@ static std::string SimulateVFATBug(std::string filename) {
}
if (apply_hack) {
+ VERBOSE_LOG(FILESYS, "Applying VFAT hack to filename: %s", filename.c_str());
// In this situation, NT would write UPPERCASE, and just set a flag to say "actually lowercase".
// That VFAT flag isn't read by the PSP firmware, so let's pretend to "not read it."
std::transform(filename.begin(), filename.end(), filename.begin(), toupper);
diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp
index b0bf0a06f6..a19c170800 100644
--- a/Core/HLE/HLE.cpp
+++ b/Core/HLE/HLE.cpp
@@ -59,6 +59,8 @@ enum
HLE_AFTER_DEBUG_BREAK = 0x20,
// Don't fill temp regs with 0xDEADBEEF.
HLE_AFTER_SKIP_DEADBEEF = 0x40,
+ // Execute pending mips calls.
+ HLE_AFTER_QUEUED_CALLS = 0x80,
};
static std::vector moduleDB;
@@ -68,6 +70,33 @@ static const char *hleAfterSyscallReschedReason;
static const HLEFunction *latestSyscall = nullptr;
static int idleOp;
+struct HLEMipsCallInfo {
+ u32 func;
+ PSPAction *action;
+ std::vector args;
+};
+
+struct HLEMipsCallStack {
+ u32_le nextOff;
+ union {
+ struct {
+ u32_le func;
+ u32_le actionIndex;
+ u32_le argc;
+ };
+ struct {
+ u32_le ra;
+ u32_le v0;
+ u32_le v1;
+ };
+ };
+};
+
+// No need to save state, always flushed at a syscall end.
+static std::vector enqueuedMipsCalls;
+// Does need to be saved, referenced by the stack and owned.
+static std::vector mipsCallActions;
+
void hleDelayResultFinish(u64 userdata, int cycleslate)
{
u32 error;
@@ -86,16 +115,14 @@ void hleDelayResultFinish(u64 userdata, int cycleslate)
WARN_LOG(HLE, "Someone else woke up HLE-blocked thread?");
}
-void HLEInit()
-{
+void HLEInit() {
RegisterAllModules();
delayedResultEvent = CoreTiming::RegisterEvent("HLEDelayedResult", hleDelayResultFinish);
idleOp = GetSyscallOp("FakeSysCalls", NID_IDLE);
}
-void HLEDoState(PointerWrap &p)
-{
- auto s = p.Section("HLE", 1);
+void HLEDoState(PointerWrap &p) {
+ auto s = p.Section("HLE", 1, 2);
if (!s)
return;
@@ -103,13 +130,35 @@ void HLEDoState(PointerWrap &p)
latestSyscall = nullptr;
p.Do(delayedResultEvent);
CoreTiming::RestoreRegisterEvent(delayedResultEvent, "HLEDelayedResult", hleDelayResultFinish);
+
+ if (s >= 2) {
+ int actions = (int)mipsCallActions.size();
+ p.Do(actions);
+ if (actions != (int)mipsCallActions.size()) {
+ mipsCallActions.resize(actions);
+ }
+
+ for (auto &action : mipsCallActions) {
+ int actionTypeID = action != nullptr ? action->actionTypeID : -1;
+ p.Do(actionTypeID);
+ if (actionTypeID != -1) {
+ if (p.mode == p.MODE_READ)
+ action = __KernelCreateAction(actionTypeID);
+ action->DoState(p);
+ }
+ }
+ }
}
-void HLEShutdown()
-{
+void HLEShutdown() {
hleAfterSyscall = HLE_AFTER_NOTHING;
latestSyscall = nullptr;
moduleDB.clear();
+ enqueuedMipsCalls.clear();
+ for (auto p : mipsCallActions) {
+ delete p;
+ }
+ mipsCallActions.clear();
}
void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable)
@@ -354,6 +403,137 @@ bool hleIsKernelMode() {
return latestSyscall && (latestSyscall->flags & HLE_KERNEL_SYSCALL) != 0;
}
+void hleEnqueueCall(u32 func, int argc, const u32 *argv, PSPAction *afterAction) {
+ std::vector args;
+ args.resize(argc);
+ memcpy(args.data(), argv, argc * sizeof(u32));
+
+ enqueuedMipsCalls.push_back({ func, afterAction, args });
+
+ hleAfterSyscall |= HLE_AFTER_QUEUED_CALLS;
+}
+
+void hleFlushCalls() {
+ u32 &sp = currentMIPS->r[MIPS_REG_SP];
+ PSPPointer stackData;
+ VERBOSE_LOG(HLE, "Flushing %d HLE mips calls from %s, sp=%08x", (int)enqueuedMipsCalls.size(), latestSyscall ? latestSyscall->name : "?", sp);
+
+ // First, we'll add a marker for the final return.
+ sp -= sizeof(HLEMipsCallStack);
+ stackData.ptr = sp;
+ stackData->nextOff = 0xFFFFFFFF;
+ stackData->ra = currentMIPS->pc;
+ stackData->v0 = currentMIPS->r[MIPS_REG_V0];
+ stackData->v1 = currentMIPS->r[MIPS_REG_V1];
+
+ // Now we'll set up the first in the chain.
+ currentMIPS->pc = enqueuedMipsCalls[0].func;
+ currentMIPS->r[MIPS_REG_RA] = HLEMipsCallReturnAddress();
+ for (int i = 0; i < (int)enqueuedMipsCalls[0].args.size(); i++) {
+ currentMIPS->r[MIPS_REG_A0 + i] = enqueuedMipsCalls[0].args[i];
+ }
+
+ // For stack info, process the first enqueued call last, so we run it first.
+ // We don't actually need to store 0's args, but keep it consistent.
+ for (int i = (int)enqueuedMipsCalls.size() - 1; i >= 0; --i) {
+ auto &info = enqueuedMipsCalls[i];
+ u32 stackRequired = (int)info.args.size() * sizeof(u32) + sizeof(HLEMipsCallStack);
+ u32 stackAligned = (stackRequired + 0xF) & ~0xF;
+
+ sp -= stackAligned;
+ stackData.ptr = sp;
+ stackData->nextOff = stackAligned;
+ stackData->func = info.func;
+ if (info.action) {
+ stackData->actionIndex = (int)mipsCallActions.size();
+ mipsCallActions.push_back(info.action);
+ } else {
+ stackData->actionIndex = 0xFFFFFFFF;
+ }
+ stackData->argc = (int)info.args.size();
+ for (int j = 0; j < (int)info.args.size(); ++j) {
+ Memory::Write_U32(info.args[j], sp + sizeof(HLEMipsCallStack) + j * sizeof(u32));
+ }
+ }
+ enqueuedMipsCalls.clear();
+
+ DEBUG_LOG(HLE, "Executing HLE mips call at %08x, sp=%08x", currentMIPS->pc, sp);
+}
+
+void HLEReturnFromMipsCall() {
+ u32 &sp = currentMIPS->r[MIPS_REG_SP];
+ PSPPointer stackData;
+
+ // At this point, we may have another mips call to run, or be at the end...
+ stackData.ptr = sp;
+
+ if ((stackData->nextOff & 0x0000000F) != 0 || !Memory::IsValidAddress(sp + stackData->nextOff)) {
+ ERROR_LOG(HLE, "Corrupt stack on HLE mips call return: %08x", stackData->nextOff);
+ Core_UpdateState(CORE_ERROR);
+ return;
+ }
+
+ if (stackData->actionIndex != 0xFFFFFFFF && stackData->actionIndex < (u32)mipsCallActions.size()) {
+ PSPAction *&action = mipsCallActions[stackData->actionIndex];
+ VERBOSE_LOG(HLE, "Executing action for HLE mips call at %08x, sp=%08x", stackData->func, sp);
+
+ // Search for the saved v0/v1 values, to preserve the PSPAction API...
+ PSPPointer finalMarker = stackData;
+ while ((finalMarker->nextOff & 0x0000000F) == 0 && Memory::IsValidAddress(finalMarker.ptr + finalMarker->nextOff)) {
+ finalMarker.ptr += finalMarker->nextOff;
+ }
+ if (finalMarker->nextOff != 0xFFFFFFFF) {
+ ERROR_LOG(HLE, "Corrupt stack on HLE mips call return action: %08x", finalMarker->nextOff);
+ Core_UpdateState(CORE_ERROR);
+ return;
+ }
+
+ MipsCall mc;
+ mc.savedV0 = finalMarker->v0;
+ mc.savedV1 = finalMarker->v1;
+ action->run(mc);
+ finalMarker->v0 = mc.savedV0;
+ finalMarker->v1 = mc.savedV1;
+
+ delete action;
+ action = nullptr;
+
+ // Note: the action could actually enqueue more, adding another layer on stack after this.
+ }
+
+ sp += stackData->nextOff;
+ stackData.ptr = sp;
+
+ if (stackData->nextOff == 0xFFFFFFFF) {
+ // We're done. Grab the HLE result's v0/v1 and return from the syscall.
+ currentMIPS->pc = stackData->ra;
+ currentMIPS->r[MIPS_REG_V0] = stackData->v0;
+ currentMIPS->r[MIPS_REG_V1] = stackData->v1;
+
+ sp += sizeof(HLEMipsCallStack);
+
+ bool canClear = true;
+ for (auto p : mipsCallActions) {
+ canClear = canClear && p == nullptr;
+ }
+ if (canClear) {
+ mipsCallActions.clear();
+ }
+
+ VERBOSE_LOG(HLE, "Finished HLE mips calls, v0=%08x, sp=%08x", currentMIPS->r[MIPS_REG_V0], sp);
+ return;
+ }
+
+ // Alright, we have another to call.
+ hleSkipDeadbeef();
+ currentMIPS->pc = stackData->func;
+ currentMIPS->r[MIPS_REG_RA] = HLEMipsCallReturnAddress();
+ for (int i = 0; i < (int)stackData->argc; i++) {
+ currentMIPS->r[MIPS_REG_A0 + i] = Memory::Read_U32(sp + sizeof(HLEMipsCallStack) + i * sizeof(u32));
+ }
+ DEBUG_LOG(HLE, "Executing next HLE mips call at %08x, sp=%08x", currentMIPS->pc, sp);
+}
+
const static u32 deadbeefRegs[12] = {0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF};
inline static void SetDeadbeefRegs()
{
@@ -375,6 +555,8 @@ inline void hleFinishSyscall(const HLEFunction &info)
if ((hleAfterSyscall & HLE_AFTER_SKIP_DEADBEEF) == 0)
SetDeadbeefRegs();
+ if ((hleAfterSyscall & HLE_AFTER_QUEUED_CALLS) != 0)
+ hleFlushCalls();
if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0 && (hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) == 0)
__KernelForceCallbacks();
@@ -661,6 +843,7 @@ void hleDoLogInternal(LogTypes::LOG_TYPE t, LogTypes::LOG_LEVELS level, u64 res,
const char *funcName = "?";
u32 funcFlags = 0;
if (latestSyscall) {
+ _dbg_assert_(HLE, latestSyscall->argmask != nullptr);
hleFormatLogArgs(formatted_args, sizeof(formatted_args), latestSyscall->argmask);
// This acts as an override (for error returns which are usually hex.)
diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h
index 4efce1cdbf..9fa4c16451 100644
--- a/Core/HLE/HLE.h
+++ b/Core/HLE/HLE.h
@@ -24,6 +24,7 @@
#include "Core/MIPS/MIPS.h"
class PointerWrap;
+class PSPAction;
typedef void (* HLEFunc)();
enum {
@@ -116,6 +117,8 @@ void hleSkipDeadbeef();
void hleSetSteppingTime(double t);
// Check if the current syscall context is kernel.
bool hleIsKernelMode();
+// Enqueue a MIPS function to be called after this HLE call finishes.
+void hleEnqueueCall(u32 func, int argc, const u32 *argv, PSPAction *afterAction = nullptr);
// Delays the result for usec microseconds, allowing other threads to run during this time.
u32 hleDelayResult(u32 result, const char *reason, int usec);
@@ -144,6 +147,8 @@ void CallSyscall(MIPSOpcode op);
void WriteFuncStub(u32 stubAddr, u32 symAddr);
void WriteFuncMissingStub(u32 stubAddr, u32 nid);
+void HLEReturnFromMipsCall();
+
const HLEFunction *GetSyscallFuncPointer(MIPSOpcode op);
// For jit, takes arg: const HLEFunction *
void *GetQuickSyscallFunc(MIPSOpcode op);
diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp
index 0f4c440c4b..c62a564b7f 100644
--- a/Core/HLE/HLETables.cpp
+++ b/Core/HLE/HLETables.cpp
@@ -89,13 +89,14 @@
//sound
//zlibdec
const HLEFunction FakeSysCalls[] = {
- {NID_THREADRETURN, __KernelReturnFromThread, "__KernelReturnFromThread"},
- {NID_CALLBACKRETURN, __KernelReturnFromMipsCall, "__KernelReturnFromMipsCall"},
- {NID_INTERRUPTRETURN, __KernelReturnFromInterrupt, "__KernelReturnFromInterrupt"},
- {NID_EXTENDRETURN, __KernelReturnFromExtendStack, "__KernelReturnFromExtendStack"},
- {NID_MODULERETURN, __KernelReturnFromModuleFunc, "__KernelReturnFromModuleFunc"},
- {NID_IDLE, __KernelIdle, "_sceKernelIdle"},
- {NID_GPUREPLAY, __KernelGPUReplay, "__KernelGPUReplay"},
+ {NID_THREADRETURN, __KernelReturnFromThread, "__KernelReturnFromThread", 'x', ""},
+ {NID_CALLBACKRETURN, __KernelReturnFromMipsCall, "__KernelReturnFromMipsCall", 'x', ""},
+ {NID_INTERRUPTRETURN, __KernelReturnFromInterrupt, "__KernelReturnFromInterrupt", 'x', ""},
+ {NID_EXTENDRETURN, __KernelReturnFromExtendStack, "__KernelReturnFromExtendStack", 'x', ""},
+ {NID_MODULERETURN, __KernelReturnFromModuleFunc, "__KernelReturnFromModuleFunc", 'x', ""},
+ {NID_IDLE, __KernelIdle, "_sceKernelIdle", 'x', ""},
+ {NID_GPUREPLAY, __KernelGPUReplay, "__KernelGPUReplay", 'x', ""},
+ {NID_HLECALLRETURN, HLEReturnFromMipsCall, "HLEReturnFromMipsCall", 'x', ""},
};
const HLEFunction UtilsForUser[] =
diff --git a/Core/HLE/HLETables.h b/Core/HLE/HLETables.h
index 2bc280f7fe..644a4efb23 100644
--- a/Core/HLE/HLETables.h
+++ b/Core/HLE/HLETables.h
@@ -22,6 +22,7 @@
#define NID_INTERRUPTRETURN 0xbadd00d5
#define NID_EXTENDRETURN 0xbad0b0c9
#define NID_MODULERETURN 0xbad0d318
+#define NID_HLECALLRETURN 0xbad0259b
#define NID_IDLE 0x1d7e1d7e
#define NID_GPUREPLAY 0x9e45bd95
diff --git a/Core/HLE/KernelThreadDebugInterface.h b/Core/HLE/KernelThreadDebugInterface.h
index 012a93fc37..55ead24e65 100644
--- a/Core/HLE/KernelThreadDebugInterface.h
+++ b/Core/HLE/KernelThreadDebugInterface.h
@@ -21,7 +21,7 @@
class KernelThreadDebugInterface : public MIPSDebugInterface {
public:
- KernelThreadDebugInterface(MIPSState *c, ThreadContext &t) : MIPSDebugInterface(c), ctx(t) {
+ KernelThreadDebugInterface(MIPSState *c, PSPThreadContext &t) : MIPSDebugInterface(c), ctx(t) {
}
unsigned int getPC() override { return ctx.pc; }
@@ -86,5 +86,5 @@ public:
}
protected:
- ThreadContext &ctx;
+ PSPThreadContext &ctx;
};
diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp
index 419d6ce53f..d248c89e88 100644
--- a/Core/HLE/proAdhoc.cpp
+++ b/Core/HLE/proAdhoc.cpp
@@ -63,6 +63,13 @@ std::recursive_mutex peerlock;
SceNetAdhocPdpStat * pdp[255];
SceNetAdhocPtpStat * ptp[255];
uint32_t localip;
+std::vector chatLog;
+std::string name = "";
+std::string incoming = "";
+std::string message = "";
+bool chatScreenVisible = false;
+bool updateChatScreen = false;
+int newChat = 0;
int isLocalMAC(const SceNetEtherAddr * addr) {
SceNetEtherAddr saddr;
@@ -1011,6 +1018,45 @@ void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) {
free(node);
}
+void sendChat(std::string chatString) {
+ SceNetAdhocctlChatPacketC2S chat;
+ auto n = GetI18NCategory("Networking");
+ chat.base.opcode = OPCODE_CHAT;
+ //TODO check network inited, check send success or not, chatlog.pushback error on failed send, pushback error on not connected
+ if (friendFinderRunning)
+ {
+ // Send Chat to Server
+ if (!chatString.empty()) {
+ //maximum char allowed is 64 character for compability with original server (pro.coldbird.net)
+ message = chatString.substr(0, 60); // 64 return chat variable corrupted is it out of memory?
+ strcpy(chat.message, message.c_str());
+ //Send Chat Messages
+ int chatResult = send(metasocket, (const char *)&chat, sizeof(chat), 0);
+ NOTICE_LOG(SCENET, "Send Chat %s to Adhoc Server", chat.message);
+ name = g_Config.sNickName.c_str();
+ chatLog.push_back(name.substr(0, 8) + ": " + chat.message);
+ if (chatScreenVisible) {
+ updateChatScreen = true;
+ }
+ }
+ }
+ else {
+ chatLog.push_back(n->T("You're in Offline Mode, go to lobby or online hall"));
+ if (chatScreenVisible) {
+ updateChatScreen = true;
+ }
+ }
+}
+
+std::vector getChatLog() {
+ // this log used by chat screen
+ if (chatLog.size() > 50) {
+ //erase the first 40 element limit the chatlog size
+ chatLog.erase(chatLog.begin(), chatLog.begin() + 40);
+ }
+ return chatLog;
+}
+
int friendFinder(){
// Receive Buffer
int rxpos = 0;
@@ -1054,13 +1100,6 @@ int friendFinder(){
}*/
}
- // Send Chat Messages
- //while(popFromOutbox(chat.message))
- //{
- // // Send Chat to Server
- // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0);
- //}
-
// Wait for Incoming Data
int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos, 0);
@@ -1110,14 +1149,23 @@ int friendFinder(){
if (rxpos >= (int)sizeof(SceNetAdhocctlChatPacketS2C)) {
// Cast Packet
SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx;
-
- // Fix for Idiots that try to troll the "ME" Nametag
- if (strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME");
-
// Add Incoming Chat to HUD
- //printf("Receive chat message %s", packet->base.message);
- DEBUG_LOG(SCENET, "Received chat message %s", packet->base.message);
-
+ NOTICE_LOG(SCENET, "Received chat message %s", packet->base.message);
+ incoming = "";
+ name = (char *)packet->name.data;
+ incoming.append(name.substr(0, 8));
+ incoming.append(": ");
+ incoming.append((char *)packet->base.message);
+ chatLog.push_back(incoming);
+ //im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming
+ if (chatScreenVisible) {
+ updateChatScreen = true;
+ }
+ else {
+ if (newChat < 50) {
+ newChat += 1;
+ }
+ }
// Move RX Buffer
memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C));
@@ -1139,7 +1187,16 @@ int friendFinder(){
// Add User
addFriend(packet);
-
+ incoming = "";
+ incoming.append((char *)packet->name.data);
+ incoming.append(" Joined ");
+ //do we need ip?
+ //joined.append((char *)packet->ip);
+ chatLog.push_back(incoming);
+ //im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming
+ if (chatScreenVisible) {
+ updateChatScreen = true;
+ }
// Update HUD User Count
#ifdef LOCALHOST_AS_PEER
setUserCount(getActivePeerCount());
diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h
index 7d266f96f9..070ea6f00f 100644
--- a/Core/HLE/proAdhoc.h
+++ b/Core/HLE/proAdhoc.h
@@ -764,10 +764,10 @@ typedef struct {
#pragma pack(pop)
#endif
-class AfterMatchingMipsCall : public Action {
+class AfterMatchingMipsCall : public PSPAction {
public:
AfterMatchingMipsCall() {}
- static Action *Create() { return new AfterMatchingMipsCall(); }
+ static PSPAction *Create() { return new AfterMatchingMipsCall(); }
void DoState(PointerWrap &p) override {
auto s = p.Section("AfterMatchingMipsCall", 1, 2);
if (!s)
@@ -851,6 +851,16 @@ SceNetAdhocMatchingMemberInternal* addMember(SceNetAdhocMatchingContext * contex
*/
void addFriend(SceNetAdhocctlConnectPacketS2C * packet);
+/**
+* Send chat or get that
+* @param std::string ChatString
+*/
+void sendChat(std::string chatString);
+std::vector getChatLog();
+extern bool chatScreenVisible;
+extern bool updateChatScreen;
+extern int newChat;
+
/*
* Find a Peer/Friend by MAC address
*/
diff --git a/Core/HLE/sceCcc.cpp b/Core/HLE/sceCcc.cpp
index 65ae665f7d..71cbfa6e40 100644
--- a/Core/HLE/sceCcc.cpp
+++ b/Core/HLE/sceCcc.cpp
@@ -28,9 +28,9 @@
#include "Core/Reporting.h"
typedef PSPPointer PSPCharPointer;
-typedef PSPPointer PSPWCharPointer;
+typedef PSPPointer PSPWCharPointer;
typedef PSPPointer PSPConstCharPointer;
-typedef PSPPointer PSPConstWCharPointer;
+typedef PSPPointer PSPConstWCharPointer;
static u16 errorUTF8;
static u16 errorUTF16;
diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp
index 876e4b5dcc..f362f65f52 100644
--- a/Core/HLE/sceDisplay.cpp
+++ b/Core/HLE/sceDisplay.cpp
@@ -49,6 +49,7 @@
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
+#include "Core/Util/PPGeDraw.h"
#include "GPU/GPU.h"
#include "GPU/GPUState.h"
@@ -549,6 +550,9 @@ static int CalculateFrameSkip() {
static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
PROFILE_THIS_SCOPE("timing");
FPSLimit fpsLimiter = PSP_CoreParameter().fpsLimit;
+ int fpsLimit = 60;
+ if (fpsLimiter != FPSLimit::NORMAL)
+ fpsLimit = fpsLimiter == FPSLimit::CUSTOM1 ? g_Config.iFpsLimit1 : g_Config.iFpsLimit2;
throttle = FrameTimingThrottled();
skipFrame = false;
@@ -556,7 +560,16 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
// we have nothing to do here.
bool doFrameSkip = g_Config.iFrameSkip != 0;
- if (!throttle && g_Config.bFrameSkipUnthrottle) {
+ bool unthrottleNeedsSkip = g_Config.bFrameSkipUnthrottle;
+ if (g_Config.bVSync && GetGPUBackend() == GPUBackend::VULKAN) {
+ // Vulkan doesn't support the interval setting, so we force frameskip.
+ unthrottleNeedsSkip = true;
+ // If it's not a clean multiple of 60, we may need frameskip to achieve it.
+ if (fpsLimit == 0 || (fpsLimit >= 0 && fpsLimit != 15 && fpsLimit != 30 && fpsLimit != 60)) {
+ doFrameSkip = true;
+ }
+ }
+ if (!throttle && unthrottleNeedsSkip) {
doFrameSkip = true;
skipFrame = true;
if (numSkippedFrames >= 7) {
@@ -571,10 +584,8 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
time_update();
float scaledTimestep = timestep;
- if (fpsLimiter == FPSLimit::CUSTOM1 && g_Config.iFpsLimit1 > 0) {
- scaledTimestep *= 60.0f / g_Config.iFpsLimit1;
- } else if (fpsLimiter == FPSLimit::CUSTOM2 && g_Config.iFpsLimit2 > 0) {
- scaledTimestep *= 60.0f / g_Config.iFpsLimit2;
+ if (fpsLimit > 0 && fpsLimit != 60) {
+ scaledTimestep *= 60.0f / fpsLimit;
}
if (lastFrameTime == 0.0 || wasPaused) {
@@ -594,13 +605,16 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
// Auto-frameskip automatically if speed limit is set differently than the default.
bool useAutoFrameskip = g_Config.bAutoFrameSkip && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
- bool forceFrameskip = (fpsLimiter == FPSLimit::CUSTOM1 && g_Config.iFpsLimit1 > 60) || (fpsLimiter == FPSLimit::CUSTOM2 && g_Config.iFpsLimit2 > 60);
+ bool forceFrameskip = fpsLimit > 60 && unthrottleNeedsSkip;
int frameSkipNum = CalculateFrameSkip();
if (g_Config.bAutoFrameSkip || forceFrameskip) {
// autoframeskip
// Argh, we are falling behind! Let's skip a frame and see if we catch up.
if (curFrameTime > nextFrameTime && doFrameSkip) {
skipFrame = true;
+ if (forceFrameskip) {
+ throttle = false;
+ }
}
} else if (frameSkipNum >= 1) {
// fixed frameskip
@@ -740,9 +754,17 @@ void __DisplayFlip(int cyclesLate) {
// Also let's always flip for animated shaders.
const ShaderInfo *shaderInfo = g_Config.sPostShaderName == "Off" ? nullptr : GetPostShaderInfo(g_Config.sPostShaderName);
bool postEffectRequiresFlip = false;
- if (shaderInfo && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE)
- postEffectRequiresFlip = shaderInfo->requires60fps;
+ // postEffectRequiresFlip is not compatible with frameskip unthrottling, see #12325.
+ if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE && !(g_Config.bFrameSkipUnthrottle && !FrameTimingThrottled())) {
+ if (shaderInfo) {
+ postEffectRequiresFlip = (shaderInfo->requires60fps || g_Config.bRenderDuplicateFrames);
+ } else {
+ postEffectRequiresFlip = g_Config.bRenderDuplicateFrames;
+ }
+ }
+
const bool fbDirty = gpu->FramebufferDirty();
+
if (fbDirty || noRecentFlip || postEffectRequiresFlip) {
int frameSleepPos = frameTimeHistoryPos;
CalculateFPS();
@@ -768,7 +790,7 @@ void __DisplayFlip(int cyclesLate) {
// Check first though, might've just quit / been paused.
if (coreState == CORE_RUNNING) {
coreState = CORE_NEXTFRAME;
- gpu->CopyDisplayToOutput();
+ gpu->CopyDisplayToOutput(fbReallyDirty);
if (fbReallyDirty) {
actualFlips++;
}
@@ -819,6 +841,7 @@ void __DisplayFlip(int cyclesLate) {
void hleAfterFlip(u64 userdata, int cyclesLate) {
gpu->BeginFrame(); // doesn't really matter if begin or end of frame.
+ PPGeNotifyFrame();
// This seems like as good a time as any to check if the config changed.
if (lagSyncScheduled != g_Config.bForceLagSync) {
@@ -929,6 +952,8 @@ void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelFormat, int sync)
if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) {
// Write immediately to the current framebuffer parameters.
framebuf = fbstate;
+ // Also update latchedFramebuf for any sceDisplayGetFramebuf() after this.
+ latchedFramebuf = fbstate;
gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt);
// IMMEDIATE means that the buffer is fine. We can just flip immediately.
// Doing it in non-buffered though creates problems (black screen) on occasion though
@@ -1033,9 +1058,7 @@ bool __DisplayGetFramebuf(PSPPointer *topaddr, u32 *linesize, u32 *pixelForm
}
static u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int latchedMode) {
- // NOTE: This is wrong and partially reverts #8753. Presumably there's something else involved here as well.
- // See #8816. Could also be a firmware version difference, there are a few of those...
- const FrameBufferState &fbState = (latchedMode == PSP_DISPLAY_SETBUF_NEXTFRAME && framebufIsLatched) ? latchedFramebuf : framebuf;
+ const FrameBufferState &fbState = latchedMode == PSP_DISPLAY_SETBUF_NEXTFRAME ? latchedFramebuf : framebuf;
if (Memory::IsValidAddress(topaddrPtr))
Memory::Write_U32(fbState.topaddr, topaddrPtr);
diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp
index 8a4ee5ed92..1e1300858d 100644
--- a/Core/HLE/sceFont.cpp
+++ b/Core/HLE/sceFont.cpp
@@ -35,9 +35,15 @@ enum {
FONT_IS_OPEN = 1,
};
+// For the save states.
+static bool useAllocCallbacks = true;
+
// Actions
static int actionPostAllocCallback;
static int actionPostOpenCallback;
+static int actionPostOpenAllocCallback;
+static int actionPostCharInfoAllocCallback;
+static int actionPostCharInfoFreeCallback;
// Monster Hunter sequence:
// 36:46:998 c:\dev\ppsspp\core\hle\scefont.cpp:469 E[HLE]: sceFontNewLib 89ad4a0, 9fff5cc
@@ -82,30 +88,31 @@ struct FontRegistryEntry {
const char *fontName;
int expireDate;
int shadow_option;
+ u32 fontFileSize;
bool ignoreIfMissing;
};
static const FontRegistryEntry fontRegistry[] = {
// This was added for Chinese translations and is not normally loaded on a PSP.
- { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_DB, 0, FONT_LANGUAGE_CHINESE, 0, 1, "zh_gb.pgf", "FTT-NewRodin Pro DB", 0, 0, true },
- { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_DB, 0, FONT_LANGUAGE_JAPANESE, 0, 1, "jpn0.pgf", "FTT-NewRodin Pro DB", 0, 0 },
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn0.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn1.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn2.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn3.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn4.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn5.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn6.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn7.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn8.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn9.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn10.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn11.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn12.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn13.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn14.pgf", "FTT-NewRodin Pro Latin", 0, 0},
- {0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn15.pgf", "FTT-Matisse Pro Latin", 0, 0},
- {0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_KOREAN, 0, 3, "kr0.pgf", "AsiaNHH(512Johab)", 0, 0},
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_DB, 0, FONT_LANGUAGE_CHINESE, 0, 1, "zh_gb.pgf", "FTT-NewRodin Pro DB", 0, 0, 1581700, true },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_DB, 0, FONT_LANGUAGE_JAPANESE, 0, 1, "jpn0.pgf", "FTT-NewRodin Pro DB", 0, 0, 1581700 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn0.pgf", "FTT-NewRodin Pro Latin", 0, 0, 69108 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn1.pgf", "FTT-Matisse Pro Latin", 0, 0, 65124 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn2.pgf", "FTT-NewRodin Pro Latin", 0, 0, 72948 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn3.pgf", "FTT-Matisse Pro Latin", 0, 0, 67700},
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn4.pgf", "FTT-NewRodin Pro Latin", 0, 0, 72828 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn5.pgf", "FTT-Matisse Pro Latin", 0, 0, 68220 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn6.pgf", "FTT-NewRodin Pro Latin", 0, 0, 77032 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn7.pgf", "FTT-Matisse Pro Latin", 0, 0, 71144 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn8.pgf", "FTT-NewRodin Pro Latin", 0, 0, 41000 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn9.pgf", "FTT-Matisse Pro Latin", 0, 0, 40164 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn10.pgf", "FTT-NewRodin Pro Latin", 0, 0, 42692 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn11.pgf", "FTT-Matisse Pro Latin", 0, 0, 41488 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn12.pgf", "FTT-NewRodin Pro Latin", 0, 0, 43136 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn13.pgf", "FTT-Matisse Pro Latin", 0, 0, 41772 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn14.pgf", "FTT-NewRodin Pro Latin", 0, 0, 45184 },
+ { 0x1c0, 0x1c0, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SERIF, FONT_STYLE_BOLD_ITALIC, 0, FONT_LANGUAGE_LATIN, 0, 1, "ltn15.pgf", "FTT-Matisse Pro Latin", 0, 0, 43044 },
+ { 0x288, 0x288, 0x2000, 0x2000, 0, 0, FONT_FAMILY_SANS_SERIF, FONT_STYLE_REGULAR, 0, FONT_LANGUAGE_KOREAN, 0, 3, "kr0.pgf", "AsiaNHH(512Johab)", 0, 0, 394192 },
};
static const float pointDPI = 72.f;
@@ -204,6 +211,7 @@ public:
PGF *GetPGF() { return &pgf_; }
const PGF *GetPGF() const { return &pgf_; }
+ u32 getSize() const { return dataSize_; }
bool IsValid() const { return valid_; }
void DoState(PointerWrap &p) {
@@ -228,6 +236,7 @@ private:
style_.fontV = (float)pgf_.header.vSize / 64.0f;
style_.fontHRes = (float)pgf_.header.hResolution / 64.0f;
style_.fontVRes = (float)pgf_.header.vResolution / 64.0f;
+ this->dataSize_ = (u32)dataSize;
}
void Init(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
@@ -247,11 +256,13 @@ private:
strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName));
style_.fontAttributes = entry.extraAttributes;
style_.fontExpire = entry.expireDate;
+ this->dataSize_ = entry.fontFileSize;
}
PGF pgf_;
PGFFontStyle style_;
bool valid_;
+ u32 dataSize_;
DISALLOW_COPY_AND_ASSIGN(Font);
};
@@ -338,10 +349,10 @@ private:
DISALLOW_COPY_AND_ASSIGN(LoadedFont);
};
-class PostAllocCallback : public Action {
+class PostAllocCallback : public PSPAction {
public:
PostAllocCallback() {}
- static Action *Create() { return new PostAllocCallback(); }
+ static PSPAction *Create() { return new PostAllocCallback(); }
void DoState(PointerWrap &p) override {
auto s = p.Section("PostAllocCallback", 1, 2);
if (!s)
@@ -360,10 +371,10 @@ private:
u32 errorCodePtr_;
};
-class PostOpenCallback : public Action {
+class PostOpenCallback : public PSPAction {
public:
PostOpenCallback() {}
- static Action *Create() { return new PostOpenCallback(); }
+ static PSPAction *Create() { return new PostOpenCallback(); }
void DoState(PointerWrap &p) override {
auto s = p.Section("PostOpenCallback", 1);
if (!s)
@@ -378,6 +389,69 @@ private:
u32 fontLibID_;
};
+class PostOpenAllocCallback : public PSPAction {
+public:
+ PostOpenAllocCallback() {}
+ static PSPAction *Create() { return new PostOpenAllocCallback(); }
+ void DoState(PointerWrap &p) override {
+ auto s = p.Section("PostOpenAllocCallback", 1);
+ if (!s)
+ return;
+
+ p.Do(fontLibID_);
+ p.Do(fontHandle_);
+ p.Do(fontIndex_);
+ }
+ void run(MipsCall &call) override;
+ void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
+ void SetFont(u32 handle, int index) { fontHandle_ = handle; fontIndex_ = index; }
+
+private:
+ u32 fontLibID_;
+ u32 fontHandle_;
+ int fontIndex_;
+};
+
+class PostCharInfoAllocCallback : public PSPAction {
+public:
+ PostCharInfoAllocCallback() {}
+ static PSPAction *Create() { return new PostCharInfoAllocCallback(); }
+ void DoState(PointerWrap &p) override {
+ auto s = p.Section("PostCharInfoAllocCallback", 1);
+ if (!s)
+ return;
+
+ p.Do(fontLibID_);
+ }
+ void run(MipsCall &call) override;
+ void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
+
+private:
+ u32 fontLibID_;
+};
+
+class PostCharInfoFreeCallback : public PSPAction {
+public:
+ PostCharInfoFreeCallback() {}
+ static PSPAction *Create() { return new PostCharInfoFreeCallback(); }
+ void DoState(PointerWrap &p) override {
+ auto s = p.Section("PostCharInfoFreeCallback", 1);
+ if (!s)
+ return;
+
+ p.Do(fontLibID_);
+ p.Do(charInfo_);
+ }
+ void run(MipsCall &call) override;
+ void SetFontLib(u32 fontLibID) { fontLibID_ = fontLibID; }
+ void SetCharInfo(PSPPointer charInfo) { charInfo_ = charInfo; }
+
+private:
+ u32 fontLibID_;
+ PSPPointer charInfo_;
+};
+
+
struct NativeFontLib {
FontNewLibParams params;
// TODO
@@ -406,7 +480,7 @@ public:
// For save states only.
}
- FontLib(u32 paramPtr, u32 errorCodePtr) : fontHRes_(128.0f), fontVRes_(128.0f), altCharCode_(0x5F) {
+ FontLib(u32 paramPtr, u32 errorCodePtr) : fontHRes_(128.0f), fontVRes_(128.0f), altCharCode_(0x5F), charInfoBitmapAddress_(0) {
nfl_ = 0;
Memory::ReadStruct(paramPtr, ¶ms_);
if (params_.numFonts > 9) {
@@ -418,8 +492,8 @@ public:
PostAllocCallback *action = (PostAllocCallback *) __KernelCreateAction(actionPostAllocCallback);
action->SetFontLib(GetListID(), errorCodePtr);
- u32 args[2] = { params_.userDataAddr, allocSize };
- __KernelDirectMipsCall(params_.allocFuncAddr, action, args, 2, true);
+ u32 args[2] = { userDataAddr(), allocSize };
+ hleEnqueueCall(allocFuncAddr(), 2, args, action);
}
u32 GetListID() {
@@ -429,25 +503,29 @@ public:
void Done() {
for (size_t i = 0; i < fonts_.size(); i++) {
if (isfontopen_[i] == FONT_IS_OPEN) {
- fontMap[fonts_[i]]->Close();
+ CloseFont(fontMap[fonts_[i]]);
delete fontMap[fonts_[i]];
fontMap.erase(fonts_[i]);
}
}
- u32 args[2] = { params_.userDataAddr, (u32)handle_ };
+ u32 args[2] = { userDataAddr(), (u32)handle_ };
// TODO: The return value of this is leaking.
if (handle_) { // Avoid calling free-callback on double-free
- __KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
+ if (coreState != CORE_POWERDOWN) {
+ hleEnqueueCall(freeFuncAddr(), 2, args);
+ }
}
handle_ = 0;
fonts_.clear();
isfontopen_.clear();
+ openAllocatedAddresses_.clear();
}
void AllocDone(u32 allocatedAddr) {
handle_ = allocatedAddr;
fonts_.resize(params_.numFonts);
isfontopen_.resize(params_.numFonts);
+ openAllocatedAddresses_.resize(params_.numFonts);
for (size_t i = 0; i < fonts_.size(); i++) {
u32 addr = allocatedAddr + 0x4C + (u32)i * 0x4C;
isfontopen_[i] = 0;
@@ -471,6 +549,9 @@ public:
u32 handle() const { return handle_; }
int numFonts() const { return params_.numFonts; }
+ u32_le userDataAddr() const{ return params_.userDataAddr; }
+ u32_le allocFuncAddr() const { return params_.allocFuncAddr; }
+ u32_le freeFuncAddr() const { return params_.freeFuncAddr; }
void SetResolution(float hres, float vres) {
fontHRes_ = hres;
@@ -524,6 +605,24 @@ public:
delete prevFont->second;
}
fontMap[loadedFont->Handle()] = loadedFont;
+
+ if (!useAllocCallbacks)
+ return loadedFont;
+
+ u32 allocSize = 12;
+ if (mode == FONT_OPEN_INTERNAL_STINGY) {
+ allocSize = 0x239B4;
+ } else if (mode == FONT_OPEN_INTERNAL_FULL) {
+ allocSize += loadedFont->GetFont()->getSize();
+ }
+
+ PostOpenAllocCallback *action = (PostOpenAllocCallback *)__KernelCreateAction(actionPostOpenAllocCallback);
+ action->SetFontLib(GetListID());
+ action->SetFont(loadedFont->Handle(), freeFontIndex);
+
+ u32 args[2] = { userDataAddr(), allocSize };
+ hleEnqueueCall(allocFuncAddr(), 2, args, action);
+
return loadedFont;
}
@@ -531,14 +630,28 @@ public:
for (size_t i = 0; i < fonts_.size(); i++) {
if (fonts_[i] == font->Handle()) {
isfontopen_[i] = 0;
-
+ if (openAllocatedAddresses_[i] != 0 && coreState != CORE_POWERDOWN) {
+ u32 args[2] = { userDataAddr(), openAllocatedAddresses_[i] };
+ hleEnqueueCall(freeFuncAddr(), 2, args);
+ openAllocatedAddresses_[i] = 0;
+ }
+ break;
}
}
+ flushFont();
font->Close();
}
+ void flushFont() {
+ if (charInfoBitmapAddress_ != 0 && coreState != CORE_POWERDOWN) {
+ u32 args[2] = { userDataAddr(), charInfoBitmapAddress_ };
+ hleEnqueueCall(freeFuncAddr(), 2, args);
+ charInfoBitmapAddress_ = 0;
+ }
+ }
+
void DoState(PointerWrap &p) {
- auto s = p.Section("FontLib", 1, 2);
+ auto s = p.Section("FontLib", 1, 3);
if (!s)
return;
@@ -555,6 +668,14 @@ public:
} else {
nfl_ = 0;
}
+
+ if (s >= 3) {
+ p.Do(openAllocatedAddresses_);
+ p.Do(charInfoBitmapAddress_);
+ } else {
+ openAllocatedAddresses_.resize(params_.numFonts);
+ charInfoBitmapAddress_ = 0;
+ }
}
void SetFileFontHandle(u32 handle) {
@@ -563,6 +684,20 @@ public:
u32 GetAltCharCode() const { return altCharCode_; }
+ u32 GetOpenAllocatedAddress(int index) const {
+ if(index < numFonts())
+ return openAllocatedAddresses_[index];
+ return 0;
+ }
+
+ void SetOpenAllocatedAddress(int index, u32 addr) {
+ if (index < numFonts())
+ openAllocatedAddresses_[index] = addr;
+ }
+
+ u32 GetCharInfoBitmapAddress() const { return charInfoBitmapAddress_; }
+ void SetCharInfoBitmapAddress(u32 addr) { charInfoBitmapAddress_ = addr; }
+
private:
std::vector fonts_;
std::vector isfontopen_;
@@ -573,6 +708,8 @@ private:
int fileFontHandle_;
int handle_;
int altCharCode_;
+ std::vector openAllocatedAddresses_;
+ u32 charInfoBitmapAddress_;
PSPPointer nfl_;
DISALLOW_COPY_AND_ASSIGN(FontLib);
@@ -590,6 +727,7 @@ void PostAllocCallback::run(MipsCall &call) {
FontLib *fontLib = fontLibList[fontLibID_];
fontLib->AllocDone(v0);
fontLibMap[fontLib->handle()] = fontLibID_;
+ // This is the same as v0 above.
call.setReturnValue(fontLib->handle());
}
INFO_LOG(SCEFONT, "Leaving PostAllocCallback::run");
@@ -601,6 +739,34 @@ void PostOpenCallback::run(MipsCall &call) {
fontLib->SetFileFontHandle(v0);
}
+void PostOpenAllocCallback::run(MipsCall &call) {
+ FontLib *fontLib = fontLibList[fontLibID_];
+ u32 v0 = currentMIPS->r[MIPS_REG_V0];
+ fontLib->SetOpenAllocatedAddress(fontIndex_, v0);
+}
+
+void PostCharInfoAllocCallback::run(MipsCall &call) {
+ FontLib *fontLib = fontLibList[fontLibID_];
+ u32 v0 = currentMIPS->r[MIPS_REG_V0];
+ if (v0 == 0) {
+ call.setReturnValue(ERROR_FONT_OUT_OF_MEMORY); // From JPCSP, if alloc size is 0, still this error value?
+ } else {
+ fontLib->SetCharInfoBitmapAddress(v0);
+ }
+}
+
+void PostCharInfoFreeCallback::run(MipsCall &call) {
+ FontLib *fontLib = fontLibList[fontLibID_];
+ fontLib->SetCharInfoBitmapAddress(0);
+
+ u32 allocSize = charInfo_->bitmapWidth * charInfo_->bitmapHeight;
+ PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);
+ action->SetFontLib(fontLibID_);
+
+ u32 args[2] = { fontLib->userDataAddr(), allocSize };
+ hleEnqueueCall(fontLib->allocFuncAddr(), 2, args, action);
+}
+
inline bool LoadedFont::GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType) const {
auto fontLib = GetFontLib();
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
@@ -709,8 +875,12 @@ int GetInternalFontIndex(Font *font) {
}
void __FontInit() {
+ useAllocCallbacks = true;
actionPostAllocCallback = __KernelRegisterActionType(PostAllocCallback::Create);
actionPostOpenCallback = __KernelRegisterActionType(PostOpenCallback::Create);
+ actionPostOpenAllocCallback = __KernelRegisterActionType(PostOpenAllocCallback::Create);
+ actionPostCharInfoAllocCallback = __KernelRegisterActionType(PostCharInfoAllocCallback::Create);
+ actionPostCharInfoFreeCallback = __KernelRegisterActionType(PostCharInfoFreeCallback::Create);
}
void __FontShutdown() {
@@ -733,7 +903,7 @@ void __FontShutdown() {
}
void __FontDoState(PointerWrap &p) {
- auto s = p.Section("sceFont", 1);
+ auto s = p.Section("sceFont", 1, 2);
if (!s)
return;
@@ -747,6 +917,16 @@ void __FontDoState(PointerWrap &p) {
__KernelRestoreActionType(actionPostAllocCallback, PostAllocCallback::Create);
p.Do(actionPostOpenCallback);
__KernelRestoreActionType(actionPostOpenCallback, PostOpenCallback::Create);
+ if (s >= 2) {
+ p.Do(actionPostOpenAllocCallback);
+ __KernelRestoreActionType(actionPostOpenAllocCallback, PostOpenAllocCallback::Create);
+ p.Do(actionPostCharInfoAllocCallback);
+ __KernelRestoreActionType(actionPostCharInfoAllocCallback, PostCharInfoAllocCallback::Create);
+ p.Do(actionPostCharInfoFreeCallback);
+ __KernelRestoreActionType(actionPostCharInfoFreeCallback, PostCharInfoFreeCallback::Create);
+ } else {
+ useAllocCallbacks = false;
+ }
}
static u32 sceFontNewLib(u32 paramPtr, u32 errorCodePtr) {
@@ -912,14 +1092,13 @@ static u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u3
static int sceFontClose(u32 fontHandle) {
LoadedFont *font = GetLoadedFont(fontHandle, false);
- if (font)
- {
+ if (font) {
DEBUG_LOG(SCEFONT, "sceFontClose(%x)", fontHandle);
FontLib *fontLib = font->GetFontLib();
- if (fontLib)
+ if (fontLib) {
fontLib->CloseFont(font);
- }
- else
+ }
+ } else
ERROR_LOG(SCEFONT, "sceFontClose(%x) - font not open?", fontHandle);
return 0;
}
@@ -1100,6 +1279,27 @@ static int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
auto charInfo = PSPPointer::Create(charInfoPtr);
font->GetCharInfo(charCode, charInfo);
+ if (!useAllocCallbacks)
+ return 0;
+
+ u32 allocSize = charInfo->bitmapWidth * charInfo->bitmapHeight;
+ if (charInfo->sfp26AdvanceH != 0 || charInfo->sfp26AdvanceV != 0) {
+ if (font->GetFontLib()->GetCharInfoBitmapAddress() != 0) {
+ PostCharInfoFreeCallback *action = (PostCharInfoFreeCallback *)__KernelCreateAction(actionPostCharInfoFreeCallback);
+ action->SetFontLib(font->GetFontLib()->GetListID());
+ action->SetCharInfo(charInfo);
+
+ u32 args[2] = { font->GetFontLib()->userDataAddr(), font->GetFontLib()->GetCharInfoBitmapAddress() };
+ hleEnqueueCall(font->GetFontLib()->freeFuncAddr(), 2, args, action);
+ } else {
+ PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);
+ action->SetFontLib(font->GetFontLib()->GetListID());
+
+ u32 args[2] = { font->GetFontLib()->userDataAddr(), allocSize };
+ hleEnqueueCall(font->GetFontLib()->allocFuncAddr(), 2, args, action);
+ }
+ }
+
return 0;
}
@@ -1215,7 +1415,15 @@ static int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode) {
static int sceFontFlush(u32 fontHandle) {
INFO_LOG(SCEFONT, "sceFontFlush(%i)", fontHandle);
- // Probably don't need to do anything here.
+
+ LoadedFont *font = GetLoadedFont(fontHandle, true);
+ if (!font) {
+ ERROR_LOG_REPORT(SCEFONT, "sceFontFlush(%08x): bad font", fontHandle);
+ return ERROR_FONT_INVALID_PARAMETER;
+ }
+
+ font->GetFontLib()->flushFont();
+
return 0;
}
diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp
index 04e1df23f7..9092260864 100644
--- a/Core/HLE/sceIo.cpp
+++ b/Core/HLE/sceIo.cpp
@@ -930,7 +930,7 @@ static u32 sceIoGetstat(const char *filename, u32 addr) {
}
static u32 sceIoChstat(const char *filename, u32 iostatptr, u32 changebits) {
- ERROR_LOG(SCEIO, "UNIMPL sceIoChstat(%s, %08x, %08x)", filename, iostatptr, changebits);
+ ERROR_LOG_REPORT(SCEIO, "UNIMPL sceIoChstat(%s, %08x, %08x)", filename, iostatptr, changebits);
if (changebits & SCE_CST_MODE)
ERROR_LOG(SCEIO, "sceIoChstat: change mode requested");
if (changebits & SCE_CST_ATTR)
@@ -2731,7 +2731,8 @@ static int IoAsyncFinish(int id) {
break;
default:
- ERROR_LOG_REPORT(SCEIO, "Unknown async op %d", params.op);
+ ERROR_LOG_REPORT(SCEIO, "Unknown async op %d", (int)params.op);
+ us = 0;
break;
}
diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp
index bed6e58e08..de9c5435ff 100644
--- a/Core/HLE/sceKernelAlarm.cpp
+++ b/Core/HLE/sceKernelAlarm.cpp
@@ -37,16 +37,14 @@ struct NativeAlarm
u32_le commonPtr;
};
-struct Alarm : public KernelObject
-{
+struct PSPAlarm : public KernelObject {
const char *GetName() override {return "[Alarm]";}
const char *GetTypeName() override {return "Alarm";}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_ALMID; }
static int GetStaticIDType() { return SCE_KERNEL_TMID_Alarm; }
int GetIDType() const override { return SCE_KERNEL_TMID_Alarm; }
- void DoState(PointerWrap &p) override
- {
+ void DoState(PointerWrap &p) override {
auto s = p.Section("Alarm", 1);
if (!s)
return;
@@ -57,7 +55,7 @@ struct Alarm : public KernelObject
NativeAlarm alm;
};
-void __KernelScheduleAlarm(Alarm *alarm, u64 micro);
+void __KernelScheduleAlarm(PSPAlarm *alarm, u64 micro);
class AlarmIntrHandler : public IntrHandler
{
@@ -69,7 +67,7 @@ public:
u32 error;
int alarmID = triggeredAlarm.front();
- Alarm *alarm = kernelObjects.Get(alarmID, error);
+ PSPAlarm *alarm = kernelObjects.Get(alarmID, error);
if (error)
{
WARN_LOG(SCEKERNEL, "Ignoring deleted alarm %08x", alarmID);
@@ -95,7 +93,7 @@ public:
{
DEBUG_LOG(SCEKERNEL, "Rescheduling alarm %08x for +%dms", alarmID, result);
u32 error;
- Alarm *alarm = kernelObjects.Get(alarmID, error);
+ PSPAlarm *alarm = kernelObjects.Get(alarmID, error);
__KernelScheduleAlarm(alarm, result);
}
else
@@ -106,21 +104,19 @@ public:
DEBUG_LOG(SCEKERNEL, "Finished alarm %08x", alarmID);
// Delete the alarm if it's not rescheduled.
- kernelObjects.Destroy(alarmID);
+ kernelObjects.Destroy(alarmID);
}
}
};
static int alarmTimer = -1;
-static void __KernelTriggerAlarm(u64 userdata, int cyclesLate)
-{
+static void __KernelTriggerAlarm(u64 userdata, int cyclesLate) {
int uid = (int) userdata;
u32 error;
- Alarm *alarm = kernelObjects.Get(uid, error);
- if (alarm)
- {
+ PSPAlarm *alarm = kernelObjects.Get(uid, error);
+ if (alarm) {
triggeredAlarm.push_back(uid);
__TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR);
}
@@ -144,14 +140,12 @@ void __KernelAlarmDoState(PointerWrap &p)
CoreTiming::RestoreRegisterEvent(alarmTimer, "Alarm", __KernelTriggerAlarm);
}
-KernelObject *__KernelAlarmObject()
-{
+KernelObject *__KernelAlarmObject() {
// Default object to load from state.
- return new Alarm;
+ return new PSPAlarm;
}
-void __KernelScheduleAlarm(Alarm *alarm, u64 micro)
-{
+void __KernelScheduleAlarm(PSPAlarm *alarm, u64 micro) {
alarm->alm.schedule = CoreTiming::GetGlobalTimeUs() + micro;
CoreTiming::ScheduleEvent(usToCycles(micro), alarmTimer, alarm->GetUID());
}
@@ -161,7 +155,7 @@ static SceUID __KernelSetAlarm(u64 micro, u32 handlerPtr, u32 commonPtr)
if (!Memory::IsValidAddress(handlerPtr))
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
- Alarm *alarm = new Alarm;
+ PSPAlarm *alarm = new PSPAlarm();
SceUID uid = kernelObjects.Create(alarm);
alarm->alm.size = NATIVEALARM_SIZE;
@@ -197,13 +191,13 @@ int sceKernelCancelAlarm(SceUID uid)
CoreTiming::UnscheduleEvent(alarmTimer, uid);
- return kernelObjects.Destroy(uid);
+ return kernelObjects.Destroy(uid);
}
int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr)
{
u32 error;
- Alarm *alarm = kernelObjects.Get(uid, error);
+ PSPAlarm *alarm = kernelObjects.Get(uid, error);
if (!alarm)
{
ERROR_LOG(SCEKERNEL, "sceKernelReferAlarmStatus(%08x, %08x): invalid alarm", uid, infoPtr);
@@ -228,4 +222,4 @@ int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr)
Memory::Write_U32(alarm->alm.commonPtr, infoPtr + 16);
return 0;
-}
\ No newline at end of file
+}
diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp
index 2674a7b2fa..6ec86f99af 100644
--- a/Core/HLE/sceKernelInterrupt.cpp
+++ b/Core/HLE/sceKernelInterrupt.cpp
@@ -48,15 +48,13 @@ static const u32 PSP_NUMBER_SUBINTERRUPTS = 32;
// INTERRUPT MANAGEMENT
//////////////////////////////////////////////////////////////////////////
-class InterruptState
-{
+class InterruptState {
public:
void save();
void restore();
void clear();
- void DoState(PointerWrap &p)
- {
+ void DoState(PointerWrap &p) {
auto s = p.Section("InterruptState", 1);
if (!s)
return;
@@ -64,7 +62,7 @@ public:
p.Do(savedCpu);
}
- ThreadContext savedCpu;
+ PSPThreadContext savedCpu;
};
// STATE
diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp
index ab71ca4d67..46e5375397 100644
--- a/Core/HLE/sceKernelMemory.cpp
+++ b/Core/HLE/sceKernelMemory.cpp
@@ -213,10 +213,6 @@ struct SceKernelVplHeader {
do {
auto b = prev->next;
if (b->sizeInBlocks > allocBlocks) {
- if (nextFreeBlock_ == b) {
- nextFreeBlock_ = prev;
- }
- prev = b;
b = SplitBlock(b, allocBlocks);
}
@@ -289,16 +285,13 @@ struct SceKernelVplHeader {
void UnlinkFreeBlock(PSPPointer b, PSPPointer prev) {
allocatedInBlocks_ += b->sizeInBlocks;
prev->next = b->next;
- if (nextFreeBlock_ == b) {
- nextFreeBlock_ = prev;
- }
+ nextFreeBlock_ = prev;
b->next = SentinelPtr();
}
PSPPointer SplitBlock(PSPPointer b, u32 allocBlocks) {
- u32 prev = b->next.ptr;
+ u32 prev = b.ptr;
b->sizeInBlocks -= allocBlocks;
- b->next = b + b->sizeInBlocks;
b += b->sizeInBlocks;
b->sizeInBlocks = allocBlocks;
diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp
index 8485136e7a..1d37b3c802 100644
--- a/Core/HLE/sceKernelModule.cpp
+++ b/Core/HLE/sceKernelModule.cpp
@@ -155,8 +155,8 @@ void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting);
void ExportFuncSymbol(const FuncSymbolExport &func);
void UnexportFuncSymbol(const FuncSymbolExport &func);
-class Module;
-static bool KernelImportModuleFuncs(Module *module, u32 *firstImportStubAddr, bool reimporting = false);
+class PSPModule;
+static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting = false);
struct NativeModule {
u32_le next;
@@ -228,10 +228,10 @@ enum NativeModuleStatus {
MODULE_STATUS_UNLOADING = 8,
};
-class Module : public KernelObject {
+class PSPModule : public KernelObject {
public:
- Module() : textStart(0), textEnd(0), libstub(0), libstubend(0), memoryBlockAddr(0), isFake(false) {}
- ~Module() {
+ PSPModule() : textStart(0), textEnd(0), libstub(0), libstubend(0), memoryBlockAddr(0), isFake(false) {}
+ ~PSPModule() {
if (memoryBlockAddr) {
// If it's either below user memory, or using a high kernel bit, it's in kernel.
if (memoryBlockAddr < PSP_GetUserMemoryBase() || memoryBlockAddr > PSP_GetUserMemoryEnd()) {
@@ -421,10 +421,10 @@ public:
KernelObject *__KernelModuleObject()
{
- return new Module;
+ return new PSPModule;
}
-class AfterModuleEntryCall : public Action {
+class AfterModuleEntryCall : public PSPAction {
public:
AfterModuleEntryCall() {}
SceUID moduleID_;
@@ -438,7 +438,7 @@ public:
p.Do(moduleID_);
p.Do(retValAddr);
}
- static Action *Create() {
+ static PSPAction *Create() {
return new AfterModuleEntryCall;
}
};
@@ -507,7 +507,7 @@ void __KernelModuleDoState(PointerWrap &p)
u32 error;
// We process these late, since they depend on loadedModules for interlinking.
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (module && module->libstub != 0) {
if (!KernelImportModuleFuncs(module, nullptr, true)) {
ERROR_LOG(LOADER, "Something went wrong loading imports on load state");
@@ -655,7 +655,7 @@ void ImportVarSymbol(const VarSymbolImport &var) {
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
continue;
}
@@ -676,7 +676,7 @@ void ImportVarSymbol(const VarSymbolImport &var) {
void ExportVarSymbol(const VarSymbolExport &var) {
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
continue;
}
@@ -694,7 +694,7 @@ void ExportVarSymbol(const VarSymbolExport &var) {
void UnexportVarSymbol(const VarSymbolExport &var) {
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module || !module->ImportsOrExportsModuleName(var.moduleName)) {
continue;
}
@@ -724,7 +724,7 @@ void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting) {
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
continue;
}
@@ -765,7 +765,7 @@ void ExportFuncSymbol(const FuncSymbolExport &func) {
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
continue;
}
@@ -790,7 +790,7 @@ void UnexportFuncSymbol(const FuncSymbolExport &func) {
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module || !module->ImportsOrExportsModuleName(func.moduleName)) {
continue;
}
@@ -806,7 +806,7 @@ void UnexportFuncSymbol(const FuncSymbolExport &func) {
}
}
-void Module::Cleanup() {
+void PSPModule::Cleanup() {
MIPSAnalyst::ForgetFunctions(textStart, textEnd);
loadedModules.erase(GetUID());
@@ -909,7 +909,7 @@ static bool IsHLEVersionedModule(const char *name) {
return false;
}
-static bool KernelImportModuleFuncs(Module *module, u32 *firstImportStubAddr, bool reimporting) {
+static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting) {
struct PspLibStubEntry {
u32_le name;
u16_le version;
@@ -1090,8 +1090,8 @@ static int gzipDecompress(u8 *OutBuffer, int OutBufferLength, u8 *InBuffer) {
return stream.total_out;
}
-static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
- Module *module = new Module;
+static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
+ PSPModule *module = new PSPModule();
kernelObjects.Create(module);
loadedModules.insert(module->GetUID());
memset(&module->nm, 0, sizeof(module->nm));
@@ -1133,7 +1133,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
if (size > elfSize) {
*error_string = StringFromFormat("ELF/PRX truncated: %d > %d", (int)size, (int)elfSize);
module->Cleanup();
- kernelObjects.Destroy(module->GetUID());
+ kernelObjects.Destroy(module->GetUID());
return nullptr;
}
const auto maxElfSize = std::max(head->elf_size, head->psp_size);
@@ -1166,7 +1166,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
if (addr == (u32)-1) {
error = SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED;
module->Cleanup();
- kernelObjects.Destroy(module->GetUID());
+ kernelObjects.Destroy(module->GetUID());
} else {
error = 0;
module->memoryBlockAddr = addr;
@@ -1207,7 +1207,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
if (newptr)
delete [] newptr;
module->Cleanup();
- kernelObjects.Destroy(module->GetUID());
+ kernelObjects.Destroy(module->GetUID());
error = SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE;
return nullptr;
}
@@ -1221,7 +1221,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
if (newptr)
delete [] newptr;
module->Cleanup();
- kernelObjects.Destroy(module->GetUID());
+ kernelObjects.Destroy(module->GetUID());
error = result;
return nullptr;
}
@@ -1536,8 +1536,8 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
return module;
}
-static Module *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOption *options, std::string *error_string) {
- Module *module = 0;
+static PSPModule *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOption *options, std::string *error_string) {
+ PSPModule *module = nullptr;
// Check for PBP
if (memcmp(fileptr, "\0PBP", 4) == 0) {
// PBP!
@@ -1583,8 +1583,7 @@ static Module *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOptio
return module;
}
-static void __KernelStartModule(Module *m, int args, const char *argp, SceKernelSMOption *options)
-{
+static void __KernelStartModule(PSPModule *m, int args, const char *argp, SceKernelSMOption *options) {
m->nm.status = MODULE_STATUS_STARTED;
if (m->nm.module_start_func != 0 && m->nm.module_start_func != (u32)-1)
{
@@ -1599,16 +1598,12 @@ static void __KernelStartModule(Module *m, int args, const char *argp, SceKernel
}
-u32 __KernelGetModuleGP(SceUID uid)
-{
+u32 __KernelGetModuleGP(SceUID uid) {
u32 error;
- Module *module = kernelObjects.Get(uid, error);
- if (module)
- {
+ PSPModule *module = kernelObjects.Get(uid, error);
+ if (module) {
return module->nm.gp_value;
- }
- else
- {
+ } else {
return 0;
}
}
@@ -1619,7 +1614,7 @@ void __KernelLoadReset() {
u32 error;
while (!loadedModules.empty()) {
SceUID moduleID = *loadedModules.begin();
- Module *module = kernelObjects.Get(moduleID, error);
+ PSPModule *module = kernelObjects.Get(moduleID, error);
if (module) {
module->Cleanup();
} else {
@@ -1635,8 +1630,6 @@ void __KernelLoadReset() {
HLEShutdown();
Replacement_Init();
HLEInit();
- assert(gpu);
- gpu->Reinitialize();
}
__KernelModuleInit();
@@ -1688,12 +1681,12 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
pspFileSystem.ReadFile(handle, temp, (size_t)info.size);
PSP_SetLoading("Loading modules...");
- Module *module = __KernelLoadModule(temp, (size_t)info.size, 0, error_string);
+ PSPModule *module = __KernelLoadModule(temp, (size_t)info.size, 0, error_string);
if (!module || module->isFake) {
if (module) {
module->Cleanup();
- kernelObjects.Destroy(module->GetUID());
+ kernelObjects.Destroy(module->GetUID());
}
ERROR_LOG(LOADER, "Failed to load module %s", filename);
*error_string = "Failed to load executable: " + *error_string;
@@ -1772,7 +1765,7 @@ bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_str
Memory::WriteUnchecked_U32(runDumpCode[i], mipsr4k.pc + (int)i * sizeof(u32_le));
}
- Module *module = new Module;
+ PSPModule *module = new PSPModule();
kernelObjects.Create(module);
loadedModules.insert(module->GetUID());
memset(&module->nm, 0, sizeof(module->nm));
@@ -1836,6 +1829,9 @@ int sceKernelLoadExec(const char *filename, u32 paramPtr)
Core_UpdateState(CORE_ERROR);
return -1;
}
+ if (gpu) {
+ gpu->Reinitialize();
+ }
return 0;
}
@@ -1846,7 +1842,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
for (size_t i = 0; i < ARRAY_SIZE(lieAboutSuccessModules); i++) {
if (!strcmp(name, lieAboutSuccessModules[i])) {
- Module *module = new Module;
+ PSPModule *module = new PSPModule();
kernelObjects.Create(module);
loadedModules.insert(module->GetUID());
memset(&module->nm, 0, sizeof(module->nm));
@@ -1897,7 +1893,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
WARN_LOG_REPORT(LOADER, "sceKernelLoadModule: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
}
- Module *module = 0;
+ PSPModule *module = nullptr;
u8 *temp = new u8[(int)size];
u32 handle = pspFileSystem.OpenFile(name, FILEACCESS_READ);
pspFileSystem.ReadFile(handle, temp, (size_t)size);
@@ -1920,6 +1916,9 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
NOTICE_LOG_REPORT(LOADER, "Module %s is blacklisted or undecryptable - we try __KernelLoadExec", name);
// Name might get deleted.
const std::string safeName = name;
+ if (gpu) {
+ gpu->Reinitialize();
+ }
return __KernelLoadExec(safeName.c_str(), 0, &error_string);
} else {
hleLogError(LOADER, error, "failed to load");
@@ -1957,7 +1956,7 @@ static void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 ret
Memory::ReadStruct(optionAddr, &smoption);
}
u32 error;
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module) {
INFO_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): error %08x", moduleId, argsize, argAddr, returnValueAddr, optionAddr, error);
RETURN(error);
@@ -2056,7 +2055,7 @@ static u32 sceKernelStopModule(u32 moduleId, u32 argSize, u32 argAddr, u32 retur
// TODO: In a lot of cases (even for errors), this should resched. Needs testing.
u32 error;
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module)
{
ERROR_LOG(SCEMODULE, "sceKernelStopModule(%08x, %08x, %08x, %08x, %08x): invalid module id", moduleId, argSize, argAddr, returnValueAddr, optionAddr);
@@ -2129,12 +2128,12 @@ static u32 sceKernelUnloadModule(u32 moduleId)
{
INFO_LOG(SCEMODULE,"sceKernelUnloadModule(%i)", moduleId);
u32 error;
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module)
return hleDelayResult(error, "module unloaded", 150);
module->Cleanup();
- kernelObjects.Destroy(moduleId);
+ kernelObjects.Destroy(moduleId);
return hleDelayResult(moduleId, "module unloaded", 500);
}
@@ -2151,7 +2150,7 @@ u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize,
// TODO: In a lot of cases (even for errors), this should resched. Needs testing.
u32 error;
- Module *module = kernelObjects.Get(moduleID, error);
+ PSPModule *module = kernelObjects.Get(moduleID, error);
if (!module) {
if (WithStatus)
ERROR_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): invalid module id", exitCode, argSize, argp, statusAddr, optionAddr);
@@ -2200,7 +2199,7 @@ u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize,
INFO_LOG(SCEMODULE, "sceKernelSelfStopUnloadModule(%08x, %08x, %08x): no stop func", exitCode, argSize, argp);
sceKernelExitDeleteThread(exitCode);
module->Cleanup();
- kernelObjects.Destroy(moduleID);
+ kernelObjects.Destroy(moduleID);
} else {
if (WithStatus)
ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): bad stop func address", exitCode, argSize, argp, statusAddr, optionAddr);
@@ -2208,7 +2207,7 @@ u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize,
ERROR_LOG_REPORT(SCEMODULE, "sceKernelSelfStopUnloadModule(%08x, %08x, %08x): bad stop func address", exitCode, argSize, argp);
sceKernelExitDeleteThread(exitCode);
module->Cleanup();
- kernelObjects.Destroy(moduleID);
+ kernelObjects.Destroy(moduleID);
}
} else {
if (WithStatus)
@@ -2244,7 +2243,7 @@ void __KernelReturnFromModuleFunc()
sceKernelDeleteThread(leftThreadID);
u32 error;
- Module *module = kernelObjects.Get(leftModuleID, error);
+ PSPModule *module = kernelObjects.Get(leftModuleID, error);
if (!module) {
ERROR_LOG_REPORT(SCEMODULE, "Returned from deleted module start/stop func");
return;
@@ -2274,7 +2273,7 @@ void __KernelReturnFromModuleFunc()
if (module->nm.status == MODULE_STATUS_UNLOADING) {
// TODO: Delete the waiting thread?
module->Cleanup();
- kernelObjects.Destroy(leftModuleID);
+ kernelObjects.Destroy(leftModuleID);
}
}
@@ -2284,11 +2283,9 @@ struct GetModuleIdByAddressArg
SceUID result;
};
-static bool __GetModuleIdByAddressIterator(Module *module, GetModuleIdByAddressArg *state)
-{
+static bool __GetModuleIdByAddressIterator(PSPModule *module, GetModuleIdByAddressArg *state) {
const u32 start = module->memoryBlockAddr, size = module->memoryBlockSize;
- if (start != 0 && start <= state->addr && start + size > state->addr)
- {
+ if (start != 0 && start <= state->addr && start + size > state->addr) {
state->result = module->GetUID();
return false;
}
@@ -2347,7 +2344,7 @@ static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr)
size_t size = pspFileSystem.SeekFile(handle, 0, FILEMOVE_END);
std::string error_string;
pspFileSystem.SeekFile(handle, pos, FILEMOVE_BEGIN);
- Module *module = 0;
+ PSPModule *module = nullptr;
u8 *temp = new u8[size - pos];
pspFileSystem.ReadFile(handle, temp, size - pos);
u32 magic;
@@ -2405,7 +2402,7 @@ static SceUID sceKernelLoadModuleBufferUsbWlan(u32 size, u32 bufPtr, u32 flags,
WARN_LOG_REPORT(LOADER, "sceKernelLoadModuleBufferUsbWlan: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
}
std::string error_string;
- Module *module = 0;
+ PSPModule *module = nullptr;
u32 magic;
u32 error;
module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), size, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
@@ -2447,7 +2444,7 @@ static u32 sceKernelQueryModuleInfo(u32 uid, u32 infoAddr)
{
INFO_LOG(SCEMODULE, "sceKernelQueryModuleInfo(%i, %08x)", uid, infoAddr);
u32 error;
- Module *module = kernelObjects.Get(uid, error);
+ PSPModule *module = kernelObjects.Get(uid, error);
if (!module)
return error;
if (!Memory::IsValidAddress(infoAddr)) {
@@ -2488,7 +2485,7 @@ static u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32
u32 error;
for (SceUID moduleId : loadedModules) {
- Module *module = kernelObjects.Get(moduleId, error);
+ PSPModule *module = kernelObjects.Get(moduleId, error);
if (!module->isFake) {
if (resultBufferOffset < resultBufferSize) {
Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset);
diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp
index 39e20fd952..38b4583c9b 100644
--- a/Core/HLE/sceKernelMutex.cpp
+++ b/Core/HLE/sceKernelMutex.cpp
@@ -62,7 +62,7 @@ struct NativeMutex
s32_le numWaitThreads;
};
-struct Mutex : public KernelObject
+struct PSPMutex : public KernelObject
{
const char *GetName() override { return nm.name; }
const char *GetTypeName() override { return "Mutex"; }
@@ -189,7 +189,7 @@ void __KernelMutexDoState(PointerWrap &p)
KernelObject *__KernelMutexObject()
{
- return new Mutex;
+ return new PSPMutex;
}
KernelObject *__KernelLwMutexObject()
@@ -202,8 +202,7 @@ void __KernelMutexShutdown()
mutexHeldLocks.clear();
}
-static void __KernelMutexAcquireLock(Mutex *mutex, int count, SceUID thread)
-{
+static void __KernelMutexAcquireLock(PSPMutex *mutex, int count, SceUID thread) {
#if defined(_DEBUG)
auto locked = mutexHeldLocks.equal_range(thread);
for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter)
@@ -216,13 +215,11 @@ static void __KernelMutexAcquireLock(Mutex *mutex, int count, SceUID thread)
mutex->nm.lockThread = thread;
}
-static void __KernelMutexAcquireLock(Mutex *mutex, int count)
-{
+static void __KernelMutexAcquireLock(PSPMutex *mutex, int count) {
__KernelMutexAcquireLock(mutex, count, __KernelGetCurThread());
}
-static void __KernelMutexEraseLock(Mutex *mutex)
-{
+static void __KernelMutexEraseLock(PSPMutex *mutex) {
if (mutex->nm.lockThread != -1)
{
SceUID id = mutex->GetUID();
@@ -259,8 +256,7 @@ static std::vector::iterator __KernelMutexFindPriority(std::vectorGetUID()))
return false;
@@ -283,8 +279,7 @@ static bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &err
return true;
}
-static bool __KernelUnlockMutexForThreadCheck(Mutex *mutex, SceUID threadID, u32 &error, int result, bool &wokeThreads)
-{
+static bool __KernelUnlockMutexForThreadCheck(PSPMutex *mutex, SceUID threadID, u32 &error, int result, bool &wokeThreads) {
if (mutex->nm.lockThread == -1 && __KernelUnlockMutexForThread(mutex, threadID, error, 0))
return true;
return false;
@@ -292,7 +287,7 @@ static bool __KernelUnlockMutexForThreadCheck(Mutex *mutex, SceUID threadID, u32
void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
- auto result = HLEKernel::WaitBeginCallback(threadID, prevCallbackId, mutexWaitTimer);
+ auto result = HLEKernel::WaitBeginCallback(threadID, prevCallbackId, mutexWaitTimer);
if (result == HLEKernel::WAIT_CB_SUCCESS)
DEBUG_LOG(SCEKERNEL, "sceKernelLockMutexCB: Suspending lock wait for callback");
else
@@ -301,7 +296,7 @@ void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId)
void __KernelMutexEndCallback(SceUID threadID, SceUID prevCallbackId)
{
- auto result = HLEKernel::WaitEndCallback(threadID, prevCallbackId, mutexWaitTimer, __KernelUnlockMutexForThreadCheck);
+ auto result = HLEKernel::WaitEndCallback(threadID, prevCallbackId, mutexWaitTimer, __KernelUnlockMutexForThreadCheck);
if (result == HLEKernel::WAIT_CB_RESUMED_WAIT)
DEBUG_LOG(SCEKERNEL, "sceKernelLockMutexCB: Resuming lock wait for callback");
}
@@ -324,7 +319,7 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio
if ((attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && initialCount > 1)
return SCE_KERNEL_ERROR_ILLEGAL_COUNT;
- Mutex *mutex = new Mutex();
+ PSPMutex *mutex = new PSPMutex();
SceUID id = kernelObjects.Create(mutex);
mutex->nm.size = sizeof(mutex->nm);
@@ -357,7 +352,7 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio
int sceKernelDeleteMutex(SceUID id)
{
u32 error;
- Mutex *mutex = kernelObjects.Get(id, error);
+ PSPMutex *mutex = kernelObjects.Get(id, error);
if (mutex)
{
DEBUG_LOG(SCEKERNEL, "sceKernelDeleteMutex(%i)", id);
@@ -373,7 +368,7 @@ int sceKernelDeleteMutex(SceUID id)
if (wokeThreads)
hleReSchedule("mutex deleted");
- return kernelObjects.Destroy(id);
+ return kernelObjects.Destroy(id);
}
else
{
@@ -382,8 +377,7 @@ int sceKernelDeleteMutex(SceUID id)
}
}
-static bool __KernelLockMutexCheck(Mutex *mutex, int count, u32 &error)
-{
+static bool __KernelLockMutexCheck(PSPMutex *mutex, int count, u32 &error) {
if (error)
return false;
@@ -411,8 +405,7 @@ static bool __KernelLockMutexCheck(Mutex *mutex, int count, u32 &error)
return false;
}
-static bool __KernelLockMutex(Mutex *mutex, int count, u32 &error)
-{
+static bool __KernelLockMutex(PSPMutex *mutex, int count, u32 &error) {
if (!__KernelLockMutexCheck(mutex, count, error))
return false;
@@ -433,8 +426,7 @@ static bool __KernelLockMutex(Mutex *mutex, int count, u32 &error)
return false;
}
-static bool __KernelUnlockMutex(Mutex *mutex, u32 &error)
-{
+static bool __KernelUnlockMutex(PSPMutex *mutex, u32 &error) {
__KernelMutexEraseLock(mutex);
bool wokeThreads = false;
@@ -459,7 +451,7 @@ static bool __KernelUnlockMutex(Mutex *mutex, u32 &error)
void __KernelMutexTimeout(u64 userdata, int cyclesLate)
{
SceUID threadID = (SceUID)userdata;
- HLEKernel::WaitExecTimeout(threadID);
+ HLEKernel::WaitExecTimeout(threadID);
}
void __KernelMutexThreadEnd(SceUID threadID)
@@ -470,7 +462,7 @@ void __KernelMutexThreadEnd(SceUID threadID)
SceUID waitingMutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error);
if (waitingMutexID)
{
- Mutex *mutex = kernelObjects.Get(waitingMutexID, error);
+ PSPMutex *mutex = kernelObjects.Get(waitingMutexID, error);
if (mutex)
HLEKernel::RemoveWaitingThread(mutex->waitingThreads, threadID);
}
@@ -481,7 +473,7 @@ void __KernelMutexThreadEnd(SceUID threadID)
{
// Need to increment early so erase() doesn't invalidate.
SceUID mutexID = (*iter++).second;
- Mutex *mutex = kernelObjects.Get(mutexID, error);
+ PSPMutex *mutex = kernelObjects.Get(mutexID, error);
if (mutex)
{
@@ -491,8 +483,7 @@ void __KernelMutexThreadEnd(SceUID threadID)
}
}
-static void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr)
-{
+static void __KernelWaitMutex(PSPMutex *mutex, u32 timeoutPtr) {
if (timeoutPtr == 0 || mutexWaitTimer == -1)
return;
@@ -511,7 +502,7 @@ static void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr)
int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr)
{
u32 error;
- Mutex *mutex = kernelObjects.Get(uid, error);
+ PSPMutex *mutex = kernelObjects.Get(uid, error);
if (mutex)
{
bool lockable = count <= 0 || __KernelLockMutexCheck(mutex, count, error);
@@ -566,7 +557,7 @@ int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
{
DEBUG_LOG(SCEKERNEL, "sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr);
u32 error;
- Mutex *mutex = kernelObjects.Get(id, error);
+ PSPMutex *mutex = kernelObjects.Get(id, error);
if (__KernelLockMutex(mutex, count, error))
return 0;
@@ -591,7 +582,7 @@ int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr)
{
DEBUG_LOG(SCEKERNEL, "sceKernelLockMutexCB(%i, %i, %08x)", id, count, timeoutPtr);
u32 error;
- Mutex *mutex = kernelObjects.Get(id, error);
+ PSPMutex *mutex = kernelObjects.Get(id, error);
if (!__KernelLockMutexCheck(mutex, count, error))
{
@@ -630,7 +621,7 @@ int sceKernelTryLockMutex(SceUID id, int count)
{
DEBUG_LOG(SCEKERNEL, "sceKernelTryLockMutex(%i, %i)", id, count);
u32 error;
- Mutex *mutex = kernelObjects.Get(id, error);
+ PSPMutex *mutex = kernelObjects.Get(id, error);
if (__KernelLockMutex(mutex, count, error))
return 0;
@@ -645,7 +636,7 @@ int sceKernelUnlockMutex(SceUID id, int count)
{
DEBUG_LOG(SCEKERNEL, "sceKernelUnlockMutex(%i, %i)", id, count);
u32 error;
- Mutex *mutex = kernelObjects.Get(id, error);
+ PSPMutex *mutex = kernelObjects.Get(id, error);
if (error)
return error;
@@ -672,7 +663,7 @@ int sceKernelUnlockMutex(SceUID id, int count)
int sceKernelReferMutexStatus(SceUID id, u32 infoAddr)
{
u32 error;
- Mutex *m = kernelObjects.Get(id, error);
+ PSPMutex *m = kernelObjects.Get(id, error);
if (!m)
{
ERROR_LOG(SCEKERNEL, "sceKernelReferMutexStatus(%i, %08x): invalid mutex id", id, infoAddr);
@@ -1136,4 +1127,4 @@ int sceKernelReferLwMutexStatus(u32 workareaPtr, u32 infoPtr)
ERROR_LOG(SCEKERNEL, "%08x=sceKernelReferLwMutexStatus(%08x, %08x)", error, workareaPtr, infoPtr);
return error;
}
-}
\ No newline at end of file
+}
diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp
index 8037fdcc12..6d96dec8e8 100644
--- a/Core/HLE/sceKernelSemaphore.cpp
+++ b/Core/HLE/sceKernelSemaphore.cpp
@@ -53,8 +53,7 @@ struct NativeSemaphore
};
-struct Semaphore : public KernelObject
-{
+struct PSPSemaphore : public KernelObject {
const char *GetName() override { return ns.name; }
const char *GetTypeName() override { return "Semaphore"; }
@@ -103,12 +102,11 @@ void __KernelSemaDoState(PointerWrap &p)
KernelObject *__KernelSemaphoreObject()
{
- return new Semaphore;
+ return new PSPSemaphore;
}
// Returns whether the thread should be removed.
-static bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &error, int result, bool &wokeThreads)
-{
+static bool __KernelUnlockSemaForThread(PSPSemaphore *s, SceUID threadID, u32 &error, int result, bool &wokeThreads) {
if (!HLEKernel::VerifyWait(threadID, WAITTYPE_SEMA, s->GetUID()))
return true;
@@ -139,7 +137,7 @@ static bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &erro
void __KernelSemaBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
- auto result = HLEKernel::WaitBeginCallback(threadID, prevCallbackId, semaWaitTimer);
+ auto result = HLEKernel::WaitBeginCallback(threadID, prevCallbackId, semaWaitTimer);
if (result == HLEKernel::WAIT_CB_SUCCESS)
DEBUG_LOG(SCEKERNEL, "sceKernelWaitSemaCB: Suspending sema wait for callback");
else
@@ -148,15 +146,14 @@ void __KernelSemaBeginCallback(SceUID threadID, SceUID prevCallbackId)
void __KernelSemaEndCallback(SceUID threadID, SceUID prevCallbackId)
{
- auto result = HLEKernel::WaitEndCallback(threadID, prevCallbackId, semaWaitTimer, __KernelUnlockSemaForThread);
+ auto result = HLEKernel::WaitEndCallback(threadID, prevCallbackId, semaWaitTimer, __KernelUnlockSemaForThread);
if (result == HLEKernel::WAIT_CB_RESUMED_WAIT)
DEBUG_LOG(SCEKERNEL, "sceKernelWaitSemaCB: Resuming sema wait for callback");
}
// Resume all waiting threads (for delete / cancel.)
// Returns true if it woke any threads.
-static bool __KernelClearSemaThreads(Semaphore *s, int reason)
-{
+static bool __KernelClearSemaThreads(PSPSemaphore *s, int reason) {
u32 error;
bool wokeThreads = false;
std::vector::iterator iter, end;
@@ -170,7 +167,7 @@ static bool __KernelClearSemaThreads(Semaphore *s, int reason)
int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
{
u32 error;
- Semaphore *s = kernelObjects.Get(id, error);
+ PSPSemaphore *s = kernelObjects.Get(id, error);
if (s)
{
if (newCount > s->ns.maxCount)
@@ -215,7 +212,7 @@ int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32
return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
}
- Semaphore *s = new Semaphore;
+ PSPSemaphore *s = new PSPSemaphore();
SceUID id = kernelObjects.Create(s);
s->ns.size = sizeof(NativeSemaphore);
@@ -244,7 +241,7 @@ int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32
int sceKernelDeleteSema(SceUID id)
{
u32 error;
- Semaphore *s = kernelObjects.Get(id, error);
+ PSPSemaphore *s = kernelObjects.Get(id, error);
if (s)
{
DEBUG_LOG(SCEKERNEL, "sceKernelDeleteSema(%i)", id);
@@ -253,7 +250,7 @@ int sceKernelDeleteSema(SceUID id)
if (wokeThreads)
hleReSchedule("semaphore deleted");
- return kernelObjects.Destroy(id);
+ return kernelObjects.Destroy(id);
}
else
{
@@ -265,7 +262,7 @@ int sceKernelDeleteSema(SceUID id)
int sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
{
u32 error;
- Semaphore *s = kernelObjects.Get(id, error);
+ PSPSemaphore *s = kernelObjects.Get(id, error);
if (s)
{
DEBUG_LOG(SCEKERNEL, "sceKernelReferSemaStatus(%i, %08x)", id, infoPtr);
@@ -290,7 +287,7 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
int sceKernelSignalSema(SceUID id, int signal)
{
u32 error;
- Semaphore *s = kernelObjects.Get(id, error);
+ PSPSemaphore *s = kernelObjects.Get(id, error);
if (s)
{
if (s->ns.currentCount + signal - (int) s->waitingThreads.size() > s->ns.maxCount)
@@ -336,10 +333,10 @@ void __KernelSemaTimeout(u64 userdata, int cycleslate)
u32 error;
SceUID uid = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error);
- HLEKernel::WaitExecTimeout(threadID);
+ HLEKernel::WaitExecTimeout(threadID);
// If in FIFO mode, that may have cleared another thread to wake up.
- Semaphore *s = kernelObjects.Get(uid, error);
+ PSPSemaphore *s = kernelObjects.Get(uid, error);
if (s && (s->ns.attr & PSP_SEMA_ATTR_PRIORITY) == PSP_SEMA_ATTR_FIFO) {
bool wokeThreads;
std::vector::iterator iter = s->waitingThreads.begin();
@@ -351,8 +348,7 @@ void __KernelSemaTimeout(u64 userdata, int cycleslate)
}
}
-static void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr)
-{
+static void __KernelSetSemaTimeout(PSPSemaphore *s, u32 timeoutPtr) {
if (timeoutPtr == 0 || semaWaitTimer == -1)
return;
@@ -378,7 +374,7 @@ static int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool pro
hleEatCycles(500);
u32 error;
- Semaphore *s = kernelObjects.Get(id, error);
+ PSPSemaphore *s = kernelObjects.Get(id, error);
if (s)
{
if (wantedCount > s->ns.maxCount)
@@ -438,7 +434,7 @@ int sceKernelPollSema(SceUID id, int wantedCount)
}
u32 error;
- Semaphore *s = kernelObjects.Get(id, error);
+ PSPSemaphore *s = kernelObjects.Get(id, error);
if (s)
{
if (s->ns.currentCount >= wantedCount && s->waitingThreads.size() == 0)
diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp
index 3255af760e..1239187659 100644
--- a/Core/HLE/sceKernelThread.cpp
+++ b/Core/HLE/sceKernelThread.cpp
@@ -135,22 +135,19 @@ struct NativeCallback
s32_le notifyArg;
};
-class Callback : public KernelObject
-{
+class PSPCallback : public KernelObject {
public:
const char *GetName() override { return nc.name; }
const char *GetTypeName() override { return "CallBack"; }
- void GetQuickInfo(char *ptr, int size) override
- {
+ void GetQuickInfo(char *ptr, int size) override {
sprintf(ptr, "thread=%i, argument= %08x",
//hackAddress,
nc.threadId,
nc.commonArgument);
}
- ~Callback()
- {
+ ~PSPCallback() {
}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_CBID; }
@@ -268,9 +265,9 @@ public:
types_[actionType] = creator;
}
- Action *createActionByType(int actionType) {
+ PSPAction *createActionByType(int actionType) {
if (actionType < (int) types_.size() && types_[actionType] != NULL) {
- Action *a = types_[actionType]();
+ PSPAction *a = types_[actionType]();
a->actionTypeID = actionType;
return a;
}
@@ -293,7 +290,7 @@ private:
u32 idGen_;
};
-class ActionAfterMipsCall : public Action
+class ActionAfterMipsCall : public PSPAction
{
ActionAfterMipsCall()
{
@@ -303,8 +300,7 @@ class ActionAfterMipsCall : public Action
public:
void run(MipsCall &call) override;
- static Action *Create()
- {
+ static PSPAction *Create() {
return new ActionAfterMipsCall();
}
@@ -345,17 +341,16 @@ public:
bool isProcessingCallbacks;
SceUID currentCallbackId;
- Action *chainedAction;
+ PSPAction *chainedAction;
};
-class ActionAfterCallback : public Action
+class ActionAfterCallback : public PSPAction
{
public:
ActionAfterCallback() {}
void run(MipsCall &call) override;
- static Action *Create()
- {
+ static PSPAction *Create() {
return new ActionAfterCallback;
}
@@ -376,8 +371,7 @@ public:
SceUID cbId;
};
-class Thread : public KernelObject
-{
+class PSPThread : public KernelObject {
public:
const char *GetName() override { return nt.name; }
const char *GetTypeName() override { return "Thread"; }
@@ -498,8 +492,7 @@ public:
return true;
}
- Thread() : debug(currentMIPS, context)
- {
+ PSPThread() : debug(currentMIPS, context) {
currentStack.start = 0;
}
@@ -508,7 +501,7 @@ public:
{
// Callbacks are automatically deleted when their owning thread is deleted.
for (auto it = callbacks.begin(), end = callbacks.end(); it != end; ++it)
- kernelObjects.Destroy(*it);
+ kernelObjects.Destroy(*it);
if (pushedStacks.size() != 0)
{
@@ -590,7 +583,7 @@ public:
u32 currentMipscallId;
SceUID currentCallbackId;
- ThreadContext context;
+ PSPThreadContext context;
KernelThreadDebugInterface debug;
std::vector callbacks;
@@ -621,11 +614,11 @@ struct WaitTypeFuncs
bool __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter);
-Thread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr);
-void __KernelResetThread(Thread *t, int lowestPriority);
+PSPThread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr);
+void __KernelResetThread(PSPThread *t, int lowestPriority);
void __KernelCancelWakeup(SceUID threadID);
void __KernelCancelThreadEndTimeout(SceUID threadID);
-bool __KernelCheckThreadCallbacks(Thread *thread, bool force);
+bool __KernelCheckThreadCallbacks(PSPThread *thread, bool force);
//////////////////////////////////////////////////////////////////////////
//STATE BEGIN
@@ -635,9 +628,10 @@ int g_inCbCount = 0;
SceUID currentCallbackThreadID = 0;
int readyCallbacksCount = 0;
SceUID currentThread;
-Thread *currentThreadPtr;
+PSPThread *currentThreadPtr;
u32 idleThreadHackAddr;
u32 threadReturnHackAddr;
+u32 hleReturnHackAddr;
u32 cbReturnHackAddr;
u32 intReturnHackAddr;
u32 extendReturnHackAddr;
@@ -690,7 +684,7 @@ void __KernelRestoreActionType(int actionType, ActionCreator creator)
mipsCalls.restoreActionType(actionType, creator);
}
-Action *__KernelCreateAction(int actionType)
+PSPAction *__KernelCreateAction(int actionType)
{
return mipsCalls.createActionByType(actionType);
}
@@ -740,17 +734,17 @@ void MipsCall::setReturnValue(u64 value)
savedV1 = (value >> 32) & 0xFFFFFFFF;
}
-inline Thread *__GetCurrentThread() {
+inline PSPThread *__GetCurrentThread() {
return currentThreadPtr;
}
-inline void __SetCurrentThread(Thread *thread, SceUID threadID, const char *name) {
+inline void __SetCurrentThread(PSPThread *thread, SceUID threadID, const char *name) {
currentThread = threadID;
currentThreadPtr = thread;
hleCurrentThreadName = name;
}
-u32 __KernelMipsCallReturnAddress() {
+u32 __KernelCallbackReturnAddress() {
return cbReturnHackAddr;
}
@@ -805,7 +799,7 @@ static void __KernelSleepBeginCallback(SceUID threadID, SceUID prevCallbackId) {
static void __KernelSleepEndCallback(SceUID threadID, SceUID prevCallbackId) {
u32 error;
- Thread *thread = kernelObjects.Get(threadID, error);
+ PSPThread *thread = kernelObjects.Get(threadID, error);
if (!thread) {
// This probably should not happen.
WARN_LOG_REPORT(SCEKERNEL, "sceKernelSleepThreadCB: thread deleted?");
@@ -825,7 +819,7 @@ static void __KernelSleepEndCallback(SceUID threadID, SceUID prevCallbackId) {
static void __KernelThreadEndBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
- auto result = HLEKernel::WaitBeginCallback(threadID, prevCallbackId, eventThreadEndTimeout);
+ auto result = HLEKernel::WaitBeginCallback(threadID, prevCallbackId, eventThreadEndTimeout);
if (result == HLEKernel::WAIT_CB_SUCCESS)
DEBUG_LOG(SCEKERNEL, "sceKernelWaitThreadEndCB: Suspending wait for callback");
else if (result == HLEKernel::WAIT_CB_BAD_WAIT_DATA)
@@ -834,13 +828,11 @@ static void __KernelThreadEndBeginCallback(SceUID threadID, SceUID prevCallbackI
WARN_LOG_REPORT(SCEKERNEL, "sceKernelWaitThreadEndCB: beginning callback with bad wait id?");
}
-static bool __KernelCheckResumeThreadEnd(Thread *t, SceUID waitingThreadID, u32 &error, int result, bool &wokeThreads)
-{
+static bool __KernelCheckResumeThreadEnd(PSPThread *t, SceUID waitingThreadID, u32 &error, int result, bool &wokeThreads) {
if (!HLEKernel::VerifyWait(waitingThreadID, WAITTYPE_THREADEND, t->GetUID()))
return true;
- if (t->nt.status == THREADSTATUS_DORMANT)
- {
+ if (t->nt.status == THREADSTATUS_DORMANT) {
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(waitingThreadID, error);
s64 cyclesLeft = CoreTiming::UnscheduleEvent(eventThreadEndTimeout, waitingThreadID);
if (timeoutPtr != 0)
@@ -855,7 +847,7 @@ static bool __KernelCheckResumeThreadEnd(Thread *t, SceUID waitingThreadID, u32
static void __KernelThreadEndEndCallback(SceUID threadID, SceUID prevCallbackId)
{
- auto result = HLEKernel::WaitEndCallback(threadID, prevCallbackId, eventThreadEndTimeout, __KernelCheckResumeThreadEnd);
+ auto result = HLEKernel::WaitEndCallback(threadID, prevCallbackId, eventThreadEndTimeout, __KernelCheckResumeThreadEnd);
if (result == HLEKernel::WAIT_CB_RESUMED_WAIT)
DEBUG_LOG(SCEKERNEL, "sceKernelWaitThreadEndCB: Resuming wait from callback");
}
@@ -878,7 +870,7 @@ u32 __KernelSetThreadRA(SceUID threadID, u32 nid)
else
{
u32 error;
- Thread *thread = kernelObjects.Get(threadID, error);
+ PSPThread *thread = kernelObjects.Get(threadID, error);
if (!thread)
return error;
@@ -899,6 +891,16 @@ static void __KernelWriteFakeSysCall(u32 nid, u32 *ptr, u32 &pos)
MIPSAnalyst::PrecompileFunction(*ptr, 8);
}
+u32 HLEMipsCallReturnAddress() {
+ if (hleReturnHackAddr == 0) {
+ // From an old save state, likely... try to recover.
+ u32 blockSize = 2 * sizeof(u32);
+ u32 pos = kernelMemory.Alloc(blockSize, false, "hlerethack");
+ __KernelWriteFakeSysCall(NID_HLECALLRETURN, &hleReturnHackAddr, pos);
+ }
+ return hleReturnHackAddr;
+}
+
void __KernelThreadingInit()
{
struct ThreadHack
@@ -922,6 +924,7 @@ void __KernelThreadingInit()
{NID_INTERRUPTRETURN, &intReturnHackAddr},
{NID_EXTENDRETURN, &extendReturnHackAddr},
{NID_MODULERETURN, &moduleReturnHackAddr},
+ {NID_HLECALLRETURN, &hleReturnHackAddr},
};
u32 blockSize = sizeof(idleThreadCode) + ARRAY_SIZE(threadHacks) * 2 * 4; // The thread code above plus 8 bytes per "hack"
@@ -963,7 +966,7 @@ void __KernelThreadingInit()
void __KernelThreadingDoState(PointerWrap &p)
{
- auto s = p.Section("sceKernelThread", 1, 3);
+ auto s = p.Section("sceKernelThread", 1, 4);
if (!s)
return;
@@ -977,6 +980,12 @@ void __KernelThreadingDoState(PointerWrap &p)
p.Do(extendReturnHackAddr);
p.Do(moduleReturnHackAddr);
+ if (s >= 4) {
+ p.Do(hleReturnHackAddr);
+ } else {
+ hleReturnHackAddr = 0;
+ }
+
p.Do(currentThread);
SceUID dv = 0;
p.Do(threadqueue, dv);
@@ -996,7 +1005,7 @@ void __KernelThreadingDoState(PointerWrap &p)
p.Do(pausedDelays);
- __SetCurrentThread(kernelObjects.GetFast(currentThread), currentThread, __KernelGetThreadName(currentThread));
+ __SetCurrentThread(kernelObjects.GetFast(currentThread), currentThread, __KernelGetThreadName(currentThread));
lastSwitchCycles = CoreTiming::GetTicks();
if (s >= 2)
@@ -1014,12 +1023,12 @@ void __KernelThreadingDoStateLate(PointerWrap &p)
KernelObject *__KernelThreadObject()
{
- return new Thread;
+ return new PSPThread;
}
KernelObject *__KernelCallbackObject()
{
- return new Callback;
+ return new PSPCallback;
}
void __KernelListenThreadEnd(ThreadCallback callback)
@@ -1037,8 +1046,7 @@ static void __KernelFireThreadEnd(SceUID threadID)
}
// TODO: Use __KernelChangeThreadState instead? It has other affects...
-static void __KernelChangeReadyState(Thread *thread, SceUID threadID, bool ready)
-{
+static void __KernelChangeReadyState(PSPThread *thread, SceUID threadID, bool ready) {
// Passing the id as a parameter is just an optimization, if it's wrong it will cause havoc.
_dbg_assert_msg_(SCEKERNEL, thread->GetUID() == threadID, "Incorrect threadID");
int prio = thread->nt.currentPriority;
@@ -1061,7 +1069,7 @@ static void __KernelChangeReadyState(Thread *thread, SceUID threadID, bool ready
static void __KernelChangeReadyState(SceUID threadID, bool ready)
{
u32 error;
- Thread *thread = kernelObjects.Get(threadID, error);
+ PSPThread *thread = kernelObjects.Get(threadID, error);
if (thread)
__KernelChangeReadyState(thread, threadID, ready);
else
@@ -1073,7 +1081,7 @@ void __KernelStartIdleThreads(SceUID moduleId)
for (int i = 0; i < 2; i++)
{
u32 error;
- Thread *t = kernelObjects.Get(threadIdleID[i], error);
+ PSPThread *t = kernelObjects.Get(threadIdleID[i], error);
t->nt.gpreg = __KernelGetModuleGP(moduleId);
t->context.r[MIPS_REG_GP] = t->nt.gpreg;
//t->context.pc += 4; // ADJUSTPC
@@ -1091,12 +1099,12 @@ bool __KernelSwitchOffThread(const char *reason)
if (threadID != threadIdleID[0] && threadID != threadIdleID[1])
{
- Thread *current = __GetCurrentThread();
+ PSPThread *current = __GetCurrentThread();
if (current && current->isRunning())
__KernelChangeReadyState(current, threadID, true);
// Idle 0 chosen entirely arbitrarily.
- Thread *t = kernelObjects.GetFast(threadIdleID[0]);
+ PSPThread *t = kernelObjects.GetFast(threadIdleID[0]);
if (t)
{
hleSkipDeadbeef();
@@ -1125,7 +1133,7 @@ bool __KernelSwitchToThread(SceUID threadID, const char *reason)
return false;
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (!t)
{
ERROR_LOG_REPORT(SCEKERNEL, "__KernelSwitchToThread: %x doesn't exist", threadID);
@@ -1133,7 +1141,7 @@ bool __KernelSwitchToThread(SceUID threadID, const char *reason)
}
else if (t->isReady() || t->isRunning())
{
- Thread *current = __GetCurrentThread();
+ PSPThread *current = __GetCurrentThread();
if (current && current->isRunning())
__KernelChangeReadyState(current, currentThread, true);
@@ -1169,6 +1177,7 @@ void __KernelThreadingShutdown() {
mipsCalls.clear();
threadReturnHackAddr = 0;
cbReturnHackAddr = 0;
+ hleReturnHackAddr = 0;
__SetCurrentThread(NULL, 0, NULL);
intReturnHackAddr = 0;
pausedDelays.clear();
@@ -1179,7 +1188,7 @@ void __KernelThreadingShutdown() {
const char *__KernelGetThreadName(SceUID threadID)
{
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
return t->nt.name;
return "ERROR";
@@ -1187,61 +1196,47 @@ const char *__KernelGetThreadName(SceUID threadID)
bool KernelIsThreadDormant(SceUID threadID) {
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
return (t->nt.status & (THREADSTATUS_DEAD | THREADSTATUS_DORMANT)) != 0;
return 0;
}
-u32 __KernelGetWaitValue(SceUID threadID, u32 &error)
-{
- Thread *t = kernelObjects.Get(threadID, error);
- if (t)
- {
+u32 __KernelGetWaitValue(SceUID threadID, u32 &error) {
+ PSPThread *t = kernelObjects.Get(threadID, error);
+ if (t) {
return t->getWaitInfo().waitValue;
- }
- else
- {
+ } else {
ERROR_LOG(SCEKERNEL, "__KernelGetWaitValue ERROR: thread %i", threadID);
return 0;
}
}
-u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error)
-{
- Thread *t = kernelObjects.Get(threadID, error);
- if (t)
- {
+u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error) {
+ PSPThread *t = kernelObjects.Get(threadID, error);
+ if (t) {
return t->getWaitInfo().timeoutPtr;
- }
- else
- {
+ } else {
ERROR_LOG(SCEKERNEL, "__KernelGetWaitTimeoutPtr ERROR: thread %i", threadID);
return 0;
}
}
-SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error)
-{
- Thread *t = kernelObjects.Get(threadID, error);
- if (t)
- {
+SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error) {
+ PSPThread *t = kernelObjects.Get(threadID, error);
+ if (t) {
return t->getWaitID(type);
- }
- else
- {
+ } else {
ERROR_LOG(SCEKERNEL, "__KernelGetWaitID ERROR: thread %i", threadID);
return -1;
}
}
-SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error)
-{
- Thread *t = kernelObjects.Get(threadID, error);
- if (t)
+SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error) {
+ PSPThread *t = kernelObjects.Get(threadID, error);
+ if (t) {
return t->currentCallbackId;
- else
- {
+ } else {
ERROR_LOG(SCEKERNEL, "__KernelGetCurrentCallbackID ERROR: thread %i", threadID);
return 0;
}
@@ -1256,7 +1251,7 @@ u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr)
threadID = __KernelGetCurThread();
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (!t) {
hleEatCycles(700);
hleReSchedule("refer thread status");
@@ -1297,7 +1292,7 @@ u32 sceKernelReferThreadRunStatus(u32 threadID, u32 statusPtr)
threadID = __KernelGetCurThread();
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (!t)
{
ERROR_LOG(SCEKERNEL,"sceKernelReferThreadRunStatus Error %08x", error);
@@ -1328,7 +1323,7 @@ u32 sceKernelReferThreadRunStatus(u32 threadID, u32 statusPtr)
int sceKernelGetThreadExitStatus(SceUID threadID)
{
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
{
if (t->nt.status == THREADSTATUS_DORMANT) // TODO: can be dormant before starting, too, need to avoid that
@@ -1366,19 +1361,19 @@ u32 sceKernelGetThreadmanIdType(u32 uid) {
}
}
-static bool __ThreadmanIdListIsSleeping(const Thread *t) {
+static bool __ThreadmanIdListIsSleeping(const PSPThread *t) {
return t->isWaitingFor(WAITTYPE_SLEEP, 0);
}
-static bool __ThreadmanIdListIsDelayed(const Thread *t) {
+static bool __ThreadmanIdListIsDelayed(const PSPThread *t) {
return t->isWaitingFor(WAITTYPE_DELAY, t->GetUID());
}
-static bool __ThreadmanIdListIsSuspended(const Thread *t) {
+static bool __ThreadmanIdListIsSuspended(const PSPThread *t) {
return t->isSuspended();
}
-static bool __ThreadmanIdListIsDormant(const Thread *t) {
+static bool __ThreadmanIdListIsDormant(const PSPThread *t) {
return t->isStopped();
}
@@ -1401,7 +1396,7 @@ u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 i
DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)", type, readBufPtr, readBufSize, idCountPtr);
total = kernelObjects.ListIDType(type, uids, readBufSize);
} else if (type >= SCE_KERNEL_TMID_SleepThread && type <= SCE_KERNEL_TMID_DormantThread) {
- bool (*checkFunc)(const Thread *t) = NULL;
+ bool (*checkFunc)(const PSPThread *t) = nullptr;
switch (type) {
case SCE_KERNEL_TMID_SleepThread:
checkFunc = &__ThreadmanIdListIsSleeping;
@@ -1424,7 +1419,7 @@ u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 i
}
for (size_t i = 0; i < threadqueue.size(); i++) {
- const Thread *t = kernelObjects.Get(threadqueue[i], error);
+ const PSPThread *t = kernelObjects.Get(threadqueue[i], error);
if (checkFunc(t)) {
if (total < readBufSize) {
*uids++ = threadqueue[i];
@@ -1444,13 +1439,11 @@ u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 i
}
// Saves the current CPU context
-void __KernelSaveContext(ThreadContext *ctx, bool vfpuEnabled)
-{
+void __KernelSaveContext(PSPThreadContext *ctx, bool vfpuEnabled) {
// r and f are immediately next to each other and must be.
memcpy((void *)ctx->r, (void *)currentMIPS->r, sizeof(ctx->r) + sizeof(ctx->f));
- if (vfpuEnabled)
- {
+ if (vfpuEnabled) {
memcpy(ctx->v, currentMIPS->v, sizeof(ctx->v));
memcpy(ctx->vfpuCtrl, currentMIPS->vfpuCtrl, sizeof(ctx->vfpuCtrl));
}
@@ -1459,13 +1452,11 @@ void __KernelSaveContext(ThreadContext *ctx, bool vfpuEnabled)
}
// Loads a CPU context
-void __KernelLoadContext(ThreadContext *ctx, bool vfpuEnabled)
-{
+void __KernelLoadContext(PSPThreadContext *ctx, bool vfpuEnabled) {
// r and f are immediately next to each other and must be.
memcpy((void *)currentMIPS->r, (void *)ctx->r, sizeof(ctx->r) + sizeof(ctx->f));
- if (vfpuEnabled)
- {
+ if (vfpuEnabled) {
memcpy(currentMIPS->v, ctx->v, sizeof(ctx->v));
memcpy(currentMIPS->vfpuCtrl, ctx->vfpuCtrl, sizeof(ctx->vfpuCtrl));
}
@@ -1483,7 +1474,7 @@ void __KernelLoadContext(ThreadContext *ctx, bool vfpuEnabled)
u32 __KernelResumeThreadFromWait(SceUID threadID, u32 retval)
{
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
{
t->resumeFromWait();
@@ -1500,7 +1491,7 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, u32 retval)
u32 __KernelResumeThreadFromWait(SceUID threadID, u64 retval)
{
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
{
t->resumeFromWait();
@@ -1523,7 +1514,8 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time
return;
}
- Thread *thread = __GetCurrentThread();
+ PSPThread *thread = __GetCurrentThread();
+ assert(thread != nullptr);
thread->nt.waitID = waitID;
thread->nt.waitType = type;
__KernelChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->nt.status & THREADSTATUS_SUSPEND)));
@@ -1546,7 +1538,7 @@ void __KernelWaitCallbacksCurThread(WaitType type, SceUID waitID, u32 waitValue,
return;
}
- Thread *thread = __GetCurrentThread();
+ PSPThread *thread = __GetCurrentThread();
thread->nt.waitID = waitID;
thread->nt.waitType = type;
__KernelChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->nt.status & THREADSTATUS_SUSPEND)));
@@ -1583,7 +1575,7 @@ void __KernelCancelWakeup(SceUID threadID)
void hleThreadEndTimeout(u64 userdata, int cyclesLate)
{
SceUID threadID = (SceUID) userdata;
- HLEKernel::WaitExecTimeout(threadID);
+ HLEKernel::WaitExecTimeout(threadID);
}
static void __KernelScheduleThreadEndTimeout(SceUID threadID, SceUID waitForID, s64 usFromNow)
@@ -1610,7 +1602,7 @@ static void __KernelRemoveFromThreadQueue(SceUID threadID) {
void __KernelStopThread(SceUID threadID, int exitStatus, const char *reason)
{
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
{
__KernelChangeReadyState(t, threadID, false);
@@ -1654,12 +1646,12 @@ u32 __KernelDeleteThread(SceUID threadID, int exitStatus, const char *reason)
}
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
{
for (auto it = t->callbacks.begin(), end = t->callbacks.end(); it != end; ++it)
{
- Callback *callback = kernelObjects.Get(*it, error);
+ PSPCallback *callback = kernelObjects.Get(*it, error);
if (callback && callback->nc.notifyCount != 0)
readyCallbacksCount--;
}
@@ -1675,7 +1667,7 @@ u32 __KernelDeleteThread(SceUID threadID, int exitStatus, const char *reason)
pendingDeleteThreads.push_back(threadID);
return 0;
} else {
- return kernelObjects.Destroy(threadID);
+ return kernelObjects.Destroy(threadID);
}
} else {
RETURN(error);
@@ -1687,8 +1679,8 @@ static void __ReportThreadQueueEmpty() {
// We failed to find a thread to schedule.
// This means something horrible happened to the idle threads.
u32 error;
- Thread *idleThread0 = kernelObjects.Get(threadIdleID[0], error);
- Thread *idleThread1 = kernelObjects.Get(threadIdleID[1], error);
+ PSPThread *idleThread0 = kernelObjects.Get(threadIdleID[0], error);
+ PSPThread *idleThread1 = kernelObjects.Get(threadIdleID[1], error);
char idleDescription0[256];
int idleStatus0 = -1;
@@ -1714,11 +1706,11 @@ static void __ReportThreadQueueEmpty() {
}
// Returns NULL if the current thread is fine.
-static Thread *__KernelNextThread() {
+static PSPThread *__KernelNextThread() {
SceUID bestThread;
// If the current thread is running, it's a valid candidate.
- Thread *cur = __GetCurrentThread();
+ PSPThread *cur = __GetCurrentThread();
if (cur && cur->isRunning()) {
bestThread = threadReadyQueue.pop_first_better(cur->nt.currentPriority);
if (bestThread != 0)
@@ -1737,7 +1729,7 @@ static Thread *__KernelNextThread() {
// Assume threadReadyQueue has not become corrupt.
if (bestThread != 0)
- return kernelObjects.GetFast(bestThread);
+ return kernelObjects.GetFast(bestThread);
else
return 0;
}
@@ -1756,7 +1748,7 @@ void __KernelReSchedule(const char *reason)
return;
}
- Thread *nextThread = __KernelNextThread();
+ PSPThread *nextThread = __KernelNextThread();
if (nextThread) {
__KernelSwitchContext(nextThread, reason);
}
@@ -1765,7 +1757,7 @@ void __KernelReSchedule(const char *reason)
void __KernelReSchedule(bool doCallbacks, const char *reason)
{
- Thread *thread = __GetCurrentThread();
+ PSPThread *thread = __GetCurrentThread();
if (doCallbacks && thread != nullptr) {
thread->isProcessingCallbacks = doCallbacks;
}
@@ -1782,7 +1774,7 @@ void __KernelReSchedule(bool doCallbacks, const char *reason)
int sceKernelCheckThreadStack()
{
u32 error;
- Thread *t = kernelObjects.Get(__KernelGetCurThread(), error);
+ PSPThread *t = kernelObjects.Get(__KernelGetCurThread(), error);
if (t) {
u32 diff = labs((long)((s64)currentMIPS->r[MIPS_REG_SP] - (s64)t->currentStack.start));
DEBUG_LOG(SCEKERNEL, "%i=sceKernelCheckThreadStack()", diff);
@@ -1793,20 +1785,16 @@ int sceKernelCheckThreadStack()
}
}
-void ThreadContext::reset()
-{
- for (int i = 0; i<32; i++)
- {
+void PSPThreadContext::reset() {
+ for (int i = 0; i<32; i++) {
r[i] = 0xDEADBEEF;
fi[i] = 0x7f800001;
}
r[0] = 0;
- for (int i = 0; i<128; i++)
- {
+ for (int i = 0; i<128; i++) {
vi[i] = 0x7f800001;
}
- for (int i = 0; i<15; i++)
- {
+ for (int i = 0; i<15; i++) {
vfpuCtrl[i] = 0x00000000;
}
vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // neutral
@@ -1831,8 +1819,7 @@ void ThreadContext::reset()
other[5] = 0;
}
-void __KernelResetThread(Thread *t, int lowestPriority)
-{
+void __KernelResetThread(PSPThread *t, int lowestPriority) {
t->context.reset();
t->context.pc = t->nt.entrypoint;
@@ -1860,10 +1847,10 @@ void __KernelResetThread(Thread *t, int lowestPriority)
ERROR_LOG_REPORT(SCEKERNEL, "Resetting thread with threads waiting on end?");
}
-Thread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr) {
+PSPThread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr) {
std::lock_guard guard(threadqueueLock);
- Thread *t = new Thread;
+ PSPThread *t = new PSPThread();
id = kernelObjects.Create(t);
threadqueue.push_back(id);
@@ -1910,12 +1897,12 @@ SceUID __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int
{
//grab mips regs
SceUID id;
- Thread *thread = __KernelCreateThread(id, moduleID, "root", currentMIPS->pc, prio, stacksize, attr);
+ PSPThread *thread = __KernelCreateThread(id, moduleID, "root", currentMIPS->pc, prio, stacksize, attr);
if (thread->currentStack.start == 0)
ERROR_LOG_REPORT(SCEKERNEL, "Unable to allocate stack for root thread.");
__KernelResetThread(thread, 0);
- Thread *prevThread = __GetCurrentThread();
+ PSPThread *prevThread = __GetCurrentThread();
if (prevThread && prevThread->isRunning())
__KernelChangeReadyState(currentThread, true);
__SetCurrentThread(thread, id, "root");
@@ -1939,7 +1926,7 @@ SceUID __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int
SceUID __KernelCreateThreadInternal(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr)
{
SceUID id;
- Thread *newThread = __KernelCreateThread(id, moduleID, threadName, entry, prio, stacksize, attr);
+ PSPThread *newThread = __KernelCreateThread(id, moduleID, threadName, entry, prio, stacksize, attr);
if (newThread->currentStack.start == 0)
return SCE_KERNEL_ERROR_NO_MEMORY;
@@ -1999,18 +1986,18 @@ int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32
}
int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) {
- Thread *cur = __GetCurrentThread();
+ PSPThread *cur = __GetCurrentThread();
bool allowKernel = cur ? (cur->nt.attr & PSP_THREAD_ATTR_KERNEL) != 0 : false;
return __KernelCreateThread(threadName, __KernelGetCurThreadModuleId(), entry, prio, stacksize, attr, optionAddr, allowKernel);
}
int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bool forceArgs) {
u32 error;
- Thread *startThread = kernelObjects.Get(threadToStartID, error);
+ PSPThread *startThread = kernelObjects.Get(threadToStartID, error);
if (startThread == 0)
return error;
- Thread *cur = __GetCurrentThread();
+ PSPThread *cur = __GetCurrentThread();
__KernelResetThread(startThread, cur ? cur->nt.currentPriority : 0);
u32 &sp = startThread->context.r[MIPS_REG_SP];
@@ -2073,7 +2060,7 @@ int __KernelStartThreadValidate(SceUID threadToStartID, int argSize, u32 argBloc
return hleReportError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad thread argument pointer/length %08x / %08x", argSize, argBlockPtr);
u32 error = 0;
- Thread *startThread = kernelObjects.Get(threadToStartID, error);
+ PSPThread *startThread = kernelObjects.Get(threadToStartID, error);
if (startThread == 0)
return hleLogError(SCEKERNEL, error, "thread does not exist");
@@ -2097,9 +2084,8 @@ int sceKernelGetThreadStackFreeSize(SceUID threadID)
threadID = __KernelGetCurThread();
u32 error;
- Thread *thread = kernelObjects.Get(threadID, error);
- if (thread == 0)
- {
+ PSPThread *thread = kernelObjects.Get(threadID, error);
+ if (thread == nullptr) {
ERROR_LOG(SCEKERNEL, "sceKernelGetThreadStackFreeSize: invalid thread id %i", threadID);
return error;
}
@@ -2122,7 +2108,7 @@ void __KernelReturnFromThread()
hleSkipDeadbeef();
int exitStatus = currentMIPS->r[MIPS_REG_V0];
- Thread *thread = __GetCurrentThread();
+ PSPThread *thread = __GetCurrentThread();
_dbg_assert_msg_(SCEKERNEL, thread != NULL, "Returned from a NULL thread.");
DEBUG_LOG(SCEKERNEL, "__KernelReturnFromThread: %d", exitStatus);
@@ -2136,9 +2122,8 @@ void __KernelReturnFromThread()
// The stack will be deallocated when the thread is deleted.
}
-void sceKernelExitThread(int exitStatus)
-{
- Thread *thread = __GetCurrentThread();
+void sceKernelExitThread(int exitStatus) {
+ PSPThread *thread = __GetCurrentThread();
_dbg_assert_msg_(SCEKERNEL, thread != NULL, "Exited from a NULL thread.");
INFO_LOG(SCEKERNEL, "sceKernelExitThread(%d)", exitStatus);
@@ -2152,9 +2137,8 @@ void sceKernelExitThread(int exitStatus)
// The stack will be deallocated when the thread is deleted.
}
-void _sceKernelExitThread(int exitStatus)
-{
- Thread *thread = __GetCurrentThread();
+void _sceKernelExitThread(int exitStatus) {
+ PSPThread *thread = __GetCurrentThread();
_dbg_assert_msg_(SCEKERNEL, thread != NULL, "_Exited from a NULL thread.");
ERROR_LOG_REPORT(SCEKERNEL, "_sceKernelExitThread(%d): should not be called directly", exitStatus);
@@ -2168,9 +2152,8 @@ void _sceKernelExitThread(int exitStatus)
// The stack will be deallocated when the thread is deleted.
}
-void sceKernelExitDeleteThread(int exitStatus)
-{
- Thread *thread = __GetCurrentThread();
+void sceKernelExitDeleteThread(int exitStatus) {
+ PSPThread *thread = __GetCurrentThread();
if (thread)
{
INFO_LOG(SCEKERNEL,"sceKernelExitDeleteThread(%d)", exitStatus);
@@ -2230,7 +2213,7 @@ int sceKernelRotateThreadReadyQueue(int priority)
{
VERBOSE_LOG(SCEKERNEL, "sceKernelRotateThreadReadyQueue(%x)", priority);
- Thread *cur = __GetCurrentThread();
+ PSPThread *cur = __GetCurrentThread();
// 0 is special, it means "my current priority."
if (priority == 0)
@@ -2257,29 +2240,23 @@ int sceKernelRotateThreadReadyQueue(int priority)
return 0;
}
-int sceKernelDeleteThread(int threadID)
-{
- if (threadID == 0 || threadID == currentThread)
- {
+int sceKernelDeleteThread(int threadID) {
+ if (threadID == 0 || threadID == currentThread) {
ERROR_LOG(SCEKERNEL, "sceKernelDeleteThread(%i): cannot delete current thread", threadID);
return SCE_KERNEL_ERROR_NOT_DORMANT;
}
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
- if (t)
- {
- if (!t->isStopped())
- {
+ PSPThread *t = kernelObjects.Get(threadID, error);
+ if (t) {
+ if (!t->isStopped()) {
ERROR_LOG(SCEKERNEL, "sceKernelDeleteThread(%i): thread not dormant", threadID);
return SCE_KERNEL_ERROR_NOT_DORMANT;
}
DEBUG_LOG(SCEKERNEL, "sceKernelDeleteThread(%i)", threadID);
return __KernelDeleteThread(threadID, SCE_KERNEL_ERROR_THREAD_TERMINATED, "thread deleted");
- }
- else
- {
+ } else {
ERROR_LOG(SCEKERNEL, "sceKernelDeleteThread(%i): thread doesn't exist", threadID);
return error;
}
@@ -2294,7 +2271,7 @@ int sceKernelTerminateDeleteThread(int threadID)
}
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t)
{
bool wasStopped = t->isStopped();
@@ -2328,7 +2305,7 @@ int sceKernelTerminateThread(SceUID threadID) {
}
u32 error;
- Thread *t = kernelObjects.Get(threadID, error);
+ PSPThread *t = kernelObjects.Get(threadID, error);
if (t) {
if (t->isStopped()) {
return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_DORMANT, "already stopped");
@@ -2356,31 +2333,28 @@ SceUID __KernelGetCurThread()
}
int KernelCurThreadPriority() {
- Thread *t = __GetCurrentThread();
+ PSPThread *t = __GetCurrentThread();
if (t)
return t->nt.currentPriority;
return 0;
}
-SceUID __KernelGetCurThreadModuleId()
-{
- Thread *t = __GetCurrentThread();
+SceUID __KernelGetCurThreadModuleId() {
+ PSPThread *t = __GetCurrentThread();
if (t)
return t->moduleId;
return 0;
}
-u32 __KernelGetCurThreadStack()
-{
- Thread *t = __GetCurrentThread();
+u32 __KernelGetCurThreadStack() {
+ PSPThread *t = __GetCurrentThread();
if (t)
return t->currentStack.end;
return 0;
}
-u32 __KernelGetCurThreadStackStart()
-{
- Thread *t = __GetCurrentThread();
+u32 __KernelGetCurThreadStackStart() {
+ PSPThread *t = __GetCurrentThread();
if (t)
return t->currentStack.start;
return 0;
@@ -2404,7 +2378,7 @@ int sceKernelChangeCurrentThreadAttr(u32 clearAttr, u32 setAttr) {
return hleReportError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ATTR, "invalid attr");
}
- Thread *t = __GetCurrentThread();
+ PSPThread *t = __GetCurrentThread();
if (!t)
return hleReportError(SCEKERNEL, -1, "no current thread");
@@ -2415,7 +2389,7 @@ int sceKernelChangeCurrentThreadAttr(u32 clearAttr, u32 setAttr) {
// Assumes validated parameters.
bool KernelChangeThreadPriority(SceUID threadID, int priority) {
u32 error;
- Thread *thread = kernelObjects.Get(threadID, error);
+ PSPThread *thread = kernelObjects.Get(threadID, error);
if (thread) {
int old = thread->nt.currentPriority;
threadReadyQueue.remove(old, threadID);
@@ -2441,7 +2415,7 @@ int sceKernelChangeThreadPriority(SceUID threadID, int priority) {
// 0 means the current (running) thread's priority, not target's.
if (priority == 0) {
- Thread *cur = __GetCurrentThread();
+ PSPThread *cur = __GetCurrentThread();
if (!cur) {
ERROR_LOG_REPORT(SCEKERNEL, "sceKernelChangeThreadPriority(%i, %i): no current thread?", threadID, priority);
} else {
@@ -2450,7 +2424,7 @@ int sceKernelChangeThreadPriority(SceUID threadID, int priority) {
}
u32 error;
- Thread *thread = kernelObjects.Get