Commit Graph
138 Commits
Author SHA1 Message Date
libretroadmin f1208a7a5a Make threading lock-free
The core and the headless tools no longer use mutexes, condition variables,
spinlocks, std::atomic, std::thread or volatile flags. Threads hand off through
libretro-common's retro_atomic and rthreads plus a few small pieces on top of
them in Common/Thread: Thread, MpscQueue, EventCounter, ParkingLot waits and
ReaderGate. Every wait blocks until it's woken; nothing polls on a timer.

State that only one thread touches just loses its lock. The PSP filesystem,
sceIo and the savedata dialog now belong to the emulation thread: async reads
and writes run when they're queued and complete later in emulated time, and
the IO and savedata threads are gone. The friend finder only talks to the
adhoc server and hands what it gets to the emulation thread. GPU init always
runs on the thread that starts the game.

The Vulkan render and compile queues, pipeline and render pass caches, delete
list and SPIR-V cache, the GL render queue, the software renderer's jit caches,
the file loader caches, the web debugger, UPnP, input, savestates, logging and
the GE debugger all hand off through queues and atomics. The IR jit's spinning
profiler thread goes.

A CPU thread with nothing to run now sleeps until work is queued instead of
spinning. Headless with --debugger waits for a client while stopped, and ends
the run once every client that connected has left. Web server shutdown keeps
servicing the CPU queue until the server has finished.
2026-10-09 04:56:16 +02:00
libretroadmin f0b97a2e90 Remove the standalone frontends
The libretro core is the frontend, and the headless tools are the test and
debugging hosts. The Windows, UWP, Android, iOS, macOS and SDL apps, the UI
framework and imgui go, along with what only they used: the Win32 debugger
hooks (g_frameMutex, the shutdown lock), JNI thread attachment, the Android
text drawer, RAIntegration, Discord, recent files, game installs, tilt input,
the audio resamplers, the control mapper, memstick moving and the remote ISO
and upload server modes. The web server keeps the debugger. The MSVC, Gradle
and ndk-build projects go too.
2026-10-09 04:56:10 +02:00
libretroadmin 5f0f72bfda Remove sleeps and timed polling from networking
Socket waits now block in select() on the socket plus a wake or cancel
socket (Common/Net/Cancel), so a stop or cancel ends them at once.

- HTTP: cancel flags become net::CancelToken; Connect waits once on all
  addresses, receives wait instead of spinning, no DNS retry sleep.
- Adhoc: the friend finder and adhoc server block on their sockets with
  a wake socket and a deadline; matching runs on a CoreTiming tick
  instead of two threads (savestate section bumped).
- sceNetInet select/poll check without blocking and park the HLE thread,
  re-checked from a CoreTiming event until ready or the emulated
  timeout.
- Vendor the aemu_postoffice client (was a submodule) with no sleeps:
  waits on the socket, close via shutdown and an eventcount, cancelable
  connects, and lock-free session slot claims.
- PortManager waits without a timeout; PSP_InitWait replaces the
  headless boot poll.
- TimeUtil: sleep_us/sleep_ms only outside the core; sleep_precise,
  sleep_random, yield and the Windows timer period are gone.
- Unit test for the socket waits.
2026-10-08 17:58:46 +02:00
libretroadmin 9f13f0f051 Remove sleeps and timed polling from the emulation and render paths
The core no longer sleeps to pace itself: the frontend runs retro_run at
its own rate, so the frame throttle, the idle-vblank delay and the real
clock sync event (and its core option) are gone, and a stepping CPU hands
straight back instead of waiting 2 ms. Waits that polled now park on a
lock-free eventcount through Common/Thread/ParkingLot and are woken by
whoever changes the state: a paused GL emu thread, which also queues a
marker behind its last frame so pausing runs the render queue up to it
instead of polling; async I/O results; the software renderer when its
queue is full; Vulkan pipeline compiles; and debugger requests once
stepping ends. Boot joins the loader thread, cache shutdown joins its
read-ahead thread, and the slow-I/O simulation is removed.

