mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Merge branch 'master' into TemporaryHackishBranch
# Conflicts: # .gitignore # CMakeLists.txt # Core/HLE/sceNet.cpp # UI/GameSettingsScreen.cpp # UI/MainScreen.cpp # UI/MiscScreens.cpp # UI/ui_atlas.cpp # UI/ui_atlas.h # Windows/resource.h # android/.gitignore # android/assets/ui_atlas.zim # assets/ui_atlas.zim # assets/ui_atlas_lowmem.zim # atlasscript_lowmem.txt # ext/native/tools/atlastool/atlastool.vcxproj # ext/native/tools/tools.sln # ext/native/ui/ui_context.cpp # gradle/wrapper/gradle-wrapper.properties also fix atlas generation.
This commit is contained in:
commit
6e202e5bdd
336 files changed
+6667
-75332
No files matched your search
+2
-4
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
+2
-2
@@ -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
|
||||
|
||||
+24
-20
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+2
-1
@@ -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);
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>stdafx.h;Common/DbgNew.h</ForcedIncludeFiles>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -164,7 +164,7 @@
|
||||
<ForcedIncludeFiles>stdafx.h;Common/DbgNew.h</ForcedIncludeFiles>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
@@ -192,7 +192,7 @@
|
||||
<ForcedIncludeFiles>stdafx.h;Common/DbgNew.h</ForcedIncludeFiles>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
@@ -220,7 +220,7 @@
|
||||
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
@@ -253,7 +253,7 @@
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@@ -283,7 +283,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -318,7 +318,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -353,7 +353,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;../ext/glslang;..</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
<ClInclude Include="Hashmaps.h" />
|
||||
<ClInclude Include="Vulkan\VulkanDebug.h" />
|
||||
<ClInclude Include="BitScan.h" />
|
||||
<ClInclude Include="MakeUnique.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.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;
|
||||
|
||||
@@ -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 <switch.h>
|
||||
#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
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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)
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
+2
-2
@@ -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__
|
||||
#endif // __ANDROID__
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
+38
-4
@@ -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<std::string, std::pair<std::string, int>> 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) {
|
||||
|
||||
+42
-1
@@ -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_;
|
||||
|
||||
+8
-11
@@ -71,7 +71,6 @@
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
@@ -134,7 +133,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -156,7 +155,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -179,7 +178,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -202,7 +201,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -229,7 +228,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
@@ -260,7 +259,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
@@ -290,7 +289,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
@@ -320,7 +319,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/native/ext/libpng17;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
@@ -834,7 +833,6 @@
|
||||
<ClCompile Include="Util\DisArm64.cpp" />
|
||||
<ClCompile Include="Util\GameManager.cpp" />
|
||||
<ClCompile Include="Util\PPGeDraw.cpp" />
|
||||
<ClCompile Include="Util\ppge_atlas.cpp" />
|
||||
<ClCompile Include="..\ext\xxhash.c">
|
||||
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IntrinsicFunctions>
|
||||
@@ -1166,7 +1164,6 @@
|
||||
<ClInclude Include="Util\DisArm64.h" />
|
||||
<ClInclude Include="Util\GameManager.h" />
|
||||
<ClInclude Include="Util\PPGeDraw.h" />
|
||||
<ClInclude Include="Util\ppge_atlas.h" />
|
||||
<ClInclude Include="..\ext\xxhash.h" />
|
||||
<ClInclude Include="WaveFile.h" />
|
||||
<ClInclude Include="WebServer.h" />
|
||||
|
||||
@@ -336,9 +336,6 @@
|
||||
<ClCompile Include="Util\PPGeDraw.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Util\ppge_atlas.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HLE\sceFont.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
@@ -1000,9 +997,6 @@
|
||||
<ClInclude Include="Util\PPGeDraw.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Util\ppge_atlas.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HLE\sceFont.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef USING_QT_UI
|
||||
#include <libpng17/png.h>
|
||||
#include <png.h>
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
#include "data/base64.h"
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
+118
-84
@@ -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 <algorithm>
|
||||
#include "base/NativeApp.h"
|
||||
#include "i18n/i18n.h"
|
||||
#include "math/math_util.h"
|
||||
#include <algorithm>
|
||||
#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 <ctype.h>
|
||||
#include <math.h>
|
||||
@@ -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<u16_
|
||||
{
|
||||
if (!em_address.IsValid())
|
||||
{
|
||||
_string = "";
|
||||
_string.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -196,17 +194,17 @@ void PSPOskDialog::ConvertUCS2ToUTF8(std::string& _string, const PSPPointer<u16_
|
||||
_string = stringBuffer;
|
||||
}
|
||||
|
||||
void GetWideStringFromPSPPointer(std::wstring& _string, const PSPPointer<u16_le>& em_address)
|
||||
void GetWideStringFromPSPPointer(std::u16string& _string, const PSPPointer<u16_le>& 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<u16_le>
|
||||
_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<std::mutex> 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<std::mutex> 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<std::mutex> 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()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#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<u16_le>& 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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <mutex>
|
||||
#include <cstring>
|
||||
|
||||
#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.
|
||||
|
||||
@@ -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<std::mutex> 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
+190
-7
@@ -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<HLEModule> 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<u32> 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<HLEMipsCallInfo> enqueuedMipsCalls;
|
||||
// Does need to be saved, referenced by the stack and owned.
|
||||
static std::vector<PSPAction *> 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<u32> 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<HLEMipsCallStack> 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<HLEMipsCallStack> 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<HLEMipsCallStack> 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.)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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[] =
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
+72
-15
@@ -63,6 +63,13 @@ std::recursive_mutex peerlock;
|
||||
SceNetAdhocPdpStat * pdp[255];
|
||||
SceNetAdhocPtpStat * ptp[255];
|
||||
uint32_t localip;
|
||||
std::vector<std::string> 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<std::string> 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());
|
||||
|
||||
+12
-2
@@ -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<std::string> getChatLog();
|
||||
extern bool chatScreenVisible;
|
||||
extern bool updateChatScreen;
|
||||
extern int newChat;
|
||||
|
||||
/*
|
||||
* Find a Peer/Friend by MAC address
|
||||
*/
|
||||
|
||||
+2
-2
@@ -28,9 +28,9 @@
|
||||
#include "Core/Reporting.h"
|
||||
|
||||
typedef PSPPointer<char> PSPCharPointer;
|
||||
typedef PSPPointer<u16> PSPWCharPointer;
|
||||
typedef PSPPointer<char16_t> PSPWCharPointer;
|
||||
typedef PSPPointer<const char> PSPConstCharPointer;
|
||||
typedef PSPPointer<const u16> PSPConstWCharPointer;
|
||||
typedef PSPPointer<const char16_t> PSPConstWCharPointer;
|
||||
|
||||
static u16 errorUTF8;
|
||||
static u16 errorUTF16;
|
||||
|
||||
+35
-12
@@ -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<u8> *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);
|
||||
|
||||
+246
-38
@@ -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<PGFCharInfo> charInfo) { charInfo_ = charInfo; }
|
||||
|
||||
private:
|
||||
u32 fontLibID_;
|
||||
PSPPointer<PGFCharInfo> 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<u32> fonts_;
|
||||
std::vector<u32> isfontopen_;
|
||||
@@ -573,6 +708,8 @@ private:
|
||||
int fileFontHandle_;
|
||||
int handle_;
|
||||
int altCharCode_;
|
||||
std::vector<u32> openAllocatedAddresses_;
|
||||
u32 charInfoBitmapAddress_;
|
||||
PSPPointer<NativeFontLib> 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<PGFCharInfo>::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;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+16
-22
@@ -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<Alarm>(alarmID, error);
|
||||
PSPAlarm *alarm = kernelObjects.Get<PSPAlarm>(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<Alarm>(alarmID, error);
|
||||
PSPAlarm *alarm = kernelObjects.Get<PSPAlarm>(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<Alarm>(alarmID);
|
||||
kernelObjects.Destroy<PSPAlarm>(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<Alarm>(uid, error);
|
||||
if (alarm)
|
||||
{
|
||||
PSPAlarm *alarm = kernelObjects.Get<PSPAlarm>(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<Alarm>(uid);
|
||||
return kernelObjects.Destroy<PSPAlarm>(uid);
|
||||
}
|
||||
|
||||
int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr)
|
||||
{
|
||||
u32 error;
|
||||
Alarm *alarm = kernelObjects.Get<Alarm>(uid, error);
|
||||
PSPAlarm *alarm = kernelObjects.Get<PSPAlarm>(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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<SceKernelVplBlock> b, PSPPointer<SceKernelVplBlock> prev) {
|
||||
allocatedInBlocks_ += b->sizeInBlocks;
|
||||
prev->next = b->next;
|
||||
if (nextFreeBlock_ == b) {
|
||||
nextFreeBlock_ = prev;
|
||||
}
|
||||
nextFreeBlock_ = prev;
|
||||
b->next = SentinelPtr();
|
||||
}
|
||||
|
||||
PSPPointer<SceKernelVplBlock> SplitBlock(PSPPointer<SceKernelVplBlock> 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;
|
||||
|
||||
@@ -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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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>(module->GetUID());
|
||||
kernelObjects.Destroy<PSPModule>(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>(module->GetUID());
|
||||
kernelObjects.Destroy<PSPModule>(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>(module->GetUID());
|
||||
kernelObjects.Destroy<PSPModule>(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>(module->GetUID());
|
||||
kernelObjects.Destroy<PSPModule>(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<Module>(uid, error);
|
||||
if (module)
|
||||
{
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleID, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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>(module->GetUID());
|
||||
kernelObjects.Destroy<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
|
||||
if (!module)
|
||||
return hleDelayResult(error, "module unloaded", 150);
|
||||
|
||||
module->Cleanup();
|
||||
kernelObjects.Destroy<Module>(moduleId);
|
||||
kernelObjects.Destroy<PSPModule>(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<Module>(moduleID, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleID);
|
||||
kernelObjects.Destroy<PSPModule>(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<Module>(moduleID);
|
||||
kernelObjects.Destroy<PSPModule>(moduleID);
|
||||
}
|
||||
} else {
|
||||
if (WithStatus)
|
||||
@@ -2244,7 +2243,7 @@ void __KernelReturnFromModuleFunc()
|
||||
sceKernelDeleteThread(leftThreadID);
|
||||
|
||||
u32 error;
|
||||
Module *module = kernelObjects.Get<Module>(leftModuleID, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(leftModuleID);
|
||||
kernelObjects.Destroy<PSPModule>(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<Module>(uid, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(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<Module>(moduleId, error);
|
||||
PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
|
||||
if (!module->isFake) {
|
||||
if (resultBufferOffset < resultBufferSize) {
|
||||
Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset);
|
||||
|
||||
+26
-35
@@ -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<SceUID>::iterator __KernelMutexFindPriority(std::vector<SceUI
|
||||
return best;
|
||||
}
|
||||
|
||||
static bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int result)
|
||||
{
|
||||
static bool __KernelUnlockMutexForThread(PSPMutex *mutex, SceUID threadID, u32 &error, int result) {
|
||||
if (!HLEKernel::VerifyWait(threadID, WAITTYPE_MUTEX, mutex->GetUID()))
|
||||
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<Mutex, WAITTYPE_MUTEX, SceUID>(threadID, prevCallbackId, mutexWaitTimer);
|
||||
auto result = HLEKernel::WaitBeginCallback<PSPMutex, WAITTYPE_MUTEX, SceUID>(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<Mutex, WAITTYPE_MUTEX, SceUID>(threadID, prevCallbackId, mutexWaitTimer, __KernelUnlockMutexForThreadCheck);
|
||||
auto result = HLEKernel::WaitEndCallback<PSPMutex, WAITTYPE_MUTEX, SceUID>(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<Mutex>(id, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(id);
|
||||
return kernelObjects.Destroy<PSPMutex>(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<Mutex, WAITTYPE_MUTEX>(threadID);
|
||||
HLEKernel::WaitExecTimeout<PSPMutex, WAITTYPE_MUTEX>(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<Mutex>(waitingMutexID, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(mutexID, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(uid, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(id, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(id, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(id, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(id, error);
|
||||
PSPMutex *mutex = kernelObjects.Get<PSPMutex>(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<Mutex>(id, error);
|
||||
PSPMutex *m = kernelObjects.Get<PSPMutex>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Semaphore, WAITTYPE_SEMA, SceUID>(threadID, prevCallbackId, semaWaitTimer);
|
||||
auto result = HLEKernel::WaitBeginCallback<PSPSemaphore, WAITTYPE_SEMA, SceUID>(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<Semaphore, WAITTYPE_SEMA, SceUID>(threadID, prevCallbackId, semaWaitTimer, __KernelUnlockSemaForThread);
|
||||
auto result = HLEKernel::WaitEndCallback<PSPSemaphore, WAITTYPE_SEMA, SceUID>(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<SceUID>::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<Semaphore>(id, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(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<Semaphore>(id, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(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<Semaphore>(id);
|
||||
return kernelObjects.Destroy<PSPSemaphore>(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -265,7 +262,7 @@ int sceKernelDeleteSema(SceUID id)
|
||||
int sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
|
||||
{
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(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<Semaphore>(id, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(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<Semaphore, WAITTYPE_SEMA>(threadID);
|
||||
HLEKernel::WaitExecTimeout<PSPSemaphore, WAITTYPE_SEMA>(threadID);
|
||||
|
||||
// If in FIFO mode, that may have cleared another thread to wake up.
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(uid, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(uid, error);
|
||||
if (s && (s->ns.attr & PSP_SEMA_ATTR_PRIORITY) == PSP_SEMA_ATTR_FIFO) {
|
||||
bool wokeThreads;
|
||||
std::vector<SceUID>::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<Semaphore>(id, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(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<Semaphore>(id, error);
|
||||
PSPSemaphore *s = kernelObjects.Get<PSPSemaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
if (s->ns.currentCount >= wantedCount && s->waitingThreads.size() == 0)
|
||||
|
||||
+217
-258
File diff suppressed because it is too large.
Load diff
+16
-16
@@ -26,7 +26,7 @@
|
||||
// There's a good description of the thread scheduling rules in:
|
||||
// http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/ThreadManForUser.java
|
||||
|
||||
class Thread;
|
||||
class PSPThread;
|
||||
class DebugInterface;
|
||||
|
||||
int sceKernelChangeThreadPriority(SceUID threadID, int priority);
|
||||
@@ -119,8 +119,7 @@ typedef void (* WaitEndCallbackFunc)(SceUID threadID, SceUID prevCallbackId);
|
||||
|
||||
void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc);
|
||||
|
||||
struct ThreadContext
|
||||
{
|
||||
struct PSPThreadContext {
|
||||
void reset();
|
||||
|
||||
// r must be followed by f.
|
||||
@@ -168,8 +167,8 @@ u32 __KernelGetCurThreadStackStart();
|
||||
const char *__KernelGetThreadName(SceUID threadID);
|
||||
bool KernelIsThreadDormant(SceUID threadID);
|
||||
|
||||
void __KernelSaveContext(ThreadContext *ctx, bool vfpuEnabled);
|
||||
void __KernelLoadContext(ThreadContext *ctx, bool vfpuEnabled);
|
||||
void __KernelSaveContext(PSPThreadContext *ctx, bool vfpuEnabled);
|
||||
void __KernelLoadContext(PSPThreadContext *ctx, bool vfpuEnabled);
|
||||
|
||||
u32 __KernelResumeThreadFromWait(SceUID threadID, u32 retval); // can return an error value
|
||||
u32 __KernelResumeThreadFromWait(SceUID threadID, u64 retval);
|
||||
@@ -205,7 +204,8 @@ void __KernelReturnFromExtendStack();
|
||||
|
||||
void __KernelIdle();
|
||||
|
||||
u32 __KernelMipsCallReturnAddress();
|
||||
u32 HLEMipsCallReturnAddress();
|
||||
u32 __KernelCallbackReturnAddress();
|
||||
u32 __KernelInterruptReturnAddress(); // TODO: remove
|
||||
|
||||
SceUID sceKernelCreateCallback(const char *name, u32 entrypoint, u32 signalArg);
|
||||
@@ -216,10 +216,10 @@ int sceKernelGetCallbackCount(SceUID cbId);
|
||||
void sceKernelCheckCallback();
|
||||
int sceKernelReferCallbackStatus(SceUID cbId, u32 statusAddr);
|
||||
|
||||
class Action;
|
||||
class PSPAction;
|
||||
|
||||
// Not an official Callback object, just calls a mips function on the current thread.
|
||||
void __KernelDirectMipsCall(u32 entryPoint, Action *afterAction, u32 args[], int numargs, bool reschedAfter);
|
||||
void __KernelDirectMipsCall(u32 entryPoint, PSPAction *afterAction, u32 args[], int numargs, bool reschedAfter);
|
||||
|
||||
void __KernelReturnFromMipsCall(); // Called as HLE function
|
||||
bool __KernelInCallback();
|
||||
@@ -228,8 +228,8 @@ bool __KernelInCallback();
|
||||
bool __KernelCheckCallbacks();
|
||||
bool __KernelForceCallbacks();
|
||||
bool __KernelCurHasReadyCallbacks();
|
||||
void __KernelSwitchContext(Thread *target, const char *reason);
|
||||
bool __KernelExecutePendingMipsCalls(Thread *currentThread, bool reschedAfter);
|
||||
void __KernelSwitchContext(PSPThread *target, const char *reason);
|
||||
bool __KernelExecutePendingMipsCalls(PSPThread *currentThread, bool reschedAfter);
|
||||
void __KernelNotifyCallback(SceUID cbId, int notifyArg);
|
||||
|
||||
// Switch to an idle / non-user thread, if not already on one.
|
||||
@@ -243,8 +243,8 @@ u32 __KernelSetThreadRA(SceUID threadID, u32 nid);
|
||||
|
||||
// A call into game code. These can be pending on a thread.
|
||||
// Similar to Callback-s (NOT CallbackInfos) in JPCSP.
|
||||
typedef Action *(*ActionCreator)();
|
||||
Action *__KernelCreateAction(int actionType);
|
||||
typedef PSPAction *(*ActionCreator)();
|
||||
PSPAction *__KernelCreateAction(int actionType);
|
||||
int __KernelRegisterActionType(ActionCreator creator);
|
||||
void __KernelRestoreActionType(int actionType, ActionCreator creator);
|
||||
|
||||
@@ -258,7 +258,7 @@ struct MipsCall {
|
||||
u32 cbId;
|
||||
u32 args[6];
|
||||
int numArgs;
|
||||
Action *doAfter;
|
||||
PSPAction *doAfter;
|
||||
u32 savedPc;
|
||||
u32 savedV0;
|
||||
u32 savedV1;
|
||||
@@ -279,10 +279,10 @@ struct MipsCall {
|
||||
}
|
||||
};
|
||||
|
||||
class Action
|
||||
class PSPAction
|
||||
{
|
||||
public:
|
||||
virtual ~Action() {}
|
||||
virtual ~PSPAction() {}
|
||||
virtual void run(MipsCall &call) = 0;
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
int actionTypeID;
|
||||
@@ -300,7 +300,7 @@ enum ThreadStatus
|
||||
THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND
|
||||
};
|
||||
|
||||
void __KernelChangeThreadState(Thread *thread, ThreadStatus newStatus);
|
||||
void __KernelChangeThreadState(PSPThread *thread, ThreadStatus newStatus);
|
||||
|
||||
typedef void (*ThreadCallback)(SceUID threadID);
|
||||
void __KernelListenThreadEnd(ThreadCallback callback);
|
||||
|
||||
+11
-3
@@ -355,11 +355,11 @@ static void AnalyzeMpeg(u8 *buffer, u32 validSize, MpegContext *ctx) {
|
||||
INFO_LOG(ME, "First timestamp: %lld, Last timestamp: %lld", ctx->mpegFirstTimestamp, ctx->mpegLastTimestamp);
|
||||
}
|
||||
|
||||
class PostPutAction : public Action {
|
||||
class PostPutAction : public PSPAction {
|
||||
public:
|
||||
PostPutAction() {}
|
||||
void setRingAddr(u32 ringAddr) { ringAddr_ = ringAddr; }
|
||||
static Action *Create() { return new PostPutAction; }
|
||||
static PSPAction *Create() { return new PostPutAction; }
|
||||
void DoState(PointerWrap &p) override {
|
||||
auto s = p.Section("PostPutAction", 1);
|
||||
if (!s)
|
||||
@@ -1524,7 +1524,7 @@ static u32 sceMpegRingbufferPut(u32 ringbufferAddr, int numPackets, int availabl
|
||||
int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets;
|
||||
u32 packetsThisRound = std::min(numPackets, (s32)ringbuffer->packets - writeOffset);
|
||||
u32 args[3] = {(u32)ringbuffer->data + (u32)writeOffset * 2048, packetsThisRound, (u32)ringbuffer->callback_args};
|
||||
__KernelDirectMipsCall(ringbuffer->callback_addr, action, args, 3, false);
|
||||
hleEnqueueCall(ringbuffer->callback_addr, 3, args, action);
|
||||
} else {
|
||||
ERROR_LOG_REPORT(ME, "sceMpegRingbufferPut: callback_addr zero");
|
||||
}
|
||||
@@ -1939,6 +1939,14 @@ static u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth
|
||||
|
||||
DEBUG_LOG(ME, "sceMpegAvcCsc(%08x, %08x, %08x, %i, %08x)", mpeg, sourceAddr, rangeAddr, frameWidth, destAddr);
|
||||
|
||||
if (frameWidth == 0) {
|
||||
if (!ctx->defaultFrameWidth) {
|
||||
frameWidth = ctx->avc.avcDetailFrameWidth;
|
||||
} else {
|
||||
frameWidth = ctx->defaultFrameWidth;
|
||||
}
|
||||
}
|
||||
|
||||
int x = Memory::Read_U32(rangeAddr);
|
||||
int y = Memory::Read_U32(rangeAddr + 4);
|
||||
int width = Memory::Read_U32(rangeAddr + 8);
|
||||
|
||||
+79
-17
@@ -28,6 +28,7 @@
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
#include "Core/HLE/sceKernelMemory.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
@@ -47,6 +48,9 @@ static bool netInetInited;
|
||||
static bool netApctlInited;
|
||||
u32 netDropRate = 0;
|
||||
u32 netDropDuration = 0;
|
||||
u32 netPoolAddr = 0;
|
||||
u32 netThread1Addr = 0;
|
||||
u32 netThread2Addr = 0;
|
||||
|
||||
static struct SceNetMallocStat netMallocStat;
|
||||
|
||||
@@ -239,14 +243,13 @@ static void __UpdateApctlHandlers(int oldState, int newState, int flag, int erro
|
||||
|
||||
for(std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); ++it) {
|
||||
args[4] = it->second.argument;
|
||||
|
||||
__KernelDirectMipsCall(it->second.entryPoint, NULL, args, 5, true);
|
||||
hleEnqueueCall(it->second.entryPoint, 5, args);
|
||||
}
|
||||
}
|
||||
|
||||
// This feels like a dubious proposition, mostly...
|
||||
void __NetDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceNet", 1, 2);
|
||||
auto s = p.Section("sceNet", 1, 3);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
@@ -262,6 +265,28 @@ void __NetDoState(PointerWrap &p) {
|
||||
p.Do(netDropRate);
|
||||
p.Do(netDropDuration);
|
||||
}
|
||||
if (s < 3) {
|
||||
netPoolAddr = 0;
|
||||
netThread1Addr = 0;
|
||||
netThread2Addr = 0;
|
||||
} else {
|
||||
p.Do(netPoolAddr);
|
||||
p.Do(netThread1Addr);
|
||||
p.Do(netThread2Addr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u32 AllocUser(u32 size, bool fromTop, const char *name) {
|
||||
u32 addr = userMemory.Alloc(size, fromTop, name);
|
||||
if (addr == -1)
|
||||
return 0;
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline void FreeUser(u32 &addr) {
|
||||
if (addr != 0)
|
||||
userMemory.Free(addr);
|
||||
addr = 0;
|
||||
}
|
||||
|
||||
static u32 sceNetTerm() {
|
||||
@@ -271,37 +296,76 @@ static u32 sceNetTerm() {
|
||||
|
||||
WARN_LOG(SCENET, "sceNetTerm()");
|
||||
netInited = false;
|
||||
FreeUser(netPoolAddr);
|
||||
FreeUser(netThread1Addr);
|
||||
FreeUser(netThread2Addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: should that struct actually be initialized here?
|
||||
static u32 sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u32 netinitStack) {
|
||||
// May need to Terminate old one first since the game (ie. GTA:VCS) might not called sceNetTerm before the next sceNetInit and behave strangely
|
||||
if (netInited)
|
||||
static int sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u32 netinitStack) {
|
||||
// TODO: The correct behavior is actually to allocate more and leak the other threads/pool.
|
||||
// But we reset here for historic reasons (GTA:VCS potentially triggers this.)
|
||||
if (netInited)
|
||||
sceNetTerm();
|
||||
|
||||
if (poolSize == 0) {
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE, "invalid pool size");
|
||||
} else if (calloutPri < 0x08 || calloutPri > 0x77) {
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_PRIORITY, "invalid callout thread priority");
|
||||
} else if (netinitPri < 0x08 || netinitPri > 0x77) {
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_PRIORITY, "invalid init thread priority");
|
||||
}
|
||||
|
||||
// TODO: Should also start the threads, probably? For now, let's just allocate.
|
||||
// TODO: Respect the stack size if firmware set to 1.50?
|
||||
u32 stackSize = 4096;
|
||||
netThread1Addr = AllocUser(stackSize, true, "netstack1");
|
||||
if (netThread1Addr == 0) {
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_NO_MEMORY, "unable to allocate thread");
|
||||
}
|
||||
netThread2Addr = AllocUser(stackSize, true, "netstack2");
|
||||
if (netThread2Addr == 0) {
|
||||
FreeUser(netThread1Addr);
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_NO_MEMORY, "unable to allocate thread");
|
||||
}
|
||||
|
||||
netPoolAddr = AllocUser(poolSize, false, "netpool");
|
||||
if (netPoolAddr == 0) {
|
||||
FreeUser(netThread1Addr);
|
||||
FreeUser(netThread2Addr);
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_NO_MEMORY, "unable to allocate pool");
|
||||
}
|
||||
|
||||
WARN_LOG(SCENET, "sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d) at %08x", poolSize, calloutPri, calloutStack, netinitPri, netinitStack, currentMIPS->pc);
|
||||
netInited = true;
|
||||
netMallocStat.maximum = poolSize;
|
||||
netMallocStat.free = poolSize;
|
||||
netMallocStat.pool = 0;
|
||||
|
||||
return 0;
|
||||
return hleLogSuccessI(SCENET, 0);
|
||||
}
|
||||
|
||||
static u32 sceWlanGetEtherAddr(u32 addrAddr) {
|
||||
if (!Memory::IsValidRange(addrAddr, 6)) {
|
||||
// More correctly, it should crash.
|
||||
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "illegal address");
|
||||
}
|
||||
|
||||
u8 *addr = Memory::GetPointer(addrAddr);
|
||||
// Read MAC Address from config
|
||||
uint8_t mac[6] = {0};
|
||||
if (PPSSPP_ID > 1) {
|
||||
memset(&mac, PPSSPP_ID, sizeof(mac));
|
||||
} else if (!ParseMacAddress(g_Config.sMACAddress.c_str(), mac)) {
|
||||
} else if (!ParseMacAddress(g_Config.sMACAddress.c_str(), addr)) {
|
||||
ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.sMACAddress.c_str());
|
||||
Memory::Memset(addrAddr, 0, 6);
|
||||
} else {
|
||||
CBreakPoints::ExecMemCheck(addrAddr, true, 6, currentMIPS->pc);
|
||||
}
|
||||
DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr);
|
||||
for (int i = 0; i < 6; i++)
|
||||
Memory::Write_U8(mac[i], addrAddr + i);
|
||||
return 0;
|
||||
|
||||
return hleLogSuccessI(SCENET, hleDelayResult(0, "get ether mac", 200));
|
||||
}
|
||||
|
||||
static u32 sceNetGetLocalEtherAddr(u32 addrAddr) {
|
||||
@@ -309,13 +373,11 @@ static u32 sceNetGetLocalEtherAddr(u32 addrAddr) {
|
||||
}
|
||||
|
||||
static u32 sceWlanDevIsPowerOn() {
|
||||
DEBUG_LOG(SCENET, "UNTESTED sceWlanDevIsPowerOn()");
|
||||
return g_Config.bEnableWlan ? 1 : 0;
|
||||
return hleLogSuccessVerboseI(SCENET, g_Config.bEnableWlan ? 1 : 0);
|
||||
}
|
||||
|
||||
static u32 sceWlanGetSwitchState() {
|
||||
VERBOSE_LOG(SCENET, "sceWlanGetSwitchState()");
|
||||
return g_Config.bEnableWlan ? 1 : 0;
|
||||
return hleLogSuccessVerboseI(SCENET, g_Config.bEnableWlan ? 1 : 0);
|
||||
}
|
||||
|
||||
// Probably a void function, but often returns a useful value.
|
||||
@@ -638,7 +700,7 @@ static int sceNetSetDropRate(u32 dropRate, u32 dropDuration)
|
||||
}
|
||||
|
||||
const HLEFunction sceNet[] = {
|
||||
{0X39AF39A6, &WrapU_UUUUU<sceNetInit>, "sceNetInit", 'x', "xxxxx"},
|
||||
{0X39AF39A6, &WrapI_UUUUU<sceNetInit>, "sceNetInit", 'i', "xxxxx"},
|
||||
{0X281928A9, &WrapU_V<sceNetTerm>, "sceNetTerm", 'x', "" },
|
||||
{0X89360950, &WrapI_UU<sceNetEtherNtostr>, "sceNetEtherNtostr", 'i', "xx" },
|
||||
{0XD27961C9, &WrapI_UU<sceNetEtherStrton>, "sceNetEtherStrton", 'i', "xx" },
|
||||
|
||||
@@ -160,8 +160,6 @@ void __NetAdhocInit() {
|
||||
}
|
||||
|
||||
u32 sceNetAdhocInit() {
|
||||
// Library uninitialized
|
||||
INFO_LOG(SCENET, "sceNetAdhocInit() at %08x", currentMIPS->pc);
|
||||
if (!netAdhocInited) {
|
||||
// Clear Translator Memory
|
||||
memset(&pdp, 0, sizeof(pdp));
|
||||
@@ -173,17 +171,17 @@ u32 sceNetAdhocInit() {
|
||||
// Create fake PSP Thread for callback
|
||||
// TODO: Should use a separated threads for friendFinder, matchingEvent, and matchingInput and created on AdhocctlInit & AdhocMatchingStart instead of here
|
||||
#define PSP_THREAD_ATTR_KERNEL 0x00001000 // PSP_THREAD_ATTR_KERNEL is located in sceKernelThread.cpp instead of sceKernelThread.h :(
|
||||
//threadAdhocID = __KernelCreateThreadInternal("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x30, 4096, PSP_THREAD_ATTR_KERNEL);
|
||||
threadAdhocID = __KernelCreateThread("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x10, 0x1000, 0, 0, false);
|
||||
// TODO: This should probably be a user thread, but maybe from sceNetAdhocctlInit?
|
||||
threadAdhocID = __KernelCreateThread("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x10, 0x1000, PSP_THREAD_ATTR_KERNEL, 0, true);
|
||||
if (threadAdhocID > 0) {
|
||||
__KernelStartThread(threadAdhocID, 0, 0);
|
||||
}
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
return hleLogSuccessInfoI(SCENET, 0, "at %08x", currentMIPS->pc);
|
||||
}
|
||||
// Already initialized
|
||||
return ERROR_NET_ADHOC_ALREADY_INITIALIZED;
|
||||
return hleLogWarning(SCENET, ERROR_NET_ADHOC_ALREADY_INITIALIZED, "already initialized");
|
||||
}
|
||||
|
||||
static u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
|
||||
@@ -1424,7 +1422,6 @@ int sceNetAdhocctlCreateEnterGameModeMin(const char *group_name, int game_type,
|
||||
}
|
||||
|
||||
int sceNetAdhocTerm() {
|
||||
INFO_LOG(SCENET, "sceNetAdhocTerm()");
|
||||
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup all the sockets right?
|
||||
|
||||
if (netAdhocctlInited) sceNetAdhocctlTerm();
|
||||
@@ -1453,10 +1450,11 @@ int sceNetAdhocTerm() {
|
||||
// if (_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET);
|
||||
// Library shutdown
|
||||
netAdhocInited = false;
|
||||
return 0;
|
||||
return hleLogSuccessInfoI(SCENET, 0);
|
||||
} else {
|
||||
// Seems to return this when called a second time after being terminated without another initialisation
|
||||
return SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND;
|
||||
// TODO: Reportedly returns SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND in some cases?
|
||||
// Only seen returning 0 in tests.
|
||||
return hleLogWarning(SCENET, 0, "already uninitialized");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -234,10 +234,10 @@ public:
|
||||
|
||||
bool HasReachedEnd() {
|
||||
// The pts are ignored - the end is when we're out of data.
|
||||
return mediaengine->IsVideoEnd() && mediaengine->IsNoAudioData();
|
||||
return mediaengine->IsVideoEnd() && (mediaengine->IsNoAudioData() || !mediaengine->IsActuallyPlayingAudio());
|
||||
}
|
||||
|
||||
u32 filehandle;
|
||||
int filehandle;
|
||||
u32 fileoffset;
|
||||
int readSize;
|
||||
int streamSize;
|
||||
@@ -1617,7 +1617,7 @@ static int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr)
|
||||
bool doVideoStep = true;
|
||||
if (psmfplayer->playMode == PSMF_PLAYER_MODE_PAUSE) {
|
||||
doVideoStep = false;
|
||||
} else if (!psmfplayer->mediaengine->IsNoAudioData()) {
|
||||
} else if (!psmfplayer->mediaengine->IsNoAudioData() && psmfplayer->mediaengine->IsActuallyPlayingAudio()) {
|
||||
s64 deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp();
|
||||
// Don't skip the very first frame, sometimes audio starts with an early timestamp.
|
||||
if (deltapts > 0 && psmfplayer->mediaengine->getVideoTimeStamp() > 0) {
|
||||
|
||||
+11
-4
@@ -37,6 +37,13 @@
|
||||
#include "Core/HLE/sceKernel.h"
|
||||
#include "Core/HLE/sceRtc.h"
|
||||
|
||||
#ifdef HAVE_LIBNX
|
||||
// I guess that works...
|
||||
#define setenv(x, y, z) (void*)0
|
||||
#define tzset() (void*)0
|
||||
#define unsetenv(x) (void*)0
|
||||
#endif // HAVE_LIBNX
|
||||
|
||||
// This is a base time that everything is relative to.
|
||||
// This way, time doesn't move strangely with savestates, turbo speed, etc.
|
||||
static PSPTimeval rtcBaseTime;
|
||||
@@ -494,7 +501,7 @@ static int sceRtcConvertLocalTimeToUTC(u32 tickLocalPtr,u32 tickUTCPtr)
|
||||
long timezone_val;
|
||||
_get_timezone(&timezone_val);
|
||||
srcTick -= -timezone_val * 1000000ULL;
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux)
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux) && !defined(HAVE_LIBNX)
|
||||
time_t timezone = 0;
|
||||
tm *time = localtime(&timezone);
|
||||
srcTick -= time->tm_gmtoff*1000000ULL;
|
||||
@@ -519,7 +526,7 @@ static int sceRtcConvertUtcToLocalTime(u32 tickUTCPtr,u32 tickLocalPtr)
|
||||
long timezone_val;
|
||||
_get_timezone(&timezone_val);
|
||||
srcTick += -timezone_val * 1000000ULL;
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux)
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux) && !defined(HAVE_LIBNX)
|
||||
time_t timezone = 0;
|
||||
tm *time = localtime(&timezone);
|
||||
srcTick += time->tm_gmtoff*1000000ULL;
|
||||
@@ -1054,7 +1061,7 @@ static int sceRtcFormatRFC2822LocalTime(u32 outPtr, u32 srcTickPtr)
|
||||
long timezone_val;
|
||||
_get_timezone(&timezone_val);
|
||||
tz_seconds = -timezone_val;
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux)
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux) && !defined(HAVE_LIBNX)
|
||||
time_t timezone = 0;
|
||||
tm *time = localtime(&timezone);
|
||||
tz_seconds = time->tm_gmtoff;
|
||||
@@ -1091,7 +1098,7 @@ static int sceRtcFormatRFC3339LocalTime(u32 outPtr, u32 srcTickPtr)
|
||||
long timezone_val;
|
||||
_get_timezone(&timezone_val);
|
||||
tz_seconds = -timezone_val;
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux)
|
||||
#elif !defined(_AIX) && !defined(__sgi) && !defined(__hpux) && !defined(HAVE_LIBNX)
|
||||
time_t timezone = 0;
|
||||
tm *time = localtime(&timezone);
|
||||
tz_seconds = time->tm_gmtoff;
|
||||
|
||||
+1
-1
@@ -269,7 +269,7 @@ static u32 sceSasGetEndFlag(u32 core) {
|
||||
endFlag |= (1 << i);
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCESAS, "%08x=sceSasGetEndFlag(%08x)", endFlag, core);
|
||||
VERBOSE_LOG(SCESAS, "%08x=sceSasGetEndFlag(%08x)", endFlag, core);
|
||||
return endFlag;
|
||||
}
|
||||
|
||||
|
||||
+37
-34
@@ -470,55 +470,46 @@ static int sceUtilityOskGetStatus()
|
||||
}
|
||||
|
||||
|
||||
static int sceUtilityNetconfInitStart(u32 paramsAddr)
|
||||
{
|
||||
static int sceUtilityNetconfInitStart(u32 paramsAddr) {
|
||||
if (currentDialogActive && currentDialogType != UTILITY_DIALOG_NET) {
|
||||
WARN_LOG(SCEUTILITY, "sceUtilityNetconfInitStart(%08x): wrong dialog type", paramsAddr);
|
||||
return SCE_ERROR_UTILITY_WRONG_TYPE;
|
||||
return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type");
|
||||
}
|
||||
|
||||
oldStatus = 100;
|
||||
currentDialogType = UTILITY_DIALOG_NET;
|
||||
currentDialogActive = true;
|
||||
int ret = netDialog.Init(paramsAddr);
|
||||
INFO_LOG(SCEUTILITY, "%08x=sceUtilityNetconfInitStart(%08x)", ret, paramsAddr);
|
||||
return ret;
|
||||
currentDialogActive = true;
|
||||
return hleLogSuccessInfoI(SCEUTILITY, netDialog.Init(paramsAddr));
|
||||
}
|
||||
|
||||
static int sceUtilityNetconfShutdownStart()
|
||||
{
|
||||
static int sceUtilityNetconfShutdownStart() {
|
||||
if (currentDialogType != UTILITY_DIALOG_NET) {
|
||||
WARN_LOG(SCEUTILITY, "sceUtilityNetconfShutdownStart(): wrong dialog type");
|
||||
return SCE_ERROR_UTILITY_WRONG_TYPE;
|
||||
return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type");
|
||||
}
|
||||
|
||||
currentDialogActive = false;
|
||||
int ret = netDialog.Shutdown();
|
||||
DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityNetconfShutdownStart()",ret);
|
||||
return ret;
|
||||
return hleLogSuccessI(SCEUTILITY, netDialog.Shutdown());
|
||||
}
|
||||
|
||||
static int sceUtilityNetconfUpdate(int animSpeed)
|
||||
{
|
||||
int ret = netDialog.Update(animSpeed);
|
||||
ERROR_LOG(SCEUTILITY, "UNIMPL %08x=sceUtilityNetconfUpdate(%i)", ret, animSpeed);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sceUtilityNetconfGetStatus()
|
||||
{
|
||||
// Spam in Danball Senki BOOST
|
||||
static int sceUtilityNetconfUpdate(int animSpeed) {
|
||||
if (currentDialogType != UTILITY_DIALOG_NET) {
|
||||
DEBUG_LOG(SCEUTILITY, "sceUtilityNetconfGetStatus(): wrong dialog type");
|
||||
return SCE_ERROR_UTILITY_WRONG_TYPE;
|
||||
return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type");
|
||||
}
|
||||
|
||||
return hleLogSuccessI(SCEUTILITY, netDialog.Update(animSpeed));
|
||||
}
|
||||
|
||||
static int sceUtilityNetconfGetStatus() {
|
||||
if (currentDialogType != UTILITY_DIALOG_NET) {
|
||||
// Spam in Danball Senki BOOST.
|
||||
return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type");
|
||||
}
|
||||
|
||||
int status = netDialog.GetStatus();
|
||||
if (oldStatus != status) {
|
||||
oldStatus = status;
|
||||
DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityNetconfGetStatus()", status);
|
||||
return hleLogSuccessI(SCEUTILITY, status);
|
||||
}
|
||||
return status;
|
||||
return hleLogSuccessVerboseI(SCEUTILITY, status);
|
||||
}
|
||||
|
||||
static int sceUtilityCheckNetParam(int id)
|
||||
@@ -769,6 +760,18 @@ static u32 sceUtilityUnloadNetModule(u32 module)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUtilityNpSigninInitStart(u32 paramsPtr) {
|
||||
return hleLogError(SCEUTILITY, 0, "not implemented");
|
||||
}
|
||||
|
||||
static int sceUtilityNpSigninUpdate(int animSpeed) {
|
||||
return hleLogError(SCEUTILITY, 0, "not implemented");
|
||||
}
|
||||
|
||||
static int sceUtilityNpSigninGetStatus() {
|
||||
return hleLogError(SCEUTILITY, 0, "not implemented");
|
||||
}
|
||||
|
||||
static void sceUtilityInstallInitStart(u32 unknown)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEUTILITY, "UNIMPL sceUtilityInstallInitStart()");
|
||||
@@ -934,7 +937,7 @@ const HLEFunction sceUtility[] =
|
||||
|
||||
{0X0251B134, &WrapI_U<sceUtilityScreenshotInitStart>, "sceUtilityScreenshotInitStart", 'i', "x" },
|
||||
{0XF9E0008C, &WrapI_V<sceUtilityScreenshotShutdownStart>, "sceUtilityScreenshotShutdownStart", 'i', "" },
|
||||
{0XAB083EA9, &WrapI_U<sceUtilityScreenshotUpdate>, "sceUtilityScreenshotUpdate", 'i', "x" },
|
||||
{0XAB083EA9, &WrapI_U<sceUtilityScreenshotUpdate>, "sceUtilityScreenshotUpdate", 'i', "i" },
|
||||
{0XD81957B7, &WrapI_V<sceUtilityScreenshotGetStatus>, "sceUtilityScreenshotGetStatus", 'i', "" },
|
||||
{0X86A03A27, &WrapI_U<sceUtilityScreenshotContStart>, "sceUtilityScreenshotContStart", 'i', "x" },
|
||||
|
||||
@@ -947,10 +950,10 @@ const HLEFunction sceUtility[] =
|
||||
{0XB57E95D9, &WrapI_V<sceUtilityGamedataInstallGetStatus>, "sceUtilityGamedataInstallGetStatus", 'i', "" },
|
||||
{0X180F7B62, &WrapI_V<sceUtilityGamedataInstallAbort>, "sceUtilityGamedataInstallAbort", 'i', "" },
|
||||
|
||||
{0X16D02AF0, nullptr, "sceUtilityNpSigninInitStart", '?', "" },
|
||||
{0XE19C97D6, nullptr, "sceUtilityNpSigninShutdownStart", '?', "" },
|
||||
{0XF3FBC572, nullptr, "sceUtilityNpSigninUpdate", '?', "" },
|
||||
{0X86ABDB1B, nullptr, "sceUtilityNpSigninGetStatus", '?', "" },
|
||||
{0X16D02AF0, &WrapI_U<sceUtilityNpSigninInitStart>, "sceUtilityNpSigninInitStart", 'i', "x" },
|
||||
{0XE19C97D6, nullptr, "sceUtilityNpSigninShutdownStart", 'i', "" },
|
||||
{0XF3FBC572, &WrapI_I<sceUtilityNpSigninUpdate>, "sceUtilityNpSigninUpdate", 'i', "i" },
|
||||
{0X86ABDB1B, &WrapI_V<sceUtilityNpSigninGetStatus>, "sceUtilityNpSigninGetStatus", 'i', "" },
|
||||
|
||||
{0X1281DA8E, &WrapV_U<sceUtilityInstallInitStart>, "sceUtilityInstallInitStart", 'v', "x" },
|
||||
{0X5EF1C24A, nullptr, "sceUtilityInstallShutdownStart", '?', "" },
|
||||
|
||||
+10
-9
@@ -231,10 +231,10 @@ void *v4l_loop(void *data) {
|
||||
if (ioctl(v4l_fd, VIDIOC_DQBUF, &buf) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_DQBUF; errno=%d(%s)", errno, strerror(errno));
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
continue;
|
||||
default:
|
||||
return NULL;
|
||||
case EAGAIN:
|
||||
continue;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,9 +265,10 @@ void *v4l_loop(void *data) {
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
if (ioctl(v4l_fd, VIDIOC_QBUF, &buf) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_QBUF");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int __v4l_startCapture(int ideal_width, int ideal_height) {
|
||||
@@ -338,10 +339,10 @@ int __v4l_startCapture(int ideal_width, int ideal_height) {
|
||||
frmsize.index++;
|
||||
if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
|
||||
INFO_LOG(HLE, "V4L2: frame size supported: %dx%d", frmsize.discrete.width, frmsize.discrete.height);
|
||||
if (frmsize.discrete.width >= ideal_width && frmsize.discrete.height >= ideal_height
|
||||
&& fmt.fmt.pix.width == 0 && fmt.fmt.pix.height == 0
|
||||
|| frmsize.discrete.width >= ideal_width && frmsize.discrete.height >= ideal_height
|
||||
&& frmsize.discrete.width < fmt.fmt.pix.width && frmsize.discrete.height < fmt.fmt.pix.height) {
|
||||
bool matchesIdeal = frmsize.discrete.width >= ideal_width && frmsize.discrete.height >= ideal_height;
|
||||
bool zeroPix = fmt.fmt.pix.width == 0 && fmt.fmt.pix.height == 0;
|
||||
bool pixLarger = frmsize.discrete.width < fmt.fmt.pix.width && frmsize.discrete.height < fmt.fmt.pix.height;
|
||||
if (matchesIdeal && (zeroPix || pixLarger)) {
|
||||
fmt.fmt.pix.width = frmsize.discrete.width;
|
||||
fmt.fmt.pix.height = frmsize.discrete.height;
|
||||
}
|
||||
|
||||
@@ -992,6 +992,10 @@ bool MediaEngine::IsNoAudioData() {
|
||||
return !m_demux->hasNextAudioFrame(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
bool MediaEngine::IsActuallyPlayingAudio() {
|
||||
return getAudioTimeStamp() >= 0;
|
||||
}
|
||||
|
||||
s64 MediaEngine::getVideoTimeStamp() {
|
||||
return m_videopts;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public:
|
||||
|
||||
bool IsVideoEnd() { return m_isVideoEnd; }
|
||||
bool IsNoAudioData();
|
||||
bool IsActuallyPlayingAudio();
|
||||
int VideoWidth() { return m_desWidth; }
|
||||
int VideoHeight() { return m_desHeight; }
|
||||
|
||||
|
||||
@@ -1022,6 +1022,8 @@ skip:
|
||||
bool ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols) {
|
||||
std::lock_guard<std::recursive_mutex> guard(functions_lock);
|
||||
|
||||
FunctionsVector new_functions;
|
||||
|
||||
AnalyzedFunction currentFunction = {startAddr};
|
||||
|
||||
u32 furthestBranch = 0;
|
||||
@@ -1142,7 +1144,7 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
functions.push_back(currentFunction);
|
||||
new_functions.push_back(currentFunction);
|
||||
|
||||
furthestBranch = 0;
|
||||
addr += 4;
|
||||
@@ -1157,10 +1159,10 @@ skip:
|
||||
|
||||
if (addr <= endAddr) {
|
||||
currentFunction.end = addr + 4;
|
||||
functions.push_back(currentFunction);
|
||||
new_functions.push_back(currentFunction);
|
||||
}
|
||||
|
||||
for (auto iter = functions.begin(); iter != functions.end(); iter++) {
|
||||
for (auto iter = new_functions.begin(); iter != new_functions.end(); iter++) {
|
||||
iter->size = iter->end - iter->start + 4;
|
||||
if (insertSymbols && !iter->foundInSymbolMap) {
|
||||
char temp[256];
|
||||
@@ -1168,6 +1170,8 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
// Concatenate the new functions to the end of the old ones.
|
||||
functions.insert(functions.end(), new_functions.begin(), new_functions.end());
|
||||
return insertSymbols;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -249,7 +249,7 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
|
||||
}
|
||||
|
||||
bool hasEncrypted = false;
|
||||
u32 fd;
|
||||
int fd;
|
||||
if ((fd = pspFileSystem.OpenFile(bootpath, FILEACCESS_READ)) >= 0)
|
||||
{
|
||||
u8 head[4];
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#ifdef USING_QT_UI
|
||||
#include <QtGui/QImage>
|
||||
#else
|
||||
#include <libpng17/png.h>
|
||||
#include <png.h>
|
||||
#include "ext/jpge/jpge.h"
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -220,6 +220,12 @@ void CPU_Init() {
|
||||
// ERROR_LOG(LOADER, "PBP directory resolution failed.");
|
||||
InitMemoryForGamePBP(loadedFile);
|
||||
break;
|
||||
case IdentifiedFileType::PSP_ELF:
|
||||
if (Memory::g_PSPModel != PSP_MODEL_FAT) {
|
||||
INFO_LOG(LOADER, "ELF, using full PSP-2000 memory access");
|
||||
Memory::g_MemorySize = Memory::RAM_DOUBLE_SIZE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -609,7 +615,7 @@ void InitSysDirectories() {
|
||||
INFO_LOG(COMMON, "Memstick directory not present, creating at '%s'", g_Config.memStickDirectory.c_str());
|
||||
}
|
||||
|
||||
const std::string testFile = g_Config.memStickDirectory + "/_writable_test.$$$";
|
||||
const std::string testFile = g_Config.memStickDirectory + "_writable_test.$$$";
|
||||
|
||||
// If any directory is read-only, fall back to the Documents directory.
|
||||
// We're screwed anyway if we can't write to Documents, or can't detect it.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifdef USING_QT_UI
|
||||
#include <QtGui/QImage>
|
||||
#else
|
||||
#include <libpng17/png.h>
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -55,7 +55,7 @@ std::string GameManager::GetTempFilename() const {
|
||||
GetTempFileName(tempPath, L"PSP", 1, buffer);
|
||||
return ConvertWStringToUTF8(buffer);
|
||||
#else
|
||||
return g_Config.memStickDirectory + "/ppsspp.dl";
|
||||
return g_Config.memStickDirectory + "ppsspp.dl";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+324
-75
@@ -18,6 +18,9 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/stringutil.h"
|
||||
#include "file/vfs.h"
|
||||
#include "gfx/texture_atlas.h"
|
||||
#include "gfx_es2/draw_text.h"
|
||||
#include "image/zim_load.h"
|
||||
#include "image/png_load.h"
|
||||
#include "util/text/utf8.h"
|
||||
@@ -36,6 +39,8 @@
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
Atlas g_ppge_atlas;
|
||||
|
||||
static u32 atlasPtr;
|
||||
static int atlasWidth;
|
||||
static int atlasHeight;
|
||||
@@ -99,6 +104,38 @@ static AtlasCharLine char_one_line;
|
||||
static AtlasLineArray char_lines;
|
||||
static AtlasTextMetrics char_lines_metrics;
|
||||
|
||||
static bool textDrawerInited = false;
|
||||
static TextDrawer *textDrawer = nullptr;
|
||||
struct PPGeTextDrawerCacheKey {
|
||||
bool operator < (const PPGeTextDrawerCacheKey &other) const {
|
||||
if (align != other.align)
|
||||
return align < other.align;
|
||||
if (wrapWidth != other.wrapWidth)
|
||||
return wrapWidth < other.wrapWidth;
|
||||
return text < other.text;
|
||||
}
|
||||
std::string text;
|
||||
int align;
|
||||
float wrapWidth;
|
||||
};
|
||||
struct PPGeTextDrawerImage {
|
||||
TextStringEntry entry;
|
||||
u32 ptr;
|
||||
};
|
||||
std::map<PPGeTextDrawerCacheKey, PPGeTextDrawerImage> textDrawerImages;
|
||||
|
||||
// Overwrite the current text lines buffer so it can be drawn later.
|
||||
void PPGePrepareText(const char *text, float x, float y, int align, float scale, float lineHeightScale,
|
||||
int WrapType = PPGE_LINE_NONE, int wrapWidth = 0);
|
||||
|
||||
// These functions must be called between PPGeBegin and PPGeEnd.
|
||||
|
||||
// Draw currently buffered text using the state from PPGeGetTextBoundingBox() call.
|
||||
// Clears the buffer and state when done.
|
||||
void PPGeDrawCurrentText(u32 color = 0xFFFFFFFF);
|
||||
|
||||
void PPGeSetTexture(u32 dataAddr, int width, int height);
|
||||
|
||||
//only 0xFFFFFF of data is used
|
||||
static void WriteCmd(u8 cmd, u32 data) {
|
||||
Memory::Write_U32((cmd << 24) | (data & 0xFFFFFF), dlWritePtr);
|
||||
@@ -125,18 +162,18 @@ static void BeginVertexData() {
|
||||
vertexStart = dataWritePtr;
|
||||
}
|
||||
|
||||
static void Vertex(float x, float y, float u, float v, int tw, int th, u32 color = 0xFFFFFFFF) {
|
||||
static void Vertex(float x, float y, float u, float v, int tw, int th, u32 color = 0xFFFFFFFF, float off = -0.5f) {
|
||||
if (g_RemasterMode) {
|
||||
PPGeRemasterVertex vtx;
|
||||
vtx.x = x - 0.5f; vtx.y = y - 0.5f; vtx.z = 0;
|
||||
vtx.u = u * tw - 0.5f; vtx.v = v * th - 0.5f;
|
||||
vtx.x = x + off; vtx.y = y + off; vtx.z = 0;
|
||||
vtx.u = u * tw + off; vtx.v = v * th + off;
|
||||
vtx.color = color;
|
||||
Memory::WriteStruct(dataWritePtr, &vtx);
|
||||
dataWritePtr += sizeof(vtx);
|
||||
} else {
|
||||
PPGeVertex vtx;
|
||||
vtx.x = x - 0.5f; vtx.y = y - 0.5f; vtx.z = 0;
|
||||
vtx.u = u * tw - 0.5f; vtx.v = v * th - 0.5f;
|
||||
vtx.x = x + off; vtx.y = y + off; vtx.z = 0;
|
||||
vtx.u = u * tw + off; vtx.v = v * th + off;
|
||||
vtx.color = color;
|
||||
Memory::WriteStruct(dataWritePtr, &vtx);
|
||||
dataWritePtr += sizeof(vtx);
|
||||
@@ -171,23 +208,30 @@ void __PPGeSetupListArgs()
|
||||
}
|
||||
}
|
||||
|
||||
void __PPGeInit()
|
||||
{
|
||||
void __PPGeInit() {
|
||||
// PPGe isn't really important for headless, and LoadZIM takes a long time.
|
||||
if (PSP_CoreParameter().gpuCore == GPUCORE_NULL || host->ShouldSkipUI()) {
|
||||
// Let's just not bother.
|
||||
dlPtr = 0;
|
||||
NOTICE_LOG(SCEGE, "Not initializing PPGe - GPU is NullGpu");
|
||||
return;
|
||||
}
|
||||
u8 *imageData[12];
|
||||
int width[12];
|
||||
int height[12];
|
||||
int flags;
|
||||
if (!LoadZIM("ppge_atlas.zim", width, height, &flags, imageData)) {
|
||||
bool skipZIM = PSP_CoreParameter().gpuCore == GPUCORE_NULL || host->ShouldSkipUI();
|
||||
|
||||
u8 *imageData[12]{};
|
||||
int width[12]{};
|
||||
int height[12]{};
|
||||
int flags = 0;
|
||||
|
||||
bool loadedZIM = !skipZIM && LoadZIM("ppge_atlas.zim", width, height, &flags, imageData);
|
||||
if (!skipZIM && !loadedZIM) {
|
||||
PanicAlert("Failed to load ppge_atlas.zim.\n\nPlace it in the directory \"assets\" under your PPSSPP directory.");
|
||||
ERROR_LOG(SCEGE, "PPGe init failed - no atlas texture. PPGe stuff will not be drawn.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadedZIM) {
|
||||
size_t atlas_data_size;
|
||||
uint8_t *atlas_data;
|
||||
if (!g_ppge_atlas.IsMetadataLoaded()) {
|
||||
atlas_data = VFSReadFile("ppge_atlas.meta", &atlas_data_size);
|
||||
if (atlas_data)
|
||||
g_ppge_atlas.Load(atlas_data, atlas_data_size);
|
||||
delete[] atlas_data;
|
||||
}
|
||||
}
|
||||
|
||||
u32 atlasSize = height[0] * width[0] / 2; // it's a 4-bit paletted texture in ram
|
||||
@@ -196,7 +240,7 @@ void __PPGeInit()
|
||||
dlPtr = __PPGeDoAlloc(dlSize, false, "PPGe Display List");
|
||||
dataPtr = __PPGeDoAlloc(dataSize, false, "PPGe Vertex Data");
|
||||
__PPGeSetupListArgs();
|
||||
atlasPtr = __PPGeDoAlloc(atlasSize, false, "PPGe Atlas Texture");
|
||||
atlasPtr = atlasSize == 0 ? 0 : __PPGeDoAlloc(atlasSize, false, "PPGe Atlas Texture");
|
||||
palette = __PPGeDoAlloc(paletteSize, false, "PPGe Texture Palette");
|
||||
|
||||
// Generate 16-greyscale palette. All PPGe graphics are greyscale so we can use a tiny paletted texture.
|
||||
@@ -206,7 +250,7 @@ void __PPGeInit()
|
||||
}
|
||||
|
||||
const u32_le *imagePtr = (u32_le *)imageData[0];
|
||||
u8 *ramPtr = (u8 *)Memory::GetPointer(atlasPtr);
|
||||
u8 *ramPtr = atlasPtr == 0 ? nullptr : (u8 *)Memory::GetPointer(atlasPtr);
|
||||
|
||||
// Palettize to 4-bit, the easy way.
|
||||
for (int i = 0; i < width[0] * height[0] / 2; i++) {
|
||||
@@ -221,13 +265,18 @@ void __PPGeInit()
|
||||
|
||||
free(imageData[0]);
|
||||
|
||||
// We can't create it here, because Android needs it on the right thread.
|
||||
textDrawerInited = false;
|
||||
textDrawer = nullptr;
|
||||
textDrawerImages.clear();
|
||||
|
||||
DEBUG_LOG(SCEGE, "PPGe drawing library initialized. DL: %08x Data: %08x Atlas: %08x (%i) Args: %08x",
|
||||
dlPtr, dataPtr, atlasPtr, atlasSize, listArgs.ptr);
|
||||
}
|
||||
|
||||
void __PPGeDoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("PPGeDraw", 1, 2);
|
||||
auto s = p.Section("PPGeDraw", 1, 3);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
@@ -245,6 +294,30 @@ void __PPGeDoState(PointerWrap &p)
|
||||
p.Do(listArgs);
|
||||
}
|
||||
|
||||
if (s >= 3) {
|
||||
uint32_t sz = (uint32_t)textDrawerImages.size();
|
||||
p.Do(sz);
|
||||
|
||||
switch (p.mode) {
|
||||
case PointerWrap::MODE_READ:
|
||||
textDrawerImages.clear();
|
||||
for (uint32_t i = 0; i < sz; ++i) {
|
||||
// We only care about the pointers, so we can free them. We'll decimate right away.
|
||||
PPGeTextDrawerCacheKey key{ StringFromFormat("__savestate__%d", i), -1, -1 };
|
||||
textDrawerImages[key] = PPGeTextDrawerImage{};
|
||||
p.Do(textDrawerImages[key].ptr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (const auto &im : textDrawerImages) {
|
||||
p.Do(im.second.ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
textDrawerImages.clear();
|
||||
}
|
||||
|
||||
p.Do(dlPtr);
|
||||
p.Do(dlWritePtr);
|
||||
p.Do(dlSize);
|
||||
@@ -280,6 +353,9 @@ void __PPGeShutdown()
|
||||
dlPtr = 0;
|
||||
savedContextPtr = 0;
|
||||
listArgs = 0;
|
||||
|
||||
delete textDrawer;
|
||||
textDrawer = nullptr;
|
||||
}
|
||||
|
||||
void PPGeBegin()
|
||||
@@ -614,31 +690,63 @@ static AtlasTextMetrics BreakLines(const char *text, const AtlasFont &atlasfont,
|
||||
return metrics;
|
||||
}
|
||||
|
||||
void PPGeMeasureText(float *w, float *h, int *n,
|
||||
const char *text, float scale, int WrapType, int wrapWidth)
|
||||
{
|
||||
const AtlasFont &atlasfont = *ppge_atlas.fonts[0];
|
||||
static bool HasTextDrawer() {
|
||||
// We create this on first use so it's on the correct thread.
|
||||
if (textDrawerInited) {
|
||||
return textDrawer != nullptr;
|
||||
}
|
||||
|
||||
// TODO: Should we pass a draw_?
|
||||
textDrawer = TextDrawer::Create(nullptr);
|
||||
if (textDrawer) {
|
||||
textDrawer->SetFontScale(1.0f, 1.0f);
|
||||
textDrawer->SetForcedDPIScale(1.0f);
|
||||
textDrawer->SetFont(g_Config.sFont.c_str(), 18, 0);
|
||||
}
|
||||
textDrawerInited = true;
|
||||
return textDrawer != nullptr;
|
||||
}
|
||||
|
||||
void PPGeMeasureText(float *w, float *h, const char *text, float scale, int WrapType, int wrapWidth) {
|
||||
if (HasTextDrawer()) {
|
||||
float mw, mh;
|
||||
textDrawer->SetFontScale(scale, scale);
|
||||
int dtalign = (WrapType & PPGE_LINE_WRAP_WORD) ? FLAG_WRAP_TEXT : 0;
|
||||
if (WrapType & PPGE_LINE_USE_ELLIPSIS)
|
||||
dtalign |= FLAG_ELLIPSIZE_TEXT;
|
||||
Bounds b(0, 0, wrapWidth <= 0 ? 480.0f : wrapWidth, 272.0f);
|
||||
textDrawer->MeasureStringRect(text, strlen(text), b, &mw, &mh, dtalign);
|
||||
|
||||
if (w)
|
||||
*w = mw;
|
||||
if (h)
|
||||
*h = mh;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_ppge_atlas.IsMetadataLoaded() || g_ppge_atlas.num_fonts < 1) {
|
||||
if (w)
|
||||
*w = 0;
|
||||
if (h)
|
||||
*h = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const AtlasFont &atlasfont = g_ppge_atlas.fonts[0];
|
||||
AtlasTextMetrics metrics = BreakLines(text, atlasfont, 0, 0, 0, scale, scale, WrapType, wrapWidth, true);
|
||||
if (w) *w = metrics.maxWidth;
|
||||
if (h) *h = metrics.lineHeight;
|
||||
if (n) *n = metrics.numLines;
|
||||
if (h) *h = metrics.lineHeight * metrics.numLines;
|
||||
}
|
||||
|
||||
void PPGePrepareText(const char *text, float x, float y, int align, float scale, float lineHeightScale, int WrapType, int wrapWidth)
|
||||
{
|
||||
const AtlasFont &atlasfont = *ppge_atlas.fonts[0];
|
||||
const AtlasFont &atlasfont = g_ppge_atlas.fonts[0];
|
||||
if (!g_ppge_atlas.IsMetadataLoaded() || g_ppge_atlas.num_fonts < 1) {
|
||||
return;
|
||||
}
|
||||
char_lines_metrics = BreakLines(text, atlasfont, x, y, align, scale, lineHeightScale, WrapType, wrapWidth, false);
|
||||
}
|
||||
|
||||
void PPGeMeasureCurrentText(float *x, float *y, float *w, float *h, int *n)
|
||||
{
|
||||
if (x) *x = char_lines_metrics.x;
|
||||
if (y) *y = char_lines_metrics.y;
|
||||
if (w) *w = char_lines_metrics.maxWidth;
|
||||
if (h) *h = char_lines_metrics.lineHeight;
|
||||
if (n) *n = char_lines_metrics.numLines;
|
||||
}
|
||||
|
||||
static void PPGeResetCurrentText() {
|
||||
char_one_line.clear();
|
||||
char_lines.clear();
|
||||
@@ -672,8 +780,110 @@ void PPGeDrawCurrentText(u32 color)
|
||||
PPGeResetCurrentText();
|
||||
}
|
||||
|
||||
void PPGeDrawText(const char *text, float x, float y, int align, float scale, u32 color)
|
||||
{
|
||||
// Return a value such that (1 << value) >= x
|
||||
int GetPow2(int x) {
|
||||
#ifdef __GNUC__
|
||||
int ret = 31 - __builtin_clz(x | 1);
|
||||
if ((1 << ret) < x)
|
||||
#else
|
||||
int ret = 0;
|
||||
while ((1 << ret) < x)
|
||||
#endif
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PPGeTextDrawerImage PPGeGetTextImage(const char *text, int align, float scale, float maxWidth, bool wrap) {
|
||||
int tdalign = (align & PPGE_ALIGN_HCENTER) ? ALIGN_HCENTER : 0;
|
||||
tdalign |= FLAG_ELLIPSIZE_TEXT;
|
||||
if (wrap) {
|
||||
tdalign |= FLAG_WRAP_TEXT;
|
||||
}
|
||||
|
||||
PPGeTextDrawerCacheKey key{ text, tdalign, maxWidth / scale };
|
||||
PPGeTextDrawerImage im;
|
||||
|
||||
auto cacheItem = textDrawerImages.find(key);
|
||||
if (cacheItem != textDrawerImages.end()) {
|
||||
im = cacheItem->second;
|
||||
cacheItem->second.entry.lastUsedFrame = gpuStats.numFlips;
|
||||
} else {
|
||||
std::vector<uint8_t> bitmapData;
|
||||
textDrawer->SetFontScale(scale, scale);
|
||||
Bounds b(0, 0, maxWidth, 272.0f);
|
||||
std::string cleaned = ReplaceAll(text, "\r", "");
|
||||
textDrawer->DrawStringBitmapRect(bitmapData, im.entry, Draw::DataFormat::R8_UNORM, cleaned.c_str(), b, tdalign);
|
||||
|
||||
int bufwBytes = ((im.entry.bmWidth + 31) / 32) * 16;
|
||||
u32 sz = bufwBytes * (im.entry.bmHeight + 1);
|
||||
u32 origSz = sz;
|
||||
im.ptr = __PPGeDoAlloc(sz, true, "PPGeText");
|
||||
|
||||
if (bitmapData.size() & 1)
|
||||
bitmapData.resize(bitmapData.size() + 1);
|
||||
|
||||
if (im.ptr) {
|
||||
int wBytes = (im.entry.bmWidth + 1) / 2;
|
||||
u8 *ramPtr = (u8 *)Memory::GetPointer(im.ptr);
|
||||
for (int y = 0; y < im.entry.bmHeight; ++y) {
|
||||
for (int x = 0; x < wBytes; ++x) {
|
||||
uint8_t c1 = bitmapData[y * im.entry.bmWidth + x * 2];
|
||||
uint8_t c2 = bitmapData[y * im.entry.bmWidth + x * 2 + 1];
|
||||
// Convert this to 4-bit palette values.
|
||||
ramPtr[y * bufwBytes + x] = (c2 & 0xF0) | (c1 >> 4);
|
||||
}
|
||||
if (bufwBytes != wBytes) {
|
||||
memset(ramPtr + y * bufwBytes + wBytes, 0, bufwBytes - wBytes);
|
||||
}
|
||||
}
|
||||
memset(ramPtr + im.entry.bmHeight * bufwBytes, 0, bufwBytes + sz - origSz);
|
||||
}
|
||||
|
||||
im.entry.lastUsedFrame = gpuStats.numFlips;
|
||||
textDrawerImages[key] = im;
|
||||
}
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, int align, float scale, u32 color) {
|
||||
int bufw = ((im.entry.bmWidth + 31) / 32) * 32;
|
||||
int wp2 = GetPow2(im.entry.bmWidth);
|
||||
int hp2 = GetPow2(im.entry.bmHeight);
|
||||
WriteCmd(GE_CMD_TEXADDR0, im.ptr & 0xFFFFF0);
|
||||
WriteCmd(GE_CMD_TEXBUFWIDTH0, bufw | ((im.ptr & 0xFF000000) >> 8));
|
||||
WriteCmd(GE_CMD_TEXSIZE0, wp2 | (hp2 << 8));
|
||||
WriteCmd(GE_CMD_TEXFLUSH, 0);
|
||||
|
||||
float w = im.entry.width * scale;
|
||||
float h = im.entry.height * scale;
|
||||
|
||||
if (align & PPGE_ALIGN_HCENTER)
|
||||
x -= w / 2.0f;
|
||||
else if (align & PPGE_ALIGN_RIGHT)
|
||||
x -= w;
|
||||
if (align & PPGE_ALIGN_VCENTER)
|
||||
y -= h / 2.0f;
|
||||
else if (align & PPGE_ALIGN_BOTTOM)
|
||||
y -= h;
|
||||
|
||||
BeginVertexData();
|
||||
float u1 = (float)im.entry.width / (1 << wp2);
|
||||
float v1 = (float)im.entry.height / (1 << hp2);
|
||||
Vertex(x, y, 0, 0, 1 << wp2, 1 << hp2, color, 0.0f);
|
||||
Vertex(x + w, y + h, u1, v1, 1 << wp2, 1 << hp2, color, 0.0f);
|
||||
EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
|
||||
|
||||
PPGeSetDefaultTexture();
|
||||
}
|
||||
|
||||
void PPGeDrawText(const char *text, float x, float y, int align, float scale, u32 color) {
|
||||
if (HasTextDrawer()) {
|
||||
PPGeTextDrawerImage im = PPGeGetTextImage(text, align, scale, 480.0f - x, false);
|
||||
PPGeDrawTextImage(im, x, y, align, scale, color);
|
||||
return;
|
||||
}
|
||||
|
||||
PPGePrepareText(text, x, y, align, scale, scale, PPGE_LINE_USE_ELLIPSIS);
|
||||
PPGeDrawCurrentText(color);
|
||||
}
|
||||
@@ -707,10 +917,40 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl
|
||||
s = StripTrailingWhite(s);
|
||||
}
|
||||
|
||||
PPGePrepareText(s.c_str(), x, y, align, scale, scale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth);
|
||||
|
||||
int zoom = (PSP_CoreParameter().pixelHeight + 479) / 480;
|
||||
float maxScaleDown = zoom == 1 ? 1.3f : 2.0f;
|
||||
|
||||
if (HasTextDrawer()) {
|
||||
float actualWidth, actualHeight;
|
||||
Bounds b(0, 0, wrapWidth <= 0 ? 480.0f - x : wrapWidth, wrapHeight);
|
||||
int tdalign = (align & PPGE_ALIGN_HCENTER) ? ALIGN_HCENTER : 0;
|
||||
textDrawer->SetFontScale(scale, scale);
|
||||
textDrawer->MeasureStringRect(s.c_str(), s.size(), b, &actualWidth, &actualHeight, tdalign | FLAG_WRAP_TEXT);
|
||||
if (wrapHeight != 0.0f && actualHeight > wrapHeight) {
|
||||
// Cheap way to get the line height.
|
||||
float oneLine, twoLines;
|
||||
textDrawer->MeasureString("|", 1, &actualWidth, &oneLine);
|
||||
textDrawer->MeasureStringRect("|\n|", 3, Bounds(0, 0, 480, 272), &actualWidth, &twoLines);
|
||||
|
||||
float lineHeight = twoLines - oneLine;
|
||||
if (actualHeight > wrapHeight * maxScaleDown) {
|
||||
float maxLines = floor(wrapHeight * maxScaleDown / lineHeight);
|
||||
actualHeight = (maxLines + 1) * lineHeight;
|
||||
// Add an ellipsis if it's just too long to be readable.
|
||||
// On a PSP, it does this without scaling it down.
|
||||
s = StripTrailingWhite(CropLinesToCount(s, (int)maxLines)) + "\n...";
|
||||
}
|
||||
|
||||
scale *= wrapHeight / actualHeight;
|
||||
}
|
||||
|
||||
PPGeTextDrawerImage im = PPGeGetTextImage(s.c_str(), align, scale, wrapWidth <= 0 ? 480.0f - x : wrapWidth, true);
|
||||
PPGeDrawTextImage(im, x, y, align, scale, color);
|
||||
return;
|
||||
}
|
||||
|
||||
PPGePrepareText(s.c_str(), x, y, align, scale, scale, PPGE_LINE_USE_ELLIPSIS | PPGE_LINE_WRAP_WORD, wrapWidth);
|
||||
|
||||
float actualHeight = char_lines_metrics.lineHeight * char_lines_metrics.numLines;
|
||||
if (wrapHeight != 0.0f && actualHeight > wrapHeight) {
|
||||
if (actualHeight > wrapHeight * maxScaleDown) {
|
||||
@@ -731,15 +971,16 @@ void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, fl
|
||||
}
|
||||
|
||||
// Draws a "4-patch" for button-like things that can be resized
|
||||
void PPGeDraw4Patch(int atlasImage, float x, float y, float w, float h, u32 color)
|
||||
{
|
||||
void PPGeDraw4Patch(ImageID atlasImage, float x, float y, float w, float h, u32 color) {
|
||||
if (!dlPtr)
|
||||
return;
|
||||
const AtlasImage &img = ppge_images[atlasImage];
|
||||
float borderx = img.w / 20;
|
||||
float bordery = img.h / 20;
|
||||
float u1 = img.u1, uhalf = (img.u1 + img.u2) / 2, u2 = img.u2;
|
||||
float v1 = img.v1, vhalf = (img.v1 + img.v2) / 2, v2 = img.v2;
|
||||
const AtlasImage *img = g_ppge_atlas.getImage(atlasImage);
|
||||
if (!img)
|
||||
return;
|
||||
float borderx = img->w / 20;
|
||||
float bordery = img->h / 20;
|
||||
float u1 = img->u1, uhalf = (img->u1 + img->u2) / 2, u2 = img->u2;
|
||||
float v1 = img->v1, vhalf = (img->v1 + img->v2) / 2, v2 = img->v2;
|
||||
float xmid1 = x + borderx;
|
||||
float xmid2 = x + w - borderx;
|
||||
float ymid1 = y + bordery;
|
||||
@@ -771,8 +1012,7 @@ void PPGeDraw4Patch(int atlasImage, float x, float y, float w, float h, u32 colo
|
||||
EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
|
||||
}
|
||||
|
||||
void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color)
|
||||
{
|
||||
void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color) {
|
||||
if (!dlPtr)
|
||||
return;
|
||||
|
||||
@@ -787,29 +1027,35 @@ void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color)
|
||||
}
|
||||
|
||||
// Just blits an image to the screen, multiplied with the color.
|
||||
void PPGeDrawImage(int atlasImage, float x, float y, int align, u32 color)
|
||||
void PPGeDrawImage(ImageID atlasImage, float x, float y, int align, u32 color)
|
||||
{
|
||||
if (!dlPtr)
|
||||
return;
|
||||
|
||||
const AtlasImage &img = ppge_atlas.images[atlasImage];
|
||||
float w = img.w;
|
||||
float h = img.h;
|
||||
const AtlasImage *img = g_ppge_atlas.getImage(atlasImage);
|
||||
if (!img) {
|
||||
return;
|
||||
}
|
||||
float w = img->w;
|
||||
float h = img->h;
|
||||
BeginVertexData();
|
||||
Vertex(x, y, img.u1, img.v1, atlasWidth, atlasHeight, color);
|
||||
Vertex(x + w, y + h, img.u2, img.v2, atlasWidth, atlasHeight, color);
|
||||
Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, color);
|
||||
Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, color);
|
||||
EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
|
||||
}
|
||||
|
||||
void PPGeDrawImage(int atlasImage, float x, float y, float w, float h, int align, u32 color)
|
||||
void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, int align, u32 color)
|
||||
{
|
||||
if (!dlPtr)
|
||||
return;
|
||||
|
||||
const AtlasImage &img = ppge_atlas.images[atlasImage];
|
||||
const AtlasImage *img = g_ppge_atlas.getImage(atlasImage);
|
||||
if (!img) {
|
||||
return;
|
||||
}
|
||||
BeginVertexData();
|
||||
Vertex(x, y, img.u1, img.v1, atlasWidth, atlasHeight, color);
|
||||
Vertex(x + w, y + h, img.u2, img.v2, atlasWidth, atlasHeight, color);
|
||||
Vertex(x, y, img->u1, img->v1, atlasWidth, atlasHeight, color);
|
||||
Vertex(x + w, y + h, img->u2, img->v2, atlasWidth, atlasHeight, color);
|
||||
EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
|
||||
}
|
||||
|
||||
@@ -823,20 +1069,6 @@ void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float
|
||||
EndVertexDataAndDraw(GE_PRIM_RECTANGLES);
|
||||
}
|
||||
|
||||
// Return a value such that (1 << value) >= x
|
||||
int GetPow2(int x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
int ret = 31 - __builtin_clz(x|1);
|
||||
if ((1 << ret) < x)
|
||||
#else
|
||||
int ret = 0;
|
||||
while ((1 << ret) < x)
|
||||
#endif
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PPGeSetDefaultTexture()
|
||||
{
|
||||
WriteCmd(GE_CMD_TEXTUREMAPENABLE, 1);
|
||||
@@ -990,3 +1222,20 @@ void PPGeImage::SetTexture() {
|
||||
}
|
||||
}
|
||||
|
||||
void PPGeNotifyFrame() {
|
||||
if (textDrawer) {
|
||||
textDrawer->OncePerFrame();
|
||||
}
|
||||
|
||||
// Do this always, in case the platform has no TextDrawer but save state did.
|
||||
for (auto it = textDrawerImages.begin(); it != textDrawerImages.end(); ) {
|
||||
if (it->second.entry.lastUsedFrame - gpuStats.numFlips >= 97) {
|
||||
kernelMemory.Free(it->second.ptr);
|
||||
it = textDrawerImages.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
PPGeImage::Decimate();
|
||||
}
|
||||
+11
-30
@@ -19,7 +19,9 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "ppge_atlas.h"
|
||||
|
||||
#include "gfx/texture_atlas.h"
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class PointerWrap;
|
||||
@@ -43,10 +45,6 @@ void __PPGeShutdown();
|
||||
void PPGeBegin();
|
||||
void PPGeEnd();
|
||||
|
||||
// If you want to draw using this texture but not go through the PSP GE emulation,
|
||||
// jsut call this. Will bind the texture to unit 0.
|
||||
void PPGeBindTexture();
|
||||
|
||||
enum {
|
||||
PPGE_ALIGN_LEFT = 0,
|
||||
PPGE_ALIGN_RIGHT = 16,
|
||||
@@ -63,11 +61,6 @@ enum {
|
||||
PPGE_ALIGN_BOTTOMRIGHT = PPGE_ALIGN_BOTTOM | PPGE_ALIGN_RIGHT,
|
||||
};
|
||||
|
||||
enum {
|
||||
PPGE_ESCAPE_NONE,
|
||||
PPGE_ESCAPE_BACKSLASHED,
|
||||
};
|
||||
|
||||
enum {
|
||||
PPGE_LINE_NONE = 0,
|
||||
PPGE_LINE_USE_ELLIPSIS = 1, // use ellipses in too long words
|
||||
@@ -76,21 +69,7 @@ enum {
|
||||
};
|
||||
|
||||
// Get the metrics of the bounding box of the text without changing the buffer or state.
|
||||
void PPGeMeasureText(float *w, float *h, int *n,
|
||||
const char *text, float scale, int WrapType = PPGE_LINE_NONE, int wrapWidth = 0);
|
||||
|
||||
// Overwrite the current text lines buffer so it can be drawn later.
|
||||
void PPGePrepareText(const char *text, float x, float y, int align, float scale, float lineHeightScale,
|
||||
int WrapType = PPGE_LINE_NONE, int wrapWidth = 0);
|
||||
|
||||
// Get the metrics of the bounding box of the currently stated text.
|
||||
void PPGeMeasureCurrentText(float *x, float *y, float *w, float *h, int *n);
|
||||
|
||||
// These functions must be called between PPGeBegin and PPGeEnd.
|
||||
|
||||
// Draw currently buffered text using the state from PPGeGetTextBoundingBox() call.
|
||||
// Clears the buffer and state when done.
|
||||
void PPGeDrawCurrentText(u32 color = 0xFFFFFFFF);
|
||||
void PPGeMeasureText(float *w, float *h, const char *text, float scale, int WrapType = PPGE_LINE_NONE, int wrapWidth = 0);
|
||||
|
||||
// Draws some text using the one font we have.
|
||||
// Clears the text buffer when done.
|
||||
@@ -98,13 +77,15 @@ void PPGeDrawText(const char *text, float x, float y, int align, float scale = 1
|
||||
void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, int align, float scale = 1.0f, u32 color = 0xFFFFFFFF);
|
||||
|
||||
// Draws a "4-patch" for button-like things that can be resized.
|
||||
void PPGeDraw4Patch(int atlasImage, float x, float y, float w, float h, u32 color = 0xFFFFFFFF);
|
||||
void PPGeDraw4Patch(ImageID atlasImage, float x, float y, float w, float h, u32 color = 0xFFFFFFFF);
|
||||
|
||||
// Just blits an image to the screen, multiplied with the color.
|
||||
void PPGeDrawImage(int atlasImage, float x, float y, int align, u32 color = 0xFFFFFFFF);
|
||||
void PPGeDrawImage(int atlasImage, float x, float y, float w, float h, int align, u32 color = 0xFFFFFFFF);
|
||||
void PPGeDrawImage(ImageID atlasImage, float x, float y, int align, u32 color = 0xFFFFFFFF);
|
||||
void PPGeDrawImage(ImageID atlasImage, float x, float y, float w, float h, int align, u32 color = 0xFFFFFFFF);
|
||||
void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float u2, float v2, int tw, int th, u32 color);
|
||||
|
||||
void PPGeNotifyFrame();
|
||||
|
||||
class PPGeImage {
|
||||
public:
|
||||
PPGeImage(const std::string &pspFilename);
|
||||
@@ -130,8 +111,9 @@ public:
|
||||
return height_;
|
||||
}
|
||||
|
||||
private:
|
||||
static void Decimate();
|
||||
|
||||
private:
|
||||
static std::vector<PPGeImage *> loadedTextures_;
|
||||
|
||||
std::string filename_;
|
||||
@@ -150,6 +132,5 @@ private:
|
||||
void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color);
|
||||
|
||||
void PPGeSetDefaultTexture();
|
||||
void PPGeSetTexture(u32 dataAddr, int width, int height);
|
||||
void PPGeDisableTexture();
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,18 +0,0 @@
|
||||
// Header generated by atlastool from ppge_atlasscript.txt (hrydgard@gmail.com)
|
||||
|
||||
#pragma once
|
||||
#include "gfx/texture_atlas.h"
|
||||
|
||||
// FONTS_ppge
|
||||
#define UBUNTU24 0
|
||||
|
||||
|
||||
// IMAGES_ppge
|
||||
#define I_CROSS 0
|
||||
#define I_CIRCLE 1
|
||||
#define I_SQUARE 2
|
||||
#define I_TRIANGLE 3
|
||||
|
||||
|
||||
extern const Atlas ppge_atlas;
|
||||
extern const AtlasImage ppge_images[4];
|
||||
@@ -37,6 +37,8 @@ DrawEngineCommon::DrawEngineCommon() : decoderMap_(16) {
|
||||
decJitCache_ = new VertexDecoderJitCache();
|
||||
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
|
||||
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
|
||||
useHWTransform_ = g_Config.bHardwareTransform;
|
||||
useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation);
|
||||
}
|
||||
|
||||
DrawEngineCommon::~DrawEngineCommon() {
|
||||
@@ -171,6 +173,9 @@ void DrawEngineCommon::Resized() {
|
||||
});
|
||||
decoderMap_.Clear();
|
||||
ClearTrackedVertexArrays();
|
||||
|
||||
useHWTransform_ = g_Config.bHardwareTransform;
|
||||
useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation);
|
||||
}
|
||||
|
||||
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize) {
|
||||
@@ -737,6 +742,19 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim,
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawEngineCommon::CanUseHardwareTransform(int prim) {
|
||||
if (!useHWTransform_)
|
||||
return false;
|
||||
return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES;
|
||||
}
|
||||
|
||||
bool DrawEngineCommon::CanUseHardwareTessellation(GEPatchPrimType prim) {
|
||||
if (useHWTessellation_) {
|
||||
return CanUseHardwareTransform(PatchPrimToPrim(prim));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TessellationDataTransfer::CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType) {
|
||||
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
|
||||
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
|
||||
|
||||
@@ -86,6 +86,9 @@ public:
|
||||
void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope);
|
||||
void ClearSplineBezierWeights();
|
||||
|
||||
bool CanUseHardwareTransform(int prim);
|
||||
bool CanUseHardwareTessellation(GEPatchPrimType prim);
|
||||
|
||||
std::vector<std::string> DebugGetVertexLoaderIDs();
|
||||
std::string DebugGetVertexLoaderString(std::string id, DebugShaderStringType stringType);
|
||||
|
||||
@@ -101,6 +104,7 @@ public:
|
||||
VertexDecoder *GetVertexDecoder(u32 vtype);
|
||||
|
||||
protected:
|
||||
virtual bool UpdateUseHWTessellation(bool enabled) { return enabled; }
|
||||
virtual void ClearTrackedVertexArrays() {}
|
||||
|
||||
int ComputeNumVertsToDecode() const;
|
||||
@@ -128,6 +132,9 @@ protected:
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool useHWTransform_ = false;
|
||||
bool useHWTessellation_ = false;
|
||||
|
||||
// Vertex collector buffers
|
||||
u8 *decoded = nullptr;
|
||||
u16 *decIndex = nullptr;
|
||||
|
||||
@@ -236,6 +236,10 @@ void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferForma
|
||||
drawing_width = scissor_width;
|
||||
drawing_height = std::max(drawing_height, scissor_height);
|
||||
}
|
||||
if (scissor_width == 481 && region_width == 480 && scissor_height == 273 && region_height == 272) {
|
||||
drawing_width = 480;
|
||||
drawing_height = 272;
|
||||
}
|
||||
} else {
|
||||
// If viewport wasn't valid, let's just take the greatest anything regardless of stride.
|
||||
drawing_width = std::min(std::max(region_width, scissor_width), fb_stride);
|
||||
@@ -848,7 +852,7 @@ void FramebufferManagerCommon::SetViewport2D(int x, int y, int w, int h) {
|
||||
draw_->SetViewports(1, &vp);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) {
|
||||
DownloadFramebufferOnSwitch(currentRenderVfb_);
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
@@ -871,12 +875,16 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
CardboardSettings cardboardSettings;
|
||||
GetCardboardSettings(&cardboardSettings);
|
||||
|
||||
VirtualFramebuffer *vfb = GetVFBAt(displayFramebufPtr_);
|
||||
// If it's not really dirty, we're probably frameskipping. Use the last working one.
|
||||
u32 fbaddr = reallyDirty ? displayFramebufPtr_ : prevDisplayFramebufPtr_;
|
||||
prevDisplayFramebufPtr_ = fbaddr;
|
||||
|
||||
VirtualFramebuffer *vfb = GetVFBAt(fbaddr);
|
||||
if (!vfb) {
|
||||
// Let's search for a framebuf within this range. Note that we also look for
|
||||
// "framebuffers" sitting in RAM (created from block transfer or similar) so we only take off the kernel
|
||||
// and uncached bits of the address when comparing.
|
||||
const u32 addr = displayFramebufPtr_ & 0x3FFFFFFF;
|
||||
const u32 addr = fbaddr & 0x3FFFFFFF;
|
||||
for (size_t i = 0; i < vfbs_.size(); ++i) {
|
||||
VirtualFramebuffer *v = vfbs_[i];
|
||||
const u32 v_addr = v->fb_address & 0x3FFFFFFF;
|
||||
@@ -914,7 +922,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
}
|
||||
|
||||
if (!vfb) {
|
||||
if (Memory::IsValidAddress(displayFramebufPtr_)) {
|
||||
if (Memory::IsValidAddress(fbaddr)) {
|
||||
// The game is displaying something directly from RAM. In GTA, it's decoded video.
|
||||
if (!vfb) {
|
||||
shaderManager_->DirtyLastShader();
|
||||
@@ -925,12 +933,12 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
|
||||
// Just a pointer to plain memory to draw. We should create a framebuffer, then draw to it.
|
||||
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
|
||||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
DrawFramebufferToOutput(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_, true);
|
||||
DrawFramebufferToOutput(Memory::GetPointer(fbaddr), displayFormat_, displayStride_, true);
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG(FRAMEBUF, "Found no FBO to display! displayFBPtr = %08x", displayFramebufPtr_);
|
||||
DEBUG_LOG(FRAMEBUF, "Found no FBO to display! displayFBPtr = %08x", fbaddr);
|
||||
// No framebuffer to display! Clear to black.
|
||||
if (useBufferedRendering_) {
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
@@ -228,7 +228,7 @@ public:
|
||||
void RebindFramebuffer();
|
||||
std::vector<FramebufferInfo> GetFramebufferList();
|
||||
|
||||
void CopyDisplayToOutput();
|
||||
void CopyDisplayToOutput(bool reallyDirty);
|
||||
|
||||
bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset, u32 skipDrawReason);
|
||||
void NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt);
|
||||
@@ -264,6 +264,10 @@ public:
|
||||
return displayFramebuf_ ? displayFormat_ : GE_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
bool UseBufferedRendering() {
|
||||
return useBufferedRendering_;
|
||||
}
|
||||
|
||||
bool MayIntersectFramebuffer(u32 start) {
|
||||
// Clear the cache/kernel bits.
|
||||
start = start & 0x3FFFFFFF;
|
||||
@@ -383,6 +387,7 @@ protected:
|
||||
u32 displayFramebufPtr_ = 0;
|
||||
u32 displayStride_ = 0;
|
||||
GEBufferFormat displayFormat_;
|
||||
u32 prevDisplayFramebufPtr_ = 0;
|
||||
|
||||
VirtualFramebuffer *displayFramebuf_ = nullptr;
|
||||
VirtualFramebuffer *prevDisplayFramebuf_ = nullptr;
|
||||
|
||||
@@ -34,12 +34,6 @@
|
||||
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
|
||||
bool CanUseHardwareTransform(int prim) {
|
||||
if (!g_Config.bHardwareTransform)
|
||||
return false;
|
||||
return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES;
|
||||
}
|
||||
|
||||
bool IsStencilTestOutputDisabled() {
|
||||
// The mask applies on all stencil ops.
|
||||
if (gstate.isStencilTestEnabled() && (gstate.pmska & 0xFF) != 0xFF) {
|
||||
|
||||
@@ -51,7 +51,6 @@ StencilValueType ReplaceAlphaWithStencilType();
|
||||
ReplaceAlphaType ReplaceAlphaWithStencil(ReplaceBlendType replaceBlend);
|
||||
ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bufferFormat);
|
||||
|
||||
bool CanUseHardwareTransform(int prim);
|
||||
LogicOpReplaceType ReplaceLogicOpType();
|
||||
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ std::string VertexShaderDesc(const VShaderID &id) {
|
||||
return desc.str();
|
||||
}
|
||||
|
||||
void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform) {
|
||||
void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, bool useHWTessellation) {
|
||||
bool isModeThrough = (vertType & GE_VTYPE_THROUGH) != 0;
|
||||
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
bool doTextureTransform = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
@@ -131,7 +131,7 @@ void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform)
|
||||
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
|
||||
id.SetBit(VS_BIT_HAS_TEXCOORD, hasTexcoord);
|
||||
|
||||
if (g_Config.bHardwareTessellation) {
|
||||
if (useHWTessellation) {
|
||||
id.SetBit(VS_BIT_BEZIER, doBezier);
|
||||
id.SetBit(VS_BIT_SPLINE, doSpline);
|
||||
if (doBezier || doSpline) {
|
||||
|
||||
@@ -223,7 +223,7 @@ class Bugs;
|
||||
}
|
||||
|
||||
|
||||
void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform);
|
||||
void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation);
|
||||
// Generates a compact string that describes the shader. Useful in a list to get an overview
|
||||
// of the current flora of shaders.
|
||||
std::string VertexShaderDesc(const VShaderID &id);
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/Math3D.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
using namespace Lin;
|
||||
|
||||
@@ -91,7 +89,7 @@ void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bo
|
||||
maxValues[3] = NAN;
|
||||
}
|
||||
|
||||
void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipViewport) {
|
||||
void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipViewport, bool useBufferedRendering) {
|
||||
if (dirtyUniforms & DIRTY_TEXENV) {
|
||||
Uint8x3ToFloat4(ub->texEnvColor, gstate.texenvcolor);
|
||||
}
|
||||
@@ -149,7 +147,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView
|
||||
ConvertProjMatrixToVulkan(flippedMatrix);
|
||||
}
|
||||
|
||||
if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE && g_display_rotation != DisplayRotation::ROTATE_0) {
|
||||
if (!useBufferedRendering && g_display_rotation != DisplayRotation::ROTATE_0) {
|
||||
flippedMatrix = flippedMatrix * g_display_rot_matrix;
|
||||
}
|
||||
CopyMatrix4x4(ub->proj, flippedMatrix.getReadPtr());
|
||||
@@ -162,7 +160,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView
|
||||
} else {
|
||||
proj_through.setOrthoVulkan(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1);
|
||||
}
|
||||
if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE && g_display_rotation != DisplayRotation::ROTATE_0) {
|
||||
if (!useBufferedRendering && g_display_rotation != DisplayRotation::ROTATE_0) {
|
||||
proj_through = proj_through * g_display_rot_matrix;
|
||||
}
|
||||
// proj_through.translateAndScale(Vec3(0, 0, 0), Vec3(1.0f / debugscale, 1.0f / debugscale, 0));
|
||||
|
||||
@@ -186,7 +186,7 @@ R"( float4x3 u_bone[8];
|
||||
|
||||
void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bool hasNegZ);
|
||||
|
||||
void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipViewport);
|
||||
void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipViewport, bool useBufferedRendering);
|
||||
void LightUpdateUniforms(UB_VS_Lights *ub, uint64_t dirtyUniforms);
|
||||
void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms);
|
||||
|
||||
@@ -517,7 +517,7 @@ void SoftwareTransform(
|
||||
numTrans = 0;
|
||||
drawIndexed = false;
|
||||
|
||||
bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
|
||||
bool useBufferedRendering = fbman->UseBufferedRendering();
|
||||
|
||||
bool flippedY = g_Config.iGPUBackend == (int)GPUBackend::OPENGL && !useBufferedRendering;
|
||||
|
||||
|
||||
@@ -28,13 +28,6 @@
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GPUState.h" // only needed for UVScale stuff
|
||||
|
||||
bool CanUseHardwareTessellation(GEPatchPrimType prim) {
|
||||
if (g_Config.bHardwareTessellation && !g_Config.bSoftwareRendering) {
|
||||
return CanUseHardwareTransform(PatchPrimToPrim(prim));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class SimpleBufferManager {
|
||||
private:
|
||||
u8 *buf_;
|
||||
|
||||
@@ -207,8 +207,6 @@ void SoftwareTessellation(OutputBuffers &output, const Surface &surface, u32 ori
|
||||
|
||||
} // namespace Spline
|
||||
|
||||
bool CanUseHardwareTessellation(GEPatchPrimType prim);
|
||||
|
||||
// Define function object for TemplateParameterDispatcher
|
||||
#define TEMPLATE_PARAMETER_DISPATCHER_FUNCTION(NAME, FUNCNAME, FUNCTYPE) \
|
||||
struct NAME { \
|
||||
|
||||
@@ -795,7 +795,7 @@ bool TextureCacheCommon::AttachFramebuffer(TexCacheEntry *entry, u32 address, Vi
|
||||
}
|
||||
} else {
|
||||
// Apply to buffered mode only.
|
||||
if (!(g_Config.iRenderingMode == FB_BUFFERED_MODE))
|
||||
if (!framebufferManager_->UseBufferedRendering())
|
||||
return false;
|
||||
|
||||
const bool clutFormat =
|
||||
@@ -875,8 +875,7 @@ void TextureCacheCommon::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFram
|
||||
_dbg_assert_msg_(G3D, framebuffer != nullptr, "Framebuffer must not be null.");
|
||||
|
||||
framebuffer->usageFlags |= FB_USAGE_TEXTURE;
|
||||
bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
|
||||
if (useBufferedRendering) {
|
||||
if (framebufferManager_->UseBufferedRendering()) {
|
||||
const u64 cachekey = entry->CacheKey();
|
||||
const auto &fbInfo = fbTexInfo_[cachekey];
|
||||
|
||||
@@ -918,7 +917,7 @@ void TextureCacheCommon::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFram
|
||||
}
|
||||
|
||||
bool TextureCacheCommon::SetOffsetTexture(u32 offset) {
|
||||
if (g_Config.iRenderingMode != FB_BUFFERED_MODE) {
|
||||
if (!framebufferManager_->UseBufferedRendering()) {
|
||||
return false;
|
||||
}
|
||||
u32 texaddr = gstate.getTextureAddress(0);
|
||||
@@ -1307,7 +1306,7 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
|
||||
memcpy(out + outPitch * y, texptr + bufw * sizeof(u16) * y, w * sizeof(u16));
|
||||
}
|
||||
}
|
||||
} else if (h >= 8 && !expandTo32bit) {
|
||||
} else if (h >= 8 && bufw <= w && !expandTo32bit) {
|
||||
// Note: this is always safe since h must be a power of 2, so a multiple of 8.
|
||||
UnswizzleFromMem((u32 *)out, outPitch, texptr, bufw, h, 2);
|
||||
if (reverseColors) {
|
||||
@@ -1346,7 +1345,7 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
|
||||
memcpy(out + outPitch * y, texptr + bufw * sizeof(u32) * y, w * sizeof(u32));
|
||||
}
|
||||
}
|
||||
} else if (h >= 8) {
|
||||
} else if (h >= 8 && bufw <= w) {
|
||||
UnswizzleFromMem((u32 *)out, outPitch, texptr, bufw, h, 4);
|
||||
if (reverseColors) {
|
||||
ReverseColors(out, out, format, h * outPitch / 4, useBGRA);
|
||||
|
||||
@@ -93,7 +93,7 @@ u32 GetTextureBufw(int level, u32 texaddr, GETextureFormat format) {
|
||||
return gstate.texbufwidth[level] & 0x1FFF;
|
||||
|
||||
u32 bufw = gstate.texbufwidth[level] & textureAlignMask16[format];
|
||||
if (bufw == 0) {
|
||||
if (bufw == 0 && format <= GE_TFMT_DXT5) {
|
||||
// If it's less than 16 bytes, use 16 bytes.
|
||||
bufw = (8 * 16) / textureBitsPerPixel[format];
|
||||
}
|
||||
|
||||
@@ -514,11 +514,11 @@ rotateVBO:
|
||||
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform, useHWTessellation_);
|
||||
ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
|
||||
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
|
||||
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
|
||||
shaderManager_->UpdateUniforms();
|
||||
shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering());
|
||||
shaderManager_->BindUniforms();
|
||||
|
||||
context_->IASetInputLayout(inputLayout);
|
||||
@@ -598,10 +598,10 @@ rotateVBO:
|
||||
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false);
|
||||
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
|
||||
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
|
||||
shaderManager_->UpdateUniforms();
|
||||
shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering());
|
||||
shaderManager_->BindUniforms();
|
||||
|
||||
// We really do need a vertex layout for each vertex shader (or at least check its ID bits for what inputs it uses)!
|
||||
|
||||
@@ -73,7 +73,6 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE);
|
||||
context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
D3D_FEATURE_LEVEL featureLevel = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL);
|
||||
lastVsync_ = g_Config.bVSync ? 1 : 0;
|
||||
|
||||
stockD3D11.Create(device_);
|
||||
|
||||
@@ -212,8 +211,7 @@ void GPU_D3D11::DeviceRestore() {
|
||||
}
|
||||
|
||||
void GPU_D3D11::InitClear() {
|
||||
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
|
||||
if (useNonBufferedRendering) {
|
||||
if (!framebufferManager_->UseBufferedRendering()) {
|
||||
// device_->Clear(0, NULL, D3DCLEAR_STENCIL | D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
|
||||
}
|
||||
}
|
||||
@@ -263,13 +261,13 @@ void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat f
|
||||
framebufferManagerD3D11_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
void GPU_D3D11::CopyDisplayToOutput() {
|
||||
void GPU_D3D11::CopyDisplayToOutput(bool reallyDirty) {
|
||||
float blendColor[4]{};
|
||||
context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF);
|
||||
|
||||
drawEngine_.Flush();
|
||||
|
||||
framebufferManagerD3D11_->CopyDisplayToOutput();
|
||||
framebufferManagerD3D11_->CopyDisplayToOutput(reallyDirty);
|
||||
framebufferManagerD3D11_->EndFrame();
|
||||
|
||||
// shaderManager_->EndFrame();
|
||||
|
||||
@@ -71,7 +71,7 @@ private:
|
||||
|
||||
void InitClear() override;
|
||||
void BeginFrame() override;
|
||||
void CopyDisplayToOutput() override;
|
||||
void CopyDisplayToOutput(bool reallyDirty) override;
|
||||
|
||||
ID3D11Device *device_;
|
||||
ID3D11DeviceContext *context_;
|
||||
@@ -81,6 +81,4 @@ private:
|
||||
DepalShaderCacheD3D11 *depalShaderCache_;
|
||||
DrawEngineD3D11 drawEngine_;
|
||||
ShaderManagerD3D11 *shaderManagerD3D11_;
|
||||
|
||||
int lastVsync_;
|
||||
};
|
||||
@@ -149,12 +149,12 @@ void ShaderManagerD3D11::DirtyLastShader() {
|
||||
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE);
|
||||
}
|
||||
|
||||
uint64_t ShaderManagerD3D11::UpdateUniforms() {
|
||||
uint64_t ShaderManagerD3D11::UpdateUniforms(bool useBufferedRendering) {
|
||||
uint64_t dirty = gstate_c.GetDirtyUniforms();
|
||||
if (dirty != 0) {
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
if (dirty & DIRTY_BASE_UNIFORMS) {
|
||||
BaseUpdateUniforms(&ub_base, dirty, true);
|
||||
BaseUpdateUniforms(&ub_base, dirty, true, useBufferedRendering);
|
||||
context_->Map(push_base, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
memcpy(map.pData, &ub_base, sizeof(ub_base));
|
||||
context_->Unmap(push_base, 0);
|
||||
@@ -183,13 +183,13 @@ void ShaderManagerD3D11::BindUniforms() {
|
||||
context_->PSSetConstantBuffers(0, 1, ps_cbs);
|
||||
}
|
||||
|
||||
void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform) {
|
||||
void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation) {
|
||||
VShaderID VSID;
|
||||
FShaderID FSID;
|
||||
|
||||
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
|
||||
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
|
||||
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
|
||||
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
|
||||
} else {
|
||||
VSID = lastVSID_;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel);
|
||||
~ShaderManagerD3D11();
|
||||
|
||||
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform);
|
||||
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation);
|
||||
void ClearShaders();
|
||||
void DirtyLastShader() override;
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
std::vector<std::string> DebugGetShaderIDs(DebugShaderType type);
|
||||
std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType);
|
||||
|
||||
uint64_t UpdateUniforms();
|
||||
uint64_t UpdateUniforms(bool useBufferedRendering);
|
||||
void BindUniforms();
|
||||
|
||||
// TODO: Avoid copying these buffers if same as last draw, can still point to it assuming we're still in the same pushbuffer.
|
||||
|
||||
@@ -139,7 +139,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
|
||||
bool useBufferedRendering = framebufferManager_->UseBufferedRendering();
|
||||
// Blend
|
||||
if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) {
|
||||
gstate_c.SetAllowShaderBlend(!g_Config.bDisableSlowFramebufEffects);
|
||||
|
||||
Loaded 100 of 336 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user