Merge pull request #21304 from hrydgard/more-ui-fixes

UI fixes, add GPU "overclock" for Outrun
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-02-26 11:47:05 +01:00
commit 6bddb90db7
11 files changed
+59 -21

No files matched your search

+4 -2
View File
@@ -46,10 +46,12 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds
p.lastY = touch.y;
}
const float dragThreshold = 5.0f / g_display.dpi_scale_y;
if (p.distanceY > p.distanceX) {
if (p.down) {
double timeDown = time_now_d() - p.downTime;
if (!p.active && p.distanceY * timeDown > 3) {
if (!p.active && p.distanceY > dragThreshold) {
p.active |= GESTURE_DRAG_VERTICAL;
// Kill the drag. TODO: Only cancel the drag in one direction.
TouchInput inp2 = touch;
@@ -64,7 +66,7 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds
if (p.distanceX > p.distanceY) {
if (p.down) {
double timeDown = time_now_d() - p.downTime;
if (!p.active && p.distanceX * timeDown > 3) {
if (!p.active && p.distanceX > dragThreshold) {
p.active |= GESTURE_DRAG_HORIZONTAL;
// Kill the drag. TODO: Only cancel the drag in one direction.
TouchInput inp2 = touch;
+1
View File
@@ -163,6 +163,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
CheckSetting(iniFile, gameID, "BoostExactFramebufferMatch", &flags_.BoostExactFramebufferMatch);
CheckSetting(iniFile, gameID, "PersistentFramebuffers", &flags_.PersistentFramebuffers);
CheckSetting(iniFile, gameID, "FileCreatedTimeHack", &flags_.FileCreatedTimeHack);
CheckSetting(iniFile, gameID, "FastEmulatedGPU", &flags_.FastEmulatedGPU);
}
void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) {
+1
View File
@@ -122,6 +122,7 @@ struct CompatFlags {
bool BoostExactFramebufferMatch;
bool PersistentFramebuffers;
bool FileCreatedTimeHack;
bool FastEmulatedGPU;
};
struct VRCompat {
+8 -2
View File
@@ -154,6 +154,7 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
: BlockDevice(fileLoader)
{
// CISO format is fairly simple, but most tools do not write the header_size.
// NOTE: CSOv2 isn't actually a thing. It was partially implemented in maxcso but it has never been in active use.
CISO_H hdr;
size_t readSize = fileLoader->ReadAt(0, sizeof(CISO_H), 1, &hdr);
@@ -322,7 +323,7 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
}
const u32 lastBlock = std::min(minBlock + count, numBlocks) - 1;
const u32 missingBlocks = (lastBlock + 1 - minBlock) - count;
const u32 missingBlocks = count - (lastBlock + 1 - minBlock);
if (lastBlock < minBlock + count) {
memset(outPtr + GetBlockSize() * (count - missingBlocks), 0, GetBlockSize() * missingBlocks);
}
@@ -367,7 +368,12 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
}
u8 *rawBuffer = &readBuffer[frameReadPos - readBufferStart];
const int plain = idx & 0x80000000;
bool plain = (idx & 0x80000000) != 0;
if (ver_ >= 2) {
// CSO v2+ requires blocks be uncompressed if large enough to be. High bit means other things.
plain = frameReadSize >= frameSize;
}
if (plain) {
memcpy(outPtr, rawBuffer + frameBlockOffset * GetBlockSize(), frameBlocks * GetBlockSize());
} else {
+4
View File
@@ -132,6 +132,10 @@ void SceKernelVplHeader::Init(u32 ptr, u32 size) {
u32 SceKernelVplHeader::Allocate(u32 size) {
u32 allocBlocks = ((size + 7) / 8) + 1;
if (!nextFreeBlock_.IsValid()) {
ERROR_LOG(Log::sceKernel, "VPL: nextFreeBlock invalid.");
return (u32)-1;
}
auto prev = nextFreeBlock_;
do {
auto b = prev->next;
+5 -3
View File
@@ -100,8 +100,7 @@ static u32 JitMemCheck(u32 pc) {
return coreState == CORE_RUNNING_CPU || coreState == CORE_NEXTFRAME ? 0 : 1;
}
namespace MIPSComp
{
namespace MIPSComp {
using namespace ArmGen;
using namespace ArmJitConstants;
@@ -244,7 +243,10 @@ void ArmJit::CompileDelaySlot(int flags) {
void ArmJit::Compile(u32 em_address) {
PROFILE_THIS_SCOPE("jitc");
// INFO_LOG(Log::JIT, "Compiling at %08x", em_address);
if (!Memory::IsValid4AlignedAddress(em_address)) {
Core_ExecException(em_address, em_address, ExecExceptionType::JUMP);
return;
}
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
ClearCache();
+6 -1
View File
@@ -242,6 +242,12 @@ void Arm64Jit::CompileDelaySlot(int flags) {
void Arm64Jit::Compile(u32 em_address) {
PROFILE_THIS_SCOPE("jitc");
if (!Memory::IsValid4AlignedAddress(em_address)) {
Core_ExecException(em_address, em_address, ExecExceptionType::JUMP);
return;
}
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
INFO_LOG(Log::JIT, "Space left: %d", (int)GetSpaceLeft());
ClearCache();
@@ -249,7 +255,6 @@ void Arm64Jit::Compile(u32 em_address) {
BeginWrite(JitBlockCache::MAX_BLOCK_INSTRUCTIONS * 16);
// To debug really wacky JIT issues, it can be a good idea to bisect the block number,
// and disable parts of the jit using jo.disableFlags for certain ranges of blocks.
+5 -4
View File
@@ -300,15 +300,16 @@ void Jit::EatInstruction(MIPSOpcode op) {
void Jit::Compile(u32 em_address) {
PROFILE_THIS_SCOPE("jitc");
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
ClearCache();
}
if (!Memory::IsValidAddress(em_address) || (em_address & 3) != 0) {
if (!Memory::IsValid4AlignedAddress(em_address)) {
Core_ExecException(em_address, em_address, ExecExceptionType::JUMP);
return;
}
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
ClearCache();
}
// Sometimes we compile fairly large blocks, although it's uncommon.
BeginWrite(JitBlockCache::MAX_BLOCK_INSTRUCTIONS * 16);
+4 -1
View File
@@ -1290,7 +1290,10 @@ bail:
int cycles = vertexCost_ * totalVertCount;
gpuStats.vertexGPUCycles += cycles;
cyclesExecuted += cycles;
if (!PSP_CoreParameter().compat.flags().FastEmulatedGPU) {
cyclesExecuted += cycles;
}
}
void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) {
+14 -8
View File
@@ -311,7 +311,7 @@ static void EmuThreadFunc() {
ERROR_LOG(Log::System, "No activity, clearing commands");
while (!frameCommands.empty())
frameCommands.pop();
return;
break;
}
// Still under lock here.
ProcessFrameCommands(env);
@@ -847,6 +847,7 @@ retry:
INFO_LOG(Log::System, "Failed to initialize Vulkan, switching to OpenGL");
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
SetGPUBackend(GPUBackend::OPENGL);
delete ctx;
goto retry;
} else {
graphicsContext = ctx;
@@ -1635,9 +1636,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_pushCameraImageAndroid(
// Call this under frameCommandLock.
static void ProcessFrameCommands(JNIEnv *env) {
while (!frameCommands.empty()) {
FrameCommand frameCmd;
frameCmd = frameCommands.front();
frameCommands.pop();
const FrameCommand &frameCmd = frameCommands.front();
DEBUG_LOG(Log::System, "frameCommand '%s' '%s'", frameCmd.command.c_str(), frameCmd.params.c_str());
@@ -1646,6 +1645,8 @@ static void ProcessFrameCommands(JNIEnv *env) {
env->CallVoidMethod(ppssppActivity, postCommand, cmd, param);
env->DeleteLocalRef(cmd);
env->DeleteLocalRef(param);
frameCommands.pop();
}
}
@@ -1693,6 +1694,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_PpssppActivity_requestExitVulkanR
}
// TODO: Merge with the Win32 EmuThread and so on, and the Java EmuThread?
// This function must release the window reference.
static void VulkanEmuThread(ANativeWindow *wnd) {
SetCurrentThreadName("EmuThread");
@@ -1703,6 +1705,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
ERROR_LOG(Log::G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context.");
renderLoopRunning = false;
exitRenderLoop = false;
ANativeWindow_release(wnd);
return;
}
@@ -1710,6 +1713,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
WARN_LOG(Log::G3D, "runVulkanRenderLoop: ExitRenderLoop requested at start, skipping the whole thing.");
renderLoopRunning = false;
exitRenderLoop = false;
ANativeWindow_release(wnd);
return;
}
@@ -1729,6 +1733,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
delete graphicsContext;
graphicsContext = nullptr;
renderLoopRunning = false;
ANativeWindow_release(wnd);
return;
}
@@ -1764,6 +1769,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
graphicsContext->ShutdownFromRenderThread();
renderLoopRunning = false;
exitRenderLoop = false;
ANativeWindow_release(wnd);
WARN_LOG(Log::G3D, "Render loop function exited.");
}
@@ -1798,15 +1804,15 @@ Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameInfo(JNIEnv * env, jclass, jobj
if (info) {
INFO_LOG(Log::System, "GetInfo successful, waiting");
// Wait for both name and icon
int attempts = 1000;
// Wait for both name and icon for a second.
int attempts = 100;
while ((!info->Ready(GameInfoFlags::PARAM_SFO) || !info->Ready(GameInfoFlags::ICON)) && attempts > 0) {
sleep_ms(1, "info-icon-poll");
sleep_ms(10, "info-icon-poll");
attempts--;
}
INFO_LOG(Log::System, "Done waiting");
if (info->fileType != IdentifiedFileType::UNKNOWN) {
if (attempts > 0 && info->fileType != IdentifiedFileType::UNKNOWN) {
// Get the game title
gameName = info->GetTitle();
if (gameName.length() > strlen("The ") && startsWithNoCase(gameName, "The ")) {
+7
View File
@@ -2140,3 +2140,10 @@ NPUZ00006 = true # MJA 2
# Silent Hill: Shattered Memories does some strange checks of the file-created time, which won't pass on some platforms. See issue #13781
ULES01352 = true
ULUS10450 = true
[FastEmulatedGPU]
# Crude hack that makes the emulated GPU appear a lot faster, removing internal slowdowns in games. This makes Outrun stick to 60fps.
# Outrun 2006: Coast to Coast - issue #11358 (car reflections)
ULES00262 = true
ULUS10064 = true
ULKS46087 = true