The path browser, the HTTP and WebSocket servers, the Windows console and
the game info cache are left out of the core build. libretro/test gains
lrgltest, which drives the GL backend on a surfaceless EGL context through
every path that pauses or stops the emu thread; run.sh and the image
checks CI job run it on llvmpipe.
2026-10-08 17:58:42 +02:00
libretroadmin d56b453891 Replace zlib, zstd, libchdr, libzip and libpng with libretro-common
Deflate, zlib and gzip streams go through rinflate and rdeflate, zstd
through rzstd, CHD images through rchd, zip archives through
rzip_archive and PNG through rpng. The bundled libraries, their build
glue and the system-library options are gone; adler32 and uncompress
keep zlib's ABI for the prebuilt FFmpeg archives that still call them.
libretro-common is one CMake library that the core, the headless tool
and the unit tests all link.

The reads take shorter paths on the way. CHD decodes straight from the
loader's reads and a range of blocks at a time, and a file read at any
alignment decodes into place; CSO keeps one inflate stream instead of
one per block; a plain ISO serves a file read with one read of its exact
bytes; a stored zip member is read in place and a deflated one through
restart points rather than a copy of the whole image in memory; zip
members decode into the caller's buffer; sequential reads through the
frontend's VFS skip the seek, which also keeps its buffering.

libretro/test reads one image as ISO, CSO, CHD and zip through the block
devices, boots each, and checks the codecs against Python-made vectors;
a CI job runs it.
2026-10-08 14:14:38 +02:00
Artem Lytkin 670486d2f8 DiskCachingFileLoader: keep the partial last block of the file too
same problem since f7f92c5db. also only count blocks that were actually
allocated.
2026-09-27 15:31:17 +03:00
Artem Lytkin a3e84adab9 CachingFileLoader: keep the partial last block of the file
since 7e6405291 only full 64 KB reads get cached, so any read touching the
shorter last block of a file came back short. count blocks with
blocks_.size() too, so failed reads can't inflate the count until
MakeCacheSpaceFor loops forever. also stop read-ahead from asking the
backend for blocks past the end of the file.
2026-09-27 15:31:04 +03:00
Henrik RydgårdandClaude Opus 5 a506d0be6f Lowercase the extension reported by ZipFileLoader
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
2026-09-04 13:10:54 -06:00
Henrik Rydgård 1910be0b47 Fix booting from extracted directories specified on the command line, reported by Kotcrab 2026-08-20 00:54:26 +02:00
Henrik Rydgård 67f2bf57cb RamCachingFileLoader: don't round a mid-file short read up to a full block
blocksActuallyRead rounded bytesRead up to the next whole block
unconditionally, intending to handle the legitimate case where the
very last block of the file is naturally shorter than BLOCK_SIZE
(cache_ is deliberately over-allocated for that). But it applied the
same rounding to any short read, including a genuine failure or a
dropped connection mid-file (this loader can sit on top of the whole
Remote ISO chain via CachingFileLoader/HTTPFileLoader when "Cache full
ISO in RAM" is enabled) - marking a block as fully cached when only a
few of its bytes were actually written. Since cache_ is malloc'd (not
zeroed), every later read of that block would serve uninitialized heap
memory as if it were real file data.

Only round up when the short read's end position exactly matches the
true end of the file.
2026-08-11 08:54:16 +02:00
Henrik Rydgård f7f92c5db7 DiskCachingFileLoader: fix partial-read caching, index bounds, and offset bug
SaveIntoCache checked `readBytes != 0` instead of comparing against the
full expected length, so any nonzero-but-short read from the backend
(e.g. a Remote ISO connection dropping mid-file) was treated as a
complete success: in the multi-block path this marked *all* requested
blocks (up to 16) as fully cached and wrote the uninitialized tail of
the read buffer to the on-disk cache file, and in both paths the
short/uninitialized data was also copied straight into the caller's
output buffer and counted in the return value - so a read failure was
reported (and permanently cached) as success. Only treat a block as
read once the backend actually delivered the full blockSize_ for it,
and stop before caching or returning anything for blocks it didn't.

Also fixes two latent bugs in the same functions, unreachable in the
current call graph (DiskCachingFileLoader is only ever driven by
CachingFileLoader, which always issues block-aligned reads) but wrong
if ever called otherwise:
- The multi-block loop reused the batch's initial `offset` (the
  position within the *first* block) for every subsequent block
  instead of resetting it to 0, which would both read from the wrong
  place in `wholeRead` and mis-copy less than a full block for i > 0.
- ReadBlockData() applied `offset` to the destination pointer instead
  of the file seek position, which would both read the wrong bytes
  from disk and write up to `offset` bytes past the end of the
  caller's buffer.

