They record whether a reschedule happened while the code under test
ran, so a diff where only the marker differs is a scheduling
difference, not a wrong value - worth knowing before going looking for
a value bug that isn't there.
Also fixes the O/E description, which had them the wrong way round: O
is PPSSPP's output, E is the expected file.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
31 languages, following each file's existing chat terminology (chatt,
bate-papo, obrolan, sembang, 聊天, الشات, ...). The rest are left to fall
back to English rather than guessed at.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
Identify_File and friends compare against lowercase extensions, the way
Path::GetFileExtension returns them, but ZipFileLoader passed the name
from the zip through unchanged. So a file stored as e.g. "DUMP.PPDMP"
inside a zip failed to load, while "dump.ppdmp" worked.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
The log was trimmed to 50 lines, which isn't enough to scroll back
through a conversation - now 250. Chat entries also carry the time they
arrived, shown as a dimmed HH:MM in front of the name, behind a new
"Show timestamps in chat" setting.
The timestamp is kept next to the text rather than baked into it, since
the chat view finds the sender by splitting the line at the first colon.
Fixes#15444
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
The generic Android pad map and the Retroid map were the only pad
defaults without it, so the right stick did nothing until mapped by
hand. Uses the same axes and directions as the desktop pad default.
Fixes#21591
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
The last platform that was missing this - it was held back waiting for
the SDL 3.0 migration, which has now happened. Without it, whatever was
held when the pad vanished stays held, which tends to walk the player
off a cliff.
Fixes#20418
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
These two were lower case for legacy reasons, unlike every other
directory, which actually matters on case sensitive file systems like
the one iOS uses. An existing lower case directory is still used if
there's no upper case one, so nobody has to move their files.
Fixes#20527
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
Previously the cursor was only hidden when entering fullscreen or
starting a game, and never came back on mouse movement. Now it hides
half a second after the mouse stops moving and reappears when it moves
again, which also covers the touch-controls case that used to be
excluded entirely.
Fixes#20572
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
Three frames in flight showed no performance benefit over two, so drop
the option and clamp existing configs (and the default) down to 2.
The now-unused "Up to 2" translation keys are left in place.
Fixes#21419
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
Choices that are just numbers have no translation, so every lookup got
logged as a missing translation - the Graphics settings screen spammed
the log once per frame as long as Frame Skipping was on.
Fixes#21455
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
Sizes up the work against the existing backends, lays out the shader generation
vs. SPIRV-Cross translation choice, and argues that programmable blending (the
framebufferFetchSupported cap that Vulkan hardcodes to false) is a better reason
to do it than dropping the MoltenVK dependency.
The shader creation helpers returned S_FALSE when compilation produced no
bytecode - but S_FALSE is a success code, so the FAILED() checks in the
D3D11VertexShader/D3D11FragmentShader constructors never fired and failed_ was
never set. Return E_FAIL instead, and only hand out the bytecode when the shader
object was actually created.
Failed() had no callers at all, so a failed shader was handed to the draw as
usual: VSSetShader(nullptr), CreateInputLayout on empty bytecode, and the
ignored HRESULT from SetupDecFmtForDraw meant IASetInputLayout(nullptr). The
draw then did nothing, with no log line to explain it. Skip the draw and warn
instead, like the GL backend does.
The cleanup loop was hardcoded to 12 entries while the array holds more and
levels can exceed that with a texture replacement pack - a 8192-pixel
replacement has 14 mip levels, so every level from 12 up leaked on each texture
build. Use ARRAY_SIZE, and shrink the array to 16 since D3D11 caps textures at
16384 pixels anyway.
The out-of-memory bail-out returned before that loop, leaking every level
decoded so far. Since the entry ends up without a texture it gets rebuilt, and
leaks again, every following frame.
Scissor the stencil readback to the region actually being read back - latent,
every caller passes a zero origin today.
Remove a DecodeVerts call that can never do anything: both branches above it
have already advanced decodeVertsCounter_ to numDrawVerts_. Worse than useless,
since in the non-skinning branch the vertices went to the push buffer, so
decoded_ doesn't hold them.
The out-of-memory bail-out added in the previous commit returned before the
status flag was set, leaving a GL_TEXTURE_3D object bound while ApplyTexture
told the shader generator it was a 2D texture. The entry stays cached, so it
would repeat every frame, not just the one that failed to allocate.
TextureCacheGLES passed a hardcoded 0.0f instead of key.aniso, so the
Anisotropic Filtering setting did nothing at all on the OpenGL backend, even
though GPU_USE_ANISOTROPY was advertised and D3D11/Vulkan both honor it. Looks
like it was left behind by the 2017 render manager refactor.
The queue runner now clamps to the device maximum it already queried into
maxAnisotropyLevel_ (until now unused), and only touches the parameter when the
extension is actually supported - the anisotropy branch there has been dead
since every caller passed 0.0f, so this is the first time it runs.
0.0f keeps its meaning of "don't care" for the CLUT/fragment-test/thin3d
callers; the texture cache now passes 1.0f when the setting is off, so turning
it off takes effect on already-uploaded textures instead of only new ones.
TexCache: Never use anisotropic filtering for CLUT8-indexed textures
What gets sampled for those is palette indices, depalettized by the shader
afterwards - averaging indices across an anisotropic footprint produces garbage
colors. Affects all backends, not just the GL one that just started honoring
key.aniso.
TexCache: Clear key.aniso wherever filtering is forced to nearest
It was only cleared in the two places inside the AUTO_MAX_QUALITY branch, so the
TEX_FILTER_AUTO path (pixel-mapped textures, the ugly color test heuristic), the
FORCE_NEAREST setting and the replacement-texture override could all end up
requesting nearest filtering with anisotropy still on.
Doing it in the switch that applies forceFiltering covers every path, so it
can't drift apart again.
GLES: Only record the applied anisotropy, and log skipped draws
The queue runner updated tex->anisotropy even when it skipped the call because
the value was 0.0f ("don't care") - harmless while nothing ever set anisotropy,
but now it would make the tracked state disagree with GL, so a later request for
the value it thinks is set would be wrongly skipped.
Also log when a draw is skipped for a missing vertex shader. The failure is
cached per shader ID, so without it geometry silently disappears for the rest of
the session after the one-shot OSD message.
The cache loader indexed &vec[0] on vectors that can legitimately be empty (a
header-sized file with zero counts passes both sanity checks), and the counts
are signed ints where only the upper bound was checked - a negative count would
reach resize() as a huge size_t.
The 3D texture branch had the out-of-memory assert but not the bail-out the 2D
branch has, so an ignored assert fell straight into memset(nullptr).
ApplyVertexShader can return null - if the requested shader fails to compile it
retries with a software transform ID, and if that fails too it returns (and
caches) null. We then called UseHWTransform() on it.
ApplyFragmentShader can likewise return null, and the hardware path ignored it,
unlike the software path. Without a linked shader nothing binds a program for
this render pass, so the draw would have gone through with whatever program a
previous pass left bound.
53aa2cc596 changed the first argument from "true" to stencilState_.writeMask,
but that slot is "bool enabled" - the writeMask argument stayed hardcoded to
0xFF, so the mask still never reached GL. The clear-mode call just above gets
the slots right.
Reachable because SoftwareTransformCommon refuses the fast clear path when the
stencil write mask is partial, so exactly those clears end up here.
Nothing has generated or used a geometry shader since the GS paths were removed
- GeometryShaderGenerator is gone, and ShaderWriter's BeginGSMain/EndGSMain had
no callers at all. Removes ShaderStage::Geometry and everything hanging off it:
the GS preambles and GSMain helpers in ShaderWriter, the stage mappings in all
three thin3d backends, the D3D11 geometry shader plumbing (curGS_, the pipeline
and module members, gs_4_0 compilation), CreateGeometryShaderD3D11, the unused
PipelineFlags::USES_GEOMETRY_SHADER and PipelineManagerVulkan's
UsesGeometryShader().
Also stop enabling the Vulkan geometryShader device feature, since we no longer
have any use for it.
Kept on purpose: the device feature is still listed in the feature dumps (like
other capabilities we don't use), and the Vulkan shader cache header keeps its
now-always-zero geometry shader count so the on-disk format stays compatible.
Keep CSO frame and block counts wide until validating their 32-bit
representation, preventing numFrames + 1 from wrapping. Also reject
index tables that cannot fit in the source file or host size_t before
allocation and indexing.
Pass the flags selected from the independent remote sharing and
debugger startup settings instead of enabling every web service.
This keeps remote disc sharing from exposing the unauthenticated
debugger and upload handlers.
Git Bash strips one level of backslash escaping even with a quoted delimiter, so a
'\n' meant to land in the output arrives as '\n' and Python writes a real newline
instead. Records both failure signatures - a C2001 for the first, a silently
non-matching anchor for the second - and when to reach for Edit or a script file.
Delete file that shouldn't be there
CustomButtonMappingScreen indexes customKeyImages[36] and customKeyShapes[11] with
values read straight from the ini, and it's reachable from the main menu - so
neither GamepadEmu nor TouchControlLayoutScreen, which both sanitize first, need
have run. Those two had the same fixup copy-pasted; hoisted it into a Sanitize()
next to the tables and called it from all three.
CmdLine used std::stoi/std::stod and Compatibility used stoi/stof, all of which
throw on junk with nothing catching them. 'PPSSPPHeadless --timeout=abc' aborted
the process, and so did a bad value in a [PostShaderSetting]-style compat section -
at startup, with no diagnostic. Parse with sscanf and report it: CmdLine already
has the pattern for this in its Bool case, and Config.cpp's ini reads were fixed
the same way earlier. A bad compat.ini entry now warns and keeps the default.
corners and verts are carved out of decoded_ at fixed offsets 6*65536 bytes apart,
and NormalizeVertices fills corners with indexUpperBound - indexLowerBound + 1
SimpleVertex. The vertexCount > 1024 guard doesn't bound that: the index values come
from the game, so 1024 indices can span the full 16-bit range and run corners into
verts, making the cull decision from overwritten data. Bail on an index over 1024
and report visible - a bbox test that large isn't worth doing anyway.
A hashrange of 'addr,w,h = 0,0' passed validation (0 isn't bigger than the source),
became desc_.newW/newH, and ReplacedTexture::Prepare divides by them. A post-shader
SSAA level multiplies the render resolution with no upper bound, while the
texture-shader Scale sitting a few lines away is checked against 2..8.
Horizon's CreateView printed 'Fatal error creating the view' and then returned base
anyway, so the caller recorded an unmapped address as a live view. Posix's
ftruncate failure was logged with a '// Should this be a failure?' - it is: the
mmaps afterwards succeed against a short file and the first touch past its end
raises SIGBUS, which is only hooked under __APPLE__.