mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Merge branch 'master' into TemporaryHackishBranch
# Conflicts: # Core/Config.cpp
This commit is contained in:
commit
92832759fa
126 files changed
+1318
-566
No files matched your search
@@ -39,6 +39,7 @@ assets/flash0
|
||||
UWP/icph
|
||||
UWP/.vs
|
||||
.vs
|
||||
.vscode
|
||||
|
||||
# For Mac
|
||||
.DS_Store
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ matrix:
|
||||
env: PPSSPP_BUILD_TYPE=Android
|
||||
APP_ABI=x86_64
|
||||
- os: linux
|
||||
compiler: "clang linux"
|
||||
compiler: "clang"
|
||||
env: PPSSPP_BUILD_TYPE=Linux
|
||||
- os: linux
|
||||
compiler: "gcc"
|
||||
|
||||
+4
-3
@@ -108,7 +108,7 @@ option(USING_EGL "Set to ON if target environment uses EGL" ${USING_EGL})
|
||||
option(USING_FBDEV "Set to ON if target environment uses fbdev (eg. Pandora)" ${USING_FBDEV})
|
||||
option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2})
|
||||
option(USING_X11_VULKAN "Set to OFF if target environment doesn't use X11 for Vulkan" ON)
|
||||
option(USE_WAYLAND_WSI "Enable or disable Wayland WSI support for Vulkan" ON)
|
||||
option(USE_WAYLAND_WSI "Enable or disable Wayland WSI support for Vulkan" ${USE_WAYLAND_WSI})
|
||||
# :: Frontends
|
||||
option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI})
|
||||
option(MOBILE_DEVICE "Set to ON when targeting a mobile device" ${MOBILE_DEVICE})
|
||||
@@ -270,8 +270,6 @@ if(NOT MSVC)
|
||||
add_compile_options(-fno-strict-aliasing)
|
||||
if(${CMAKE_C_COMPILER_ID} STREQUAL "Intel")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -parallel -fopenmp")
|
||||
else()
|
||||
add_compile_options(-ffast-math)
|
||||
endif()
|
||||
|
||||
if(X86 OR X86_64)
|
||||
@@ -1992,6 +1990,9 @@ if(TargetBin)
|
||||
add_executable(${TargetBin} MACOSX_BUNDLE ${ICON_PATH_ABS} ${NativeAssets} ${SHADER_FILES} ${FLASH0_FILES} ${LANG_FILES} ${NativeAppSource} "ios/Launch Screen.storyboard")
|
||||
else()
|
||||
add_executable(${TargetBin} MACOSX_BUNDLE ${ICON_PATH_ABS} ${NativeAssets} ${SHADER_FILES} ${FLASH0_FILES} ${LANG_FILES} ${NativeAppSource})
|
||||
if(TARGET SDL2::SDL2)
|
||||
add_custom_command(TARGET ${TargetBin} POST_BUILD COMMAND /bin/bash "${CMAKE_SOURCE_DIR}/SDL/macbundle.sh" "${CMAKE_BINARY_DIR}/PPSSPPSDL.app")
|
||||
endif()
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
add_executable(${TargetBin} WIN32 ${NativeAppSource})
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
@@ -103,7 +103,7 @@
|
||||
<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>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@@ -133,7 +133,7 @@
|
||||
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -166,7 +166,7 @@
|
||||
<AdditionalIncludeDirectories>../ext/native;../ext/snappy;..</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
|
||||
+2
-1
@@ -133,6 +133,7 @@ std::string ResolvePath(const std::string &path) {
|
||||
int result = getFinalPathNameByHandleW(hFile, buf, BUF_SIZE - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
if (result >= BUF_SIZE || result == 0)
|
||||
wcscpy_s(buf, BUF_SIZE - 1, input.c_str());
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
} else {
|
||||
wchar_t *longBuf = new wchar_t[BUF_SIZE];
|
||||
@@ -829,7 +830,7 @@ const std::string &GetExeDirectory()
|
||||
uint32_t program_path_size = sizeof(program_path) - 1;
|
||||
|
||||
#if defined(__linux__)
|
||||
if (readlink("/proc/self/exe", program_path, 4095) > 0)
|
||||
if (readlink("/proc/self/exe", program_path, program_path_size) > 0)
|
||||
#elif defined(__APPLE__) && !defined(IOS)
|
||||
if (_NSGetExecutablePath(program_path, &program_path_size) == 0)
|
||||
#elif defined(KERN_PROC_PATHNAME)
|
||||
|
||||
@@ -30,7 +30,7 @@ static bool IsDepthStencilFormat(VkFormat format) {
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
|
||||
bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, VulkanDeviceAllocator *allocator, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
|
||||
Wipe();
|
||||
|
||||
width_ = w;
|
||||
@@ -75,7 +75,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
|
||||
bool dedicatedAllocation = false;
|
||||
vulkan_->GetImageMemoryRequirements(image_, &mem_reqs, &dedicatedAllocation);
|
||||
|
||||
if (allocator_ && !dedicatedAllocation) {
|
||||
if (allocator && !dedicatedAllocation) {
|
||||
allocator_ = allocator;
|
||||
offset_ = allocator_->Allocate(mem_reqs, &mem_, Tag());
|
||||
if (offset_ == VulkanDeviceAllocator::ALLOCATE_FAILED) {
|
||||
ELOG("Image memory allocation failed (mem_reqs.size=%d, typebits=%08x", (int)mem_reqs.size, (int)mem_reqs.memoryTypeBits);
|
||||
@@ -231,10 +232,13 @@ void VulkanTexture::Destroy() {
|
||||
if (image_ != VK_NULL_HANDLE) {
|
||||
vulkan_->Delete().QueueDeleteImage(image_);
|
||||
}
|
||||
if (mem_ != VK_NULL_HANDLE && !allocator_) {
|
||||
vulkan_->Delete().QueueDeleteDeviceMemory(mem_);
|
||||
} else if (mem_ != VK_NULL_HANDLE) {
|
||||
allocator_->Free(mem_, offset_);
|
||||
mem_ = VK_NULL_HANDLE;
|
||||
if (mem_ != VK_NULL_HANDLE) {
|
||||
if (allocator_) {
|
||||
allocator_->Free(mem_, offset_);
|
||||
mem_ = VK_NULL_HANDLE;
|
||||
allocator_ = nullptr;
|
||||
} else {
|
||||
vulkan_->Delete().QueueDeleteDeviceMemory(mem_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ class VulkanDeviceAllocator;
|
||||
// Not very optimal - if you have many small textures you should use other strategies.
|
||||
class VulkanTexture {
|
||||
public:
|
||||
VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator)
|
||||
: vulkan_(vulkan), allocator_(allocator) {
|
||||
VulkanTexture(VulkanContext *vulkan)
|
||||
: vulkan_(vulkan) {
|
||||
}
|
||||
~VulkanTexture() {
|
||||
Destroy();
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
// Fast uploads from buffer. Mipmaps supported.
|
||||
// Usage must at least include VK_IMAGE_USAGE_TRANSFER_DST_BIT in order to use UploadMip.
|
||||
// When using UploadMip, initialLayout should be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
|
||||
bool CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, const VkComponentMapping *mapping = nullptr);
|
||||
bool CreateDirect(VkCommandBuffer cmd, VulkanDeviceAllocator *allocator, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, const VkComponentMapping *mapping = nullptr);
|
||||
void UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels
|
||||
void GenerateMip(VkCommandBuffer cmd, int mip);
|
||||
void EndCreate(VkCommandBuffer cmd, bool vertexTexture = false);
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
int32_t height_ = 0;
|
||||
int32_t numMips_ = 1;
|
||||
VkFormat format_ = VK_FORMAT_UNDEFINED;
|
||||
VulkanDeviceAllocator *allocator_;
|
||||
VulkanDeviceAllocator *allocator_ = nullptr; // If set, memory is from this allocator.
|
||||
size_t offset_ = 0;
|
||||
std::string tag_;
|
||||
};
|
||||
@@ -23,9 +23,8 @@
|
||||
#include "base/timeutil.h"
|
||||
#include "math/math_util.h"
|
||||
|
||||
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size) : device_(vulkan->GetDevice()), buf_(0), offset_(0), size_(size), writePtr_(nullptr) {
|
||||
vulkan->MemoryTypeFromProperties(0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &memoryTypeIndex_);
|
||||
|
||||
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size, VkBufferUsageFlags usage)
|
||||
: vulkan_(vulkan), size_(size), usage_(usage) {
|
||||
bool res = AddBuffer();
|
||||
assert(res);
|
||||
}
|
||||
@@ -36,43 +35,42 @@ VulkanPushBuffer::~VulkanPushBuffer() {
|
||||
|
||||
bool VulkanPushBuffer::AddBuffer() {
|
||||
BufInfo info;
|
||||
VkDevice device = vulkan_->GetDevice();
|
||||
|
||||
VkBufferCreateInfo b{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
b.size = size_;
|
||||
b.flags = 0;
|
||||
b.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
b.usage = usage_;
|
||||
b.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
b.queueFamilyIndexCount = 0;
|
||||
b.pQueueFamilyIndices = nullptr;
|
||||
|
||||
VkResult res = vkCreateBuffer(device_, &b, nullptr, &info.buffer);
|
||||
VkResult res = vkCreateBuffer(device, &b, nullptr, &info.buffer);
|
||||
if (VK_SUCCESS != res) {
|
||||
_assert_msg_(G3D, false, "vkCreateBuffer failed! result=%d", (int)res);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make validation happy.
|
||||
// Get the buffer memory requirements. None of this can be cached!
|
||||
VkMemoryRequirements reqs;
|
||||
vkGetBufferMemoryRequirements(device_, info.buffer, &reqs);
|
||||
// TODO: We really should use memoryTypeIndex here..
|
||||
vkGetBufferMemoryRequirements(device, info.buffer, &reqs);
|
||||
|
||||
// Okay, that's the buffer. Now let's allocate some memory for it.
|
||||
VkMemoryAllocateInfo alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
// TODO: Should check here that memoryTypeIndex_ matches reqs.memoryTypeBits.
|
||||
alloc.memoryTypeIndex = memoryTypeIndex_;
|
||||
alloc.allocationSize = reqs.size;
|
||||
vulkan_->MemoryTypeFromProperties(reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &alloc.memoryTypeIndex);
|
||||
|
||||
res = vkAllocateMemory(device_, &alloc, nullptr, &info.deviceMemory);
|
||||
res = vkAllocateMemory(device, &alloc, nullptr, &info.deviceMemory);
|
||||
if (VK_SUCCESS != res) {
|
||||
_assert_msg_(G3D, false, "vkAllocateMemory failed! size=%d result=%d", (int)reqs.size, (int)res);
|
||||
vkDestroyBuffer(device_, info.buffer, nullptr);
|
||||
vkDestroyBuffer(device, info.buffer, nullptr);
|
||||
return false;
|
||||
}
|
||||
res = vkBindBufferMemory(device_, info.buffer, info.deviceMemory, 0);
|
||||
res = vkBindBufferMemory(device, info.buffer, info.deviceMemory, 0);
|
||||
if (VK_SUCCESS != res) {
|
||||
ELOG("vkBindBufferMemory failed! result=%d", (int)res);
|
||||
vkFreeMemory(device_, info.deviceMemory, nullptr);
|
||||
vkDestroyBuffer(device_, info.buffer, nullptr);
|
||||
vkFreeMemory(device, info.deviceMemory, nullptr);
|
||||
vkDestroyBuffer(device, info.buffer, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -137,7 +135,7 @@ size_t VulkanPushBuffer::GetTotalSize() const {
|
||||
|
||||
void VulkanPushBuffer::Map() {
|
||||
_dbg_assert_(G3D, !writePtr_);
|
||||
VkResult res = vkMapMemory(device_, buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_));
|
||||
VkResult res = vkMapMemory(vulkan_->GetDevice(), buffers_[buf_].deviceMemory, 0, size_, 0, (void **)(&writePtr_));
|
||||
_dbg_assert_(G3D, writePtr_);
|
||||
assert(VK_SUCCESS == res);
|
||||
}
|
||||
@@ -152,7 +150,7 @@ void VulkanPushBuffer::Unmap() {
|
||||
range.memory = buffers_[buf_].deviceMemory;
|
||||
vkFlushMappedMemoryRanges(device_, 1, &range);
|
||||
*/
|
||||
vkUnmapMemory(device_, buffers_[buf_].deviceMemory);
|
||||
vkUnmapMemory(vulkan_->GetDevice(), buffers_[buf_].deviceMemory);
|
||||
writePtr_ = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class VulkanPushBuffer {
|
||||
};
|
||||
|
||||
public:
|
||||
VulkanPushBuffer(VulkanContext *vulkan, size_t size);
|
||||
VulkanPushBuffer(VulkanContext *vulkan, size_t size, VkBufferUsageFlags usage);
|
||||
~VulkanPushBuffer();
|
||||
|
||||
void Destroy(VulkanContext *vulkan);
|
||||
@@ -108,13 +108,13 @@ private:
|
||||
void NextBuffer(size_t minSize);
|
||||
void Defragment(VulkanContext *vulkan);
|
||||
|
||||
VkDevice device_;
|
||||
VulkanContext *vulkan_;
|
||||
std::vector<BufInfo> buffers_;
|
||||
size_t buf_;
|
||||
size_t offset_;
|
||||
size_t size_;
|
||||
uint32_t memoryTypeIndex_;
|
||||
uint8_t *writePtr_;
|
||||
size_t buf_ = 0;
|
||||
size_t offset_ = 0;
|
||||
size_t size_ = 0;
|
||||
uint8_t *writePtr_ = nullptr;
|
||||
VkBufferUsageFlags usage_;
|
||||
};
|
||||
|
||||
// VulkanDeviceAllocator
|
||||
|
||||
@@ -73,6 +73,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
CheckSetting(iniFile, gameID, "YugiohSaveFix", &flags_.YugiohSaveFix);
|
||||
CheckSetting(iniFile, gameID, "ForceUMDDelay", &flags_.ForceUMDDelay);
|
||||
CheckSetting(iniFile, gameID, "ForceMax60FPS", &flags_.ForceMax60FPS);
|
||||
CheckSetting(iniFile, gameID, "JitInvalidationHack", &flags_.JitInvalidationHack);
|
||||
}
|
||||
|
||||
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
|
||||
|
||||
@@ -73,6 +73,7 @@ struct CompatFlags {
|
||||
bool YugiohSaveFix;
|
||||
bool ForceUMDDelay;
|
||||
bool ForceMax60FPS;
|
||||
bool JitInvalidationHack;
|
||||
};
|
||||
|
||||
class IniFile;
|
||||
|
||||
+6
-6
@@ -400,7 +400,7 @@ static ConfigSetting generalSettings[] = {
|
||||
ConfigSetting("SimpleFrameStats", &g_Config.bSimpleFrameStats, false),
|
||||
ConfigSetting("CheckForNewVersion", &g_Config.bCheckForNewVersion, false),
|
||||
ConfigSetting("Language", &g_Config.sLanguageIni, &DefaultLangRegion),
|
||||
ConfigSetting("ForceLagSync", &g_Config.bForceLagSync, false, true, true),
|
||||
ConfigSetting("ForceLagSync2", &g_Config.bForceLagSync, false, true, true),
|
||||
ConfigSetting("DiscordPresence", &g_Config.bDiscordPresence, false, false, false), // Or maybe it makes sense to have it per-game? Race conditions abound...
|
||||
|
||||
ReportedConfigSetting("NumWorkerThreads", &g_Config.iNumWorkerThreads, &DefaultNumWorkers, true, true),
|
||||
@@ -437,7 +437,7 @@ static ConfigSetting generalSettings[] = {
|
||||
ConfigSetting("RemoteDebuggerOnStartup", &g_Config.bRemoteDebuggerOnStartup, false),
|
||||
|
||||
#ifdef __ANDROID__
|
||||
ConfigSetting("ScreenRotation", &g_Config.iScreenRotation, ROTATION_LOCKED_HORIZONTAL),
|
||||
ConfigSetting("ScreenRotation", &g_Config.iScreenRotation, ROTATION_AUTO_HORIZONTAL),
|
||||
#endif
|
||||
ConfigSetting("InternalScreenRotation", &g_Config.iInternalScreenRotation, ROTATION_LOCKED_HORIZONTAL),
|
||||
|
||||
@@ -1120,7 +1120,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
||||
}
|
||||
}
|
||||
|
||||
void Config::Save() {
|
||||
void Config::Save(const char *saveReason) {
|
||||
if (jitForcedOff) {
|
||||
// if JIT has been forced off, we don't want to screw up the user's ppsspp.ini
|
||||
g_Config.iCpuCore = (int)CPUCore::JIT;
|
||||
@@ -1173,11 +1173,11 @@ void Config::Save() {
|
||||
LogManager::GetInstance()->SaveConfig(log);
|
||||
|
||||
if (!iniFile.Save(iniFilename_.c_str())) {
|
||||
ERROR_LOG(LOADER, "Error saving config - can't write ini '%s'", iniFilename_.c_str());
|
||||
ERROR_LOG(LOADER, "Error saving config (%s)- can't write ini '%s'", saveReason, iniFilename_.c_str());
|
||||
System_SendMessage("toast", "Failed to save settings!\nCheck permissions, or try to restart the device.");
|
||||
return;
|
||||
}
|
||||
INFO_LOG(LOADER, "Config saved: '%s'", iniFilename_.c_str());
|
||||
INFO_LOG(LOADER, "Config saved (%s): '%s'", saveReason, iniFilename_.c_str());
|
||||
|
||||
if (!bGameSpecific) //otherwise we already did this in saveGameConfig()
|
||||
{
|
||||
@@ -1364,7 +1364,7 @@ bool Config::hasGameConfig(const std::string &pGameId) {
|
||||
}
|
||||
|
||||
void Config::changeGameSpecific(const std::string &pGameId) {
|
||||
Save();
|
||||
Save("changeGameSpecific");
|
||||
gameId_ = pGameId;
|
||||
bGameSpecific = !pGameId.empty();
|
||||
}
|
||||
|
||||
+1
-1
@@ -421,7 +421,7 @@ public:
|
||||
std::string dismissedVersion;
|
||||
|
||||
void Load(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr);
|
||||
void Save();
|
||||
void Save(const char *saveReason);
|
||||
void RestoreDefaults();
|
||||
|
||||
//per game config managment, should maybe be in it's own class
|
||||
|
||||
@@ -37,6 +37,7 @@ enum {
|
||||
ROTATION_LOCKED_VERTICAL = 2,
|
||||
ROTATION_LOCKED_HORIZONTAL180 = 3,
|
||||
ROTATION_LOCKED_VERTICAL180 = 4,
|
||||
ROTATION_AUTO_HORIZONTAL = 5,
|
||||
};
|
||||
|
||||
enum BufferFilter {
|
||||
|
||||
+4
-4
@@ -73,7 +73,7 @@
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../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>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@@ -95,7 +95,7 @@
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../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>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
@@ -121,7 +121,7 @@
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WIN32;_ARCH_32=1;_M_IX86=1;_LIB;NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@@ -150,7 +150,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext/native/ext</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
|
||||
+37
-10
@@ -237,6 +237,21 @@ static void __CheatStart() {
|
||||
cheatsEnabled = true;
|
||||
}
|
||||
|
||||
static int GetRefreshMs() {
|
||||
int refresh = g_Config.iCwCheatRefreshRate;
|
||||
|
||||
if (!cheatsEnabled)
|
||||
refresh = 1000;
|
||||
|
||||
// Horrible hack for Tony Hawk - Underground 2. See #3854. Avoids crashing somehow
|
||||
// but still causes regular JIT invalidations which causes stutters.
|
||||
if (PSP_CoreParameter().compat.flags().JitInvalidationHack) {
|
||||
refresh = 2;
|
||||
}
|
||||
|
||||
return refresh;
|
||||
}
|
||||
|
||||
void __CheatInit() {
|
||||
// Always register the event, want savestates to be compatible whether cheats on or off.
|
||||
CheatEvent = CoreTiming::RegisterEvent("CheatEvent", &hleCheat);
|
||||
@@ -245,10 +260,8 @@ void __CheatInit() {
|
||||
__CheatStart();
|
||||
}
|
||||
|
||||
int refresh = g_Config.iCwCheatRefreshRate;
|
||||
|
||||
// Only check once a second for cheats to be enabled.
|
||||
CoreTiming::ScheduleEvent(msToCycles(cheatsEnabled ? refresh : 1000), CheatEvent, 0);
|
||||
CoreTiming::ScheduleEvent(msToCycles(GetRefreshMs()), CheatEvent, 0);
|
||||
}
|
||||
|
||||
void __CheatShutdown() {
|
||||
@@ -264,13 +277,11 @@ void __CheatDoState(PointerWrap &p) {
|
||||
p.Do(CheatEvent);
|
||||
CoreTiming::RestoreRegisterEvent(CheatEvent, "CheatEvent", &hleCheat);
|
||||
|
||||
int refresh = g_Config.iCwCheatRefreshRate;
|
||||
|
||||
if (s < 2) {
|
||||
// Before this we didn't have a checkpoint, so reset didn't work.
|
||||
// Let's just force one in.
|
||||
CoreTiming::RemoveEvent(CheatEvent);
|
||||
CoreTiming::ScheduleEvent(msToCycles(cheatsEnabled ? refresh : 1000), CheatEvent, 0);
|
||||
CoreTiming::ScheduleEvent(msToCycles(GetRefreshMs()), CheatEvent, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,14 +295,30 @@ void hleCheat(u64 userdata, int cyclesLate) {
|
||||
}
|
||||
}
|
||||
|
||||
int refresh = g_Config.iCwCheatRefreshRate;
|
||||
// Check periodically for cheats.
|
||||
CoreTiming::ScheduleEvent(msToCycles(GetRefreshMs()), CheatEvent, 0);
|
||||
|
||||
// Only check once a second for cheats to be enabled.
|
||||
CoreTiming::ScheduleEvent(msToCycles(cheatsEnabled ? refresh : 1000), CheatEvent, 0);
|
||||
if (PSP_CoreParameter().compat.flags().JitInvalidationHack) {
|
||||
std::string gameTitle = g_paramSFO.GetValueString("DISC_ID");
|
||||
|
||||
// Horrible hack for Tony Hawk - Underground 2. See #3854. Avoids crashing somehow
|
||||
// but still causes regular JIT invalidations which causes stutters.
|
||||
if (gameTitle == "ULUS10014") {
|
||||
cheatEngine->InvalidateICache(0x08865600, 72);
|
||||
cheatEngine->InvalidateICache(0x08865690, 4);
|
||||
} else if (gameTitle == "ULES00033" || gameTitle == "ULES00034" || gameTitle == "ULES00035") { // euro, also 34 and 35
|
||||
cheatEngine->InvalidateICache(0x088655D8, 72);
|
||||
cheatEngine->InvalidateICache(0x08865668, 4);
|
||||
} else if (gameTitle == "ULUS10138") { // MTX MotoTrax. No hack for ULES00581 known.
|
||||
cheatEngine->InvalidateICache(0x0886DCC0, 72);
|
||||
cheatEngine->InvalidateICache(0x0886DC20, 4);
|
||||
cheatEngine->InvalidateICache(0x0886DD40, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cheatEngine || !cheatsEnabled)
|
||||
return;
|
||||
|
||||
|
||||
if (g_Config.bReloadCheats) { //Checks if the "reload cheats" button has been pressed.
|
||||
cheatEngine->ParseCheats();
|
||||
g_Config.bReloadCheats = false;
|
||||
|
||||
+1
-1
@@ -45,8 +45,8 @@ public:
|
||||
void Run();
|
||||
bool HasCheats();
|
||||
|
||||
private:
|
||||
void InvalidateICache(u32 addr, int size);
|
||||
private:
|
||||
u32 GetAddress(u32 value);
|
||||
|
||||
CheatOperation InterpretNextOp(const CheatCode &cheat, size_t &i);
|
||||
|
||||
@@ -146,7 +146,7 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK)
|
||||
float WRAP_WIDTH = 300.0f;
|
||||
if (UTF8StringNonASCIICount(text.c_str()) > 3)
|
||||
WRAP_WIDTH = 372.0f;
|
||||
|
||||
|
||||
float y = 140.0f;
|
||||
float h, sy ,ey;
|
||||
int n;
|
||||
|
||||
@@ -403,7 +403,7 @@ void PSPSaveDialog::DisplaySaveDataInfo1()
|
||||
char saveDetail[1024];
|
||||
|
||||
char am_pm[] = "AM";
|
||||
char hour_time[10] ;
|
||||
char hour_time[32];
|
||||
int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour;
|
||||
int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min;
|
||||
switch (g_Config.iTimeFormat) {
|
||||
@@ -412,17 +412,17 @@ void PSPSaveDialog::DisplaySaveDataInfo1()
|
||||
strcpy(am_pm, "PM");
|
||||
hour -= 12;
|
||||
}
|
||||
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
|
||||
snprintf(hour_time, sizeof(hour_time), "%02d:%02d %s", hour, min, am_pm);
|
||||
break;
|
||||
case 2:
|
||||
snprintf(hour_time,10,"%02d:%02d", hour, min);
|
||||
snprintf(hour_time, sizeof(hour_time), "%02d:%02d", hour, min);
|
||||
break;
|
||||
default:
|
||||
if (hour > 12) {
|
||||
strcpy(am_pm, "PM");
|
||||
hour -= 12;
|
||||
}
|
||||
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
|
||||
snprintf(hour_time, sizeof(hour_time), "%02d:%02d %s", hour, min, am_pm);
|
||||
}
|
||||
|
||||
snprintf(title, sizeof(title), "%s", param.GetFileInfo(currentSelectedSave).title);
|
||||
@@ -485,7 +485,7 @@ void PSPSaveDialog::DisplaySaveDataInfo2(bool showNewData) {
|
||||
|
||||
char date[256];
|
||||
char am_pm[] = "AM";
|
||||
char hour_time[10] ;
|
||||
char hour_time[32];
|
||||
int hour = modif_time.tm_hour;
|
||||
int min = modif_time.tm_min;
|
||||
switch (g_Config.iTimeFormat) {
|
||||
@@ -494,17 +494,17 @@ void PSPSaveDialog::DisplaySaveDataInfo2(bool showNewData) {
|
||||
strcpy(am_pm, "PM");
|
||||
hour -= 12;
|
||||
}
|
||||
snprintf(hour_time, 10, "%02d:%02d %s", hour, min, am_pm);
|
||||
snprintf(hour_time, sizeof(hour_time), "%02d:%02d %s", hour, min, am_pm);
|
||||
break;
|
||||
case 2:
|
||||
snprintf(hour_time, 10, "%02d:%02d", hour, min);
|
||||
snprintf(hour_time, sizeof(hour_time), "%02d:%02d", hour, min);
|
||||
break;
|
||||
default:
|
||||
if (hour > 12) {
|
||||
strcpy(am_pm, "PM");
|
||||
hour -= 12;
|
||||
}
|
||||
snprintf(hour_time, 10, "%02d:%02d %s", hour, min, am_pm);
|
||||
snprintf(hour_time, sizeof(hour_time), "%02d:%02d %s", hour, min, am_pm);
|
||||
}
|
||||
|
||||
int day = modif_time.tm_mday;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "file/file_util.h"
|
||||
@@ -30,7 +31,10 @@
|
||||
|
||||
LocalFileLoader::LocalFileLoader(const std::string &filename)
|
||||
: filesize_(0), filename_(filename) {
|
||||
|
||||
if (filename.empty()) {
|
||||
ERROR_LOG(FILESYS, "LocalFileLoader can't load empty filenames");
|
||||
return;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
|
||||
fd_ = open(filename.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
@@ -47,7 +51,7 @@ LocalFileLoader::LocalFileLoader(const std::string &filename)
|
||||
lseek(fd_, 0, SEEK_SET);
|
||||
#endif
|
||||
|
||||
#else // !_WIN32
|
||||
#else // _WIN32
|
||||
|
||||
const DWORD access = GENERIC_READ, share = FILE_SHARE_READ, mode = OPEN_EXISTING, flags = FILE_ATTRIBUTE_NORMAL;
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
@@ -60,14 +64,15 @@ LocalFileLoader::LocalFileLoader(const std::string &filename)
|
||||
}
|
||||
LARGE_INTEGER end_offset;
|
||||
const LARGE_INTEGER zero = { 0 };
|
||||
if(SetFilePointerEx(handle_, zero, &end_offset, FILE_END) == 0) {
|
||||
if (SetFilePointerEx(handle_, zero, &end_offset, FILE_END) == 0) {
|
||||
// Couldn't seek in the file. Close it and give up? This should never happen.
|
||||
CloseHandle(handle_);
|
||||
handle_ = INVALID_HANDLE_VALUE;
|
||||
return;
|
||||
}
|
||||
filesize_ = end_offset.QuadPart;
|
||||
SetFilePointerEx(handle_, zero, nullptr, FILE_BEGIN);
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
LocalFileLoader::~LocalFileLoader() {
|
||||
|
||||
@@ -154,6 +154,10 @@ DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string
|
||||
hAlloc = _hAlloc;
|
||||
}
|
||||
|
||||
DirectoryFileSystem::~DirectoryFileSystem() {
|
||||
CloseAll();
|
||||
}
|
||||
|
||||
std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath)
|
||||
{
|
||||
if (localpath.empty())
|
||||
@@ -445,16 +449,12 @@ void DirectoryFileHandle::Close()
|
||||
|
||||
void DirectoryFileSystem::CloseAll() {
|
||||
for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
|
||||
INFO_LOG(FILESYS, "DirectoryFileSystem::CloseAll(): Force closing %d (%s)", (int)iter->first, iter->second.guestFilename.c_str());
|
||||
iter->second.hFile.Close();
|
||||
}
|
||||
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
DirectoryFileSystem::~DirectoryFileSystem() {
|
||||
CloseAll();
|
||||
}
|
||||
|
||||
std::string DirectoryFileSystem::GetLocalPath(std::string localpath) {
|
||||
if (localpath.empty())
|
||||
return basePath;
|
||||
|
||||
@@ -38,7 +38,7 @@ static int kuKernelGetModel() {
|
||||
|
||||
const HLEFunction KUBridge[] =
|
||||
{
|
||||
{ 0x4C25EA72, &WrapI_CUU<kuKernelLoadModule>, "kuKernelLoadModule", 'i', "cuu" },
|
||||
{ 0x4C25EA72, &WrapI_CUU<kuKernelLoadModule>, "kuKernelLoadModule", 'i', "sxx" },
|
||||
{ 0x24331850, &WrapI_V<kuKernelGetModel>, "kuKernelGetModel", 'i', "" },
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
@@ -509,7 +508,7 @@ static void __CtrlWriteUserLatch(CtrlLatch *userLatch, int bufs) {
|
||||
userLatch->btnMake &= CTRL_MASK_USER;
|
||||
userLatch->btnPress &= CTRL_MASK_USER;
|
||||
if (bufs > 0) {
|
||||
userLatch->btnRelease |= CTRL_MASK_USER;
|
||||
userLatch->btnRelease |= ~CTRL_MASK_USER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -436,7 +436,9 @@ public:
|
||||
}
|
||||
u32 args[2] = { params_.userDataAddr, (u32)handle_ };
|
||||
// TODO: The return value of this is leaking.
|
||||
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
|
||||
if (handle_) { // Avoid calling free-callback on double-free
|
||||
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
|
||||
}
|
||||
handle_ = 0;
|
||||
fonts_.clear();
|
||||
isfontopen_.clear();
|
||||
|
||||
@@ -1934,7 +1934,8 @@ static void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 ret
|
||||
if (module->nm.module_start_func != 0 && module->nm.module_start_func != (u32)-1)
|
||||
{
|
||||
entryAddr = module->nm.module_start_func;
|
||||
attribute = module->nm.module_start_thread_attr;
|
||||
if (module->nm.module_start_thread_attr != 0)
|
||||
attribute = module->nm.module_start_thread_attr;
|
||||
}
|
||||
else if ((entryAddr == (u32)-1) || entryAddr == module->memoryBlockAddr - 1)
|
||||
{
|
||||
@@ -1967,7 +1968,7 @@ static void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 ret
|
||||
stacksize = module->nm.module_start_thread_stacksize;
|
||||
}
|
||||
|
||||
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0);
|
||||
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0, (module->nm.attribute & 0x1000) != 0);
|
||||
__KernelStartThreadValidate(threadID, argsize, argAddr);
|
||||
__KernelSetThreadRA(threadID, NID_MODULERETURN);
|
||||
__KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "started module");
|
||||
@@ -2049,7 +2050,7 @@ static u32 sceKernelStopModule(u32 moduleId, u32 argSize, u32 argAddr, u32 retur
|
||||
|
||||
if (Memory::IsValidAddress(stopFunc))
|
||||
{
|
||||
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, stopFunc, priority, stacksize, attr, 0);
|
||||
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, stopFunc, priority, stacksize, attr, 0, (module->nm.attribute & 0x1000) != 0);
|
||||
__KernelStartThreadValidate(threadID, argSize, argAddr);
|
||||
__KernelSetThreadRA(threadID, NID_MODULERETURN);
|
||||
__KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "stopped module");
|
||||
@@ -2132,7 +2133,7 @@ u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize,
|
||||
}
|
||||
|
||||
if (Memory::IsValidAddress(stopFunc)) {
|
||||
SceUID threadID = __KernelCreateThread(module->nm.name, moduleID, stopFunc, priority, stacksize, attr, 0);
|
||||
SceUID threadID = __KernelCreateThread(module->nm.name, moduleID, stopFunc, priority, stacksize, attr, 0, (module->nm.attribute & 0x1000) != 0);
|
||||
__KernelStartThreadValidate(threadID, argSize, argp);
|
||||
__KernelSetThreadRA(threadID, NID_MODULERETURN);
|
||||
__KernelWaitCurThread(WAITTYPE_MODULE, moduleID, 1, 0, false, "unloadstopped module");
|
||||
|
||||
@@ -1944,7 +1944,7 @@ SceUID __KernelCreateThreadInternal(const char *threadName, SceUID moduleID, u32
|
||||
return id;
|
||||
}
|
||||
|
||||
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) {
|
||||
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr, bool allowKernel) {
|
||||
if (threadName == nullptr)
|
||||
return hleReportError(SCEKERNEL, SCE_KERNEL_ERROR_ERROR, "NULL thread name");
|
||||
|
||||
@@ -1961,7 +1961,7 @@ int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32
|
||||
if (entry != 0)
|
||||
return hleReportError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "invalid thread entry %08x", entry);
|
||||
}
|
||||
if ((attr & ~PSP_THREAD_ATTR_USER_MASK) != 0)
|
||||
if ((attr & ~PSP_THREAD_ATTR_USER_MASK) != 0 && !allowKernel)
|
||||
return hleReportWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ATTR, "illegal thread attributes %08x", attr);
|
||||
|
||||
if ((attr & ~PSP_THREAD_ATTR_SUPPORTED) != 0)
|
||||
@@ -1997,7 +1997,9 @@ int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32
|
||||
}
|
||||
|
||||
int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) {
|
||||
return __KernelCreateThread(threadName, __KernelGetCurThreadModuleId(), entry, prio, stacksize, attr, optionAddr);
|
||||
Thread *cur = __GetCurrentThread();
|
||||
bool allowKernel = cur ? (cur->nt.attr & PSP_THREAD_ATTR_KERNEL) != 0 : false;
|
||||
return __KernelCreateThread(threadName, __KernelGetCurThreadModuleId(), entry, prio, stacksize, attr, optionAddr, allowKernel);
|
||||
}
|
||||
|
||||
int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bool forceArgs) {
|
||||
|
||||
@@ -31,7 +31,7 @@ class DebugInterface;
|
||||
|
||||
int sceKernelChangeThreadPriority(SceUID threadID, int priority);
|
||||
SceUID __KernelCreateThreadInternal(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr);
|
||||
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr);
|
||||
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr, bool allowKernel);
|
||||
int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr);
|
||||
int sceKernelDelayThread(u32 usec);
|
||||
int sceKernelDelayThreadCB(u32 usec);
|
||||
|
||||
@@ -318,12 +318,12 @@ static void AnalyzeMpeg(u8 *buffer, u32 validSize, MpegContext *ctx) {
|
||||
ctx->audioFrameCount = 0;
|
||||
ctx->endOfAudioReached = false;
|
||||
ctx->endOfVideoReached = false;
|
||||
|
||||
|
||||
// Sanity Check ctx->mpegFirstTimestamp
|
||||
if (ctx->mpegFirstTimestamp != 90000) {
|
||||
WARN_LOG_REPORT(ME, "Unexpected mpeg first timestamp: %llx / %lld", ctx->mpegFirstTimestamp, ctx->mpegFirstTimestamp);
|
||||
}
|
||||
|
||||
|
||||
if (ctx->mpegMagic != PSMF_MAGIC || ctx->mpegVersion < 0 ||
|
||||
(ctx->mpegOffset & 2047) != 0 || ctx->mpegOffset == 0) {
|
||||
// mpeg header is invalid!
|
||||
@@ -511,7 +511,7 @@ static u32 sceMpegCreate(u32 mpegAddr, u32 dataPtr, u32 size, u32 ringbufferAddr
|
||||
Memory::Write_U32(ringbufferAddr, mpegHandle + 16);
|
||||
Memory::Write_U32(ringbuffer->dataUpperBound, mpegHandle + 20);
|
||||
}
|
||||
MpegContext *ctx = new MpegContext;
|
||||
MpegContext *ctx = new MpegContext();
|
||||
if (mpegMap.find(mpegHandle) != mpegMap.end()) {
|
||||
WARN_LOG_REPORT(HLE, "Replacing existing mpeg context at %08x", mpegAddr);
|
||||
// Otherwise, it would leak.
|
||||
@@ -532,6 +532,8 @@ static u32 sceMpegCreate(u32 mpegAddr, u32 dataPtr, u32 size, u32 ringbufferAddr
|
||||
ctx->ignorePcm = false;
|
||||
ctx->ignoreAvc = false;
|
||||
ctx->defaultFrameWidth = frameWidth;
|
||||
ctx->mpegStreamSize = 0;
|
||||
ctx->mpegOffset = 0;
|
||||
for (int i = 0; i < MPEG_DATA_ES_BUFFERS; i++) {
|
||||
ctx->esBuffers[i] = false;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ u32 sceNetAdhocInit() {
|
||||
// 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);
|
||||
threadAdhocID = __KernelCreateThread("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x10, 0x1000, 0, 0, false);
|
||||
if (threadAdhocID > 0) {
|
||||
__KernelStartThread(threadAdhocID, 0, 0);
|
||||
}
|
||||
|
||||
@@ -179,8 +179,17 @@ namespace MIPSComp
|
||||
return;
|
||||
}
|
||||
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address? CPU bug?");
|
||||
load ? gpr.MapDirtyIn(rt, rs, false) : gpr.MapInIn(rt, rs);
|
||||
// This gets hit in a few games, as a result of never-taken delay slots (some branch types
|
||||
// conditionally execute the delay slot instructions). Ignore in those cases.
|
||||
if (!js.inDelaySlot) {
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address %08x? CPU bug?", iaddr);
|
||||
}
|
||||
|
||||
if (load) {
|
||||
gpr.MapDirtyIn(rt, rs, false);
|
||||
} else {
|
||||
gpr.MapInIn(rt, rs);
|
||||
}
|
||||
|
||||
if (!g_Config.bFastMemory && rs != MIPS_REG_SP) {
|
||||
SetCCAndR0ForSafeAddress(rs, offset, SCRATCHREG2, true);
|
||||
|
||||
@@ -2301,10 +2301,16 @@ namespace MIPSComp
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
// Actually, not sure that this instruction accepts an S prefix. We don't apply it in the
|
||||
// interpreter. But whatever.
|
||||
// This is a hack that modifies prefixes. We eat them later, so just overwrite.
|
||||
// S prefix forces the negate flags.
|
||||
js.prefixS |= 0x000F0000;
|
||||
// T prefix forces constants on and regnum to 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
js.prefixT = (js.prefixT & ~0x000000FF) | 0x00000055 | 0x0000F000;
|
||||
|
||||
u8 sregs[4], tregs[4], dregs[4];
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
GetVectorRegsPrefixT(tregs, sz, _VS);
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
|
||||
MIPSReg tempregs[4];
|
||||
@@ -2316,10 +2322,9 @@ namespace MIPSComp
|
||||
}
|
||||
}
|
||||
|
||||
MOVI2F(S0, 1.0f, SCRATCHREG1);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
fpr.MapDirtyInV(tempregs[i], sregs[i]);
|
||||
VSUB(fpr.V(tempregs[i]), S0, fpr.V(sregs[i]));
|
||||
fpr.MapDirtyInInV(tempregs[i], sregs[i], tregs[i]);
|
||||
VADD(fpr.V(tempregs[i]), fpr.V(tregs[i]), fpr.V(sregs[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
||||
@@ -1433,12 +1433,21 @@ void ArmJit::CompNEON_Vocp(MIPSOpcode op) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// TODO: Handle T prefix. Right now it uses 1.0f always.
|
||||
|
||||
// This is a hack that modifies prefixes. We eat them later, so just overwrite.
|
||||
// S prefix forces the negate flags.
|
||||
js.prefixS |= 0x000F0000;
|
||||
// T prefix forces constants on and regnum to 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
js.prefixT = (js.prefixT & ~0x000000FF) | 0x00000055 | 0x0000F000;
|
||||
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
MappedRegs regs = NEONMapDirtyIn(op, sz, sz);
|
||||
MOVI2F_neon(Q0, 1.0f, R0);
|
||||
VSUB(F_32, regs.vd, Q0, regs.vs);
|
||||
VADD(F_32, regs.vd, Q0, regs.vs);
|
||||
NEONApplyPrefixD(regs.vd);
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace MIPSComp {
|
||||
return;
|
||||
}
|
||||
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address? CPU bug?");
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address %08x? CPU bug?", iaddr);
|
||||
if (load) {
|
||||
gpr.MapDirtyIn(rt, rs, false);
|
||||
} else {
|
||||
@@ -364,13 +364,19 @@ namespace MIPSComp {
|
||||
addrReg = SCRATCH1;
|
||||
}
|
||||
} else {
|
||||
// This actually gets hit in micro machines! rs = ZR rt = ZR. Probably a bug.
|
||||
// Leaving this a debug assert for future investigation.
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address? CPU bug?");
|
||||
// This gets hit in a few games, as a result of never-taken delay slots (some branch types
|
||||
// conditionally execute the delay slot instructions). Ignore in those cases.
|
||||
if (!js.inDelaySlot) {
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address %08x? CPU bug?", iaddr);
|
||||
}
|
||||
|
||||
// If we already have a targetReg, we optimized an imm, and rs is already mapped.
|
||||
if (targetReg == INVALID_REG) {
|
||||
load ? gpr.MapDirtyIn(rt, rs) : gpr.MapInIn(rt, rs);
|
||||
if (load) {
|
||||
gpr.MapDirtyIn(rt, rs);
|
||||
} else {
|
||||
gpr.MapInIn(rt, rs);
|
||||
}
|
||||
targetReg = gpr.R(rt);
|
||||
}
|
||||
|
||||
@@ -413,9 +419,9 @@ namespace MIPSComp {
|
||||
}
|
||||
|
||||
void Arm64Jit::Comp_Cache(MIPSOpcode op) {
|
||||
// int imm = (s16)(op & 0xFFFF);
|
||||
// int rs = _RS;
|
||||
// int addr = R(rs) + imm;
|
||||
// int imm = (s16)(op & 0xFFFF);
|
||||
// int rs = _RS;
|
||||
// int addr = R(rs) + imm;
|
||||
int func = (op >> 16) & 0x1F;
|
||||
|
||||
// It appears that a cache line is 0x40 (64) bytes, loops in games
|
||||
|
||||
@@ -1952,10 +1952,16 @@ namespace MIPSComp {
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
// Actually, not sure that this instruction accepts an S prefix. We don't apply it in the
|
||||
// interpreter. But whatever.
|
||||
// This is a hack that modifies prefixes. We eat them later, so just overwrite.
|
||||
// S prefix forces the negate flags.
|
||||
js.prefixS |= 0x000F0000;
|
||||
// T prefix forces constants on and regnum to 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
js.prefixT = (js.prefixT & ~0x000000FF) | 0x00000055 | 0x0000F000;
|
||||
|
||||
u8 sregs[4], tregs[4], dregs[4];
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
GetVectorRegsPrefixT(tregs, sz, _VS);
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
|
||||
MIPSReg tempregs[4];
|
||||
@@ -1969,8 +1975,8 @@ namespace MIPSComp {
|
||||
|
||||
fp.MOVI2F(S0, 1.0f, SCRATCH1);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
fpr.MapDirtyInV(tempregs[i], sregs[i]);
|
||||
fp.FSUB(fpr.V(tempregs[i]), S0, fpr.V(sregs[i]));
|
||||
fpr.MapDirtyInInV(tempregs[i], sregs[i], tregs[i]);
|
||||
fp.FADD(fpr.V(tempregs[i]), fpr.V(tregs[i]), fpr.V(sregs[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
||||
@@ -1174,9 +1174,14 @@ namespace MIPSComp {
|
||||
// Many more instructions to interpret.
|
||||
void IRFrontend::Comp_Vmmul(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE(VFPU_MTX);
|
||||
if (!js.HasNoPrefix()) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// Matrix multiply (no prefixes)
|
||||
// D[0 .. N,0 .. M] = S[0 .. N, 0 .. M] * T[0 .. N,0 .. M]
|
||||
// Matrix multiply (wierd prefixes)
|
||||
// D[0 .. N, 0 .. M] = S[0 .. N, 0 .. M]' * T[0 .. N, 0 .. M]
|
||||
// Note: Behaves as if it's implemented through a series of vdots.
|
||||
// Important: this is a matrix multiply with a pre-transposed S.
|
||||
|
||||
MatrixSize sz = GetMtxSize(op);
|
||||
int n = GetMatrixSide(sz);
|
||||
@@ -1229,7 +1234,7 @@ namespace MIPSComp {
|
||||
// TODO: Skip this and resort to method one and transpose the output?
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ir.Write(IROp::Vec4Dot, s0 + i, sregs[i], tregs[j * 4]);
|
||||
ir.Write(IROp::Vec4Dot, s0 + i, sregs[i * 4], tregs[j * 4]);
|
||||
}
|
||||
ir.Write(IROp::Vec4Mov, dregs[j * 4], s0);
|
||||
}
|
||||
@@ -1840,27 +1845,36 @@ namespace MIPSComp {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// Vector one's complement
|
||||
// d[N] = 1.0 - s[N]
|
||||
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
// Actually, not sure that this instruction accepts an S prefix. We don't apply it in the
|
||||
// interpreter. But whatever.
|
||||
// This is a hack that modifies prefixes. We eat them later, so just overwrite.
|
||||
// S prefix forces the negate flags.
|
||||
js.prefixS |= 0x000F0000;
|
||||
// T prefix forces constants on and regnum to 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
js.prefixT = (js.prefixT & ~0x000000FF) | 0x00000055 | 0x0000F000;
|
||||
|
||||
u8 sregs[4], tregs[4], dregs[4];
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
// There's no bits for t, so just reuse s. It'll be constants only.
|
||||
GetVectorRegsPrefixT(tregs, sz, _VS);
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
|
||||
u8 tempregs[4];
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (!IsOverlapSafe(dregs[i], n, sregs)) {
|
||||
tempregs[i] = IRVTEMP_PFX_T + i; // using IRTEMP0 for other things
|
||||
tempregs[i] = IRVTEMP_0 + i;
|
||||
} else {
|
||||
tempregs[i] = dregs[i];
|
||||
}
|
||||
}
|
||||
|
||||
ir.Write(IROp::SetConstF, IRVTEMP_0, ir.AddConstantFloat(1.0f));
|
||||
for (int i = 0; i < n; ++i) {
|
||||
ir.Write(IROp::FSub, tempregs[i], IRVTEMP_0, sregs[i]);
|
||||
ir.Write(IROp::FAdd, tempregs[i], tregs[i], sregs[i]);
|
||||
}
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (dregs[i] != tempregs[i]) {
|
||||
|
||||
+85
-23
@@ -544,15 +544,24 @@ namespace MIPSInt
|
||||
|
||||
void Int_Vocp(MIPSOpcode op)
|
||||
{
|
||||
float s[4], d[4];
|
||||
float s[4], t[4], d[4];
|
||||
int vd = _VD;
|
||||
int vs = _VS;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
ReadVector(s, sz, vs);
|
||||
for (int i = 0; i < GetNumVectorElements(sz); i++)
|
||||
{
|
||||
// Always positive NaN.
|
||||
d[i] = my_isnan(s[i]) ? fabsf(s[i]) : 1.0f - s[i];
|
||||
|
||||
// S prefix forces the negate flags.
|
||||
u32 sprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX];
|
||||
ApplyPrefixST(s, sprefix | 0x000F0000, sz);
|
||||
|
||||
// T prefix forces constants on and regnum to 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
u32 tprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX];
|
||||
ApplyPrefixST(t, (tprefix & ~0x000000FF) | 0x00000055 | 0x0000F000, sz);
|
||||
|
||||
for (int i = 0; i < GetNumVectorElements(sz); i++) {
|
||||
// Always positive NaN. Note that s is always negated from the registers.
|
||||
d[i] = my_isnan(s[i]) ? fabsf(s[i]) : t[i] + s[i];
|
||||
}
|
||||
ApplyPrefixD(d, sz);
|
||||
WriteVector(d, sz, vd);
|
||||
@@ -562,22 +571,32 @@ namespace MIPSInt
|
||||
|
||||
void Int_Vsocp(MIPSOpcode op)
|
||||
{
|
||||
float s[4], d[4];
|
||||
float s[4], t[4], d[4];
|
||||
int vd = _VD;
|
||||
int vs = _VS;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
VectorSize outSize = GetDoubleVectorSize(sz);
|
||||
ReadVector(s, sz, vs);
|
||||
|
||||
// S prefix forces negate in even/odd and xxyy swizzle.
|
||||
// abs works, and applies to final position (not source.)
|
||||
u32 sprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX];
|
||||
ApplyPrefixST(s, (sprefix & ~0x000F00FF) | 0x00000050 | 0x00050000, outSize);
|
||||
|
||||
// T prefix forces constants on and regnum to 0, 1, 0, 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
u32 tprefix = currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX];
|
||||
ApplyPrefixST(t, (tprefix & ~0x000000FF) | 0x00000011 | 0x0000F000, outSize);
|
||||
|
||||
int n = GetNumVectorElements(sz);
|
||||
float x = s[0];
|
||||
d[0] = nanclamp(1.0f - x, 0.0f, 1.0f);
|
||||
d[1] = nanclamp(x, 0.0f, 1.0f);
|
||||
VectorSize outSize = V_Pair;
|
||||
if (n > 1) {
|
||||
float y = s[1];
|
||||
d[2] = nanclamp(1.0f - y, 0.0f, 1.0f);
|
||||
d[3] = nanclamp(y, 0.0f, 1.0f);
|
||||
outSize = V_Quad;
|
||||
}
|
||||
// Essentially D prefix saturation is forced.
|
||||
d[0] = nanclamp(t[0] + s[0], 0.0f, 1.0f);
|
||||
d[1] = nanclamp(t[1] + s[1], 0.0f, 1.0f);
|
||||
if (outSize == V_Quad) {
|
||||
d[2] = nanclamp(t[2] + s[2], 0.0f, 1.0f);
|
||||
d[3] = nanclamp(t[3] + s[3], 0.0f, 1.0f);
|
||||
}
|
||||
ApplyPrefixD(d, sz);
|
||||
WriteVector(d, outSize, vd);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
@@ -1801,11 +1820,33 @@ bad:
|
||||
|
||||
void Int_Vlgb(MIPSOpcode op)
|
||||
{
|
||||
// S & D valid
|
||||
Reporting::ReportMessage("vlgb not implemented");
|
||||
if (!PSP_CoreParameter().headLess) {
|
||||
_dbg_assert_msg_(CPU,0,"vlgb not implemented");
|
||||
// Vector log binary (extract exponent)
|
||||
int vd = _VD;
|
||||
int vs = _VS;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
|
||||
FloatBits d;
|
||||
FloatBits s;
|
||||
|
||||
ReadVector(s.f, sz, vs);
|
||||
// TODO: Test swizzle, t?
|
||||
ApplySwizzleS(s.f, sz);
|
||||
|
||||
if (sz != V_Single) {
|
||||
ERROR_LOG_REPORT(CPU, "vlgb not implemented for size %d", GetNumVectorElements(sz));
|
||||
}
|
||||
for (int i = 0; i < GetNumVectorElements(sz); ++i) {
|
||||
int exp = (s.u[i] & 0x7F800000) >> 23;
|
||||
if (exp == 0xFF) {
|
||||
d.f[i] = s.f[i];
|
||||
} else if (exp == 0) {
|
||||
d.f[i] = -INFINITY;
|
||||
} else {
|
||||
d.f[i] = (float)(exp - 127);
|
||||
}
|
||||
}
|
||||
ApplyPrefixD(d.f, sz);
|
||||
WriteVector(d.f, sz, vd);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
}
|
||||
@@ -1886,10 +1927,31 @@ bad:
|
||||
|
||||
void Int_Vsbz(MIPSOpcode op)
|
||||
{
|
||||
Reporting::ReportMessage("vsbz not implemented");
|
||||
if (!PSP_CoreParameter().headLess) {
|
||||
_dbg_assert_msg_(CPU,0,"vsbz not implemented");
|
||||
// Vector scale by zero (set exp to 0 to extract mantissa)
|
||||
int vd = _VD;
|
||||
int vs = _VS;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
|
||||
FloatBits d;
|
||||
FloatBits s;
|
||||
|
||||
ReadVector(s.f, sz, vs);
|
||||
// TODO: Test swizzle, t?
|
||||
ApplySwizzleS(s.f, sz);
|
||||
|
||||
if (sz != V_Single) {
|
||||
ERROR_LOG_REPORT(CPU, "vsbz not implemented for size %d", GetNumVectorElements(sz));
|
||||
}
|
||||
for (int i = 0; i < GetNumVectorElements(sz); ++i) {
|
||||
// NAN and denormals pass through.
|
||||
if (my_isnan(s.f[i]) || (s.u[i] & 0x7F800000) == 0) {
|
||||
d.u[i] = s.u[i];
|
||||
} else {
|
||||
d.u[i] = (127 << 23) | (s.u[i] & 0x007FFFFF);
|
||||
}
|
||||
}
|
||||
ApplyPrefixD(d.f, sz);
|
||||
WriteVector(d.f, sz, vd);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
}
|
||||
|
||||
+18
-30
@@ -524,8 +524,8 @@ const MIPSInstruction tableVFPU0[8] = // 011000 xxx ....... . ....... . .......
|
||||
{
|
||||
INSTR("vadd", JITFUNC(Comp_VecDo3), Dis_VectorSet3, Int_VecDo3, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsub", JITFUNC(Comp_VecDo3), Dis_VectorSet3, Int_VecDo3, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vsbn", JITFUNC(Comp_Generic), Dis_VectorSet3, Int_Vsbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
// TODO: Disasm is wrong.
|
||||
INSTR("vsbn", JITFUNC(Comp_Generic), Dis_VectorSet3, Int_Vsbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
|
||||
INSTR("vdiv", JITFUNC(Comp_VecDo3), Dis_VectorSet3, Int_VecDo3, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
@@ -577,20 +577,18 @@ const MIPSInstruction tableVFPU4Jump[32] = // 110100 xxxxx ..... . ....... . ...
|
||||
INVALID,
|
||||
INVALID,
|
||||
//24 - 110100 11 ........ . ....... . .......
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vwbn.s", JITFUNC(Comp_Generic), Dis_Vwbn, Int_Vwbn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
};
|
||||
|
||||
const MIPSInstruction tableVFPU7[32] = // 110100 00001 xxxxx . ....... . .......
|
||||
{
|
||||
// TODO disasm
|
||||
INSTR("vrnds", JITFUNC(Comp_Generic), Dis_Vrnds, Int_Vrnds, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vrndi", JITFUNC(Comp_Generic), Dis_VrndX, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vrndf1", JITFUNC(Comp_Generic), Dis_VrndX, Int_VrndX, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
@@ -599,9 +597,7 @@ const MIPSInstruction tableVFPU7[32] = // 110100 00001 xxxxx . ....... . .......
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
//8
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
// TODO: Flags may not be correct (prefixes, etc.) Is this the correct encoding? Others say 10110.
|
||||
INSTR("vsbz", JITFUNC(Comp_Generic), Dis_Generic, Int_Vsbz, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INVALID, INVALID, INVALID,
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
//16
|
||||
INVALID,
|
||||
INVALID,
|
||||
@@ -610,9 +606,8 @@ const MIPSInstruction tableVFPU7[32] = // 110100 00001 xxxxx . ....... . .......
|
||||
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vlgb", JITFUNC(Comp_Generic), Dis_Generic, Int_Vlgb, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vsbz", JITFUNC(Comp_Generic), Dis_Generic, Int_Vsbz, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vlgb", JITFUNC(Comp_Generic), Dis_Generic, Int_Vlgb, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
//24
|
||||
INSTR("vuc2i", JITFUNC(Comp_Vx2i), Dis_Vs2i, Int_Vx2i, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // Seen in BraveStory, initialization 110100 00001110000 000 0001 0000 0000
|
||||
INSTR("vc2i", JITFUNC(Comp_Vx2i), Dis_Vs2i, Int_Vx2i, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
@@ -731,23 +726,18 @@ const MIPSInstruction tableVFPUMatrixSet1[16] = // 111100 11100 .xxxx . .......
|
||||
|
||||
const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . .......
|
||||
{
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vsrt1", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt1, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vsrt2", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt2, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vsrt1", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt1, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt2", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt2, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vbfy1", JITFUNC(Comp_Vbfy), Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vbfy2", JITFUNC(Comp_Vbfy), Dis_Vbfy, Int_Vbfy, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
//4
|
||||
INSTR("vocp", JITFUNC(Comp_Vocp), Dis_Vbfy, Int_Vocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX), // one's complement
|
||||
INSTR("vsocp", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsocp, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vfad", JITFUNC(Comp_Vhoriz), Dis_Vfad, Int_Vfad, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vavg", JITFUNC(Comp_Vhoriz), Dis_Vfad, Int_Vavg, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vavg", JITFUNC(Comp_Vhoriz), Dis_Vfad, Int_Vavg, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
//8
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vsrt3", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt3, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vsrt4", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt4, IN_OTHER|OUT_OTHER|IS_VFPU),
|
||||
INSTR("vsrt3", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt3, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsrt4", JITFUNC(Comp_Generic), Dis_Vbfy, Int_Vsrt4, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INSTR("vsgn", JITFUNC(Comp_Vsgn), Dis_Vbfy, Int_Vsgn, IN_OTHER|OUT_OTHER|IS_VFPU|OUT_EAT_PREFIX),
|
||||
INVALID,
|
||||
//12
|
||||
@@ -757,9 +747,7 @@ const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... . .......
|
||||
INVALID,
|
||||
|
||||
//16
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vmfvc", JITFUNC(Comp_Vmfvc), Dis_Vmftvc, Int_Vmfvc, IN_OTHER|IN_VFPU_CC|OUT_OTHER|IS_VFPU),
|
||||
// TODO: Flags may not be correct (prefixes, etc.)
|
||||
INSTR("vmtvc", JITFUNC(Comp_Vmtvc), Dis_Vmftvc, Int_Vmtvc, IN_OTHER|OUT_VFPU_CC|OUT_OTHER|IS_VFPU),
|
||||
INVALID,
|
||||
INVALID,
|
||||
|
||||
@@ -2026,12 +2026,24 @@ void Jit::Comp_Vocp(MIPSOpcode op) {
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
// This is a hack that modifies prefixes. We eat them later, so just overwrite.
|
||||
// S prefix forces the negate flags.
|
||||
js.prefixS |= 0x000F0000;
|
||||
// T prefix forces constants on and regnum to 1.
|
||||
// That means negate still works, and abs activates a different constant.
|
||||
js.prefixT = (js.prefixT & ~0x000000FF) | 0x00000055 | 0x0000F000;
|
||||
|
||||
u8 sregs[4], tregs[4], dregs[4];
|
||||
// Actually uses the T prefixes (despite being VS.)
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
if (js.prefixT != 0x0000F055)
|
||||
GetVectorRegsPrefixT(tregs, sz, _VS);
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
|
||||
// Flush SIMD.
|
||||
fpr.SimpleRegsV(sregs, sz, 0);
|
||||
if (js.prefixT != 0x0000F055)
|
||||
fpr.SimpleRegsV(tregs, sz, 0);
|
||||
fpr.SimpleRegsV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
|
||||
X64Reg tempxregs[4];
|
||||
@@ -2048,11 +2060,17 @@ void Jit::Comp_Vocp(MIPSOpcode op) {
|
||||
}
|
||||
}
|
||||
|
||||
MOV(PTRBITS, R(TEMPREG), ImmPtr(&one));
|
||||
MOVSS(XMM1, MatR(TEMPREG));
|
||||
if (js.prefixT == 0x0000F055) {
|
||||
MOV(PTRBITS, R(TEMPREG), ImmPtr(&one));
|
||||
MOVSS(XMM1, MatR(TEMPREG));
|
||||
}
|
||||
for (int i = 0; i < n; ++i) {
|
||||
MOVSS(XMM0, R(XMM1));
|
||||
SUBSS(XMM0, fpr.V(sregs[i]));
|
||||
if (js.prefixT == 0x0000F055) {
|
||||
MOVSS(XMM0, R(XMM1));
|
||||
} else {
|
||||
MOVSS(XMM0, fpr.V(tregs[i]));
|
||||
}
|
||||
ADDSS(XMM0, fpr.V(sregs[i]));
|
||||
MOVSS(tempxregs[i], R(XMM0));
|
||||
}
|
||||
|
||||
|
||||
@@ -477,7 +477,7 @@ static AtlasTextMetrics BreakLines(const char *text, const AtlasFont &atlasfont,
|
||||
utfWord = utfPrev;
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++numChars;
|
||||
@@ -549,7 +549,7 @@ static AtlasTextMetrics BreakLines(const char *text, const AtlasFont &atlasfont,
|
||||
}
|
||||
lineWidth += nextWidth;
|
||||
|
||||
u32 cval = utf.next();
|
||||
u32 cval = utf.end() ? 0 : utf.next();
|
||||
if (spaceWidth > 0)
|
||||
{
|
||||
if (!dryRun)
|
||||
|
||||
@@ -1865,7 +1865,8 @@ Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u
|
||||
}
|
||||
|
||||
textureCache_->ForgetLastTexture();
|
||||
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth });
|
||||
bool z_stencil = reason == TempFBO::STENCIL;
|
||||
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, z_stencil, depth });
|
||||
if (!fbo)
|
||||
return fbo;
|
||||
|
||||
|
||||
@@ -162,6 +162,8 @@ enum class TempFBO {
|
||||
BLIT,
|
||||
// For copies of framebuffers (e.g. shader blending.)
|
||||
COPY,
|
||||
// Used to copy stencil data, means we need a stencil backing.
|
||||
STENCIL,
|
||||
};
|
||||
|
||||
inline Draw::DataFormat GEFormatToThin3D(int geFormat) {
|
||||
|
||||
@@ -1344,7 +1344,7 @@ void ConvertStencilFuncState(GenericStencilFuncState &state) {
|
||||
return;
|
||||
|
||||
// The PSP's mask is reversed (bits not to write.)
|
||||
state.writeMask = (~gstate.pmska) & 0xFF;
|
||||
state.writeMask = (~gstate.getStencilWriteMask()) & 0xFF;
|
||||
|
||||
state.sFail = gstate.getStencilOpSFail();
|
||||
state.zFail = gstate.getStencilOpZFail();
|
||||
|
||||
@@ -324,6 +324,9 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade
|
||||
// Set some options.
|
||||
spirv_cross::CompilerGLSL::Options options;
|
||||
options.version = gl_extensions.GLSLVersion();
|
||||
// macOS OpenGL 4.1 implementation does not support GL_ARB_shading_language_420pack.
|
||||
// Prevent explicit binding location emission enabled in SPIRV-Cross by default.
|
||||
options.enable_420pack_extension = gl_extensions.ARB_shading_language_420pack;
|
||||
glsl.set_common_options(options);
|
||||
// Compile to GLSL, ready to give to GL driver.
|
||||
*dest = glsl.compile();
|
||||
|
||||
@@ -30,16 +30,18 @@ void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bo
|
||||
// Account for the projection viewport adjustment when viewport is too large.
|
||||
auto reverseViewportX = [](float x) {
|
||||
float pspViewport = (x - gstate.getViewportXCenter()) * (1.0f / gstate.getViewportXScale());
|
||||
return (pspViewport - gstate_c.vpXOffset) * gstate_c.vpWidthScale;
|
||||
return (pspViewport * gstate_c.vpWidthScale) - gstate_c.vpXOffset;
|
||||
};
|
||||
auto reverseViewportY = [flipViewport](float y) {
|
||||
float heightScale = gstate_c.vpHeightScale;
|
||||
float yOffset = gstate_c.vpYOffset;
|
||||
if (flipViewport) {
|
||||
// For D3D11 and GLES non-buffered.
|
||||
heightScale = -heightScale;
|
||||
yOffset = -yOffset;
|
||||
}
|
||||
float pspViewport = (y - gstate.getViewportYCenter()) * (1.0f / gstate.getViewportYScale());
|
||||
return (pspViewport - gstate_c.vpYOffset) * heightScale;
|
||||
return (pspViewport * heightScale) - yOffset;
|
||||
};
|
||||
auto reverseViewportZ = [hasNegZ](float z) {
|
||||
float vpZScale = gstate.getViewportZScale();
|
||||
|
||||
@@ -457,7 +457,9 @@ void SoftwareTransform(
|
||||
// If alpha is not allowed to be separate, it must match for both depth/stencil and color. Vulkan requires this.
|
||||
bool alphaMatchesColor = gstate.isClearModeColorMask() == gstate.isClearModeAlphaMask();
|
||||
bool depthMatchesStencil = gstate.isClearModeAlphaMask() == gstate.isClearModeDepthMask();
|
||||
if (params->allowSeparateAlphaClear || (alphaMatchesColor && depthMatchesStencil)) {
|
||||
bool matchingComponents = params->allowSeparateAlphaClear || (alphaMatchesColor && depthMatchesStencil);
|
||||
bool stencilNotMasked = !gstate.isClearModeAlphaMask() || gstate.getStencilWriteMask() == 0x00;
|
||||
if (matchingComponents && stencilNotMasked) {
|
||||
result->color = transformed[1].color0_32;
|
||||
// Need to rescale from a [0, 1] float. This is the final transformed value.
|
||||
result->depth = ToScaledDepthFromIntegerScale((int)(transformed[1].z * 65535.0f));
|
||||
|
||||
@@ -89,7 +89,7 @@ static const u32 textureAlignMask16[16] = {
|
||||
|
||||
u32 GetTextureBufw(int level, u32 texaddr, GETextureFormat format) {
|
||||
// This is a hack to allow for us to draw the huge PPGe texture, which is always in kernel ram.
|
||||
if (texaddr < PSP_GetKernelMemoryEnd())
|
||||
if (texaddr >= PSP_GetKernelMemoryBase() && texaddr < PSP_GetKernelMemoryEnd())
|
||||
return gstate.texbufwidth[level] & 0x1FFF;
|
||||
|
||||
u32 bufw = gstate.texbufwidth[level] & textureAlignMask16[format];
|
||||
|
||||
@@ -127,7 +127,9 @@ GPU_D3D11::~GPU_D3D11() {
|
||||
void GPU_D3D11::CheckGPUFeatures() {
|
||||
u32 features = 0;
|
||||
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
if (!PSP_CoreParameter().compat.flags().DepthRangeHack) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
features |= GPU_SUPPORTS_BLEND_MINMAX;
|
||||
features |= GPU_PREFER_CPU_DOWNLOAD;
|
||||
|
||||
|
||||
@@ -330,7 +330,8 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
||||
// A normal clear will be 2 points, the second point has the color.
|
||||
// We override this value in the pipeline from software transform for clear rectangles.
|
||||
dynState_.stencilRef = 0xFF;
|
||||
keys_.depthStencil.stencilWriteMask = 0xFF;
|
||||
// But we still apply the stencil write mask.
|
||||
keys_.depthStencil.stencilWriteMask = (~gstate.getStencilWriteMask()) & 0xFF;
|
||||
} else {
|
||||
keys_.depthStencil.stencilTestEnable = false;
|
||||
dynState_.useStencil = false;
|
||||
|
||||
+15
-13
@@ -176,21 +176,23 @@ void GPU_DX9::CheckGPUFeatures() {
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
}
|
||||
|
||||
// VS range culling (killing triangles in the vertex shader using NaN) causes problems on Intel.
|
||||
// Also causes problems on old NVIDIA.
|
||||
switch (vendor) {
|
||||
case Draw::GPUVendor::VENDOR_INTEL:
|
||||
break;
|
||||
case Draw::GPUVendor::VENDOR_NVIDIA:
|
||||
// Older NVIDIAs don't seem to like NaNs in their DX9 vertex shaders.
|
||||
// No idea if KEPLER is the right cutoff, but let's go with it.
|
||||
if (NVIDIAGetDeviceGeneration(draw_->GetDeviceCaps().deviceID) >= NV_KEPLER) {
|
||||
if (!PSP_CoreParameter().compat.flags().DepthRangeHack) {
|
||||
// VS range culling (killing triangles in the vertex shader using NaN) causes problems on Intel.
|
||||
// Also causes problems on old NVIDIA.
|
||||
switch (vendor) {
|
||||
case Draw::GPUVendor::VENDOR_INTEL:
|
||||
break;
|
||||
case Draw::GPUVendor::VENDOR_NVIDIA:
|
||||
// Older NVIDIAs don't seem to like NaNs in their DX9 vertex shaders.
|
||||
// No idea if KEPLER is the right cutoff, but let's go with it.
|
||||
if (NVIDIAGetDeviceGeneration(draw_->GetDeviceCaps().deviceID) >= NV_KEPLER) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
break;
|
||||
}
|
||||
|
||||
D3DCAPS9 caps;
|
||||
|
||||
@@ -233,7 +233,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
||||
dxstate.stencilTest.enable();
|
||||
dxstate.stencilOp.set(D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE);
|
||||
dxstate.stencilFunc.set(D3DCMP_ALWAYS, 255, 0xFF);
|
||||
dxstate.stencilMask.set(0xFF);
|
||||
dxstate.stencilMask.set((~gstate.getStencilWriteMask()) & 0xFF);
|
||||
} else {
|
||||
dxstate.stencilTest.disable();
|
||||
}
|
||||
|
||||
@@ -312,8 +312,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
||||
// TODO: Not sure the right way to do this for projection.
|
||||
// This path destroys resolution on older PowerVR no matter what I do if projection is needed,
|
||||
// so we disable it on SGX 540 and lesser, and live with the consequences.
|
||||
bool badPrecision = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_TERRIBLE) != 0;
|
||||
if (needShaderTexClamp && !(doTextureProjection && badPrecision)) {
|
||||
bool terriblePrecision = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_TERRIBLE) != 0;
|
||||
bool clampDisabled = doTextureProjection && terriblePrecision;
|
||||
// Also with terrible precision we can't do wrapping without destroying the image. See #9189
|
||||
if (terriblePrecision && (!id.Bit(FS_BIT_CLAMP_S) || !id.Bit(FS_BIT_CLAMP_T))) {
|
||||
clampDisabled = true;
|
||||
}
|
||||
if (needShaderTexClamp && !clampDisabled) {
|
||||
// We may be clamping inside a larger surface (tex = 64x64, buffer=480x272).
|
||||
// We may also be wrapping in such a surface, or either one in a too-small surface.
|
||||
// Obviously, clamping to a smaller surface won't work. But better to clamp to something.
|
||||
@@ -356,6 +361,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
||||
} else {
|
||||
if (doTextureProjection) {
|
||||
// We don't use textureProj because we need better control and it's probably not much of a savings anyway.
|
||||
// However it is good for precision on older hardware like PowerVR.
|
||||
WRITE(p, " vec2 uv = %s.xy/%s.z;\n vec2 uv_round;\n", texcoord, texcoord);
|
||||
} else {
|
||||
WRITE(p, " vec2 uv = %s.xy;\n vec2 uv_round;\n", texcoord);
|
||||
|
||||
@@ -149,7 +149,9 @@ void GPU_GLES::CheckGPUFeatures() {
|
||||
features |= GPU_SUPPORTS_16BIT_FORMATS;
|
||||
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
if (!PSP_CoreParameter().compat.flags().DepthRangeHack) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
}
|
||||
|
||||
if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) {
|
||||
|
||||
@@ -828,7 +828,7 @@ std::string ShaderManagerGLES::DebugGetShaderString(std::string id, DebugShaderT
|
||||
// as sometimes these features might have an effect on the ID bits.
|
||||
|
||||
#define CACHE_HEADER_MAGIC 0x83277592
|
||||
#define CACHE_VERSION 13
|
||||
#define CACHE_VERSION 14
|
||||
struct CacheHeader {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
|
||||
@@ -277,7 +277,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
||||
framebufferManager_->SetDepthUpdated();
|
||||
}
|
||||
renderManager->SetStencilFunc(gstate.isClearModeAlphaMask(), GL_ALWAYS, 0xFF, 0xFF);
|
||||
renderManager->SetStencilOp(0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
renderManager->SetStencilOp((~gstate.getStencilWriteMask()) & 0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS);
|
||||
} else {
|
||||
// Depth Test
|
||||
|
||||
@@ -168,7 +168,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
||||
|
||||
Draw::Framebuffer *blitFBO = nullptr;
|
||||
if (useBlit) {
|
||||
blitFBO = GetTempFBO(TempFBO::COPY, w, h, Draw::FBO_8888);
|
||||
blitFBO = GetTempFBO(TempFBO::STENCIL, w, h, Draw::FBO_8888);
|
||||
draw_->BindFramebufferAsRenderTarget(blitFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
|
||||
} else if (dstBuffer->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::DONT_CARE });
|
||||
|
||||
+5
-5
@@ -88,7 +88,7 @@
|
||||
<AdditionalIncludeDirectories>..\dx9sdk\Include\DX11;../common;..;../ext;../ext/native;../ext/glew;../ext/snappy;</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@@ -109,7 +109,7 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\dx9sdk\Include\DX11;../common;..;../ext;../ext/native;../ext/glew;../ext/snappy;</AdditionalIncludeDirectories>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
@@ -136,7 +136,7 @@
|
||||
<AdditionalIncludeDirectories>..\dx9sdk\Include\DX11;../common;..;../ext;../ext/native;../ext/glew;../ext/snappy;</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_LIB;NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -162,7 +162,7 @@
|
||||
<AdditionalIncludeDirectories>..\dx9sdk\Include\DX11;../common;..;../ext;../ext/native;../ext/glew;../ext/snappy;</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -390,4 +390,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -562,7 +562,8 @@ static inline Vec4<int> GetTextureFunctionOutput(const Vec4<int>& prim_color, co
|
||||
const __m128 b = _mm_mul_ps(p, t);
|
||||
if (gstate.isColorDoublingEnabled()) {
|
||||
// We double right here, only for modulate. Other tex funcs do not color double.
|
||||
out_rgb.ivec = _mm_cvtps_epi32(_mm_mul_ps(b, _mm_set_ps1(2.0f / 255.0f)));
|
||||
const __m128 doubleColor = _mm_setr_ps(2.0f / 255.0f, 2.0f / 255.0f, 2.0f / 255.0f, 1.0f / 255.0f);
|
||||
out_rgb.ivec = _mm_cvtps_epi32(_mm_mul_ps(b, doubleColor));
|
||||
} else {
|
||||
out_rgb.ivec = _mm_cvtps_epi32(_mm_mul_ps(b, _mm_set_ps1(1.0f / 255.0f)));
|
||||
}
|
||||
|
||||
@@ -129,16 +129,18 @@ VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat
|
||||
VkFormat destFormat = GetClutDestFormat(clutFormat, &componentMapping);
|
||||
int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
|
||||
|
||||
VulkanTexture *vktex = new VulkanTexture(vulkan_);
|
||||
vktex->SetTag("DepalClut");
|
||||
VkCommandBuffer cmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
|
||||
if (!vktex->CreateDirect(cmd, alloc_, texturePixels, 1, 1, destFormat,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, &componentMapping)) {
|
||||
ERROR_LOG(G3D, "Failed to create texture for CLUT");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VkBuffer pushBuffer;
|
||||
uint32_t pushOffset = push_->PushAligned(rawClut, 1024, 4, &pushBuffer);
|
||||
|
||||
VulkanTexture *vktex = new VulkanTexture(vulkan_, alloc_);
|
||||
vktex->SetTag("DepalClut");
|
||||
VkCommandBuffer cmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
|
||||
if (!vktex->CreateDirect(cmd, texturePixels, 1, 1, destFormat,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, &componentMapping)) {
|
||||
Crash();
|
||||
}
|
||||
vktex->UploadMip(cmd, 0, texturePixels, 1, pushBuffer, pushOffset, texturePixels);
|
||||
vktex->EndCreate(cmd);
|
||||
|
||||
|
||||
@@ -148,9 +148,11 @@ void DrawEngineVulkan::InitDeviceObjects() {
|
||||
// if creating and updating them turns out to be expensive.
|
||||
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
|
||||
// We now create descriptor pools on demand, so removed from here.
|
||||
frame_[i].pushUBO = new VulkanPushBuffer(vulkan_, 8 * 1024 * 1024);
|
||||
frame_[i].pushVertex = new VulkanPushBuffer(vulkan_, 2 * 1024 * 1024);
|
||||
frame_[i].pushIndex = new VulkanPushBuffer(vulkan_, 1 * 1024 * 1024);
|
||||
// Note that pushUBO is also used for tessellation data (search for SetPushBuffer), and to upload
|
||||
// the null texture. This should be cleaned up...
|
||||
frame_[i].pushUBO = new VulkanPushBuffer(vulkan_, 8 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
frame_[i].pushVertex = new VulkanPushBuffer(vulkan_, 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
frame_[i].pushIndex = new VulkanPushBuffer(vulkan_, 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
}
|
||||
|
||||
VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
@@ -174,7 +176,7 @@ void DrawEngineVulkan::InitDeviceObjects() {
|
||||
res = vkCreateSampler(device, &samp, nullptr, &nullSampler_);
|
||||
assert(VK_SUCCESS == res);
|
||||
|
||||
vertexCache_ = new VulkanPushBuffer(vulkan_, VERTEX_CACHE_SIZE);
|
||||
vertexCache_ = new VulkanPushBuffer(vulkan_, VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
|
||||
tessDataTransferVulkan = new TessellationDataTransferVulkan(vulkan_);
|
||||
tessDataTransfer = tessDataTransferVulkan;
|
||||
@@ -276,7 +278,7 @@ void DrawEngineVulkan::BeginFrame() {
|
||||
if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) {
|
||||
vertexCache_->Destroy(vulkan_);
|
||||
delete vertexCache_; // orphans the buffers, they'll get deleted once no longer used by an in-flight frame.
|
||||
vertexCache_ = new VulkanPushBuffer(vulkan_, VERTEX_CACHE_SIZE);
|
||||
vertexCache_ = new VulkanPushBuffer(vulkan_, VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
vai_.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -195,9 +195,9 @@ void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFor
|
||||
VkCommandBuffer initCmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
|
||||
|
||||
// There's only ever a few of these alive, don't need to stress the allocator with these big ones.
|
||||
drawPixelsTex_ = new VulkanTexture(vulkan_, nullptr);
|
||||
drawPixelsTex_ = new VulkanTexture(vulkan_);
|
||||
drawPixelsTex_->SetTag("DrawPixels");
|
||||
if (!drawPixelsTex_->CreateDirect(initCmd, width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)) {
|
||||
if (!drawPixelsTex_->CreateDirect(initCmd, nullptr, width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)) {
|
||||
// out of memory?
|
||||
delete drawPixelsTex_;
|
||||
drawPixelsTex_ = nullptr;
|
||||
|
||||
@@ -181,13 +181,19 @@ GPU_Vulkan::~GPU_Vulkan() {
|
||||
void GPU_Vulkan::CheckGPUFeatures() {
|
||||
uint32_t features = 0;
|
||||
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
if (!PSP_CoreParameter().compat.flags().DepthRangeHack) {
|
||||
features |= GPU_SUPPORTS_VS_RANGE_CULLING;
|
||||
}
|
||||
|
||||
switch (vulkan_->GetPhysicalDeviceProperties().properties.vendorID) {
|
||||
case VULKAN_VENDOR_AMD:
|
||||
// Accurate depth is required on AMD (due to reverse-Z driver bug) so we ignore the compat flag to disable it on those. See #9545
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
break;
|
||||
case VULKAN_VENDOR_QUALCOMM:
|
||||
// Accurate depth is required on Adreno too (seems to also have a reverse-Z driver bug).
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
break;
|
||||
case VULKAN_VENDOR_ARM:
|
||||
// Also required on older ARM Mali drivers, like the one on many Galaxy S7.
|
||||
if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth ||
|
||||
@@ -457,7 +463,8 @@ void GPU_Vulkan::InitDeviceObjects() {
|
||||
// Initialize framedata
|
||||
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
|
||||
assert(!frameData_[i].push_);
|
||||
frameData_[i].push_ = new VulkanPushBuffer(vulkan_, 64 * 1024);
|
||||
VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
frameData_[i].push_ = new VulkanPushBuffer(vulkan_, 64 * 1024, usage);
|
||||
}
|
||||
|
||||
VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
||||
@@ -135,7 +135,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
PROFILE_THIS_SCOPE("pipelinebuild");
|
||||
bool useBlendConstant = false;
|
||||
|
||||
VkPipelineColorBlendAttachmentState blend0 = {};
|
||||
VkPipelineColorBlendAttachmentState blend0{};
|
||||
blend0.blendEnable = key.blendEnable;
|
||||
if (key.blendEnable) {
|
||||
blend0.colorBlendOp = (VkBlendOp)key.blendOpColor;
|
||||
@@ -174,7 +174,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
dss.depthWriteEnable = key.depthWriteEnable;
|
||||
}
|
||||
|
||||
VkDynamicState dynamicStates[8];
|
||||
VkDynamicState dynamicStates[8]{};
|
||||
int numDyn = 0;
|
||||
if (key.blendEnable &&
|
||||
(UsesBlendConstant(key.srcAlpha) || UsesBlendConstant(key.srcColor) || UsesBlendConstant(key.destAlpha) || UsesBlendConstant(key.destColor))) {
|
||||
@@ -208,16 +208,14 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
ms.pSampleMask = nullptr;
|
||||
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkPipelineShaderStageCreateInfo ss[2];
|
||||
VkPipelineShaderStageCreateInfo ss[2]{};
|
||||
ss[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
ss[0].pNext = nullptr;
|
||||
ss[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
ss[0].pSpecializationInfo = nullptr;
|
||||
ss[0].module = vs->GetModule();
|
||||
ss[0].pName = "main";
|
||||
ss[0].flags = 0;
|
||||
ss[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
ss[1].pNext = nullptr;
|
||||
ss[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
ss[1].pSpecializationInfo = nullptr;
|
||||
ss[1].module = fs->GetModule();
|
||||
@@ -252,7 +250,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
vertexStride = 36;
|
||||
}
|
||||
|
||||
VkVertexInputBindingDescription ibd;
|
||||
VkVertexInputBindingDescription ibd{};
|
||||
ibd.binding = 0;
|
||||
ibd.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
ibd.stride = vertexStride;
|
||||
@@ -297,7 +295,12 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
VkPipeline pipeline;
|
||||
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
|
||||
if (result != VK_SUCCESS) {
|
||||
_assert_msg_(G3D, false, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||
if (result == VK_INCOMPLETE) {
|
||||
// Bad return value seen on Adreno in Burnout :( Try to ignore?
|
||||
// TODO: Log all the information we can here!
|
||||
} else {
|
||||
_dbg_assert_msg_(G3D, false, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||
}
|
||||
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||
// Create a placeholder to avoid creating over and over if something is broken.
|
||||
VulkanPipeline *nullPipeline = new VulkanPipeline();
|
||||
|
||||
@@ -361,7 +361,7 @@ VulkanFragmentShader *ShaderManagerVulkan::GetFragmentShaderFromModule(VkShaderM
|
||||
// instantaneous.
|
||||
|
||||
#define CACHE_HEADER_MAGIC 0xff51f420
|
||||
#define CACHE_VERSION 16
|
||||
#define CACHE_VERSION 17
|
||||
struct VulkanCacheHeader {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
|
||||
@@ -294,7 +294,8 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
||||
// A normal clear will be 2 points, the second point has the color.
|
||||
// We override this value in the pipeline from software transform for clear rectangles.
|
||||
dynState.stencilRef = 0xFF;
|
||||
dynState.stencilWriteMask = 0xFF;
|
||||
// But we still apply the stencil write mask.
|
||||
dynState.stencilWriteMask = (~gstate.getStencilWriteMask()) & 0xFF;
|
||||
} else {
|
||||
key.stencilTestEnable = false;
|
||||
key.stencilCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
|
||||
@@ -351,7 +351,7 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr
|
||||
depalShaderCache_->SetPushBuffer(drawEngine_->GetPushBufferForTextureData());
|
||||
const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();
|
||||
VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_);
|
||||
drawEngine_->SetDepalTexture(clutTexture->GetImageView());
|
||||
drawEngine_->SetDepalTexture(clutTexture ? clutTexture->GetImageView() : VK_NULL_HANDLE);
|
||||
// Only point filtering enabled.
|
||||
samplerKey.magFilt = false;
|
||||
samplerKey.minFilt = false;
|
||||
@@ -604,7 +604,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||
|
||||
{
|
||||
delete entry->vkTex;
|
||||
entry->vkTex = new VulkanTexture(vulkan_, allocator_);
|
||||
entry->vkTex = new VulkanTexture(vulkan_);
|
||||
VulkanTexture *image = entry->vkTex;
|
||||
|
||||
const VkComponentMapping *mapping;
|
||||
@@ -630,7 +630,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||
snprintf(texName, sizeof(texName), "Texture%08x", entry->addr);
|
||||
image->SetTag(texName);
|
||||
|
||||
bool allocSuccess = image->CreateDirect(cmdInit, w * scaleFactor, h * scaleFactor, maxLevel + 1, actualFmt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping);
|
||||
bool allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevel + 1, actualFmt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping);
|
||||
if (!allocSuccess && !lowMemoryMode_) {
|
||||
WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode");
|
||||
lowMemoryMode_ = true;
|
||||
@@ -649,7 +649,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||
scaleFactor = 1;
|
||||
actualFmt = dstFmt;
|
||||
|
||||
allocSuccess = image->CreateDirect(cmdInit, w * scaleFactor, h * scaleFactor, maxLevel + 1, actualFmt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping);
|
||||
allocSuccess = image->CreateDirect(cmdInit, allocator_, w * scaleFactor, h * scaleFactor, maxLevel + 1, actualFmt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping);
|
||||
}
|
||||
|
||||
if (!allocSuccess) {
|
||||
|
||||
+4
-1
@@ -119,6 +119,9 @@ void System_SendMessage(const char *command, const char *parameter) {
|
||||
QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFileEvent));
|
||||
} else if (!strcmp(command, "browse_folder")) {
|
||||
QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent));
|
||||
} else if (!strcmp(command, "graphics_restart")) {
|
||||
// Should find a way to properly restart the app.
|
||||
qApp->exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +405,7 @@ bool MainUI::event(QEvent *e) {
|
||||
if (QFile::exists(fileName)) {
|
||||
QDir newPath;
|
||||
g_Config.currentDirectory = newPath.filePath(fileName).toStdString();
|
||||
g_Config.Save();
|
||||
g_Config.Save("browseFileEvent");
|
||||
|
||||
NativeMessageReceived("boot", fileName.toStdString().c_str());
|
||||
}
|
||||
|
||||
@@ -30,6 +30,36 @@ No BIOS file required to play, PPSSPP is an "HLE" emulator. Default settings ba
|
||||
Also includes a really awful hack for MOHH2 multiplayer(MOHH1 works fine without it;p).
|
||||
~ LunaMoo
|
||||
|
||||
What's new in 1.8.0
|
||||
-------------------
|
||||
* Avoid crash when starting PPSSPP due to bad AMD Vulkan drivers (#11802)
|
||||
* PowerVR Vulkan display corruption fixed (#11744, #11747)
|
||||
* Naruto Shippuden 3 hang fixed (#11780)
|
||||
* Fixes to various lighting bugs (#11567, #11574, #11577)
|
||||
* Fix control issue in Sonic Rivals and Rock Band (#11878, #11798, #11879)
|
||||
* Significant performance improvement in Earth Defense Force 2 (#11172)
|
||||
* Fix "real clock sync" setting (helps with latency for music games - #11813)
|
||||
* More speed in FF4 effects and other generated curves (#11425)
|
||||
* Support for resizing Vulkan on Linux (#11451)
|
||||
* Improved support for GLES on Linux/IoT (#11507, #11537, #11541, #11632, #11746, #11806, #11845)
|
||||
* Percentage based frameskipping (#11523)
|
||||
* DXT accuracy improved, fixing thick white line in Gran Turismo sky (#11530)
|
||||
* Fix Motorstorm freeze on non-Windows (#11618)
|
||||
* Faster block transfer in some games like Digimon Adventures (#11531, #11553, #11776)
|
||||
* Blending optimizations and improvements (#11543, #11620)
|
||||
* Improve D3D11 rendering issues (#11584)
|
||||
* Change default graphics backend to D3D11 or OpenGL (#11621, #11658)
|
||||
* Remove some outdated settings (#11665, #11666, #11667)
|
||||
* Fix remote disc streaming with ipv6 (#11689, #11700)
|
||||
* Vulkan: Workarounds for some driver bugs for 5xx series Qualcomm GPUs (#11691, #11694)
|
||||
* Fix some Qt port issues with recent performance improvements (#11720, #11807, #11808)
|
||||
* UWP Xbox One: fix X/Back button confusion (#11740)
|
||||
* Fix Formula 1 2006 timing issue (#11767)
|
||||
* Fixes and workarounds for some vertex range culling bugs that broke a few games (#11785, #11859), and disable it on older GPUs (#11712, #11773, #11787)
|
||||
* Android: Allow putting PSP storage on custom paths like SD cards (#11812)
|
||||
* Corrected vocp instruction, fixing models in Artdink games (#11822, #11835)
|
||||
* Bundle SDL in binary for macOS builds (#11831)
|
||||
* Prevent keeping games open on Windows (#11842)
|
||||
|
||||
What's new in 1.7.3/1.7.4/1.7.5
|
||||
-------------------
|
||||
|
||||
@@ -27,10 +27,9 @@ static Display* g_Display = NULL;
|
||||
#endif
|
||||
static NativeWindowType g_Window = (NativeWindowType)NULL;
|
||||
|
||||
int8_t CheckEGLErrors(const std::string& file, uint16_t line) {
|
||||
int CheckEGLErrors(const char *file, int line) {
|
||||
EGLenum error;
|
||||
std::string errortext;
|
||||
|
||||
const char *errortext = "unknown";
|
||||
error = eglGetError();
|
||||
switch (error)
|
||||
{
|
||||
@@ -50,7 +49,7 @@ int8_t CheckEGLErrors(const std::string& file, uint16_t line) {
|
||||
case EGL_BAD_NATIVE_WINDOW: errortext = "EGL_BAD_NATIVE_WINDOW"; break;
|
||||
default: errortext = "unknown"; break;
|
||||
}
|
||||
printf( "ERROR: EGL Error detected in file %s at line %d: %s (0x%X)\n", file.c_str(), line, errortext.c_str(), error );
|
||||
printf( "ERROR: EGL Error %s detected in file %s at line %d (0x%X)\n", errortext, file, line, error );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -108,8 +107,13 @@ EGLConfig EGL_FindConfig(int *contextVersion) {
|
||||
return val;
|
||||
};
|
||||
|
||||
int colorScore = readConfig(EGL_RED_SIZE) + readConfig(EGL_BLUE_SIZE) + readConfig(EGL_GREEN_SIZE);
|
||||
int alphaScore = readConfig(EGL_ALPHA_SIZE);
|
||||
// We don't want HDR modes with more than 8 bits per component.
|
||||
auto readConfigMax = [&](EGLint attr, EGLint m) -> EGLint {
|
||||
EGLint val = readConfig(attr);
|
||||
return val > m ? 1 : val; // why not 0?
|
||||
};
|
||||
int colorScore = readConfigMax(EGL_RED_SIZE, 8) + readConfigMax(EGL_BLUE_SIZE, 8) + readConfigMax(EGL_GREEN_SIZE, 8);
|
||||
int alphaScore = readConfigMax(EGL_ALPHA_SIZE, 8);
|
||||
int depthScore = readConfig(EGL_DEPTH_SIZE);
|
||||
int levelScore = readConfig(EGL_LEVEL) == 0 ? 100 : 0;
|
||||
int samplesScore = readConfig(EGL_SAMPLES) == 0 ? 100 : 0;
|
||||
@@ -120,6 +124,11 @@ EGLConfig EGL_FindConfig(int *contextVersion) {
|
||||
EGLint caveat = readConfig(EGL_CONFIG_CAVEAT);
|
||||
int caveatScore = caveat == EGL_NONE ? 100 : (caveat == EGL_NON_CONFORMANT_CONFIG ? 50 : 0);
|
||||
|
||||
#ifndef USING_FBDEV
|
||||
EGLint surfaceType = readConfig(EGL_SURFACE_TYPE);
|
||||
int surfaceScore = (surfaceType & EGL_WINDOW_BIT) ? 100 : 0;
|
||||
#endif
|
||||
|
||||
EGLint renderable = readConfig(EGL_RENDERABLE_TYPE);
|
||||
bool renderableGLES3 = (renderable & EGL_OPENGL_ES3_BIT_KHR) != 0;
|
||||
bool renderableGLES2 = (renderable & EGL_OPENGL_ES2_BIT) != 0;
|
||||
@@ -138,11 +147,15 @@ EGLConfig EGL_FindConfig(int *contextVersion) {
|
||||
|
||||
int score = 0;
|
||||
// Here's a good place to play with the weights to pick a better config.
|
||||
score += (colorScore + alphaScore) * 10;
|
||||
score += colorScore * 10 + alphaScore * 2;
|
||||
score += depthScore * 5 + stencilScore;
|
||||
score += levelScore + samplesScore + sampleBufferScore + transparentScore;
|
||||
score += caveatScore + renderableScoreGLES + renderableScoreGL;
|
||||
|
||||
#ifndef USING_FBDEV
|
||||
score += surfaceScore;
|
||||
#endif
|
||||
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
best = config;
|
||||
@@ -154,11 +167,12 @@ EGLConfig EGL_FindConfig(int *contextVersion) {
|
||||
return best;
|
||||
}
|
||||
|
||||
int8_t EGL_Init() {
|
||||
int8_t EGL_Init(SDL_Window *window) {
|
||||
int contextVersion = 0;
|
||||
EGLConfig eglConfig = EGL_FindConfig(&contextVersion);
|
||||
if (!eglConfig) {
|
||||
EGL_ERROR("Unable to find a usable EGL config.", true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EGLint contextAttributes[] = {
|
||||
@@ -172,22 +186,28 @@ int8_t EGL_Init() {
|
||||
g_eglContext = eglCreateContext(g_eglDisplay, eglConfig, nullptr, contextAttributes);
|
||||
if (g_eglContext == EGL_NO_CONTEXT) {
|
||||
EGL_ERROR("Unable to create GLES context!", true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined(USING_FBDEV) && !defined(__APPLE__)
|
||||
//Get the SDL window handle
|
||||
// Get the SDL window handle
|
||||
SDL_SysWMinfo sysInfo; //Will hold our Window information
|
||||
SDL_VERSION(&sysInfo.version); //Set SDL version
|
||||
SDL_GetWindowWMInfo(window, &sysInfo);
|
||||
g_Window = (NativeWindowType)sysInfo.info.x11.window;
|
||||
#else
|
||||
g_Window = (NativeWindowType)NULL;
|
||||
#endif
|
||||
g_eglSurface = eglCreateWindowSurface(g_eglDisplay, eglConfig, g_Window, nullptr);
|
||||
if (g_eglSurface == EGL_NO_SURFACE)
|
||||
if (g_eglSurface == EGL_NO_SURFACE) {
|
||||
EGL_ERROR("Unable to create EGL surface!", true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext) != EGL_TRUE)
|
||||
if (eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext) != EGL_TRUE) {
|
||||
EGL_ERROR("Unable to make GLES context current.", true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -296,7 +316,10 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std:
|
||||
SDL_ShowWindow(window);
|
||||
|
||||
#ifdef USING_EGL
|
||||
EGL_Init();
|
||||
if (EGL_Init(window) != 0) {
|
||||
printf("EGL_Init() failed\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef USING_GLES2
|
||||
|
||||
+6
-4
@@ -1,6 +1,5 @@
|
||||
// SDL/EGL implementation of the framework.
|
||||
// This is quite messy due to platform-specific implementations and #ifdef's.
|
||||
// Note: SDL1.2 implementation is deprecated and will soon be replaced by SDL2.0.
|
||||
// If your platform is not supported, it is suggested to use Qt instead.
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -116,6 +115,9 @@ void System_SendMessage(const char *command, const char *parameter) {
|
||||
} else if (!strcmp(command, "finish")) {
|
||||
// Do a clean exit
|
||||
g_QuitRequested = true;
|
||||
} else if (!strcmp(command, "graphics_restart")) {
|
||||
// Not sure how we best do this, but do a clean exit, better than being stuck in a bad state.
|
||||
g_QuitRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,9 +350,9 @@ int main(int argc, char *argv[]) {
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||
|
||||
if (VulkanMayBeAvailable()) {
|
||||
printf("Vulkan might be available.\n");
|
||||
printf("DEBUG: Vulkan might be available.\n");
|
||||
} else {
|
||||
printf("Vulkan is not available.\n");
|
||||
printf("DEBUG: Vulkan is not available, not using Vulkan.\n");
|
||||
}
|
||||
|
||||
int set_xres = -1;
|
||||
@@ -618,7 +620,7 @@ int main(int argc, char *argv[]) {
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED: // better than RESIZED, more general
|
||||
{
|
||||
Uint32 window_flags = SDL_GetWindowFlags(window);
|
||||
bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN);
|
||||
|
||||
@@ -25,16 +25,11 @@ public:
|
||||
}
|
||||
|
||||
void Resize() override {
|
||||
/*
|
||||
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
vulkan_->DestroyObjects();
|
||||
// TODO: Take from real window dimensions
|
||||
int width = 1024;
|
||||
int height = 768;
|
||||
vulkan_->ReinitSurface(width, height);
|
||||
vulkan_->ReinitSurface();
|
||||
vulkan_->InitObjects();
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
*/
|
||||
}
|
||||
|
||||
void SwapInterval(int interval) override {
|
||||
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
PPSSPP="${1}"
|
||||
PPSSPPSDL="${PPSSPP}/Contents/MacOS/PPSSPPSDL"
|
||||
|
||||
if [ ! -f "${PPSSPPSDL}" ]; then
|
||||
echo "No such file: ${PPSSPPSDL}!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SDL=$(otool -L "${PPSSPPSDL}" | grep -v @executable_path | grep -Eo /.+libSDL.+dylib)
|
||||
if [ "${SDL}" = "" ]; then
|
||||
echo "SDL is already bundled/unused."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -f "${SDL}" ]; then
|
||||
echo "Cannot locate SDL: ${SDL}!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Installing SDL from ${SDL}..."
|
||||
|
||||
SDLNAME=$(basename "${SDL}")
|
||||
mkdir -p "${PPSSPP}/Contents/Frameworks" || exit 1
|
||||
cp -r "$SDL" "${PPSSPP}/Contents/Frameworks" || exit 1
|
||||
install_name_tool -change "${SDL}" "@executable_path/../Frameworks/${SDLNAME}" "${PPSSPPSDL}" || exit 1
|
||||
@@ -44,7 +44,7 @@ void Combo_keyScreen::CreateViews() {
|
||||
static const int comboKeyImages[5] = {
|
||||
I_1, I_2, I_3, I_4, I_5,
|
||||
};
|
||||
|
||||
|
||||
comboselect = new ChoiceStrip(ORIENT_VERTICAL, new AnchorLayoutParams(10, 10, NONE, NONE));
|
||||
comboselect->SetSpacing(10);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -169,7 +169,7 @@ void Combo_keyScreen::onFinish(DialogResult result) {
|
||||
g_Config.iCombokey4 = arrayToInt(array);
|
||||
break;
|
||||
}
|
||||
g_Config.Save();
|
||||
g_Config.Save("Combo_keyScreen::onFInish");
|
||||
}
|
||||
|
||||
UI::EventReturn Combo_keyScreen::ChoiceEventHandler::onChoiceClick(UI::EventParams &e){
|
||||
|
||||
@@ -431,8 +431,8 @@ class JoystickHistoryView : public UI::InertView {
|
||||
public:
|
||||
JoystickHistoryView(int xAxis, int xDevice, int xDir, int yAxis, int yDevice, int yDir, UI::LayoutParams *layoutParams = nullptr)
|
||||
: UI::InertView(layoutParams),
|
||||
xAxis_(xAxis), xDevice_(xDevice), xDir_(xDir),
|
||||
yAxis_(yAxis), yDevice_(yDevice), yDir_(yDir),
|
||||
xAxis_(xAxis), xDir_(xDir),
|
||||
yAxis_(yAxis), yDir_(yDir),
|
||||
curX_(0.0f), curY_(0.0f),
|
||||
maxCount_(500) {}
|
||||
void Draw(UIContext &dc) override;
|
||||
@@ -455,10 +455,8 @@ private:
|
||||
};
|
||||
|
||||
int xAxis_;
|
||||
int xDevice_;
|
||||
int xDir_;
|
||||
int yAxis_;
|
||||
int yDevice_;
|
||||
int yDir_;
|
||||
|
||||
float curX_;
|
||||
|
||||
@@ -173,7 +173,7 @@ void DisplayLayoutScreen::resized() {
|
||||
}
|
||||
|
||||
void DisplayLayoutScreen::onFinish(DialogResult reason) {
|
||||
g_Config.Save();
|
||||
g_Config.Save("DisplayLayoutScreen::onFinish");
|
||||
}
|
||||
|
||||
UI::EventReturn DisplayLayoutScreen::OnCenter(UI::EventParams &e) {
|
||||
|
||||
+2
-19
@@ -381,10 +381,7 @@ static void AfterStateBoot(SaveState::Status status, const std::string &message,
|
||||
void EmuScreen::sendMessage(const char *message, const char *value) {
|
||||
// External commands, like from the Windows UI.
|
||||
if (!strcmp(message, "pause") && screenManager()->topScreen() == this) {
|
||||
releaseButtons();
|
||||
screenManager()->push(new GamePauseScreen(gamePath_));
|
||||
} else if (!strcmp(message, "lost_focus")) {
|
||||
releaseButtons();
|
||||
} else if (!strcmp(message, "stop")) {
|
||||
// We will push MainScreen in update().
|
||||
PSP_Shutdown();
|
||||
@@ -420,15 +417,12 @@ void EmuScreen::sendMessage(const char *message, const char *value) {
|
||||
RecreateViews();
|
||||
} else if (!strcmp(message, "control mapping") && screenManager()->topScreen() == this) {
|
||||
UpdateUIState(UISTATE_PAUSEMENU);
|
||||
releaseButtons();
|
||||
screenManager()->push(new ControlMappingScreen());
|
||||
} else if (!strcmp(message, "display layout editor") && screenManager()->topScreen() == this) {
|
||||
UpdateUIState(UISTATE_PAUSEMENU);
|
||||
releaseButtons();
|
||||
screenManager()->push(new DisplayLayoutScreen());
|
||||
} else if (!strcmp(message, "settings") && screenManager()->topScreen() == this) {
|
||||
UpdateUIState(UISTATE_PAUSEMENU);
|
||||
releaseButtons();
|
||||
screenManager()->push(new GameSettingsScreen(gamePath_));
|
||||
} else if (!strcmp(message, "gpu dump next frame")) {
|
||||
if (gpu)
|
||||
@@ -1023,7 +1017,6 @@ void EmuScreen::CreateViews() {
|
||||
}
|
||||
|
||||
UI::EventReturn EmuScreen::OnDevTools(UI::EventParams ¶ms) {
|
||||
releaseButtons();
|
||||
I18NCategory *dev = GetI18NCategory("Developer");
|
||||
DevMenu *devMenu = new DevMenu(dev);
|
||||
if (params.v)
|
||||
@@ -1062,8 +1055,8 @@ void EmuScreen::update() {
|
||||
return;
|
||||
}
|
||||
I18NCategory *err = GetI18NCategory("Error");
|
||||
std::string errLoadingFile = err->T("Error loading file", "Could not load game");
|
||||
|
||||
std::string errLoadingFile = gamePath_ + "\n";
|
||||
errLoadingFile.append(err->T("Error loading file", "Could not load game"));
|
||||
errLoadingFile.append(" ");
|
||||
errLoadingFile.append(err->T(errorMessage_.c_str()));
|
||||
|
||||
@@ -1082,7 +1075,6 @@ void EmuScreen::update() {
|
||||
// This is here to support the iOS on screen back button.
|
||||
if (pauseTrigger_) {
|
||||
pauseTrigger_ = false;
|
||||
releaseButtons();
|
||||
screenManager()->push(new GamePauseScreen(gamePath_));
|
||||
}
|
||||
|
||||
@@ -1394,15 +1386,6 @@ void EmuScreen::autoLoad() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add generic loss-of-focus handling for Screens, use this.
|
||||
void EmuScreen::releaseButtons() {
|
||||
TouchInput input;
|
||||
input.flags = TOUCH_RELEASE_ALL;
|
||||
input.timestamp = time_now_d();
|
||||
input.id = 0;
|
||||
touch(input);
|
||||
}
|
||||
|
||||
void EmuScreen::resized() {
|
||||
RecreateViews();
|
||||
}
|
||||
@@ -66,8 +66,6 @@ private:
|
||||
void setVKeyAnalogX(int stick, int virtualKeyMin, int virtualKeyMax);
|
||||
void setVKeyAnalogY(int stick, int virtualKeyMin, int virtualKeyMax);
|
||||
|
||||
void releaseButtons();
|
||||
|
||||
void autoLoad();
|
||||
void checkPowerDown();
|
||||
|
||||
|
||||
+7
-17
@@ -88,6 +88,7 @@ bool GameInfo::Delete() {
|
||||
case IdentifiedFileType::ARCHIVE_RAR:
|
||||
case IdentifiedFileType::ARCHIVE_ZIP:
|
||||
case IdentifiedFileType::ARCHIVE_7Z:
|
||||
case IdentifiedFileType::PPSSPP_GE_DUMP:
|
||||
{
|
||||
const std::string &fileToRemove = filePath_;
|
||||
File::Delete(fileToRemove);
|
||||
@@ -110,27 +111,11 @@ bool GameInfo::Delete() {
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t GetDirectoryRecursiveSize(const std::string &path) {
|
||||
std::vector<FileInfo> fileInfo;
|
||||
getFilesInDir(path.c_str(), &fileInfo);
|
||||
int64_t sizeSum = 0;
|
||||
// Note: getFileInDir does not fill in fileSize properly.
|
||||
for (size_t i = 0; i < fileInfo.size(); i++) {
|
||||
FileInfo finfo;
|
||||
getFileInfo(fileInfo[i].fullName.c_str(), &finfo);
|
||||
if (!finfo.isDirectory)
|
||||
sizeSum += finfo.size;
|
||||
else
|
||||
sizeSum += GetDirectoryRecursiveSize(finfo.fullName);
|
||||
}
|
||||
return sizeSum;
|
||||
}
|
||||
|
||||
u64 GameInfo::GetGameSizeInBytes() {
|
||||
switch (fileType) {
|
||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
|
||||
return GetDirectoryRecursiveSize(ResolvePBPDirectory(filePath_));
|
||||
return getDirectoryRecursiveSize(ResolvePBPDirectory(filePath_), nullptr, GETFILES_GETHIDDEN);
|
||||
|
||||
default:
|
||||
return GetFileLoader()->FileSize();
|
||||
@@ -229,6 +214,11 @@ bool GameInfo::LoadFromPath(const std::string &gamePath) {
|
||||
}
|
||||
|
||||
std::shared_ptr<FileLoader> GameInfo::GetFileLoader() {
|
||||
if (filePath_.empty()) {
|
||||
// Happens when workqueue tries to figure out priorities in PrioritizedWorkQueue::Pop(),
|
||||
// because priority() calls GetFileLoader()... gnarly.
|
||||
return fileLoader;
|
||||
}
|
||||
if (!fileLoader) {
|
||||
fileLoader.reset(ConstructFileLoader(filePath_));
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ protected:
|
||||
// Note: this can change while loading, use GetTitle().
|
||||
std::string title;
|
||||
|
||||
// TODO: Get rid of this shared_ptr and managae lifetime better instead.
|
||||
std::shared_ptr<FileLoader> fileLoader;
|
||||
std::string filePath_;
|
||||
|
||||
|
||||
@@ -1142,7 +1142,7 @@ void GameSettingsScreen::onFinish(DialogResult result) {
|
||||
|
||||
Reporting::Enable(enableReports_, "report.ppsspp.org");
|
||||
Reporting::UpdateConfig();
|
||||
g_Config.Save();
|
||||
g_Config.Save("GameSettingsScreen::onFinish");
|
||||
if (editThenRestore_) {
|
||||
g_Config.unloadGameConfig();
|
||||
}
|
||||
@@ -1215,7 +1215,7 @@ void GameSettingsScreen::CallbackMemstickFolder(bool yes) {
|
||||
writeDataToFile(true, pendingMemstickFolder_.c_str(), pendingMemstickFolder_.size(), memstickDirFile.c_str());
|
||||
// Save so the settings, at least, are transferred.
|
||||
g_Config.memStickDirectory = pendingMemstickFolder_ + "/";
|
||||
g_Config.Save();
|
||||
g_Config.Save("MemstickPathChanged");
|
||||
screenManager()->RecreateAllViews();
|
||||
}
|
||||
}
|
||||
@@ -1227,7 +1227,7 @@ void GameSettingsScreen::CallbackRenderingBackend(bool yes) {
|
||||
if (yes) {
|
||||
// Extra save here to make sure the choice really gets saved even if there are shutdown bugs in
|
||||
// the GPU backend code.
|
||||
g_Config.Save();
|
||||
g_Config.Save("GameSettingsScreen::RenderingBackendYes");
|
||||
System_SendMessage("graphics_restart", "");
|
||||
} else {
|
||||
g_Config.iGPUBackend = (int)GetGPUBackend();
|
||||
@@ -1240,7 +1240,7 @@ void GameSettingsScreen::CallbackRenderingDevice(bool yes) {
|
||||
if (yes) {
|
||||
// Extra save here to make sure the choice really gets saved even if there are shutdown bugs in
|
||||
// the GPU backend code.
|
||||
g_Config.Save();
|
||||
g_Config.Save("GameSettingsScreen::RenderingDeviceYes");
|
||||
System_SendMessage("graphics_restart", "");
|
||||
} else {
|
||||
std::string *deviceNameSetting = GPUDeviceNameSetting();
|
||||
@@ -1473,7 +1473,7 @@ void DeveloperToolsScreen::CreateViews() {
|
||||
}
|
||||
|
||||
void DeveloperToolsScreen::onFinish(DialogResult result) {
|
||||
g_Config.Save();
|
||||
g_Config.Save("DeveloperToolsScreen::onFinish");
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-12
@@ -114,8 +114,8 @@ static bool IsTempPath(const std::string &str) {
|
||||
|
||||
class GameButton : public UI::Clickable {
|
||||
public:
|
||||
GameButton(const std::string &gamePath, bool gridStyle, UI::LayoutParams *layoutParams = 0)
|
||||
: UI::Clickable(layoutParams), gridStyle_(gridStyle), gamePath_(gamePath), holdStart_(0), holdEnabled_(true) {}
|
||||
GameButton(const std::string &gamePath, bool gridStyle, UI::LayoutParams *layoutParams = 0)
|
||||
: UI::Clickable(layoutParams), gridStyle_(gridStyle), gamePath_(gamePath) {}
|
||||
|
||||
void Draw(UIContext &dc) override;
|
||||
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
|
||||
@@ -157,8 +157,12 @@ public:
|
||||
}
|
||||
} else if (hovering_ && key.deviceId == DEVICE_ID_MOUSE && key.keyCode == NKCODE_EXT_MOUSEBUTTON_2) {
|
||||
// If it's the right mouse button, and it's not otherwise mapped, show the info also.
|
||||
if (key.flags & KEY_UP) {
|
||||
if (key.flags & KEY_DOWN) {
|
||||
showInfoPressed_ = true;
|
||||
}
|
||||
if ((key.flags & KEY_UP) && showInfoPressed_) {
|
||||
showInfo = true;
|
||||
showInfoPressed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,9 +210,10 @@ private:
|
||||
std::string gamePath_;
|
||||
std::string title_;
|
||||
|
||||
double holdStart_;
|
||||
bool holdEnabled_;
|
||||
bool hovering_;
|
||||
double holdStart_ = 0.0;
|
||||
bool holdEnabled_ = true;
|
||||
bool showInfoPressed_ = false;
|
||||
bool hovering_ = false;
|
||||
};
|
||||
|
||||
void GameButton::Draw(UIContext &dc) {
|
||||
@@ -404,7 +409,7 @@ void DirButton::Draw(UIContext &dc) {
|
||||
if (text == "..") {
|
||||
image = I_UP_DIRECTORY;
|
||||
}
|
||||
|
||||
|
||||
float tw, th;
|
||||
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, text.c_str(), &tw, &th, 0);
|
||||
|
||||
@@ -802,10 +807,10 @@ void MainScreen::CreateViews() {
|
||||
scrollHomebrew->SetTag("MainScreenHomebrew");
|
||||
|
||||
GameBrowser *tabAllGames = new GameBrowser(g_Config.currentDirectory, true, &g_Config.bGridView2,
|
||||
mm->T("How to get games"), "http://www.ppsspp.org/getgames.html", 0,
|
||||
mm->T("How to get games"), "https://www.ppsspp.org/getgames.html", 0,
|
||||
new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
GameBrowser *tabHomebrew = new GameBrowser(GetSysDirectory(DIRECTORY_GAME), false, &g_Config.bGridView3,
|
||||
mm->T("How to get homebrew & demos", "How to get homebrew && demos"), "http://www.ppsspp.org/gethomebrew.html",
|
||||
mm->T("How to get homebrew & demos", "How to get homebrew && demos"), "https://www.ppsspp.org/gethomebrew.html",
|
||||
FLAG_HOMEBREWSTOREBUTTON,
|
||||
new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
||||
@@ -904,7 +909,7 @@ void MainScreen::CreateViews() {
|
||||
TextView *ver = rightColumnItems->Add(new TextView(versionString, new LinearLayoutParams(Margins(70, -6, 0, 0))));
|
||||
ver->SetSmall(true);
|
||||
ver->SetClip(false);
|
||||
#if defined(USING_WIN_UI) || defined(USING_QT_UI)
|
||||
#if defined(USING_WIN_UI) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP)
|
||||
rightColumnItems->Add(new Choice(mm->T("Load","Load...")))->OnClick.Handle(this, &MainScreen::OnLoadFile);
|
||||
#endif
|
||||
rightColumnItems->Add(new Choice(mm->T("Game Settings", "Settings")))->OnClick.Handle(this, &MainScreen::OnGameSettings);
|
||||
@@ -1203,7 +1208,7 @@ UI::EventReturn MainScreen::OnExit(UI::EventParams &e) {
|
||||
System_SendMessage("finish", "");
|
||||
|
||||
// However, let's make sure the config was saved, since it may not have been.
|
||||
g_Config.Save();
|
||||
g_Config.Save("MainScreen::OnExit");
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID_NDK_PROFILER
|
||||
@@ -1271,7 +1276,7 @@ void UmdReplaceScreen::CreateViews() {
|
||||
scrollAllGames->SetTag("UmdReplaceAllGames");
|
||||
|
||||
GameBrowser *tabAllGames = new GameBrowser(g_Config.currentDirectory, true, &g_Config.bGridView2,
|
||||
mm->T("How to get games"), "http://www.ppsspp.org/getgames.html", 0,
|
||||
mm->T("How to get games"), "https://www.ppsspp.org/getgames.html", 0,
|
||||
new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
||||
scrollAllGames->Add(tabAllGames);
|
||||
|
||||
+1
-1
@@ -507,7 +507,7 @@ void LogoScreen::render() {
|
||||
int ppsspp_org_y = yres / 2 + 130;
|
||||
dc.DrawText("www.ppsspp.org", bounds.centerX(), ppsspp_org_y, textColor, ALIGN_CENTER);
|
||||
|
||||
#if (defined(_WIN32) && !PPSSPP_PLATFORM(UWP)) || PPSSPP_PLATFORM(ANDROID)
|
||||
#if (defined(_WIN32) && !PPSSPP_PLATFORM(UWP)) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX)
|
||||
// Draw the graphics API, except on UWP where it's always D3D11
|
||||
std::string apiName = screenManager()->getDrawContext()->GetInfoString(InfoField::APINAME);
|
||||
dc.DrawText(gr->T(apiName), bounds.centerX(), ppsspp_org_y + 50, textColor, ALIGN_CENTER);
|
||||
|
||||
+3
-3
@@ -401,7 +401,7 @@ static void CheckFailedGPUBackends() {
|
||||
writeStringToFile(true, g_Config.sFailedGPUBackends, cache.c_str());
|
||||
} else {
|
||||
// Just save immediately, since we have storage.
|
||||
g_Config.Save();
|
||||
g_Config.Save("got storage permission");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ static void ClearFailedGPUBackends() {
|
||||
if (System_GetPropertyBool(SYSPROP_SUPPORTS_PERMISSIONS)) {
|
||||
File::Delete(GetSysDirectory(DIRECTORY_APP_CACHE) + "/FailedGraphicsBackends.txt");
|
||||
} else {
|
||||
g_Config.Save();
|
||||
g_Config.Save("clearFailedGPUBackends");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1298,7 +1298,7 @@ void NativeShutdown() {
|
||||
delete host;
|
||||
host = nullptr;
|
||||
#endif
|
||||
g_Config.Save();
|
||||
g_Config.Save("NativeShutdown");
|
||||
|
||||
// Avoid shutting this down when restarting core.
|
||||
if (!restarting)
|
||||
|
||||
+3
-3
@@ -330,7 +330,7 @@ EventReturn ReportScreen::HandleSubmit(EventParams &e) {
|
||||
|
||||
if (Reporting::Enable(enableReporting_, "report.ppsspp.org")) {
|
||||
Reporting::UpdateConfig();
|
||||
g_Config.Save();
|
||||
g_Config.Save("ReportScreen::HandleSubmit");
|
||||
}
|
||||
|
||||
std::string filename = includeScreenshot_ ? screenshotFilename_ : "";
|
||||
@@ -341,7 +341,7 @@ EventReturn ReportScreen::HandleSubmit(EventParams &e) {
|
||||
}
|
||||
|
||||
EventReturn ReportScreen::HandleBrowser(EventParams &e) {
|
||||
const std::string url = "http://" + Reporting::ServerHost() + "/";
|
||||
const std::string url = "https://" + Reporting::ServerHost() + "/";
|
||||
LaunchBrowser(url.c_str());
|
||||
return EVENT_DONE;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ void ReportFinishScreen::ShowSuggestions() {
|
||||
}
|
||||
|
||||
UI::EventReturn ReportFinishScreen::HandleViewFeedback(UI::EventParams &e) {
|
||||
const std::string url = "http://" + Reporting::ServerHost() + "/game/" + Reporting::CurrentGameID();
|
||||
const std::string url = "https://" + Reporting::ServerHost() + "/game/" + Reporting::CurrentGameID();
|
||||
LaunchBrowser(url.c_str());
|
||||
return EVENT_DONE;
|
||||
}
|
||||
+38
-24
@@ -132,8 +132,9 @@ public:
|
||||
: UI::LinearLayout(orientation, layoutParams) {
|
||||
}
|
||||
|
||||
void SetCompare(CompareFunc lessFunc, DoneFunc) {
|
||||
void SetCompare(CompareFunc lessFunc, DoneFunc doneFunc) {
|
||||
lessFunc_ = lessFunc;
|
||||
doneFunc_ = doneFunc;
|
||||
}
|
||||
|
||||
void Update() override;
|
||||
@@ -336,43 +337,56 @@ bool SavedataBrowser::ByFilename(const UI::View *v1, const UI::View *v2) {
|
||||
return strcmp(b1->GamePath().c_str(), b2->GamePath().c_str()) < 0;
|
||||
}
|
||||
|
||||
static time_t GetTotalSize(const SavedataButton *b) {
|
||||
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath()));
|
||||
tm datetm;
|
||||
bool success;
|
||||
switch (Identify_File(fileLoader.get())) {
|
||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
|
||||
return getDirectoryRecursiveSize(ResolvePBPDirectory(b->GamePath()), nullptr, GETFILES_GETHIDDEN);
|
||||
|
||||
default:
|
||||
return fileLoader->FileSize();
|
||||
}
|
||||
}
|
||||
|
||||
bool SavedataBrowser::BySize(const UI::View *v1, const UI::View *v2) {
|
||||
const SavedataButton *b1 = static_cast<const SavedataButton *>(v1);
|
||||
const SavedataButton *b2 = static_cast<const SavedataButton *>(v2);
|
||||
|
||||
std::shared_ptr<GameInfo> g1info = g_gameInfoCache->GetInfo(nullptr, b1->GamePath(), GAMEINFO_WANTSIZE);
|
||||
std::shared_ptr<GameInfo> g2info = g_gameInfoCache->GetInfo(nullptr, b2->GamePath(), GAMEINFO_WANTSIZE);
|
||||
if (GetTotalSize(b1) > GetTotalSize(b2))
|
||||
return true;
|
||||
return strcmp(b1->GamePath().c_str(), b2->GamePath().c_str()) < 0;
|
||||
}
|
||||
|
||||
// They might be zero, but that's fine.
|
||||
return g1info->gameSize > g2info->gameSize;
|
||||
static time_t GetDateSeconds(const SavedataButton *b) {
|
||||
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath()));
|
||||
tm datetm;
|
||||
bool success;
|
||||
if (Identify_File(fileLoader.get()) == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||
success = File::GetModifTime(b->GamePath() + "/PARAM.SFO", datetm);
|
||||
} else {
|
||||
success = File::GetModifTime(b->GamePath(), datetm);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
return mktime(&datetm);
|
||||
}
|
||||
return (time_t)0;
|
||||
}
|
||||
|
||||
bool SavedataBrowser::ByDate(const UI::View *v1, const UI::View *v2) {
|
||||
const SavedataButton *b1 = static_cast<const SavedataButton *>(v1);
|
||||
const SavedataButton *b2 = static_cast<const SavedataButton *>(v2);
|
||||
|
||||
auto getDateSeconds = [&](const SavedataButton *b) {
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, b->GamePath(), 0);
|
||||
tm datetm;
|
||||
bool success;
|
||||
if (ginfo && ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||
success = File::GetModifTime(b->GamePath() + "/PARAM.SFO", datetm);
|
||||
} else {
|
||||
success = File::GetModifTime(b->GamePath(), datetm);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
return mktime(&datetm);
|
||||
}
|
||||
return (time_t)0;
|
||||
};
|
||||
|
||||
return getDateSeconds(b1) > getDateSeconds(b2);
|
||||
if (GetDateSeconds(b1) > GetDateSeconds(b2))
|
||||
return true;
|
||||
return strcmp(b1->GamePath().c_str(), b2->GamePath().c_str()) < 0;
|
||||
}
|
||||
|
||||
bool SavedataBrowser::SortDone() {
|
||||
PrioritizedWorkQueue *wq = g_gameInfoCache->WorkQueue();
|
||||
return wq->Done();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SavedataBrowser::Refresh() {
|
||||
|
||||
@@ -286,7 +286,7 @@ void TouchControlLayoutScreen::resized() {
|
||||
}
|
||||
|
||||
void TouchControlLayoutScreen::onFinish(DialogResult reason) {
|
||||
g_Config.Save();
|
||||
g_Config.Save("TouchControlLayoutScreen::onFinish");
|
||||
}
|
||||
|
||||
UI::EventReturn TouchControlLayoutScreen::OnVisibility(UI::EventParams &e) {
|
||||
|
||||
@@ -106,14 +106,14 @@ void TouchControlVisibilityScreen::CreateViews() {
|
||||
}
|
||||
|
||||
choice->SetCentered(true);
|
||||
|
||||
|
||||
row->Add(choice);
|
||||
grid->Add(row);
|
||||
}
|
||||
}
|
||||
|
||||
void TouchControlVisibilityScreen::onFinish(DialogResult result) {
|
||||
g_Config.Save();
|
||||
g_Config.Save("TouchControlVisibilityScreen::onFinish");
|
||||
}
|
||||
|
||||
UI::EventReturn TouchControlVisibilityScreen::OnToggleAll(UI::EventParams &e) {
|
||||
|
||||
+404
-15
@@ -31,15 +31,31 @@
|
||||
[VertexDepthRounding]
|
||||
# Phantasy Star Portable needs depth rounding to 16-bit precision for text to show up.
|
||||
# It's enough to do it at the vertex granularity. #3777
|
||||
# Phantasy Star Portable
|
||||
ULJM05309 = true
|
||||
ULUS10410 = true
|
||||
ULES01218 = true
|
||||
ULJM08023 = true
|
||||
ULES01218 = true
|
||||
# Phantasy Star Portable 2 JP (missing text)
|
||||
# Phantasy Star Portable 1 Demo
|
||||
NPUH90023 = true
|
||||
# Phantasy Star Portable 2
|
||||
ULES01439 = true
|
||||
ULUS10529 = true
|
||||
ULJM05493 = true
|
||||
NPJH50043 = true
|
||||
ULJM08030 = true
|
||||
NPUH90023 = true
|
||||
ULJM91014 = true
|
||||
NPJH90002 = true
|
||||
ULJM05732 = true
|
||||
NPJH50332 = true
|
||||
# Phantasy Star Portable 2 JP Demo
|
||||
ULJM91018 = true
|
||||
NPJH90062 = true
|
||||
# Phantasy Star Portable Infinity Demo
|
||||
NPJH90157 = true # Infinity demo
|
||||
|
||||
# Puyo Puyo Fever 2 #3663 (layering)
|
||||
ULJM05058 = true
|
||||
# NBA 2K13 #6603 (menu glitches)
|
||||
@@ -48,6 +64,7 @@ ULJS00551 = true
|
||||
NPJH50713 = true
|
||||
ULJS00596 = true
|
||||
ULES01578 = true
|
||||
ULUS10598 = true
|
||||
# Power Stone Collection #6257 (map arrow)
|
||||
ULES00496 = true
|
||||
ULUS10171 = true
|
||||
@@ -70,47 +87,83 @@ ULJS00454 = true
|
||||
# Heroes Phantasia Limited Edition Disc requires pixel depth rounding.
|
||||
ULJS00455 = true
|
||||
# Phantasy Star games flickering
|
||||
# Phantasy Star Portable 1
|
||||
# Phantasy Star Portable
|
||||
ULJM05309 = true
|
||||
ULUS10410 = true
|
||||
ULES01218 = true
|
||||
ULJM08023 = true
|
||||
ULES01218 = true
|
||||
# Phantasy Star Portable 2 JP
|
||||
# Phantasy Star Portable 1 Demo
|
||||
NPUH90023 = true
|
||||
# Phantasy Star Portable 2
|
||||
ULES01439 = true
|
||||
ULUS10529 = true
|
||||
ULJM05493 = true
|
||||
NPJH50043 = true
|
||||
ULJM08030 = true
|
||||
# Phantasy Star Portable 1 Demo
|
||||
NPUH90023 = true
|
||||
ULJM91014 = true
|
||||
NPJH90002 = true
|
||||
ULJM05732 = true
|
||||
NPJH50332 = true
|
||||
# Phantasy Star Portable 2 JP Demo
|
||||
ULJM91018 = true
|
||||
NPJH90062 = true
|
||||
# Phantasy Star Portable Infinity Demo
|
||||
NPJH90157 = true # Infinity demo
|
||||
|
||||
[DepthRangeHack]
|
||||
# Phantasy Star Portable 2 and Infinity both use viewport depth outside [0, 1].
|
||||
# This gets clamped in our current implementation, but attempts to fix it run into
|
||||
# Other bugs, so we've restored this hack for now.
|
||||
# Phantasy Star Portable
|
||||
ULJM05309 = true
|
||||
ULUS10410 = true
|
||||
ULES01218 = true
|
||||
ULJM08023 = true
|
||||
ULES01218 = true
|
||||
# Phantasy Star Portable 1 Demo
|
||||
NPUH90023 = true
|
||||
# Phantasy Star Portable 2
|
||||
ULES01439 = true
|
||||
ULUS10529 = true
|
||||
ULJM05493 = true
|
||||
NPJH50043 = true
|
||||
ULJM08030 = true
|
||||
ULES01439 = true
|
||||
ULUS10529 = true
|
||||
ULJM91018 = true # Infinity demo disc?
|
||||
NPJH90157 = true # Infinity demo
|
||||
NPUH90023 = true
|
||||
ULJM91014 = true
|
||||
NPJH90002 = true
|
||||
ULJM05732 = true
|
||||
NPJH50332 = true
|
||||
# Phantasy Star Portable 2 JP Demo
|
||||
ULJM91018 = true
|
||||
NPJH90062 = true
|
||||
# Phantasy Star Portable Infinity Demo
|
||||
NPJH90157 = true # Infinity demo
|
||||
|
||||
[ClearToRAM]
|
||||
# SOCOM Navy Seals games require this. See issue #8973.
|
||||
# Navy Seals
|
||||
UCUS98615 = true
|
||||
ULES00038 = true
|
||||
UCKS45021 = true
|
||||
# Fireteam Bravo 3
|
||||
UCJS10102 = true
|
||||
# Navy Seals : Tactical Strike
|
||||
UCES00855 = true
|
||||
UCUS98649 = true
|
||||
NPJG00035 = true
|
||||
NPJG90068 = true
|
||||
UCJS10102 = true
|
||||
# Tactical Strike demo
|
||||
NPUG70003 = true
|
||||
# Fireteam Bravo
|
||||
UCKS45021 = true
|
||||
UCUS98615 = true
|
||||
UCES00038 = true
|
||||
ULES00038 = true
|
||||
# Fireteam Bravo 2
|
||||
UCES00543 = true
|
||||
UCUS98645 = true
|
||||
# Fireteam Bravo 2 Demo
|
||||
UCUS98677 = true
|
||||
UCUS98691 = true
|
||||
# Fireteam Bravo 3
|
||||
NPHG00032 = true
|
||||
UCUS98716 = true
|
||||
UCES01242 = true
|
||||
|
||||
@@ -130,15 +183,25 @@ UCKS45022 = true
|
||||
ULJS19009 = true
|
||||
NPJH50141 = true
|
||||
|
||||
[DisableReadbacks]
|
||||
# MotoGP copies the framebuffer to RAM every frame. We have a hack to display it directly,
|
||||
# which means we don't also need a readback.
|
||||
ULJS00078 = true
|
||||
ULUS10153 = true
|
||||
UCES00373 = true
|
||||
|
||||
[DrawSyncEatCycles]
|
||||
# This replaced Crash Tag Team Racing hack to also fix Gundam games
|
||||
# It makes sceGeDrawSync eat a lot of cycles which can affect timing in lots of games,
|
||||
# might be negative for others, but happens to fix games below.
|
||||
# Crash Tag Team Racing needs it to pass checking memory stick screen.
|
||||
ULUS10044 = true
|
||||
ULES00168 = true
|
||||
ULES00169 = true
|
||||
ULES00170 = true
|
||||
ULES00171 = true
|
||||
ULES00172 = true
|
||||
ULJM05036 = true
|
||||
ULUS10044 = true
|
||||
# Gundam Battle Royale might need it to avoid crashes when certain Ace enemies shows up
|
||||
ULJS00083 = true
|
||||
ULKS46104 = true
|
||||
@@ -153,6 +216,14 @@ ULKS46183 = true
|
||||
ULJS00260 = true
|
||||
ULJS19041 = true
|
||||
NPJH50843 = true
|
||||
# Helps with Jeanne d'Arc weird 40/40 fps problem #5154
|
||||
UCAS40129 = true
|
||||
UCJS10048 = true
|
||||
UCKS45033 = true
|
||||
UCJS18014 = true
|
||||
UCUS98700 = true
|
||||
NPJG00032 = true
|
||||
UCJX90019 = true
|
||||
|
||||
[FakeMipmapChange]
|
||||
# This hacks separates each mipmap to independent textures to display wrong-size mipmaps.
|
||||
@@ -162,3 +233,321 @@ NPJH50843 = true
|
||||
ULJM05753 = true
|
||||
NPJH50348 = true
|
||||
ULJM06009 = true
|
||||
|
||||
[RequireBufferedRendering]
|
||||
# Warn the user that the game will not work and have issue, if buffered rendering is not enabled.
|
||||
# Midnight Club: LA Remix
|
||||
ULUS10383 = true
|
||||
ULES01144 = true
|
||||
ULJS00180 = true
|
||||
ULJS00267 = true
|
||||
ULJM05904 = true
|
||||
NPJH50440 = true
|
||||
# Midnight Club 3 : DUB edition
|
||||
ULUS10021 = true
|
||||
ULES00108 = true
|
||||
# GTA : VCS
|
||||
ULUS10160 = true
|
||||
ULES00502 = true
|
||||
ULJM05297 = true
|
||||
ULJM05395 = true
|
||||
ULJM05884 = true
|
||||
NPJH50827 = true
|
||||
# GTA : LCS
|
||||
ULUS10041 = true
|
||||
ULES00151 = true
|
||||
ULJM05255 = true
|
||||
ULJM05359 = true
|
||||
ULJM05885 = true
|
||||
NPJH50825 = true
|
||||
# GOW : JP/Korean
|
||||
UCJS10114 = true
|
||||
UCKS45084 = true
|
||||
# GOW : Ghost of Sparta
|
||||
UCUS98737 = true
|
||||
UCAS40323 = true
|
||||
NPHG00092 = true
|
||||
NPEG00044 = true
|
||||
NPEG00045 = true
|
||||
NPJG00120 = true
|
||||
NPUG80508 = true
|
||||
UCJS10114 = true
|
||||
UCES01401 = true
|
||||
UCES01473 = true
|
||||
# GOW : Ghost of Sparta Demo
|
||||
NPJG90095 = true
|
||||
NPEG90035 = true
|
||||
NPUG70125 = true
|
||||
# GOW : Chains Of Olympus
|
||||
UCAS40198 = true
|
||||
UCUS98653 = true
|
||||
UCES00842 = true
|
||||
ULJM05438 = true
|
||||
ULJM05348 = true
|
||||
UCKS45084 = true
|
||||
NPUG80325 = true
|
||||
NPEG00023 = true
|
||||
NPHG00027 = true
|
||||
NPHG00028 = true
|
||||
NPJH50170 = true
|
||||
UCET00844 = true
|
||||
# GOW: Chains of Olympus Demo
|
||||
UCUS98705 = true
|
||||
UCED00971 = true
|
||||
UCUS98713 = true
|
||||
# Daxter
|
||||
UCUS98618 = true
|
||||
UCES00044 = true
|
||||
NPUG80329 = true
|
||||
NPEG00025 = true
|
||||
# Ys Seven
|
||||
ULUS10551 = true
|
||||
ULJM05475 = true
|
||||
NPEH00065 = true
|
||||
NPJH50350 = true
|
||||
ULJM08041 = true
|
||||
NPEH00065 = true
|
||||
# The Legend of Heroes: Trails in the Sky
|
||||
ULUS10540 = true
|
||||
ULUS10578 = true
|
||||
ULES01556 = true
|
||||
ULJM05170 = true
|
||||
ULJM08033 = true
|
||||
NPJH50373 = true
|
||||
# Grand Knights History
|
||||
ULJS00394 = true
|
||||
ULJS19068 = true
|
||||
NPJH50518 = true
|
||||
# Tactics Ogre
|
||||
ULUS10565 = true
|
||||
ULES01500 = true
|
||||
ULJM05753 = true
|
||||
NPJH50348 = true
|
||||
ULJM06009 = true
|
||||
UCKS45164 = true
|
||||
# Metal Gear Solid : Peace Walker
|
||||
ULUS10509 = true
|
||||
ULES01372 = true
|
||||
ULJM08038 = true
|
||||
NPJH50045 = true
|
||||
ULJM05630 = true
|
||||
# Star Ocean : Second Evolution
|
||||
ULUS10375 = true
|
||||
ULES01187 = true
|
||||
ULJM05591 = true
|
||||
ULJM05325 = true
|
||||
UCAS40203 = true
|
||||
# Driver 76
|
||||
ULUS10235 = true
|
||||
ULES00740 = true
|
||||
# Chili Con Carnage
|
||||
ULUS10216 = true
|
||||
ULES00629 = true
|
||||
# TODO: There are many more.
|
||||
|
||||
[RequireBlockTransfer]
|
||||
# Warn the user that the game will have issue graphic, if simulate block transfer is not enabled.
|
||||
# Ys Seven need it to fix minimap. See issues #2928
|
||||
ULUS10551 = true
|
||||
ULJM05475 = true
|
||||
NPEH00065 = true
|
||||
NPJH50350 = true
|
||||
ULJM08041 = true
|
||||
NPEH00065 = true
|
||||
# The Legend of Heroes: Trails in the Sky need it to fix graphical glitch in menu screen. See issues #8053
|
||||
ULUS10540 = true
|
||||
ULUS10578 = true
|
||||
ULES01556 = true
|
||||
ULJM05170 = true
|
||||
ULJM08033 = true
|
||||
NPJH50373 = true
|
||||
NPUH10191 = true
|
||||
NPUH10197 = true
|
||||
# Grand Knights History need it to fix blackboxes on characters and flickering texture . See issues #2135 , #6099
|
||||
ULJS00394 = true
|
||||
ULJS19068 = true
|
||||
NPJH50518 = true
|
||||
# TODO: Will add some games in the future
|
||||
NPJH50686 = true # Digimon Adventures (JP, and English patches...)
|
||||
ULJS00078 = true # MotoGP
|
||||
ULUS10153 = true # MotoGP
|
||||
UCES00373 = true # MotoGP
|
||||
ULUS10551 = true # Ys Seven
|
||||
ULJM05475 = true # Ys Seven JP
|
||||
ULUS10549 = true # Ys Seven
|
||||
NPEH00065 = true # Ys Seven
|
||||
NPJH50350 = true # Ys Seven
|
||||
ULJM08041 = true # Ys Seven
|
||||
|
||||
[DisableAccurateDepth]
|
||||
# Midnight Club: LA Remix
|
||||
ULUS10383 = true
|
||||
ULES01144 = true
|
||||
ULJS00180 = true
|
||||
ULJS00267 = true
|
||||
ULJM05904 = true
|
||||
NPJH50440 = true
|
||||
# Midnight Club 3 : DUB edition
|
||||
ULUS10021 = true
|
||||
ULES00108 = true
|
||||
|
||||
# Shadow of Destiny (#9545)
|
||||
ULUS10459 = true
|
||||
NPJH50036 = true
|
||||
|
||||
# Burnout games have problems with this on Mali, and have no use for it
|
||||
# Legends
|
||||
ULES00125 = true
|
||||
ULUS10025 = true
|
||||
ULJM05228 = true
|
||||
NPJH50305 = true
|
||||
ULJM05049 = true
|
||||
ULKS46027 = true
|
||||
ULAS42019 = true
|
||||
|
||||
# Dominator
|
||||
ULUS10236 = true
|
||||
ULES00750 = true
|
||||
ULJM05242 = true
|
||||
ULJM05371 = true
|
||||
NPJH50304 = true
|
||||
ULES00703 = true
|
||||
ULAS42095 = true
|
||||
|
||||
[RequireDefaultCPUClock]
|
||||
# GOW : Ghost of Sparta
|
||||
UCUS98737 = true
|
||||
UCAS40323 = true
|
||||
NPHG00092 = true
|
||||
NPEG00044 = true
|
||||
NPEG00045 = true
|
||||
NPJG00120 = true
|
||||
NPUG80508 = true
|
||||
UCJS10114 = true
|
||||
UCES01401 = true
|
||||
UCES01473 = true
|
||||
# GOW : Ghost of Sparta Demo
|
||||
NPJG90095 = true
|
||||
NPEG90035 = true
|
||||
NPUG70125 = true
|
||||
|
||||
[MGS2AcidHack]
|
||||
ULES00008 = true
|
||||
ULES00284 = true
|
||||
ULJM05047 = true
|
||||
ULKS46065 = true
|
||||
ULJM08001 = true
|
||||
ULJM05001 = true
|
||||
ULAS42007 = true
|
||||
ULUS10006 = true
|
||||
ULUS10077 = true
|
||||
|
||||
[SonicRivalsHack]
|
||||
ULES00622 = true # SR1
|
||||
ULUS10195 = true # SR1
|
||||
ULUS10323 = true # SR2
|
||||
ULES00940 = true # SR2
|
||||
ULET00958 = true
|
||||
|
||||
[BlockTransferAllowCreateFB]
|
||||
NPJH50686 = true # Digimon Adventures (JP, and English patches...)
|
||||
ULJS00078 = true # MotoGP
|
||||
ULUS10153 = true # MotoGP
|
||||
UCES00373 = true # MotoGP
|
||||
ULUS10551 = true # Ys Seven
|
||||
ULJM05475 = true # Ys Seven JP
|
||||
ULUS10549 = true # Ys Seven
|
||||
NPEH00065 = true # Ys Seven
|
||||
NPJH50350 = true # Ys Seven
|
||||
ULJM08041 = true # Ys Seven
|
||||
|
||||
[YugiohSaveFix]
|
||||
# The cause of Yu-gi-oh series 's bad save (cannot save) are load "save status" and use cwcheat,
|
||||
# but the real cause still unknown. #7914
|
||||
|
||||
# Yu-Gi-Oh! Duel Monsters GX: Tag Force
|
||||
ULJM05151 = true
|
||||
ULES00600 = true
|
||||
ULUS10136 = true
|
||||
|
||||
# Yu-Gi-Oh! Duel Monsters GX: Tag Force 2
|
||||
ULUS10302 = true
|
||||
ULJM05260 = true
|
||||
ULES00925 = true
|
||||
ULES00926 = true
|
||||
|
||||
# Yu-Gi-Oh! Duel Monsters GX: Tag Force 3
|
||||
ULES01183 = true
|
||||
ULJM05373 = true
|
||||
|
||||
# Yu-Gi-Oh! 5D's Tag Force 4
|
||||
ULUS10481 = true
|
||||
ULJM05479 = true
|
||||
ULES01362 = true
|
||||
|
||||
# Yu-Gi-Oh! 5D's Tag Force 5
|
||||
ULUS10555 = true
|
||||
ULJM05734 = true
|
||||
ULES01474 = true
|
||||
|
||||
# Yu-Gi-Oh! 5D's Tag Force 6
|
||||
ULJM05940 = true
|
||||
NPJH50794 = true
|
||||
|
||||
# Yu-Gi-Oh! 5D's Tag Force
|
||||
ULJM05940 = true
|
||||
|
||||
# Yu-Gi-Oh! ARC-V Tag Force Special
|
||||
NPJH00142 = true
|
||||
|
||||
[ForceUMDDelay]
|
||||
# F1 2006 won't boot at all with our standard unrealistically fast timing.
|
||||
UCES00238 = true
|
||||
UCJS10045 = true
|
||||
# F1 2005, japan only?
|
||||
UCJS10019 = true
|
||||
|
||||
[ForceMax60FPS]
|
||||
# The GOW games are very heavy and render as fast as they can. They benefit greatly from
|
||||
# capping the framerate at 60fps.
|
||||
|
||||
UCJS10114 = true
|
||||
UCKS45084 = true
|
||||
# GOW : Ghost of Sparta
|
||||
UCUS98737 = true
|
||||
UCAS40323 = true
|
||||
NPHG00092 = true
|
||||
NPEG00044 = true
|
||||
NPEG00045 = true
|
||||
NPJG00120 = true
|
||||
NPUG80508 = true
|
||||
UCJS10114 = true
|
||||
UCES01401 = true
|
||||
UCES01473 = true
|
||||
# GOW : Ghost of Sparta Demo
|
||||
NPEG90035 = true
|
||||
NPUG70125 = true
|
||||
NPJG90095 = true
|
||||
# GOW : Chains Of Olympus
|
||||
UCAS40198 = true
|
||||
UCUS98653 = true
|
||||
UCES00842 = true
|
||||
ULJM05438 = true
|
||||
ULJM05348 = true
|
||||
UCKS45084 = true
|
||||
NPUG80325 = true
|
||||
NPEG00023 = true
|
||||
NPHG00027 = true
|
||||
NPHG00028 = true
|
||||
NPJH50170 = true
|
||||
UCET00844 = true
|
||||
# GOW: Chains of Olympus Demo
|
||||
UCUS98705 = true
|
||||
UCED00971 = true
|
||||
UCUS98713 = true
|
||||
|
||||
# F1 2006 has extremely long loading times if we don't limit the framerate.
|
||||
UCES00238 = true
|
||||
UCJS10045 = true
|
||||
# F1 2005, japan only?
|
||||
UCJS10019 = true
|
||||
@@ -153,3 +153,4 @@ d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,righ
|
||||
05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
|
||||
03000000380700008532000010010000,MadCatz Madcatz Fightpad,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:b5,righttrigger:b7,
|
||||
030000000d0f0000ee00000011010000,HORI CO.,LTD. HORIPAD mini4,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
|
||||
030000000d0f0000c100000011010000,HORI CO.,LTD. HORIPAD S,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Common/CommonWindows.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "ext/xxhash.h"
|
||||
#include "base/display.h"
|
||||
|
||||
#include <CommDlg.h>
|
||||
#include <tchar.h>
|
||||
@@ -154,17 +155,21 @@ CtrlDisAsmView::CtrlDisAsmView(HWND _wnd)
|
||||
wnd=_wnd;
|
||||
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL);
|
||||
SetScrollRange(wnd, SB_VERT, -1,1,TRUE);
|
||||
SetScrollRange(wnd, SB_VERT, -1, 1, TRUE);
|
||||
|
||||
charWidth = g_Config.iFontWidth;
|
||||
rowHeight = g_Config.iFontHeight+2;
|
||||
const float fontScale = 1.0f / g_dpi_scale_real_y;
|
||||
charWidth = g_Config.iFontWidth * fontScale;
|
||||
rowHeight = (g_Config.iFontHeight + 2) * fontScale;
|
||||
int scaledFontHeight = g_Config.iFontHeight * fontScale;
|
||||
font = CreateFont(scaledFontHeight, charWidth, 0, 0,
|
||||
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
boldfont = CreateFont(scaledFontHeight, charWidth, 0, 0,
|
||||
FW_DEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
|
||||
font = CreateFont(rowHeight-2,charWidth,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
boldfont = CreateFont(rowHeight-2,charWidth,0,0,FW_DEMIBOLD,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
curAddress=0;
|
||||
showHex=false;
|
||||
curAddress = 0;
|
||||
showHex = false;
|
||||
hasFocus = false;
|
||||
dontRedraw = false;
|
||||
keyTaken = false;
|
||||
@@ -974,8 +979,8 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
|
||||
std::string newname;
|
||||
truncate_cpy(name, g_symbolMap->GetLabelString(funcBegin).c_str());
|
||||
if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), L"New function name", name, newname)) {
|
||||
g_symbolMap->SetLabelName(newname.c_str(),funcBegin);
|
||||
u32 funcSize = g_symbolMap->GetFunctionSize(curAddress);
|
||||
g_symbolMap->SetLabelName(newname.c_str(), funcBegin);
|
||||
u32 funcSize = g_symbolMap->GetFunctionSize(funcBegin);
|
||||
MIPSAnalyst::RegisterFunction(funcBegin, funcSize, newname.c_str());
|
||||
MIPSAnalyst::UpdateHashMap();
|
||||
MIPSAnalyst::ApplyHashMap();
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "../resource.h"
|
||||
#include "../../Core/MemMap.h"
|
||||
#include "../W32Util/Misc.h"
|
||||
#include "Windows/resource.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Windows/W32Util/Misc.h"
|
||||
#include "Windows/InputBox.h"
|
||||
#include "../Main.h"
|
||||
#include "../../Core/Debugger/SymbolMap.h"
|
||||
#include "Windows/main.h"
|
||||
#include "Core/Debugger/SymbolMap.h"
|
||||
#include "base/display.h"
|
||||
|
||||
#include "Debugger_Disasm.h"
|
||||
#include "DebuggerShared.h"
|
||||
@@ -26,19 +27,20 @@ CtrlMemView::CtrlMemView(HWND _wnd)
|
||||
SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL);
|
||||
SetScrollRange(wnd, SB_VERT, -1,1,TRUE);
|
||||
|
||||
rowHeight = g_Config.iFontHeight;
|
||||
charWidth = g_Config.iFontWidth;
|
||||
offsetPositionY = offsetLine*rowHeight;
|
||||
const float fontScale = 1.0f / g_dpi_scale_real_y;
|
||||
rowHeight = g_Config.iFontHeight * fontScale;
|
||||
charWidth = g_Config.iFontWidth * fontScale;
|
||||
offsetPositionY = offsetLine * rowHeight;
|
||||
|
||||
font =
|
||||
CreateFont(rowHeight,charWidth,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,L"Lucida Console");
|
||||
underlineFont =
|
||||
CreateFont(rowHeight,charWidth,0,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,L"Lucida Console");
|
||||
curAddress=0;
|
||||
font = CreateFont(rowHeight, charWidth, 0, 0,
|
||||
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
underlineFont = CreateFont(rowHeight, charWidth, 0, 0,
|
||||
FW_DONTCARE, FALSE, TRUE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
curAddress = 0;
|
||||
debugger = 0;
|
||||
|
||||
|
||||
searchQuery = "";
|
||||
matchAddress = -1;
|
||||
searching = false;
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include <math.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "base/display.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "../resource.h"
|
||||
#include "Windows/resource.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "../W32Util/Misc.h"
|
||||
#include "../InputBox.h"
|
||||
#include "Windows/W32Util/Misc.h"
|
||||
#include "Windows/InputBox.h"
|
||||
|
||||
#include "CtrlRegisterList.h"
|
||||
#include "Debugger_MemoryDlg.h"
|
||||
@@ -16,11 +17,10 @@
|
||||
#include "Debugger_Disasm.h"
|
||||
#include "DebuggerShared.h"
|
||||
|
||||
#include "../main.h"
|
||||
#include "Windows/main.h"
|
||||
|
||||
static const int numCPUs = 1;
|
||||
|
||||
//#include "DbgHelp.h"
|
||||
extern HMENU g_hPopupMenus;
|
||||
|
||||
enum { REGISTER_PC = 32, REGISTER_HI, REGISTER_LO, REGISTERS_END };
|
||||
@@ -29,23 +29,22 @@ TCHAR CtrlRegisterList::szClassName[] = _T("CtrlRegisterList");
|
||||
|
||||
void CtrlRegisterList::init()
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.lpszClassName = szClassName;
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = CtrlRegisterList::wndProc;
|
||||
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
|
||||
wc.hIcon = 0;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
|
||||
wc.style = CS_DBLCLKS;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = sizeof( CtrlRegisterList * );
|
||||
wc.hIconSm = 0;
|
||||
|
||||
|
||||
RegisterClassEx(&wc);
|
||||
WNDCLASSEX wc;
|
||||
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.lpszClassName = szClassName;
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = CtrlRegisterList::wndProc;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hIcon = 0;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
|
||||
wc.style = CS_DBLCLKS;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = sizeof(CtrlRegisterList *);
|
||||
wc.hIconSm = 0;
|
||||
|
||||
RegisterClassEx(&wc);
|
||||
}
|
||||
|
||||
void CtrlRegisterList::deinit()
|
||||
@@ -53,8 +52,6 @@ void CtrlRegisterList::deinit()
|
||||
//UnregisterClass(szClassName, hInst)
|
||||
}
|
||||
|
||||
|
||||
|
||||
LRESULT CALLBACK CtrlRegisterList::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CtrlRegisterList *ccp = CtrlRegisterList::getFrom(hwnd);
|
||||
@@ -109,44 +106,30 @@ LRESULT CALLBACK CtrlRegisterList::wndProc(HWND hwnd, UINT msg, WPARAM wParam, L
|
||||
break;
|
||||
case WM_GETDLGCODE: // want chars so that we can return 0 on key press and supress the beeping sound
|
||||
return DLGC_WANTARROWS|DLGC_WANTCHARS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
CtrlRegisterList *CtrlRegisterList::getFrom(HWND hwnd)
|
||||
{
|
||||
return (CtrlRegisterList *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
return (CtrlRegisterList *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CtrlRegisterList::CtrlRegisterList(HWND _wnd)
|
||||
{
|
||||
wnd=_wnd;
|
||||
: wnd(_wnd) {
|
||||
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
//SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL);
|
||||
//SetScrollRange(wnd, SB_VERT, -1,1,TRUE);
|
||||
|
||||
rowHeight=g_Config.iFontHeight;
|
||||
|
||||
font = CreateFont(rowHeight,g_Config.iFontWidth,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY,DEFAULT_PITCH,L"Lucida Console");
|
||||
selecting=false;
|
||||
selection=0;
|
||||
category=0;
|
||||
showHex=false;
|
||||
cpu=0;
|
||||
lastPC = 0;
|
||||
lastCat0Values = NULL;
|
||||
changedCat0Regs = NULL;
|
||||
const float fontScale = 1.0f / g_dpi_scale_real_y;
|
||||
rowHeight = g_Config.iFontHeight * fontScale;
|
||||
int charWidth = g_Config.iFontWidth * fontScale;
|
||||
font = CreateFont(rowHeight, charWidth, 0, 0,
|
||||
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
|
||||
L"Lucida Console");
|
||||
}
|
||||
|
||||
|
||||
CtrlRegisterList::~CtrlRegisterList()
|
||||
{
|
||||
DeleteObject(font);
|
||||
|
||||
@@ -27,23 +27,23 @@ class CtrlRegisterList
|
||||
RECT rect;
|
||||
|
||||
int rowHeight;
|
||||
int selection;
|
||||
int marker;
|
||||
int category;
|
||||
int selection = 0;
|
||||
int marker = 0;
|
||||
int category = 0;
|
||||
|
||||
int oldSelection;
|
||||
int oldSelection = 0;
|
||||
|
||||
bool selectionChanged;
|
||||
bool selecting;
|
||||
bool hasFocus;
|
||||
bool showHex;
|
||||
DebugInterface *cpu;
|
||||
bool selectionChanged = false;
|
||||
bool selecting = false;
|
||||
bool hasFocus = false;
|
||||
bool showHex = false;
|
||||
DebugInterface *cpu = nullptr;
|
||||
static TCHAR szClassName[];
|
||||
|
||||
u32 lastPC;
|
||||
u32 *lastCat0Values;
|
||||
bool *changedCat0Regs;
|
||||
bool ctrlDown;
|
||||
u32 lastPC = 0;
|
||||
u32 *lastCat0Values = nullptr;
|
||||
bool *changedCat0Regs = nullptr;
|
||||
bool ctrlDown = false;
|
||||
|
||||
u32 getSelectedRegValue(char *out, size_t size);
|
||||
void copyRegisterValue();
|
||||
@@ -79,4 +79,4 @@ public:
|
||||
{
|
||||
return cpu;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -159,7 +159,7 @@ void MainThreadFunc() {
|
||||
if (performingRestart) {
|
||||
// Okay, switching graphics didn't work out. Probably a driver bug - fallback to restart.
|
||||
// This happens on NVIDIA when switching OpenGL -> Vulkan.
|
||||
g_Config.Save();
|
||||
g_Config.Save("switch_graphics_failed");
|
||||
W32Util::ExitAndRestart();
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ void MainThreadFunc() {
|
||||
g_Config.iGPUBackend = (int)nextBackend;
|
||||
// Clear this to ensure we try their selection.
|
||||
g_Config.sFailedGPUBackends.clear();
|
||||
g_Config.Save();
|
||||
g_Config.Save("save_graphics_fallback");
|
||||
|
||||
W32Util::ExitAndRestart();
|
||||
} else {
|
||||
|
||||
@@ -145,10 +145,10 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
|
||||
std::wstring title = ConvertUTF8ToWString(err->T("D3D11InitializationError", "Direct3D 11 initialization error"));
|
||||
bool yes = IDYES == MessageBox(hWnd_, error.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO);
|
||||
if (yes) {
|
||||
// Change the config to D3D and restart.
|
||||
// Change the config to D3D9 and restart.
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9;
|
||||
g_Config.sFailedGPUBackends.clear();
|
||||
g_Config.Save();
|
||||
g_Config.Save("save_d3d9_fallback");
|
||||
|
||||
W32Util::ExitAndRestart();
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
|
||||
const char *defaultError = "Insufficient OpenGL driver support detected!\n\n"
|
||||
"Your GPU reports that it does not support OpenGL 2.0. Would you like to try using DirectX instead?\n\n"
|
||||
"DirectX is currently compatible with less games, but on your GPU it may be the only choice.\n\n"
|
||||
"Visit the forums at http://forums.ppsspp.org for more information.\n\n";
|
||||
"Visit the forums at https://forums.ppsspp.org for more information.\n\n";
|
||||
|
||||
std::wstring versionDetected = ConvertUTF8ToWString(glVersion + "\n\n");
|
||||
std::wstring error = ConvertUTF8ToWString(err->T("InsufficientOpenGLDriver", defaultError));
|
||||
@@ -271,7 +271,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
|
||||
bool d3d9 = IDYES == MessageBox(hWnd_, whichD3D9.c_str(), title.c_str(), MB_YESNO);
|
||||
g_Config.iGPUBackend = d3d9 ? (int)GPUBackend::DIRECT3D9 : (int)GPUBackend::DIRECT3D11;
|
||||
g_Config.sFailedGPUBackends.clear();
|
||||
g_Config.Save();
|
||||
g_Config.Save("save_d3d11_fallback");
|
||||
|
||||
W32Util::ExitAndRestart();
|
||||
}
|
||||
|
||||
@@ -127,9 +127,9 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
|
||||
if (g_Vulkan->DeviceExtensions().EXT_debug_utils) {
|
||||
int bits = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
|
||||
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||
// We're intentionally skipping VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT and
|
||||
// VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, just too spammy.
|
||||
g_Vulkan->InitDebugUtilsCallback(&VulkanDebugUtilsCallback, bits, &g_LogOptions);
|
||||
} else {
|
||||
int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||
|
||||
@@ -821,25 +821,25 @@ namespace MainWindow {
|
||||
|
||||
case ID_OPTIONS_DIRECT3D9:
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9;
|
||||
g_Config.Save();
|
||||
g_Config.Save("gpu_choice");
|
||||
RestartApp();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_DIRECT3D11:
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
g_Config.Save();
|
||||
g_Config.Save("gpu_choice");
|
||||
RestartApp();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_OPENGL:
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
g_Config.Save();
|
||||
g_Config.Save("gpu_choice");
|
||||
RestartApp();
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_VULKAN:
|
||||
g_Config.iGPUBackend = (int)GPUBackend::VULKAN;
|
||||
g_Config.Save();
|
||||
g_Config.Save("gpu_choice");
|
||||
RestartApp();
|
||||
break;
|
||||
|
||||
@@ -1051,15 +1051,15 @@ namespace MainWindow {
|
||||
break;
|
||||
|
||||
case ID_HELP_OPENWEBSITE:
|
||||
ShellExecute(NULL, L"open", L"http://www.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL);
|
||||
ShellExecute(NULL, L"open", L"https://www.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL);
|
||||
break;
|
||||
|
||||
case ID_HELP_BUYGOLD:
|
||||
ShellExecute(NULL, L"open", L"http://central.ppsspp.org/buygold", NULL, NULL, SW_SHOWNORMAL);
|
||||
ShellExecute(NULL, L"open", L"https://central.ppsspp.org/buygold", NULL, NULL, SW_SHOWNORMAL);
|
||||
break;
|
||||
|
||||
case ID_HELP_OPENFORUM:
|
||||
ShellExecute(NULL, L"open", L"http://forums.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL);
|
||||
ShellExecute(NULL, L"open", L"https://forums.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL);
|
||||
break;
|
||||
|
||||
case ID_HELP_GITHUB:
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
<ForcedIncludeFiles>stdafx.h;Common/DbgNew.h</ForcedIncludeFiles>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<Optimization>Disabled</Optimization>
|
||||
@@ -168,7 +168,7 @@
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<Optimization>Disabled</Optimization>
|
||||
@@ -199,7 +199,7 @@
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@@ -248,7 +248,7 @@
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@@ -587,4 +587,4 @@
|
||||
<UserProperties RESOURCE_FILE="DaSh.rc" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.ppsspp.ppsspp"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="17050000"
|
||||
android:versionName="1.7.5.0">
|
||||
android:versionCode="18000000"
|
||||
android:versionName="1.8.0.0">
|
||||
<!-- Note that versionCode should be in the format xyzzrrrr. Example: 16030000 -->
|
||||
<!-- In this same case, versionName should be 1.6.3.0 -->
|
||||
|
||||
|
||||
@@ -882,11 +882,6 @@ void getDesiredBackbufferSize(int &sz_x, int &sz_y) {
|
||||
sz_x = 0;
|
||||
sz_y = 0;
|
||||
}
|
||||
// Round the size up to the nearest multiple of 4. While this may cause a tiny aspect ratio distortion,
|
||||
// there's some hope that #11151 is a driver bug that might be worked around this way. If this fixes it,
|
||||
// it'll be worth trying to round to a multiple of 2 instead.
|
||||
sz_x = (sz_x + 3) & ~3;
|
||||
sz_y = (sz_y + 3) & ~3;
|
||||
}
|
||||
|
||||
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_setDisplayParameters(JNIEnv *, jclass, jint xres, jint yres, jint dpi, jfloat refreshRate) {
|
||||
|
||||
Loaded 100 of 126 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user