Routing platform_unix.c's JNI thread-local storage through rthreads made
it depend on the sthread_tls_* API, which is gated behind
HAVE_THREAD_STORAGE in both rthreads.h and rthreads.c. The griffin
ndk-build (pkg/android/phoenix-common/jni/Android.mk) never defined that
flag -- the previous raw pthread_key_* code did not need it -- so the
whole TLS API compiled out and the Android build failed:
platform_unix.c:125: unknown type name 'sthread_tls_t'
platform_unix.c:425: call to undeclared function 'sthread_tls_set'
platform_unix.c:573: call to undeclared function 'sthread_tls_create_with_dtor'
Android/Bionic fully supports pthread thread-local storage (including
pthread_key_create destructors), so declare the capability alongside
-DHAVE_THREADS. This also activates retroarch.c's rarch_tls, which uses
the same API and is purely additive (no #else path). The configure-based
Linux/Unix builds autodetect HAVE_THREAD_STORAGE and were unaffected.
The vendored ibxm dependency is gone; the module replayer is now a
libretro-common citizen (formats/mod/rmodtracker.c) built like the
other decoders. Mechanical flag migration across the tree:
- Makefile.common: flag block renamed, object path moved from
$(DEPS_DIR)/ibxm/ibxm.o to
$(LIBRETRO_COMM_DIR)/formats/mod/rmodtracker.o (the rvorbis /
rflac object pattern).
- griffin: define and single-TU include swapped to the new file.
- qb/config.params.sh and Makefile.griffin: flag renamed.
- 15 platform Makefiles (dingux, dos, dos.salamander, emscripten,
lfx000, libnx, miyoo, ngc, retrofw, rg350, rg350_odbeta, rs90,
switch, webos, wii): flag renamed, values preserved (including
ngc's =0).
- retroarch.c, msg_hash.c, audio/audio_driver.c,
menu/cbs/menu_cbs_deferred_push.c: the mod/s3m/xm extension
gates renamed.
- msvc-uwp vcxproj: 9 PreprocessorDefinitions entries renamed
(define-only; UWP compiles via griffin, so there is no per-file
entry to swap). BOM and line endings preserved.
- The iOS9 xcodeproj needed nothing: its apparent matches are the
substring 'ibxm' inside 'libxml2'.
- deps/ibxm: removed.
Tree-wide residual check: zero HAVE_IBXM / deps/ibxm references
remain; the only 'ibxm' tokens left are the provenance attribution
and licence retention inside rmodtracker itself.
The DDS loader landed with only the core wiring (Makefile.common,
griffin, qb). Enable it everywhere the WebP loader (HAVE_RWEBP) is
enabled, so DDS decodes on every target rather than only default builds.
- platform Makefiles: mirror every HAVE_RWEBP toggle and inline
-DHAVE_RWEBP with HAVE_RDDS (ctr, dingux, dos, emscripten, griffin,
lfx000, libnx, miyoo, ngc, openpandora, orbis, ps2, psl1ght, psp1,
retrofw, rg350, rg350_odbeta, rs90, switch, vita, webos, wii, wiiu,
msvc).
- MSVC .vcxproj (2010-2022, 360, UWP) and the Android NativeActivity
project: add the HAVE_RDDS preprocessor define next to HAVE_RWEBP.
- Apple .xcodeproj (OSX107, PPC, iOS6-11 incl. Metal/static): add
-DHAVE_RDDS to OTHER_CFLAGS next to -DHAVE_RWEBP.
- pkg/android Android.mk: add -DHAVE_RDDS.
- feature reporting: SUPPORTS_RDDS (config.features.h), the retroarch
--features string, the menu Core Information image-format list, and
the imageviewer core extension list (adds |dds).
All these targets build the image loaders through the griffin unity TU,
which already includes rdds.c under HAVE_RDDS, so defining the flag is
sufficient to compile and enable the loader.
The WebP decoder was only enabled through the qb configure default, so
platforms with static build files never compiled it. Wire HAVE_RWEBP
everywhere HAVE_RPNG is wired, following each file's existing style:
- Variable assignments (routed through Makefile.common's define/object
block or Makefile.griffin's CFLAGS emit): dingux, dos, emscripten,
lfx000, libnx, miyoo, msvc, ngc, retrofw, rg350, rg350_odbeta, rs90,
webos, wii, and every per-platform block in Makefile.griffin, which
also gains the matching CFLAGS emit.
- Platforms with both a griffin branch (inline -D defines) and a
default Makefile.common branch (variable assignments) get both:
ps2, ctr, switch, orbis, wiiu.
- Continuation-style define lists: psl1ght, psp1, vita, openpandora,
and the Android NDK build.
- MSVC project files (griffin-based, PreprocessorDefinitions):
msvc-2010 through msvc-2022, UWP, Xbox 360, and the legacy Android
NativeActivity project.
- Xcode projects (griffin-based, -D flag lists): all eleven, including
the PPC and legacy iOS projects.
The decoder itself is C89-clean scalar C on platforms without SSE2 or
NEON (the SIMD paths are compile-time gated), so no platform needs
anything beyond the define. The salamander Makefiles are deliberately
left alone: the loaders do not decode images beyond their existing
boot path. Console targets are not buildable in this environment; the
edits mechanically mirror the existing HAVE_RPNG wiring in each file,
and the Makefile.common route they rely on is the same one exercised
by the regular Linux build.
The mixer internals and the build files were moved onto
HAVE_RFLAC/HAVE_RVORBIS/HAVE_RMP3 (matching HAVE_RWAV), but the
extension-registration and file-type sites in audio_driver.c,
msg_hash.c, retroarch.c and the menu still gated on the pre-rename
HAVE_STB_VORBIS / HAVE_DR_MP3 / HAVE_DR_FLAC. Those are now defined in
no build file (vorbis, mp3) or only some (flac), so ogg and mp3 were
silently dropped as loadable mixer formats and flac hung off a stale
flag. Rename the remaining sites to the unified flags, drop the dead
HAVE_DR_FLAC define from Android.mk, and switch Makefile.orbis to
HAVE_RFLAC.
The rflac and rvorbis extractions regressed targets that were not
exercised when they landed:
- rvorbis.c included <alloca.h> unconditionally, which does not exist
on DJGPP; alloca is declared there in <stdlib.h> (already included).
Skip the include on __DJGPP__.
- libchdr_flac.c is the CHD FLAC decoder and uses the rflac API
unconditionally, yet its rflac.h include was gated on HAVE_RFLAC.
On builds that decode CHD FLAC without defining HAVE_RFLAC (Android,
griffin without the audio mixer) the rflac types went undeclared.
Include rflac.h unconditionally: the file is only compiled under CHD
and always needs the decoder.
- griffin pulled in the rflac implementation only under
HAVE_AUDIOMIXER && HAVE_RFLAC, leaving CHD-only builds without it.
Include rflac.c whenever either the mixer (HAVE_RFLAC) or CHD
(HAVE_CHD) needs it, once, ahead of both consumers.
- Makefile.common added rflac.o only via HAVE_BUILTINFLAC; a system
libFLAC + CHD build compiled libchdr_flac.o without the decoder.
Add rflac.o alongside libchdr_flac.o when the built-in FLAC library
is not in use.
- Android.mk carried the FLAC feature flag but never the decoder flag;
add -DHAVE_RFLAC so mixer FLAC and rflac.c are actually compiled.
Carve the vendored dr_mp3 single-header decoder into a first-party in-tree
decoder (rmp3), wire it under the codec-agnostic audio_transfer layer as the
AUDIO_TYPE_MP3 backend, repoint the audio mixer's MP3 voice onto
audio_transfer, and remove deps/dr/dr_mp3.h (deps/dr is now empty).
rmp3 is the whole dr_mp3 decoder with every exported symbol namespaced from
drmp3/DRMP3/dr_mp3 to rmp3/RMP3, so a statically-linked console core
vendoring its own dr_mp3 cannot collide at link with RetroArch's copy: the
object exports rmp3_* symbols only. dr_mp3 is already memory-only (no file
I/O to strip) and self-includes its CRT headers, so the impl wrapper is just
RMP3_IMPLEMENTATION plus the include.
dr_mp3 exposes only a float decode path (rmp3_read_f32) and no integer API,
so the backend reads f32 natively and quantises to s16 at the boundary via
the shared audio_transfer_f32_to_s16 helper (round-half-away, clamp) that
now also serves the Vorbis backend. Unlike FLAC/Vorbis the drmp3 handle is
embedded in the transfer context by value (dr_mp3 initialises in place), so
validity is tracked with a flag. The mixer's MP3 voice holds an opaque
audio_transfer context and drives it through
new/start/info/read_f32/seek/free.
Build: HAVE_DR_MP3 is renamed HAVE_RMP3 across the platform makefiles, the qb
knob and Android.mk. The existing Makefile.common HAVE_RMP3 branch gains
formats/mp3/rmp3.o (and audio_transfer.o once, guarded against the FLAC and
Vorbis branches). griffin includes rmp3.c under HAVE_RMP3 and shares
audio_transfer.c across all three backends.
Carve the vendored stb_vorbis single-header decoder into a first-party
in-tree decoder (rvorbis), wire it under the codec-agnostic audio_transfer
layer as the AUDIO_TYPE_VORBIS backend, repoint the audio mixer's OGG voice
onto audio_transfer, and remove deps/stb/stb_vorbis.h.
rvorbis is the whole stb_vorbis decoder with file I/O stripped
(RVORBIS_NO_STDIO) and every exported symbol namespaced from
stb_vorbis/STB_VORBIS/STBVorbis/VORBIS_ to rvorbis/RVORBIS/RVorbis/RVORBIS_,
so a statically-linked console core vendoring its own stb_vorbis cannot
collide at link with RetroArch's copy: the object exports rvorbis_* symbols
only. The header carries its own <stdint.h>/<stddef.h> and keeps the
fixed-width types the vendored copy already used.
Vorbis is a float-internal codec with no integer decode API, so the backend
reads f32 natively and quantises to s16 at the boundary (round-half-away,
clamp) rather than round-tripping. The mixer's OGG voice holds an opaque
audio_transfer context and drives it through
new/start/info/read_f32/seek/free; loop-to-start routes through
rvorbis_seek_start, since stb_vorbis's seek(0) does not rewind.
Build: HAVE_STB_VORBIS is renamed HAVE_RVORBIS across the platform
makefiles, the qb knob and Android.mk. Makefile.common gains a HAVE_RVORBIS
branch adding formats/vorbis/rvorbis.o (and audio_transfer.o once, guarded
against the FLAC branch). griffin includes rvorbis.c under HAVE_RVORBIS and
shares audio_transfer.c across both backends.
* sdl3: Add SDL3 Controller support
* sdl3: Add to feature list
* sdl3: Update
* Update SDL3
* Apply suggestion from @RobLoach
* Apply suggestion from @RobLoach
* sdl3: Use a different ID for sdl3_joypad.c
* sdl3: Have a standard mapping flag
* sdl3: Clean up
* sdl3: Only load mappings if the autodetect system is enabled
* sdl3: Add docs pointing to SDL3 directly
* sdl3: Probably don't need to reload the mappings before quitting
* sdl3: Safety checks and protection
* sdl3: Add SDL_SetHints() for Wii
* sdl3: LED
---------
Co-authored-by: Rob Loach <[email protected]>
The previous fix added image: nil to the synonyms-bearing
DisplayRepresentation call, but the build still failed with:
RetroArchAppShortcuts.swift Extra argument 'synonyms' in call
No synonyms-bearing DisplayRepresentation initializer that also takes a
subtitle is callable across the SDKs/deployment targets RetroArch builds
against, so overload resolution falls back to init(title:subtitle:image:)
and reports synonyms as extra. The symbol is absent at compile time, so
an #available guard cannot rescue it. Drop the synonyms argument from
DisplayRepresentation; the synonyms remain stored and continue to drive
GameMatchingEngine (entities(matching:)) for fuzzy game-name resolution,
which is the path that actually consumes them.
This also fixes:
Stored property 'displayRepresentation' of 'Sendable'-conforming
struct 'GameEntity' has non-sendable type 'DisplayRepresentation'
AppEntity refines Sendable, but the representation was a stored property
and DisplayRepresentation is not Sendable. Store the game title instead
and compute displayRepresentation on demand (the AppEntity requirement is
get-only), deriving the system-context subtitle from the stored
systemName/coreName. All stored fields are now Sendable.
The three matcher call sites that read the title via
displayRepresentation.title now read the stored title directly, avoiding
construction of a throwaway DisplayRepresentation inside the sort/match
loops.
The macOS 14 / iOS 17 / tvOS 17 branch built the GameEntity
DisplayRepresentation with title, subtitle and synonyms but omitted the
image argument:
RetroArchAppShortcuts.swift:169:37 Extra argument 'synonyms' in call
The synonyms-bearing overload that also carries a subtitle is
init(title:subtitle:image:synonyms:), and its image parameter has no
default value. Omitting image makes overload resolution fall back to
init(title:subtitle:image:) (image defaulted), against which synonyms is
an extra argument, hence the diagnostic.
Pass image: nil explicitly so the call resolves to
init(title:subtitle:image:synonyms:). The synonyms are preserved for
system-side Siri/Shortcuts entity matching; the stored synonyms property
that feeds GameMatchingEngine is unaffected.
metal_common.h was a 420-line header included from exactly three
translation units: metal.m itself, ui/drivers/ui_cocoa.m, and
ui/drivers/ui_cocoatouch.m. Of those, only metal.m used more than a
single declaration -- both UI files only needed the empty
@interface MetalView : MTKView @end forward declaration to type the
result of [MetalView new] and a (MetalView *) cast on _renderView.
The other ~415 lines (Context, FrameView, MetalDriver, MenuDisplay,
HDR machinery, RPixelFormat enum, the slang_process.h transitive
include, etc.) were dead weight on the two UI translation units.
Move the header's content into metal.m where it was already used as
a single TU via griffin_objc.m's umbrella, and replace the includes
in the two UI files with the three-line MetalView forward decl plus
<MetalKit/MetalKit.h>. No public Metal driver C/Obj-C symbols are
referenced outside metal.m, so nothing else needs to change.
Optimisations enabled by the fold:
- The four file-scope C functions exposed only for "external"
consumers that did not exist (RPixelFormatToBPP, matrix_proj_ortho,
glslang_format_to_metal, SelectOptimalPixelFormat) become static.
glslang_format_to_metal and SelectOptimalPixelFormat get matching
static forward decls near the top of the file because their
definitions sit below their first call sites.
- Three properties that were declared in the public header surface
for downstream consumers that never materialised are dead in the
closed system and have been removed:
Context.drawableFormat (getter returned _layer.pixelFormat)
Context.hdrOffscreenFormat (getter returned _hdrOffscreenFormat)
FrameView.shaderEmitsHDR10
FrameView.shaderEmitsHDR16
The backing ivars _hdrOffscreenFormat, _shaderEmitsHDR10, and
_shaderEmitsHDR16 are kept -- they are still read inside the
owning class. Only the public Obj-C accessors and their @property
declarations are gone.
- RETRO_BEGIN_DECLS / RETRO_END_DECLS dropped along with the
retro_common_api.h include they required (no public C API left).
- Foundation/Metal/MetalKit/QuartzCore umbrella imports collapsed to
the set already present at the top of metal.m.
The two pkg/apple/RetroArch_Metal.xcodeproj entries for metal_common.h
are removed. The header had two PBXFileReference IDs in the project
(one declared, one dangling under the metal/ group); both group
children entries and the lone declaration are dropped.
Diff: +391 / -446 metal.m, -420 metal_common.h, -8/-9 ui_cocoa{,touch}.m,
-3 project.pbxproj. Net -61 lines.
griffin/griffin_objc.m only #imports metal.m and is unaffected. The
Makefile.common metal.o rule and the per-file -fobjc-arc override in
the top-level Makefile (metal.m only) are unchanged; MRC-compiled
ui_cocoa{,touch}.m gain a tiny @interface MetalView : MTKView @end
that has no methods or properties and so compiles identically under
either memory model.
Commit 23a945639 deleted the @interface RApplication : NSApplication
from ui/drivers/ui_cocoa.m when unifying the Cocoa + Metal event
pump on RAWindow : NSWindow. The macOS Info.plist was left pointing
NSPrincipalClass at a class that no longer exists on the macOS side
(the iOS ui_cocoatouch.m RApplication is a separate UIApplication
subclass with its own Info.plist).
Harmless at runtime - AppKit's NSClassFromString lookup returns nil
and NSApplicationMain silently falls back to NSApplication, which
is what we want anyway - but a misleading breadcrumb. Align with
the sibling pkg/apple/OSX/Info_Metal.plist and Info_AppStore.plist,
which already say NSApplication.
Affects the three xcodeprojs that consume OSX/Info.plist
(RetroArch.xcodeproj, RetroArch_OSX107.xcodeproj, RetroArch_PPC.
xcodeproj). No behavioral change - they were already silently
using NSApplication before this cleanup.
The Windows 7.x Platform SDK (shipped with MSVC 2010 and earlier) does
not include dxguid.lib. Requiring it forces developers to install the
legacy June 2010 DirectX SDK just to link, which is painful on modern
systems because of the S1023 installer bug (VC++ 2010 runtime
conflict).
Instead, emit the required COM GUID storage ourselves via
<initguid.h>. Each GUID must be defined in exactly one translation
unit across the program:
* griffin.c picks it up for the griffin unity build (every
RetroArch-msvc*.vcxproj project) via #include <initguid.h>
inserted after the license header.
* gfx/common/dx_guids.c is a new dedicated TU for the non-griffin
build (Makefile.common: MinGW, command-line MSVC, cross-compile).
Both paths are guarded against UWP/WinRT (WINAPI_FAMILY !=
DESKTOP_APP) and Xbox (_XBOX) targets, where either dxguid.lib ships
with the modern Windows SDK or GUIDs come from a console SDK.
Changes:
* gfx/common/dx_guids.c: new file, emits GUID storage for the
non-griffin build path. Guarded against Xbox, UWP, and griffin
so it compiles to an empty TU on those targets. Includes the
DX headers in newest-to-oldest order (D3D12, D3D11, D3D10, D3D9,
D3D8) so that d3d11.h's transitive include of d3d10_1.h lands
before d3d10.h is seen, satisfying the SAL-annotation ordering
check inside d3d10_1.h.
* griffin/griffin.c: add gated #include <initguid.h> after the
license block so griffin unity builds emit GUIDs before the
first DirectX header is pulled in (d3d*.c includes start around
line 432, dinput at 701, xaudio at 889).
* Makefile.common: add gfx/common/dx_guids.o to the Win32 OBJ
list; remove the now-dead HAVE_DX_COMMON bookkeeping (four
assignments from the HAVE_DSOUND, HAVE_DINPUT, HAVE_D3D9, and
HAVE_D3D8 blocks, plus the conditional that appended -ldxguid
to LIBS).
* audio/drivers/dsound.c: remove #pragma comment(lib, "dxguid").
This MSVC-specific directive embeds a library dependency in
the .obj file and would silently re-introduce dxguid.lib at
link time even after it was stripped from the project files.
* pkg/msvc/**/*.vcxproj, pkg/msvc/**/*.vcproj: remove dxguid.lib
from AdditionalDependencies in every desktop MSVC project from
2003 through 2022. The Xbox 360 and Xbox One project files are
left untouched — their console SDKs handle GUIDs separately.
Replaced QtConcurrent::run() with a ThumbnailLoader worker thread class and removed the Qt5Concurrent/Qt6Concurrent dependency entirely.
Source changes:
ui_qt.h: Added ThumbnailLoader class (a QThread subclass with a mutex-protected request queue), added #include <QThread>, #include <QMutex>, #include <QWaitCondition>, removed #include <QFutureWatcher>, added ThumbnailLoader *m_thumbnailLoader member to PlaylistModel, removed loadImage private method
ui_qt_widgets.cpp: Removed #include <QtConcurrent>, replaced QtConcurrent::run() with m_thumbnailLoader->request(), removed PlaylistModel::loadImage() method, updated constructor to create/start the loader thread and connect its signal
ui_qt.cpp: Removed #include <QtConcurrentRun>
Build system changes:
Makefile.common: Removed $(QT5CONCURRENT_CFLAGS/LIBS) and $(QT6CONCURRENT_CFLAGS/LIBS)
qb/config.libs.sh: Removed check_pkgconf QT5CONCURRENT/QT6CONCURRENT and check_enabled lines
MSVC 2017/2019/2022: Removed QtConcurrent from include paths and Qt5Concurrent.lib/Qt5Network.lib from linker dependencies
Xcode Metal: Removed QtConcurrent.framework references
The Qt companion UI now only depends on Qt5Core, Qt5Gui, and Qt5Widgets (or their Qt6 equivalents).
Ran synthetic benchmark
QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins/platforms ./bench_thumbnail.exe C:/RetroArch/thumbnails 200
Searching for up to 200 images in: C:/RetroArch/thumbnails
Found 200 images
Synchronous: 200 images in 554 ms (2.8 ms/image)
QThread worker: 200 images in 560 ms (2.8 ms/image)
Note: QThread worker has signal overhead but identical decode speed.
QtConcurrent::run would show similar numbers to QThread for single-thread.
With thread pool (N cores), QtConcurrent would be ~Nx faster for batch loads,
but grid view loads are throttled by visible items (typically 20-50), not CPU.
Identical performance — 2.8 ms/image for both. The QThread worker adds only 6ms total overhead across 200 images (signal/slot marshalling), which is 0.03ms per image. Completely negligible.
And in practice, the grid view only loads the ~20-50 thumbnails currently visible on screen, not hundreds at once, so even the theoretical multi-core advantage of QtConcurrent's thread pool never actually matters. The bottleneck is PNG decode at 2.8ms/image, not thread dispatch.