LoadCacheIndex's sanity check on persisted block indices used `>`
instead of `>=` against maxBlocks_ (blockIndexLookup_ only has
maxBlocks_ entries, valid indices 0..maxBlocks_-1), so a corrupted
cache file's index entry with block == maxBlocks_ exactly would pass
validation and then index one past the end of blockIndexLookup_.
2026-08-11 08:54:16 +02:00
Henrik Rydgård 7e64052914 CachingFileLoader: don't cache blocks the backend failed to fully read
SaveIntoCache() discarded backend_->ReadAt()'s return value entirely
and unconditionally marked the requested block(s) as cached. A short
or failed read from the backend (e.g. a Remote ISO connection dropping
mid-file, now that LocalFileLoader/RetryingFileLoader correctly report
failures as 0 rather than a huge count) would still get stored as a
"valid" cached block, permanently serving its uninitialized tail as if
it were real file data on every later read, with no retry.

Only insert a block once we've confirmed the backend actually
delivered the full BLOCK_SIZE for it.
2026-08-11 08:54:16 +02:00
Henrik Rydgård 1671814be1 LocalFileLoader: report 0, not a huge bogus count, on read failure
ReadAt()'s contract is to return the number of bytes/units actually
read. On every platform branch, an OS-level read failure (ReadFile
returning FALSE, or pread/read returning -1) was fed straight into a
division by `bytes` without checking for it first:
- Windows explicitly returned (size_t)-1.
- Elsewhere, the signed -1 from pread/read was implicitly converted to
  size_t (via the usual arithmetic conversions with the unsigned
  `bytes`) before the division, producing a huge bogus count instead
  of a small one.

Every caller in the caching chain (CachingFileLoader,
RamCachingFileLoader, RetryingFileLoader, ZipFileLoader's libzip
source callback) loops on "did we get at least what we asked for",
which a huge return value trivially satisfies - so a local I/O error
(removable media ejected, a content-URI permission problem mid-read,
etc.) would be reported as a fully successful read of whatever
uninitialized memory happened to be in the destination buffer.
2026-08-11 08:54:16 +02:00
Henrik Rydgård a8195e7ca6 Clamp HTTP response body to the requested range in HTTPFileLoader
A malicious or MITM'd server could send a Content-Range header matching
the requested range but a larger entity body, overflowing the caller's
fixed-size buffer via output.Take. Clamp the copied size to the requested
range.
2026-08-01 11:57:27 +02:00
Henrik Rydgård a0fe36f470 Fix mismatched new[]/delete in CachingFileLoader cache eviction
MakeCacheSpaceFor freed cache blocks (allocated with new u8[]) using
scalar delete instead of delete[]. Correct to delete[].
2026-08-01 11:41:24 +02:00
Henrik Rydgård 2d8de4c1bf Improve error checking on game launch.
See #21886
2026-07-08 12:04:15 +02:00
Henrik Rydgård 0e55129fab Prepare for dumping NPDRM isos, use shared_ptr to manage lifetime of BlockDevice 2026-03-19 13:59:04 +01:00
Henrik Rydgård 2b946094a9 Warning fixes 2026-03-10 12:19:27 +01:00
Henrik Rydgård 0a1be41fa7 Additional fixes to ZipFileLoader 2026-03-08 12:33:46 +01:00
Henrik Rydgård 4f09c24825 Fix crash in ZipFileLoader. Was missing a terminator to the va_args list. Gemini found this. 2026-03-08 12:25:51 +01:00
Henrik Rydgård a2de96a4d1 iOS: Try to avoid leaking file bookmarks. Don't try to install zips into iCloud folder. 2026-03-08 10:20:24 +01:00
Henrik Rydgård e2b99fc921 Add a safety check in DetectZipFileContents 2026-02-10 15:50:39 +01:00
Henrik Rydgård 991d7bdfab VertexDecoder: Refactor away lowerbound/upperbound parameters 2026-02-05 13:26:17 +01:00
Henrik Rydgård 35da931fb3 Minor libretro vfs logging improvements
See #21140
2026-01-22 09:12:19 +01:00
刘皓 5716cbd41d Use the libretro VFS interface in libretro builds 2026-01-01 00:24:01 -05:00
Henrik Rydgård 05b82d6ce4 Allow passing in a custom resolver to HTTPRequest and Connection. This inverts the bad dependency. 2025-08-06 00:16:34 +02:00
Henrik Rydgård 44d06ec42f Add some sanity checks guided by Android crash reports 2025-06-07 16:35:19 +02:00
Kevin Reinholz 335695935a Fix build with system libzip and miniupnpc 2025-05-31 16:06:37 -07:00
Kevin Reinholz 795c8678a6 Fixed build with system libzip and miniupnpc 2025-05-31 16:03:57 -07:00
Henrik Rydgård 5260be6f69 Warning fixes, alignment checks 2025-05-15 09:48:23 +02:00
Henrik Rydgård dbe6ec80a0 Fix some bad "for (auto x : y)" usage 2025-04-29 16:46:14 +02:00
Henrik Rydgård 1babbca72a Move the zip file content checker into Loaders.cpp, should fix the libretro build 2025-04-12 23:38:59 +02:00
Henrik Rydgård fffbed53bc Add a ZipFileLoader, which can let us load any single-file file type from a zip.
Useful for loading framedumps from github without manually having to
unzip each one, for example.
2025-04-12 22:23:23 +02:00
Henrik Rydgård d426ccf178 Remove redundant sleep in RamCachingFileLoader 2025-03-30 11:22:19 +02:00
Henrik Rydgård b05d6171d4 Add a consistent feature check - only desktops get to use CacheFullISOInRAM. 2025-03-27 01:02:28 +01:00
Henrik Rydgård 8d9b3f28f2 Reintroduce "cache ISO in RAM" 2025-03-27 00:46:31 +01:00
Henrik Rydgård 4eaad7d5af Remove the "Cache full ISO in RAM" feature
It's been broken for years and nobody has even noticed enough to report
it.
2025-03-26 09:06:33 +01:00
Henrik Rydgård c91169e702 Restore removed <algorithm> includes.
Turns out these were needed after all. For some reason, on Windows and
Mac, <algorithm> gets auto-included by something else so I don't notice
when it's missing, and MSVC's include dependency tracker doesn't see it
either.
2024-12-19 09:53:07 +01:00
Henrik Rydgård 3e198c53b2 More include cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård 5eeb15b30a Use Exists instead of GetFileInfo in more cases 2024-11-30 00:39:38 +01:00
Henrik Rydgård 59a56d66c7 Add a "reason" argument to sleep_ms().
sleep_ms() should generally be avoided when possible. This can be used to try
to track down unnecessary sleeps by adding some logging.

This commit on its own doesn't actually add any logging.
2024-11-21 15:28:51 +01:00
Henrik Rydgård e01ca5b057 Logging API change (refactor) (#19324)
* Rename LogType to Log

* Explicitly use the Log:: enum when logging. Allows for autocomplete when editing.

* Mac/ARM64 buildfix

* Do the same with the hle result log macros

* Rename the log names to mixed case while at it.

* iOS buildfix

* Qt buildfix attempt, ARM32 buildfix
2024-07-14 14:42:59 +02:00
Henrik Rydgård 157f262cd2 Make some timeouts a bit more visible in the code. Some should be re-evaluated. 2024-01-24 09:50:26 +01:00
Henrik Rydgård 00f53ad767 Handle file type detection of extracted ISO directories better. Reported by Nemoumbra. 2024-01-12 15:37:53 +01:00
Henrik Rydgård e3177ac870 Make some global string pointers const, not just the strings.
Minor cleanup.
2023-12-29 14:09:45 +01:00
Henrik Rydgård a416d94e38 CHD over http wasn't actually working, disable again until it can be fixed 2023-12-29 12:19:06 +01:00
Herman Semenov b871e76d05 [Core/Debugger/FileLoaders/FileSystems/MIPS] Using reserve if possible 2023-12-15 13:59:19 +03:00
Henrik Rydgård ecea3844b0 Improved progress bar popups for downloads
Now shows the filename, and also there's a delay mode where they'll only
be visible if the download takes more than a second, plus they can be
named.
2023-07-18 15:13:44 +02:00
xielei 8ff78cb921 aioemu 2023-02-15 17:21:45 +08:00
Henrik Rydgård b56eef487c Strict mode checking - no way to forget detaching now.
And if we forget to attach, boom. Hopefully I caught all of them.
2023-01-05 08:38:52 +01:00