mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
* ui/companion: add shared toolkit-agnostic companion core (C89)
First step of the companion UI native-backend refactor: a pure-C89
model/command layer with no toolkit types, to be shared by the Qt,
Win32 and Cocoa desktop companions.
- opaque companion_core_t + callback table for model changes, status,
log and refresh notifications
- playlist file enumeration and accessors
- selected-playlist loading driven through playlist_parse_step() under
a microsecond budget from companion_core_iterate(), so parsing a
large playlist never stalls the runloop
- load requests routed through the existing
task_push_load_content_*_from_companion_ui paths
Passes tools/mingw_syntax_check.sh (mingw gnu99 + linux c89 pedantic).
Not yet wired into any build; the next commits add the consumers.
* ui: make the desktop companion a selectable driver (Settings -> Drivers -> Companion UI)
The companion layer now has two slots. The platform driver (win32 /
cocoa / cocoatouch) is unchanged and always active: it keeps owning the
message pump, message boxes, file browser and window glue, so the Qt
companion on Windows and macOS behaves exactly as before. The desktop
("WIMP") companion - the playlist / content browser window that used to
be hard-wired to Qt via qt_data - is now chosen from a driver table by
the new ui_companion_driver string setting, exposed as
Settings -> Drivers -> Companion UI. When a build carries more than one
desktop companion the user can switch between them.
- uico_driver_state_t: qt_data -> wimp + wimp_data,
UICO_ST_FLAG_QT_IS_INITED -> UICO_ST_FLAG_WIMP_IS_INITED
- HAVE_COMPANION_WIMP (ui_companion_driver.h): any desktop companion is
available (Qt, Cocoa, or desktop Win32); replaces the HAVE_QT /
HAVE_QT||HAVE_COCOA gates in retroarch.c, menu_displaylist.c,
menu_setting.c, menu_cbs_sublabel.c and settings_def_desktop_menu.h
- new iterate slot in ui_companion_driver_t (all initialiser tables
updated) and ui_companion_driver_wimp_iterate(), called from the main
loop in retroarch.c and from rarch_main in ui_cocoa.m, so native
companions that ride the platform pump still get per-frame time
- ui_companion_wimp_find_driver/_find_ident,
config_get_ui_companion_driver_options, config_get_default_ui_companion,
STRING_LIST_UI_COMPANION_DRIVERS, find_driver_nonempty case
- companion core wired into Makefile.common (once, for Qt / Win32 /
Cocoa) and griffin.c
- tools/settings_table.reference regenerated (no row changes; verified
with --check, unity and settings_migrate_selftest)
Verified: tools/mingw_syntax_check.sh --consumers-of
ui/ui_companion_driver.h ui/companion/companion_core.h (16 TUs clean).
* ui/drivers/qt: route status and log messages through the shared companion core
Phase 1 plumbing proof for the companion refactor: ui_companion_qt_t
now owns a companion_core_t; msg_queue_push and log_msg go
core -> callback -> MainWindow::showStatusMessage / appendLogMessage.
No behaviour change for Qt users; further subsystems (playlists, scan,
load requests, thumbnails) follow the same route one at a time.
* ui/drivers: add native Win32 desktop companion ("win32" companion UI driver)
Pure C89 (MSVC 2003 / Win9x baseline) desktop companion built on the
shared companion core and classic common controls only: LISTBOX for
playlists, SysListView32 report view for entries, msctls_statusbar32,
ANSI entry points, no static imports of post-9x APIs. Load Core / Load
Content reuse the platform driver's existing dialog flow through
win32_menu_loop(); Run / double-click loads through the core's task
path. The window is dispatched by ui_win32.c's existing thread pump;
the only per-frame work is a 2 ms-budgeted companion_core_iterate()
from the iterate slot, so the runloop is never blocked.
When this driver is selected the companion is Win32-only: Qt is not
touched. Wired into Makefile.common (Win32 targets) and griffin.c
(MSVC projects). Playlist browser / load only for now; scan, core
association, thumbnails and the parity checklist follow.
Verified with x86_64-w64-mingw32-gcc -fsyntax-only (gnu99, -Wall
-Wextra clean); no MSVC 2003 toolchain on this box.
* ui/drivers: add native Cocoa desktop companion ("cocoa" companion UI driver)
OS X 10.4-baseline AppKit shell over the shared companion core:
NSWindow, NSSplitView, two NSTableViews using the classic dataSource /
delegate protocols (no blocks, no view-based cells, no properties),
NSTextField status line and a "Companion" menu appended to the main
menu bar. Load Core / Load Content forward to the app delegate's
existing openCore: / openDocument: actions; Run / double-click loads
through the core's task path. Pumped by ui_cocoa.m's existing run loop;
per-frame work is a 2 ms-budgeted companion_core_iterate().
Objective-C is confined to the RACompanionController; all AppKit
objects are its ivars so both the MRC per-file Makefile build and the
ARC griffin_objc.m Xcode build own them correctly. The controller is
held from the C driver struct through CFBridgingRetain under ARC and
plain +1 under MRC. Uses the NSWindowStyleMask* compat names from
defines/cocoa_defines.h and a 10.4-SDK NSInteger fallback.
When this driver is selected the companion is Cocoa-only: Qt is not
touched. Wired into Makefile.common (HAVE_COCOA_COMMON) and
griffin_objc.m (TARGET_OS_OSX).
Not compiled here (no Apple toolchain on this box);
tools/apple_mrc_ownership_check.py reports nothing for the new file.
* ui: fix Win32 link (comctl32) and Xcode Metal link (HAVE_COCOA_METAL) of the native companions
Two CI link failures on the uicompanion branch:
- MSYS2 (CLANG64/MINGW32/MINGW64): undefined InitCommonControls. The
native Win32 companion uses comctl32 (list view, status bar) and
the Makefile never linked it - ui_win32.c only carried the MSVC
#pragma comment. Add -lcomctl32 to LIBS in the Companion UI block,
and the same pragma to ui_win32_companion.c for MSVC per-file builds.
- Xcode RetroArch_Metal (arm64): companion_core_* undefined. Xcode
defines HAVE_COCOA_METAL, not HAVE_COCOA, so HAVE_COMPANION_WIMP was
never set for griffin.c and companion_core.c was not compiled, while
griffin_objc.m (TARGET_OS_OSX) pulled in ui_cocoa_companion.m and its
references. HAVE_COMPANION_WIMP, the wimp driver table and the
desktop-menu settings_def guard now all include HAVE_COCOA_METAL, so
the three stay in sync as the header comment requires.
tools/settings_table.reference regenerated (unchanged).
* ui/companion: move load-request and core lifecycle logic out of the Qt companion
Phase 2, first subsystem. The tail of MainWindow::loadContent (core path
sanitising via core_info_find, caching it across CMD_EVENT_UNLOAD_CORE,
.lpl suffixing of db_name, the load task push and the pending quick
menu), LoadCoreWindow::loadCore's core-load sequence, the unload-core
paths and getPlaylistDefaultCore now live in companion_core:
- companion_core_request_load_content()
- companion_core_load_core() (HAVE_DYNAMIC)
- companion_core_unload_core()
- companion_core_current_core_path()
- companion_core_playlist_default_core()
companion_core_request_load_entry() now routes through
request_load_content too, so the native Win32/Cocoa companions get the
same core-path sanitising and quick-menu behaviour as Qt. Qt keeps only
the widget logic and the failure message boxes; it reaches the core via
ui_companion_qt_core() (ui_qt_widgets.cpp is a separate TU).
Behaviour is unchanged for Qt users. playlist_default_core still parses
the playlist synchronously when it is not the menu's cached one, exactly
as the Qt code did; moving that onto the budgeted parse is a follow-up.
Verified: ui_qt.cpp / ui_qt_widgets.cpp compile against Qt 6;
tools/mingw_syntax_check.sh on companion_core.c and the consumers of
companion_core.h (mingw gnu99 + linux c89 pedantic clean).
* ui/companion: move playlist editing out of the Qt companion
Phase 2, second subsystem. Every Qt playlist edit repeated the same
sequence: borrow the menu's cached playlist when it is the same file,
otherwise parse; mutate; write; free if owned. That now lives once in
the shared core:
- companion_core_playlist_open() / _release() (cache borrow, parse,
write, free)
- companion_core_playlist_update_entry()
- companion_core_playlist_delete_entry()
- companion_core_playlist_set_default_core() (core_info lookup,
"DETECT" fallback)
Qt callers reduced to string marshalling + one call:
MainWindow::updateCurrentPlaylistEntry, deleteCurrentPlaylistItem, the
"Associate core" context-menu action, and PlaylistModel::getPlaylistItems
(read path, still populating the Qt model itself).
companion_core_playlist_default_core() uses the same open/release.
The per-call playlist_config_t setup disappears from four Qt functions;
the config is built in one place in the core.
Behaviour unchanged for Qt users; the native Win32/Cocoa companions can
now offer entry editing and core association through the same calls.
Verified: ui_qt.cpp / ui_qt_widgets.cpp compile against Qt 6 (only the
two pre-existing warnings); companion_core.c and the consumers of
companion_core.h pass tools/mingw_syntax_check.sh.
* ui/drivers: playlist editing in the native Win32 and Cocoa companions
Wire the shared core's editing surface into both native companions so
they match the Qt companion's context menus:
- entries: right-click -> Run / Delete Entry (with confirmation); the
playlist is re-selected through the core's budgeted parse afterwards
- playlists: right-click -> Associate Core submenu (<Detect> plus every
installed core, rebuilt on open) / Refresh Playlists
companion_core gains read-only accessors for the installed core list
(companion_core_installed_core_count/_path/_name) so backends do not
include core_info.h.
Win32: WM_CONTEXTMENU on both controls, LB_ITEMFROMPOINT so the action
applies to the right-clicked playlist (a list box does not move its
selection on right-click), menu IDs 51000+ reserved for core entries.
Cocoa: per-table -setMenu:, NSMenuDelegate -menuNeedsUpdate: fills the
core submenu, actions use -clickedRow; NSAlert confirm (10.3+).
Verified: mingw gnu99 -Wall -Wextra and linux c89 pedantic clean on the
Win32 file and the core; tools/apple_mrc_ownership_check.py reports
nothing for the Cocoa file (no Apple toolchain here).
* ui/drivers/qt: populate the playlist model through the companion core's budgeted parse
Phase 2, third subsystem, and the first non-blocking win for Qt users:
PlaylistModel::getPlaylistItems parsed the whole playlist on the UI
thread (the "first touch of a large playlist is the grid view's hitch"
the code itself documented). It now asks the core to
companion_core_select_playlist_path(); the parse advances in 2 ms slices
from the runloop via the new ui_companion_qt_iterate() hook, and
on_playlist_changed lands in PlaylistModel::onCorePlaylistChanged(),
which deep-copies the entries and starts the next pending file. The
"all playlists" view chains through its list one completion at a time.
Entries are committed to the model in a single reset when the last
playlist is in, then playlistsLoaded() fires.
MainWindow::initContentTableWidget() no longer sorts / counts / scrolls
right after asking for the data; that moved to the new
onPlaylistModelLoaded() slot, which also refreshes the launch-with
actions (they read the current entry, which did not exist yet).
Restarting a load supersedes the one in flight: the core aborts the
pending parse on the new selection and partial entries are dropped.
Core additions: companion_core_select_playlist_path() (any .lpl path,
not just the playlist directory) and
companion_core_selected_playlist_path().
Verified: ui_qt.cpp, ui_qt_widgets.cpp and both moc TUs compile against
Qt 6 (only the two pre-existing warnings); companion_core.c and the
consumers of companion_core.h pass tools/mingw_syntax_check.sh. Not run
here (no display); the grid, list, history and all-playlists paths need
a manual pass on a desktop.
* ui/companion: move bulk playlist add out of the Qt companion
Phase 2, fourth subsystem. MainWindow::addFilesToPlaylist was the last
Qt code constructing a playlist_config_t and calling playlist_init /
playlist_push / playlist_write_file directly. The core now provides the
bulk-add surface:
- companion_core_playlist_open_private(): a fresh instance, never the
menu's cached playlist, so a cancelled add is discarded unwritten via
companion_core_playlist_release(core, pl, true, false) and committed
with (…, true, true)
- companion_core_resolve_content_path(): the "archive with exactly one
file -> archive#file" rule, previously duplicated in the add and the
update-entry paths
- companion_core_playlist_push(): DETECT defaults for core path / name,
the unknown-crc marker
Qt keeps the dialog, the file/directory gathering, the progress dialog
and the extension filter (which now applies to the resolved path from
the core). updateCurrentPlaylistEntry uses the same resolver. After
this no Qt source touches playlist_config_t, playlist_init(),
playlist_get_cached() or playlist_push(); all playlist model logic the
plan lists for extraction goes through ui/companion.
Verified: ui_qt_widgets.cpp compiles against Qt 6 (only the pre-existing
warning); companion_core.c and the consumers of companion_core.h pass
tools/mingw_syntax_check.sh.
* ui/companion: move directory scan out of the Qt companion; add it to the native companions
Phase 2, fifth subsystem. The scan was already task-based; the request
plumbing and the completion handling move into the core:
- companion_core_request_scan(path, directory, show_hidden): pushes
task_push_dbscan against the configured playlist directory and content
database; false when the build has no libretrodb or the push failed
- on_scan_finished callback: fired after the menu's horizontal list has
been reset (that reset was Qt's scan_finished_handler; it belongs to
RetroArch state, so it is the core's now). task_push_dbscan carries
no user data, so the requesting core is remembered in a static and
cleared in companion_core_free (one desktop companion is active at
a time).
Qt: onFileBrowserTreeContextMenuRequested calls the core; the
"scan finished" confirmation dialog stays in Qt as the callback.
Native companions gain File -> Scan Directory...: Win32 through
SHBrowseForFolderA (BIF_RETURNONLYFSDIRS, no new-style flag; shell32 /
ole32 added to LIBS and the MSVC pragmas), Cocoa through NSOpenPanel
using the same URL-or-objc_msgSend split as ui_cocoa.m so the 10.4
selectors do not appear as declarations to a modern SDK. Both refresh
the playlist list on completion.
Verified: ui_qt.cpp compiles against Qt 6; companion_core.c with and
without HAVE_LIBRETRODB, ui_win32_companion.c and the consumers of
companion_core.h pass tools/mingw_syntax_check.sh (mingw -Wall -Wextra
clean). apple_mrc_ownership_check.py reports the local
[NSOpenPanel openPanel], used within the pool exactly as ui_cocoa.m
does - a read-and-dismiss hit.
* ui/companion: move thumbnail path resolution out of the Qt companion
Phase 2, sixth subsystem. The thumbnail repository layout, the label
sanitising rule (& * / : ` < > ? \ | -> '_'), the extension probe order
(.png .jpg .jpeg .bmp .tga, .png as the save target) and the
"image content is its own thumbnail" rule were all Qt-side. They are
now C89 in the core:
- COMPANION_THUMB_BOXART / _SCREENSHOT / _TITLE / _LOGO subdirectory
names (ui_qt.h's THUMBNAIL_* macros alias them)
- companion_core_thumbnail_dir(db_name, subdir)
- companion_core_thumbnail_path(db_name, subdir, label, content_path)
PlaylistModel keeps three thin QString wrappers (getPlaylistThumbnailsDir,
getThumbnailPath, getRepositoryThumbnailPath - the last for the save
target and the sidebar images, where the content path must not short-
circuit the lookup); getSanitizedThumbnailName and the sanitiser
QRegularExpression are gone. changeThumbnail and the current-item
thumbnail loader use the wrappers.
The same calls are what the native companions' grid / list thumbnails
will resolve through.
Verified: ui_qt.cpp, ui_qt_widgets.cpp and moc_ui_qt compile against
Qt 6 (only the two pre-existing warnings); companion_core.c and the
consumers of companion_core.h pass tools/mingw_syntax_check.sh.
* ui/drivers/qt: define MainWindow::playlistModel()
The getter was declared in ui_qt.h but never defined - nothing used it
until the companion core's on_playlist_changed callback did, so the
MSYS2 Qt builds failed to link:
undefined reference to `MainWindow::playlistModel()'
Define it alongside the other trivial accessors. This box only ever
compiled ui_qt.o, never linked a Qt retroarch, which is how it slipped.
* ui/companion: move "launch with" core selection out of the Qt companion
Phase 2, seventh subsystem. MainWindow::setCoreActions built the
"Launch with" list itself: the running core, the entry's own core, the
playlist's default core, each de-duplicated against the others by path,
core name, display name and core_file_id prefix, spread over ~150 lines
of QVariantMap juggling (including a per-row loop that re-resolved the
same default core for the all-playlists view). The selection logic is
now C89:
- companion_core_launch_options(entry core, playlist name,
suggest_loaded_first, out[], max): the de-duplicated candidates in
menu order, each tagged companion_launch_selection
- companion_core_current_core_name() / _version() /
_supports_no_content(): the runloop system info Qt read directly
Qt's core_selection enum now aliases companion_launch_selection so the
combo box stores what the core hands back; setCoreActions fills the
combo from the array and appends its Ask / Load Core... entries;
setCurrentCoreLabel uses the accessors instead of runloop_state.
Verified: full Qt 6 retroarch links on Linux (the miss behind the
playlistModel() CI failure is now covered on this box) and starts
headless with desktop_menu_enable + the qt companion under
QT_QPA_PLATFORM=offscreen without faulting; companion_core.c and the
consumers of companion_core.h pass tools/mingw_syntax_check.sh.
* ui/companion: move thumbnail downloads out of the Qt companion
Phase 2, eighth subsystem. The single-thumbnail and thumbnail-pack
downloads - server URLs and per-component percent-encoding, the label
scrub the server expects, the .partial write + rename, the pack's
"delete or rename aside with .tmp" replacement pass, the decompress
task and its source cleanup, plus three retro_task callbacks and a
userdata struct - were ~430 lines of Qt. They are C89 in the core now:
- companion_core_thumbnail_download(db_name, label, subdir)
- companion_core_thumbnail_pack_download(db_name) (download + extract)
- companion_core_download_cancel() / _active()
- on_thumbnail_downloaded / on_thumbnail_pack_finished callbacks, the
latter carrying a companion_download_result the UI maps to its
messages (network / rename / delete / empty archive / extract)
One transfer is in flight at a time, as before. The task user data is
owned by the task chain; the core only points at it and clears the
back-pointer when the transfer is cancelled or the core is freed, so a
late callback frees the data and notifies nobody.
Qt keeps its queues (per-type list for one entry, per-playlist list),
counters and the three progress dialogs; downloadThumbnail,
downloadAllThumbnails and downloadNextPlaylistThumbnail are now a core
call plus the dialog. onExtractArchive, the cb_* callbacks,
qt_download_userdata_t, m_currentHttpTask, the extraction progress
dialog and scrub_qstring are gone. A cancelled transfer no longer
touches the UI at all.
Verified: full Qt 6 retroarch links on Linux and starts headless with
the qt companion; companion_core.c with and without HAVE_NETWORKING and
the consumers of companion_core.h pass tools/mingw_syntax_check.sh. The
actual transfers are not exercised here (no thumbnail server access
from this box).
* ui/drivers: Win32 companion keeps RetroArch running while dragged, gets a splitter; Qt gains Scan Directory / Quit
Win32 companion:
- Dragging or sizing the companion window (or browsing its menu bar)
froze RetroArch's video: DefWindowProc runs those loops modally on
the main thread, and only the main window's WndProc clocked the run
loop through them. win32_common.c's modal clock (win32_modal_enter /
_exit / _tick, the WM_RA_MODAL_TICK message and WIN32_MODAL_TIMER_ID)
is now exported, and the companion window routes WM_ENTERSIZEMOVE /
WM_ENTERMENULOOP / WM_EXITSIZEMOVE / WM_EXITMENULOOP and the ticks to
it exactly as the main window does; win32_modal_window_destroyed()
ends a session if the clocked window goes away mid-drag.
- The playlist pane was fixed at 200 px. A 5 px splitter between the
pane and the entry list now drags (IDC_SIZEWE, capture, clamped to
100 px from either edge, re-clamped on window resize).
Qt companion: File menu gains "Scan Directory" (QFileDialog directory
picker -> companion_core_request_scan) and "Quit RetroArch"
(CMD_EVENT_QUIT through the core), matching the native companions'
menus. Both use existing menu strings.
The two native callback tables spell out the new thumbnail callbacks as
NULL (they were relying on zero-initialisation; -Wextra flagged it).
Verified: ui_win32_companion.c and win32_common.c pass
tools/mingw_syntax_check.sh (the one consumer of win32_common.h that
fails, uwp_egl_ctx.c, fails identically on the branch tip); full Qt 6
retroarch links and starts headless with the qt companion.
* verbosity: mirror the log into any desktop companion, not just Qt
The companion log path in verbosity.c was Qt-specific twice over: it
was gated on HAVE_QT, and it replaced the platform sink - on a Qt build
the line was formatted into a buffer, written to the log file from
there and handed to ui_companion_driver_log_msg(), while the macOS
terminal/asl path and the plain vfprintf path were skipped entirely.
Now:
- verbosity.c includes ui_companion_driver.h (RARCH_INTERNAL) and gates
on HAVE_COMPANION_WIMP, so the native Win32 and Cocoa companions get
the log too
- the companion copy is orthogonal to the platform sink: it is formatted
from a va_copy of the arguments and the normal output below still
happens unchanged (macOS Qt builds regain their Terminal/asl output).
A va_copy fallback (__va_copy, or plain assignment) keeps the file
C89-clean; the linux-c89 job compiles it
- nothing is formatted unless someone is listening:
ui_companion_driver_log_active() (setting + inited + is_active +
log_msg present) is asked once per line, and
ui_companion_driver_log_msg() then delivers without repeating the
setting lookup and is_active() round trip - the previous code paid
both on every RARCH_LOG whenever Qt was compiled in, even with the
desktop menu disabled
- the __WINRT__ buffered path is unchanged, just no longer shared with Qt
The native companions gain the log view the plan asks for (View > Log
on Win32: a read-only multiline EDIT appended via EM_REPLACESEL at the
end, trimmed by half in one cut past 256 KiB so appends stay O(line);
Companion > Log on Cocoa: an NSTextView added under the split while
shown, same trim rule). The 10.4 NSInteger fallback grows NSUInteger.
Verified: verbosity.c and ui_companion_driver.c compile with the
linux-c89 flags; all 15 consumers of ui_companion_driver.h pass
tools/mingw_syntax_check.sh; ui_win32_companion.c is mingw -Wall
-Wextra clean; full Qt 6 retroarch links and runs headless with
--verbose (the mirror path exercised into Qt's log widget).
* ui/companion: move the core picker filter and the core-information rows out of the Qt companion
Phase 2, ninth subsystem: everything the Qt companion still computed
from core_info itself.
- LoadCoreWindow::initCoreList filtered the core list by gathering the
content's extension plus every archive member's extension into a
QStringList and matching it against each core's supported_extensions
string. That was a Qt re-implementation of core_info's own matcher;
companion_core_installed_cores_supporting(content_path) now calls
core_info_list_get_supported_cores() - the exact rule the menu uses,
directories included - and reports how many cores lead the list. The
table is built from the installed-core accessors (a _version accessor
is added; _name falls back to the core file's base name, as the table
did) and hides the rows past that count. MainWindow::loadContent's
CORE_SELECTION_ASK path no longer walks archives; it passes the path.
- The core-information collector (~240 lines: name / version / system /
authors / permissions / licences / extensions / firmware status with
per-row colouring / notes) was already toolkit-free C living in
ui_qt.cpp under a qt_ prefix. It moves verbatim into the core as
companion_core_core_info_rows() with companion_core_info_row_status;
MainWindow::getCoreInfo keeps only the HTML/CSS decoration of the
firmware rows.
Both are what the native companions' Load Core dialog and core-info
panel will consume.
Verified: full Qt 6 retroarch links and starts headless with the qt
companion; companion_core.c and the consumers of companion_core.h pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean).
* ui/companion: one window hand-off and one start-core path for all three companions
Two pieces of RetroArch-facing logic were still written three times,
once per backend, and once in Qt only:
- Raising the companion window meant "release the mouse grab, show the
cursor, leave fullscreen" in ui_qt.cpp, ui_win32_companion.c and
ui_cocoa_companion.m, each reading input_state / video_state /
settings itself. companion_core_prepare_show_window() is that
sequence; companion_core_video_started_fullscreen() answers Qt's
"stay behind the video window" question. The two native files drop
their video_driver.h / input_driver.h includes.
- Starting a contentless core: Qt cleared RARCH_PATH_BASENAME and
pushed task_push_start_current_core; the native companions had been
wired to companion_core_request_load(NULL, NULL), which is a different
task. companion_core_start_core() is the Qt sequence, and all three
use it (native ones report failure in the status bar).
getSelectedCorePath's CORE_SELECTION_CURRENT reads the core path from
the core accessor; the Win32 Quit item goes through
companion_core_event_command like the Qt one. ui_qt.cpp no longer
calls command_event, input_state_get_ptr or video_state_get_ptr.
Verified: full Qt 6 retroarch links and starts headless with the qt
companion; companion_core.c, ui_win32_companion.c (mingw -Wall -Wextra)
and the consumers of companion_core.h pass tools/mingw_syntax_check.sh.
* ui/drivers: Load Core window for the native Win32 and Cocoa companions
Parity with Qt's LoadCoreWindow: File -> Load Core... in both native
companions now opens the companion's own picker - a Name / Version list
of the installed cores from companion_core_installed_core_* - with
Load / Cancel buttons and double-click, and loads through
companion_core_load_core(). Previously the Win32 item forwarded to the
main window's file-open dialog and the Cocoa item to the app delegate's
openCore:, i.e. a raw .dll / .dylib chooser.
Win32: a second top-level window owned by the companion (stays above it,
hides with it, WS_EX_TOOLWINDOW), SysListView32 report view sorted by
name with the core index in lParam so a sorted row still maps back, and
the same modal-loop clocking as the companion window so dragging it
does not stall RetroArch. Cocoa: an NSWindow with an NSTableView fed by
the same controller (keyed on the table object), created on first use.
Load Content keeps using the platform driver's dialog.
Verified: ui_win32_companion.c passes tools/mingw_syntax_check.sh
(mingw -Wall -Wextra clean); apple_mrc_ownership_check.py reports only
the known local NSOpenPanel hit. Not run here (no Windows / macOS).
* ui/drivers: core-information pane for the native Win32 and Cocoa companions
Parity with Qt's core-info dock: View -> Core Information (Win32) /
Companion -> Core Information (Cocoa) shows the rows
companion_core_core_info_rows() produces for the running core - name,
version, system, authors, permissions, licences, extensions, firmware
status, notes - as a two-column key / value list beside the entries.
Win32: a SysListView32 pane on the right of the entry list; it yields
when the window is too narrow for three panes. Cocoa: a third pane that
joins the NSSplitView while shown, rows cached in two string_lists.
Only the shader commands are forwarded to companions, so a core load or
unload is not an event a companion sees; both panes instead follow the
running core from the per-frame iterate hook with one short strcmp
while shown, refilling only when the path changed.
Verified: ui_win32_companion.c passes tools/mingw_syntax_check.sh (mingw
-Wall -Wextra clean); apple_mrc_ownership_check.py reports only the
known local NSOpenPanel hit. Not run here (no Windows / macOS).
* ui/drivers: icon view with thumbnails for the native Win32 companion
Parity with Qt's grid view. View -> Icons switches the entry list to
LVS_ICON with 128 px boxart thumbnails; View -> List returns to the
report view. Thumbnails resolve through companion_core_thumbnail_path()
(the same rule as Qt: repository layout, sanitised label, extension
probe, image content as its own thumbnail) and decode through
image_texture_load(), whose ARGB8888 output is exactly the 32-bit BGRA
DIB order Windows wants, so a thumbnail is a nearest-neighbour
letterbox into a CreateDIBSection and an ImageList_Add.
Never blocks: the image list starts with a placeholder at index 0 for
every item, and the iterate hook decodes one pending thumbnail per frame
while the icon view is showing - one file decode per frame however long
the playlist. Decoding is sequential from the top for now; prioritising
the visible range is a follow-up.
Everything used exists on Windows 95 with comctl32 4.70 (ImageList_*,
LVS_ICON, LVM_SETICONSPACING); ILC_COLOR32 degrades to what the
installed comctl32 supports.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean, linux
c89 pass skipped for the Win32 path as the script does). Not run here.
* ui/companion: destroy the desktop companion window at quit, before the drivers go away
Quitting from RetroArch's own menu with the native Win32 companion open
left the process hung ("Not Responding") with an undestroyed window:
the companion window is a top-level window on the main thread, and the
only thing that destroyed it was ui_companion_driver_deinit(), which
main_exit() runs after driver_uninit(DRIVERS_CMD_ALL) has already torn
down the video driver - i.e. after the message pump that services the
window (ui_application_win32_process_events on the main thread, or the
video thread under threaded video) is gone. DestroyWindow() then has no
pump to run the window's WM_DESTROY through, and shutdown stalls.
Fix: close the companion window while its pump and the drivers are
still alive. ui_companion_driver_wimp_deinit() is split out of
ui_companion_driver_deinit() (which now calls it), made idempotent, and
invoked right after the run loop breaks - in retroarch.c's
retroarch_main_loop and in ui_cocoa.m's rarch_main - before main_exit().
main_exit()'s existing ui_companion_driver_deinit() still runs and is
now a harmless second call for the WIMP part while still tearing down
the platform driver.
This is the Qt companion's behaviour too (it lived inside the same
deinit), so no change there; it fixes the native Win32 and Cocoa
companions, whose windows previously outlived the pump.
Verified: retroarch.c, ui/ui_companion_driver.c and all 15 consumers of
ui_companion_driver.h pass tools/mingw_syntax_check.sh; full Linux
build links. The hang itself is Windows-only and not reproducible here.
* ui/drivers: icon (grid) view for the native Cocoa companion
Parity with Qt's grid and the Win32 icon view. Companion -> Icons swaps
the entries table in its scroll view for a thumbnail grid; Companion ->
List swaps it back.
NSCollectionView is 10.5+ and the baseline is 10.4, so the grid is a
hand-laid flipped NSView (RACompanionGrid): fixed 128 px cells flow-laid
to the width, each drawing a letterboxed boxart above a truncated label,
with mouse and arrow / Return selection and double-click to load. The
scroll view is reused, so no second data path.
Thumbnails resolve through companion_core_thumbnail_path() - the same
rule as everywhere else - and load as NSImage; like the Win32 icon
view, one is decoded per frame from the iterate hook while the grid is
showing, so a playlist of any size never costs more than one decode per
frame. One NSImage per row is cached and drawn as it arrives.
Verified: apple_mrc_ownership_check.py reports only local autoreleased
objects used within their pool (the drawRect: attributes dictionary and
the existing NSOpenPanel), neither stored past the pool. Not compiled
here (no Apple toolchain).
* ui: pick a core on Run when a playlist entry has none (native companions)
When a playlist entry's core is empty or "DETECT" and no core is
loaded, Run silently failed on the native companions (Qt shows its
core-selection combo / Load Core window). companion_core_entry_needs_core()
reports that case and hands back the content path; both native companions
then open their Load Core window filtered to the cores that can run that
content, and the pick launches the content with the chosen core through
companion_core_request_load_content().
Win32: cw_run_selected checks first and calls cw_cores_show(content); the
Load Core window carries the pending content, filters its list with
companion_core_installed_cores_supporting(), and its OK path runs the
content instead of just loading the core. Cocoa: runSelected and gridRun
do the same via -showCoresForContent:; the window build is split into
-buildCoresWindow so it is populated and raised once. Plain File -> Load
Core is unchanged (no content, full list, loads the core only).
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); the consumers of
companion_core.h pass; apple_mrc_ownership_check.py reports only the two
known local-autorelease hits. Not run here (no Windows / macOS).
* ui: file-system browser for the native Win32 and Cocoa companions
Parity with Qt's File Browser tab: File -> Browse Files (Win32) /
Companion -> Browse Files (Cocoa) turns the entry list into a filesystem
browser - directories first with a ".." parent link, a directory
descends, a file loads through the current core (or, when the file has
no usable core, opens the Load Core picker filtered to it). Picking a
playlist returns to playlist mode.
The listing and navigation are in the core, toolkit-free:
companion_core_browse_open() (dir_list_new + dir-first sort, defaulting
to the content directory), _browse_count/_name/_path/_is_dir with a
synthesised ".." entry, and _browse_activate() which descends, loads, or
reports needs-core with the content path for the picker - reusing
companion_core_request_load_content(), so the same core-path sanitising
and quick-menu behaviour as everywhere else.
Backends only present it: Win32 reuses the entries list view (trailing
slash marks directories), Cocoa the entries table; both branch their
rebuild / run on a browse_mode flag and leave it on playlist select.
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean, linux c89 pass);
the consumers of companion_core.h pass; apple_mrc_ownership_check.py
reports only the two known local-autorelease hits. Not run here.
* tools: companion backend feature-parity check (Phase 6)
The refactor's final phase requires the three desktop companions - Qt,
native Win32, native Cocoa - to stay interchangeable: "same actions
produce the same results". Nothing enforced that. A backend can omit a
whole feature (file browser, scan, core picker, core-info panel) and
still compile and run; the gap only surfaces when a user switches the
Companion UI driver and finds a menu entry gone.
companion_parity.py defines the feature set by the companion_core_*
entry point each feature needs and checks every backend references it -
the same source-level, zero-cost, Linux-only shape as
vfs_backend_parity.py. Qt's two presentation TUs are checked together;
where Qt implements a feature a toolkit-native way (playlist listing and
the file browser through its own QDir / QFileSystemModel, Run and the
core picker through the launch-with combo) the equivalent call is
recorded in QT_EQUIVALENT with a reason. A backend that genuinely should
not carry a feature goes in WAIVERS, so dropping one is a reviewed
choice, not an oversight. --list prints the matrix.
Wired into Linux-libretro-common-tests.yml beside the VFS parity check.
Confirmed it passes on the current three backends (19 features) and
fails when a feature call is removed from one.
This is Phase 6's parity gate as an enforced check rather than a static
checklist that would drift; the remaining visual / behavioural parity
pass stays manual.
* ui/drivers: Win32 companion opens at the Qt companion's startup size
The Qt companion opens at 1280x720 centred on the primary monitor,
clamped to it; the native Win32 companion opened at CW_USEDEFAULT with a
fixed 800x520 fallback - a much smaller window in a different place, so
the two look nothing alike on first F5. Match Qt: 1280x720, centred on
the work area (screen minus taskbar), clamped to it.
Made scalable for small displays, which the 9x baseline can hit (640x480
/ 800x600 CRTs): the size is clamped to the work area and only floored to
the window's own minimum when the work area is large enough for it, so it
never opens larger than the screen. SPI_GETWORKAREA falls back to the
full screen metrics when it fails, as it can on 9x.
The default view stays the report list, which matches the Qt companion's
own default (VIEW_TYPE_LIST); the grid in the reference screenshot was a
persisted user choice, not the startup state.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean). Not
run here (no Windows).
* ui/drivers: search box and Edit menu in the native Win32 companion
Visual/behavioural parity with the Qt companion, which has a Search box
and an Edit -> Search action. The Win32 companion gains an EDIT strip
above the entry list and an Edit menu with Search (Ctrl+F focuses the
box, matching Qt's shortcut). Typing filters the current content view -
playlist entries or the file browser - by case-insensitive substring,
the same field Qt's proxy model filters on.
Filtering makes list-view rows non-contiguous with entry indices, so the
entry index now rides in each row's lParam and the readers use it: a new
cw_selected_entry() resolves the selection through lParam (browse rows
are never filtered, so they stay row == index), and the lazy thumbnail
decode walks visible rows and reads each row's lParam. The image list is
sized to the full count and installed before items reference it; the
per-frame decode budget is unchanged.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean, linux
c89 pass for the shared paths). Not run here (no Windows).
* ui/drivers: boxart preview pane for the native Win32 and Cocoa companions
Parity with the Qt companion's Boxart dock. View -> Boxart (Win32) /
Companion -> Boxart (Cocoa) shows the selected playlist entry's boxart,
updated as the selection moves. It resolves through the same
companion_core_thumbnail_path() rule as the grid, so image content and
the repository layout behave identically.
Win32: a STATIC (SS_BITMAP) in the right column below the core-info pane
- the column appears when either is shown and splits between them. The
image is decoded on LVN_ITEMCHANGED, scaled to the pane preserving
aspect into a 32-bit DIB (image_texture_load's ARGB8888 is Windows' BGRA
order), and the previous HBITMAP is freed. Cocoa: an NSImageView on the
right edge (proportional scaling), refreshed from the entries table's
selection-changed delegate.
Nothing decodes while the pane is hidden or in file-browser mode, and
only the selected entry is decoded, so there is no per-frame cost.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean);
companion_parity.py green; apple_mrc_ownership_check.py reports only the
two known local-autorelease hits. Not run here (no Windows / macOS).
* ui/companion: lead the playlist list with the special playlists
The Qt companion's left pane starts with Favorites, History, Images,
Music and Videos above the system playlists; the native companions,
which build their list from companion_core_playlist_count/_name/_path,
only saw the .lpl files in the playlist directory - so History and
Favorites were unreachable there.
The core now returns those five as leading playlist entries, in the Qt
order, each a real .lpl at its configured path
(path_content_favorites / _history / _image_history / _music_history /
_video_history); a path left empty in the config is skipped, so the
lead count is not always five. Names come from the existing *_TAB label
strings. Selection, delete and core-association already key off the
public index / path, which now map through the specials, so they follow
without change; select_playlist_path matches against the public paths
too.
Qt is unaffected: it builds its own special-playlist items (including
the synthetic "All Playlists", which is not a file and stays a
presentation concern) and does not enumerate through these accessors.
Verified: companion_core.c and the consumers of companion_core.h pass
tools/mingw_syntax_check.sh; companion_parity.py green.
* ui/drivers: Win32 companion puts the search box in the left column
The Qt companion's search field sits at the top of the left content
column, above the playlist list; the native Win32 companion had it above
the entry list on the right. Move it to match: the left column is now
the search box on top and the playlist list below it, and the entry list
spans the full height on the right, so the two windows line up.
Layout only - the EDIT still filters the current content view the same
way, and the splitter, browse, info and boxart panes are unchanged.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean);
companion_parity.py green. Not run here (no Windows).
* ui/drivers: lay the Win32 companion out like the Qt companion
The Qt companion is the reference look; the native Win32 window had the
same features behind a different shape. This makes its structure match
the Qt startup layout, using classic controls only (all on Windows 95
with comctl32 4.70) and the same msg_hash strings Qt shows:
Left column, as Qt's docks:
Search [edit][Clear]
Content Browser
[Playlists | File Browser] (a tab control; the second tab enters
the file browser, the first returns)
[playlist list] (a list view with the shell folder icon
per row, like Qt's, replacing the LISTBOX)
Core
[launch-with combo][Info][Run]
The Core section is Qt's launch-with combo: companion_core_launch_options
for the selected entry (running / entry's own / playlist default core),
plus "Ask" and "Load Core..."; Run launches with the chosen core, Ask and
Load Core open the picker. This was the last Qt behaviour the natives
lacked - they previously always asked.
Centre: the entry list over Qt's footer ("N items" from
QT_ITEMS_COUNT on the left, a View: List / Icons combo on the right).
Right column: "Core Info" and "Boxart" captions over their panes, both
shown by default as Qt does. Menubar: File / Edit / View / Help with
Qt's titles; Help gains Documentation (docs.libretro.com) and About.
Status bar defaults to "<version> - <core or No Core>" and follows the
running core.
Every control is set to DEFAULT_GUI_FONT - the bold bitmapped System
font the controls default to was most of why the window looked nothing
like Qt.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean);
companion_parity.py green. Not run here (no Windows) - the pixel pass
against the Qt screenshot needs a real box.
* ui/drivers: Win32 companion scales with the display DPI like Qt
The side-by-side on a 200% display showed the Win32 companion at half
the Qt companion's size with captions overlapping their controls and
text truncated everywhere. Cause: Qt sizes in logical (96-dpi) pixels
and renders them at the monitor's DPI - its 1280x720 fills a 2560x1440
screen - while the native window used the same numbers as raw pixels,
and its DEFAULT_GUI_FONT is a fixed 8pt bitmap that does not scale, so
the rows sized for it could not hold the text the display wanted.
Now everything scales the way Qt does:
- LOGPIXELSY is read once and every logical size (startup 1280x720,
minimums, pane and column widths, splitter, boxart height, icon size,
icon-view spacing, padding) goes through MulDiv against 96
- the font is the system message font from NONCLIENTMETRICS, which is
the DPI-scaled UI font (Segoe UI at the display's size on modern
Windows, MS Sans Serif on 9x), created once and freed on deinit; the
stock font remains the fallback
- row heights derive from that font's TEXTMETRIC (caption = one line,
control = line + chrome) instead of fixed 18/24
- list columns are sized to their panes on every layout (playlist
column to the pane, Name/Core 2:1 across the entry list, info key
column narrow with the value taking the rest), so nothing truncates;
the info list drops its column header as Qt has none
- the left pane defaults to 280 logical px, Qt's dock width
All APIs used date from Windows 95 (GetDeviceCaps, CreateFontIndirect,
SPI_GETNONCLIENTMETRICS, MulDiv).
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean);
companion_parity.py green. Not run here (no Windows).
* ui/drivers: fix the zero-size Win32 companion window and the Xcode build
Win32: the DPI-scaling commit read w->dpi before it was set. The DPI /
font block sat after the main window's size was computed and the window
created, so CW_S() ran MulDiv(x, 0, 96) = 0 for the startup size and the
WM_GETMINMAXINFO minimums - a zero-size window, the near-invisible strip
in the report. Move the DPI / font setup to the top of cw_create_window,
before anything is sized.
Cocoa: the Xcode (ARC) build failed on the core-info pane's construction
- "passing address of non-local object to __autoreleasing parameter for
write-back": an ivar (infoScroll) was used as the scroll-view
out-parameter of -makeTable:scroll:twoColumns:. Under ARC such a
parameter is __autoreleasing and must be a local; go through one and
assign it to the ivar (ARC retains the strong ivar, KEEP_IVAR adds the
retain under MRC). The other three callers already used locals.
Also declare the controller's protocols (NSTableViewDataSource /
Delegate, NSWindowDelegate, NSMenuDelegate) when the SDK is 10.6+, so
the four setDataSource: / setDelegate:self "incompatible type" warnings
in that build go away; older SDKs use the informal protocols and keep
the plain declaration.
Verified: ui_win32_companion.c passes tools/mingw_syntax_check.sh (mingw
-Wall -Wextra clean); companion_parity.py green;
apple_mrc_ownership_check.py unchanged (the two known local hits).
* ui: playlist icons, single-column core info, 50/50 right column on Win32 (Qt parity)
Second side-by-side pass at 200% DPI, Qt leading. The window now opens
at the same size with legible controls; the remaining differences were:
- Playlist icons. Qt shows the XMB dot-art asset for each system
(<assets>/xmb/dot-art/png/<playlist>.png, folder.png as fallback) at a
large row height; Win32 showed a 16 px shell folder on every row. The
asset rule moves into the core (companion_core_playlist_icon_path, so
Cocoa gets the same icons) and the Win32 list decodes each icon into a
32 px image list through the existing scaler, which also gives the
rows Qt's height. The shell folder stays at index 0 as the fallback
when the asset set is not installed. Icons are rebuilt with the list,
i.e. on playlist-directory changes only, not per frame.
- Core Info. It was a two-column key / value list, so the no-core text
(a key with no value) truncated at the key column, and long firmware
lines were cut. Qt renders "Key: value" as one text line per row; do
the same in a single wide column that scrolls horizontally instead.
- The right column splits 50/50 between Core Info and Boxart, as Qt's
two docks do, rather than a fixed boxart height.
- Entry columns titled "Name" / "Core" (QT_NAME / QT_CORE) rather than
the entry-dialog labels with their colons; the footer drops the
separate "View" caption Qt does not have.
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); consumers of
companion_core.h pass; companion_parity.py green. Not run here.
* ui: the main loops and the Win32 window stop hard-coding Qt as "the" companion
Sweep of HAVE_QT / HAVE_QT6 outside the Qt driver itself. Most sites are
legitimately Qt-specific (griffin_cpp's TU list, the feature-list
strings, the griffin HAVE_MAIN hack, config.features.h, Qt's own entry
in the companion driver table, and ui_cocoa.m choosing rarch_main over
the draw observer because of Qt's event loop) and stay. Five were
companion-generic behaviour wired to Qt alone:
- retroarch.c main loop: `ui_companion_qt.application->exiting` and
`->quit()` under HAVE_QT. That is "the active desktop companion asked
to exit / tell it to quit", whichever driver is selected. New
ui_companion_driver_wimp_exiting() / _wimp_quit() route it through
uico_st->wimp; ui_cocoa.m's rarch_main and cocoa_common.m's draw
observer use the same two calls (the observer path also gains the
wimp deinit before main_exit, the ordering fix the Win32 quit hang
needed, which it had missed).
- ui_win32.c: the main window's "Toggle Desktop Menu" item (and its
label lookup) existed only #ifdef HAVE_QT, so a native-companion
build had no menu entry to open its companion. Now HAVE_COMPANION_WIMP.
- configuration.c: the ui_companion_toggle SETTING_BOOL was gated on
HAVE_QT || HAVE_COCOA - the pre-refactor condition, missing desktop
Win32 and HAVE_COCOA_METAL. Now HAVE_COMPANION_WIMP.
- settings_def_menu_main_lists_2.h: the SHOW_WIMP ("Show Desktop Menu")
action row was HAVE_QT only, so the main menu had no way to open a
native companion. Guard widened to the HAVE_COMPANION_WIMP condition,
spelled out as settings_def cannot include the header.
tools/settings_table.reference regenerated (unchanged - the desktop
profile already defines HAVE_QT).
Behaviour for Qt builds is identical (same calls, through the driver
slot). Verified: settings table --check, unity (3 profiles) and
migrate selftest pass; all 15 consumers of ui_companion_driver.h,
configuration.c, ui_win32.c and retroarch.c pass
tools/mingw_syntax_check.sh; full Qt 6 retroarch links and starts
headless; companion_parity.py green.
* ui/companion: native companions read and write retroarch_qt.cfg
The Qt companion keeps its own settings in retroarch_qt.cfg beside
retroarch.cfg (QSettings, INI form); the native Win32 and Cocoa
companions ignored it, so a view type, thumbnail type, start playlist or
"suggest loaded core first" set in one did not carry to the others. All
three now share that file.
RetroArch's config_file cannot read it: its key scan takes every graph
character as part of the key, so QSettings' unspaced `key=value` becomes
a key with no '=' and the line is dropped - confirmed with a harness, it
parsed zero entries from a real retroarch_qt.cfg. Rather than touch that
hot parser, the core gets a small dedicated reader/writer for the
dialect: "[section]" and comment lines skipped, split at the first '=',
values verbatim, written back in QSettings' own shape so Qt reads it.
Unknown keys (Qt's @ByteArray geometry, theme...) survive a rewrite.
Verified with the harness: every key read, a set-and-reread round trip,
and the geometry blob preserved.
companion_core_setting_get / _get_bool / _get_int / _set / _set_bool
Both native companions honour the keys Qt writes:
view_type list / icons at startup; persisted on switch
icon_view_thumbnail_type boxart / screenshot / title / logo for the
icon view and the boxart pane
initial_playlist opened at startup, History as the fallback
(Qt's default), applied once
suggest_loaded_core_first launch-with combo ordering
show_hidden_files directory scan
save_last_tab / last_tab restore the Playlists / File Browser tab;
persisted on change when save_last_tab is on
Reads are a file load per call: only at startup and on user actions,
never per frame.
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); consumers of
companion_core.h pass; full Qt 6 retroarch links; companion_parity.py
green; apple_mrc_ownership_check.py unchanged. Not run here.
* ui: companion settings move from retroarch_qt.cfg into retroarch.cfg; Qt-isms dropped
The Qt companion kept its presentation settings in a private QSettings
INI, retroarch_qt.cfg, and the previous commit taught the natives to
read that file. One config is cleaner: the values become real RetroArch
settings in retroarch.cfg, saved with everything else, visible in the
Settings menu, and read by all three companions through settings_t. The
retroarch_qt.cfg reader/writer added last commit is removed again.
New settings (settings_def_desktop_menu.h, same HAVE_COMPANION_WIMP
guard; menu placement beside desktop_menu_enable; tools/
settings_table.reference regenerated, 19 rows):
desktop_menu_view_type uint 0 list / 1 icons
desktop_menu_thumbnail_type uint boxart/screenshot/title/logo
desktop_menu_suggest_loaded_core_first bool
desktop_menu_save_last_tab / _last_tab bool / uint
desktop_menu_save_geometry bool
desktop_menu_window_x/_y/_width/_height uint - the window geometry as
plain ints, replacing Qt's
QByteArray saveGeometry() blob
desktop_menu_show_welcome_screen bool
desktop_menu_scan_finish_confirm bool
desktop_menu_thumbnail_cache_limit / _max_size / _quality uint
desktop_menu_icon_view_zoom uint
desktop_menu_all_playlists_list_max_count / _grid_max_count uint
desktop_menu_theme uint system/dark/custom
desktop_menu_initial_playlist, desktop_menu_custom_theme (SETTING_PATH)
desktop_menu_hidden_playlists (comma list), desktop_menu_highlight_color
("#rrggbb") (SETTING_ARRAY)
Qt's private copy of show_hidden_files is dropped for RetroArch's own
show_hidden_files.
Qt-isms removed rather than carried: the QByteArray blobs for dock
positions (and its View Options checkbox), the file-browser table
header state and the options-dialog geometry are gone; window geometry
restores from the four ints. QSettings is no longer used anywhere: the
member, its construction, MainWindow::settings() and the two widget
copies are deleted, and every read/write goes through settings_t (the
View Options dialog included). Writes take effect immediately and reach
disk when RetroArch saves its config.
The companion core exposes the shared values to the backends as typed
accessors (companion_core_pref_*), including the thumbnail-type ->
repository-subdir mapping in one place; both native companions use them.
Verified: settings table --check, unity (3 profiles) and migrate
selftest pass; label strings regenerated (gen_lbl_str.py); consumers of
companion_core.h, ui_win32_companion.c, configuration.c,
menu_displaylist.c and menu_setting.c pass tools/mingw_syntax_check.sh
(mingw -Wall -Wextra clean); full Qt 6 retroarch links and starts
headless; companion_parity.py green; apple_mrc_ownership_check.py
unchanged.
* ui/companion: retroarch_qt.cfg is gone - one-time import into retroarch.cfg, then deleted
The previous commit moved the companion settings into retroarch.cfg; this
one makes sure the old file actually disappears. On the first companion
start that still finds retroarch_qt.cfg beside retroarch.cfg, the core
imports the values that have a home into settings_t and deletes the
file, so it does not linger as dead configuration after an upgrade.
Runs once per process at most.
Imported (with the same value mapping the Qt companion used):
view_type, icon_view_thumbnail_type, initial_playlist,
suggest_loaded_core_first, show_hidden_files, save_last_tab / last_tab,
save_geometry, show_welcome_screen, scan_finish_confirm,
thumbnail_cache_limit / _max_size / _quality, icon_view_zoom,
all_playlists_list/grid_max_count, theme, custom_theme, highlight_color,
hidden_playlists (QStringList's ", " separators normalised to ",").
Dropped with the file: the Qt blobs (geometry, dock_positions,
options_dialog_geometry, file_browser_table_headers).
Stale comments naming retroarch_qt.cfg in the natives, config.def.h,
settings_def_desktop_menu.h and menu_displaylist.c are updated; no
source mentions the file any more except this migration.
Verified with a harness against a real QSettings-shaped file: every key
lands as the right typed value, blobs are skipped, the file is removed
(a whole-process run confirmed the import log line and the deletion;
the exit-time config save could not be exercised headless).
companion_core.c passes tools/mingw_syntax_check.sh; consumers of
companion_core.h pass; full Qt 6 retroarch links; companion_parity.py
green.
* ui/drivers: Win32 companion - core combo and Core Info work, icon alpha, zoom, Boxart tabs
Five defects from the side-by-side, all in the Win32 companion:
- The Core combo dropped down to nothing. A COMBOBOX's window height is
the height of its *dropped list*, and the layout sized both combos to
one closed row, so the list had no room. They are now given list room
(the closed control stays one row tall regardless). The combo was in
fact populated; it just could not show its items.
- Core Info always read "No Core Information Available". The pane
followed the running core; Qt shows the core picked in the Core combo
(the entry's own or the playlist default). It now does the same:
cw_combo_core_path() resolves the combo's selection and the pane
refreshes on entry selection, on combo change, and when that core
changes.
- Playlist icons sat on black. The scaler forced alpha to opaque, so
transparent XMB PNGs kept whatever was under them. It now composites
the source alpha over the control colour, giving an opaque result
every comctl32 draws identically (v6 alpha and 9x mask-less alike).
- No thumbnail zoom and a fixed thumbnail size. The icon-view edge now
comes from desktop_menu_icon_view_zoom (0..100 -> 64..320 logical px,
DPI-scaled), with Qt's Zoom slider (msctls_trackbar32) and Thumbnail
type combo in the footer; a change rebuilds the image list and
redecodes. New companion_core_pref_icon_view_zoom / _thumbnail_type
accessors (and setters) back both.
- No way to switch the boxart pane's type. It gets Qt's four tabs
(Boxart / Title Screen / Screenshot / Logo) under its caption; the pane
keeps its own type, independent of the grid's Thumbnail combo, as Qt's
dock does.
Also: the status bar returns to "<version> - <core>" once a playlist has
loaded instead of staying on "Loading playlist...".
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); consumers of
companion_core.h pass; full Qt 6 retroarch links; companion_parity.py
green. Not run here (no Windows).
* ui/drivers: fix the Win32 icon view's cell spacing (grid came up scrambled)
After the zoom change the icon view laid items out in cells a few pixels
wide: labels wrapped to three characters and items piled on top of each
other. The cell spacing was computed from w->thumb_px, which is only set
when the thumbnail image list is (re)built - but at startup the view
type is applied before the first playlist builds it, so the spacing was
0 + 24 by 0 + 40 px. A zoom or thumbnail-type rebuild then resized the
image list without ever reapplying the spacing either.
The spacing now comes from the live thumbnail edge whenever it is
applied (cw_icon_spacing_apply), is reapplied every time the image list
is rebuilt at a new size, and the grid is re-arranged (LVM_ARRANGE)
after a rebuild or a view switch so existing items take the new cells.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean);
companion_parity.py green. Not run here (no Windows).
* ui: "All Playlists" for every companion, and it is where all three start
Qt's playlist list begins with All Playlists - the union of every
playlist - and that is the view it opens on. The native companions had
neither, so the two windows came up on different pages and the natives
could not show the combined library at all.
The aggregate is in the core so every backend shares it. Public playlist
index 0 is now All Playlists (name from QT_ALL_PLAYLISTS, path the token
"|||ALL|||" Qt has always used, so desktop_menu_initial_playlist can
name it and the setting means the same thing everywhere); the specials
and files follow. Selecting it parses every playlist file in turn under
the same per-frame budget as a single playlist - one file's parse
finishes, the next begins, the view updates once at the end - and the
entries are referenced through a (list, index) table rather than copied,
then sorted by label (strcasecmp) as Qt sorts, and capped by the larger
of desktop_menu_all_playlists_list/grid_max_count (0 = no cap).
Edits under the aggregate go to the entry's own file: new
companion_core_entry_playlist_path() / _entry_index_in_playlist()
resolve an aggregate row to the file it came from and its index there;
the Win32 and Cocoa delete actions use them, and playlist_open() rejects
the token so nothing can ever try to write "|||ALL|||.lpl".
Startup: with desktop_menu_initial_playlist empty, Qt, Win32 and Cocoa
all open All Playlists (Qt's History fallback goes too, so the three
agree). The All slot shows the folder icon like the specials.
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); consumers of
companion_core.h pass; full Qt 6 retroarch links; companion_parity.py
green; apple_mrc_ownership_check.py unchanged. The aggregate itself
needs a run with real playlists (it cannot be driven headless here).
* ui: select the first entry on load, and All Playlists is uncapped by default
Two more from the side-by-side, Qt leading:
- Qt selects the first entry of a freshly loaded playlist, so the boxart
pane and the Core section have content immediately; the natives left
nothing selected and the panes empty. Win32 now selects row 0 after the
entry list is rebuilt (LVN_ITEMCHANGED drives boxart, core combo and
core info from there); Cocoa selects row 0 in the table and the grid.
- All Playlists showed "1000 items" against Qt's 42116. The cap I gave
it took the larger of the list / grid max counts, and I had invented a
grid default of 1000. Qt in fact never applies either count (the
setters are set-only and their spin boxes are commented out), which is
why it shows everything. The grid default is now 0, and a cap applies
only when both counts are set (0 = no cap on that side), then the
larger - so the default is uncapped like Qt, while a user who sets
both still gets a bound. tools/settings_table.reference updated for
the default.
Verified: settings table --check, unity (3 profiles) and migrate
selftest pass; companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); full Qt 6
retroarch links; companion_parity.py green; apple_mrc_ownership_check.py
unchanged.
* ui: align companion guards with master's HAVE_COCOA; unretained grid back-pointer
* ui/drivers: bring the Cocoa companion up to the Qt / Win32 layout and feature set
The native Cocoa companion had fallen well behind: two bare tables in a
split view, no launch-with core, no zoom, no thumbnail or boxart type
switches, no search, no playlist icons, Core Info following the running
core, and its own status text. This puts it on the same footing as the
Win32 companion, Qt leading:
Layout (explicit frames recomputed in -layoutViews on resize; 10.4-safe,
no autolayout; points, so the display scales it as it does Qt):
Left column, as Qt's docks: Search [field][Clear]; Content Browser
with a Playlists | File Browser NSTabView (the second tab enters the
file browser, the first returns); the playlist table with an icon
column (XMB dot-art per system via companion_core_playlist_icon_path,
the Finder folder as fallback) at Qt's row height; Core: launch-with
NSPopUpButton + Info + Run.
Centre: the entries table or grid over Qt's footer - "N items", Zoom
slider, Thumbnail type popup, View (List / Icons) popup.
Right column: Core Info caption + single-column "Key: value" list,
Boxart caption + NSSegmentedControl for the four types + image view;
both shown by default, 50/50, like Qt's docks.
Window opens at 1280x720 centred, clamped to the screen; status bar
reads "<version> - <core or No Core>" and follows the core.
Behaviour, all through the shared core and its pref accessors:
- launch-with popup from companion_core_launch_options plus Ask and
Load Core...; Run launches with the choice, Ask / Load Core open the
picker; Core Info follows the popup's core as Qt's does, refreshed on
entry / grid selection and popup change
- zoom slider drives the grid's thumbnail edge (64..320 pt) and
persists desktop_menu_icon_view_zoom; thumbnail popup switches the
grid's type and redecodes; boxart segments switch the pane's own type
- search field filters the entry table (case-insensitive substring)
through a row -> entry map, so run / delete / boxart / popup resolve
the right entry under a filter; Clear resets it; Cmd-F focuses it
- view popup and menu items stay in sync; last tab persisted when
desktop_menu_save_last_tab is on; shared settings applied at start
- grid selection now drives boxart / popup / info like table selection
- Companion menu uses Qt's strings and gains Documentation
The split view and the toggles that added panes to it are gone; Core Info
/ Boxart toggles show or hide within the fixed layout.
Verified: apple_mrc_ownership_check.py unchanged (the two known local
autoreleased objects); bracket / brace / paren balance checked by a
character-level scan; every declared selector has an implementation;
companion_parity.py green. Not compiled here (no Apple toolchain) - the
Xcode build and a run are the real test for this one.
* ui/drivers: fix the Cocoa companion build (undeclared -wimp, Carbon icon constant)
CI on the Cocoa layout commit (95dee5f) fails the three Apple jobs -
macOS (Xcode, clang/ARC) and macOS PowerPC cross 10.4 / 10.5 (GCC 14,
10.5 SDK, MRC) - while every Windows, MSVC, MXE, c89 and Linux job is
green, so the breakage is confined to ui_cocoa_companion.m. Two errors,
found by auditing the file against those toolchains (the job logs are
not readable without a login from here):
- RACompanionGrid's -drawRect: calls [owner wimp] to reach the core,
but the controller never declared or defined a -wimp accessor. GCC
rejects the unknown selector on a typed receiver; clang under ARC
rejects the resulting id -> ui_companion_cocoa_wimp_t* conversion
outright ("implicit conversion of an Objective-C pointer to a C
pointer is disallowed with ARC"). Declared and defined.
- The playlist folder fallback used kGenericFolderIcon, a Carbon
constant from Icons.h that AppKit alone does not declare. The generic
folder's HFS type is 'fldr'; pass the literal to
NSFileTypeForHFSTypeCode (10.0), which the 10.4u import audit accepts.
Re-checked: every selector sent to self / owner is now declared and
implemented; all top-level C functions are static (the build carries
-Werror=missing-declarations); bracket balance by character scan;
apple_mrc_ownership_check.py unchanged; companion_parity.py green.
* ui/drivers: fix the Cocoa companion build (Xcode log: shadowed grid edge, BOOL receiver)
From the CI Xcode log on c2e0e39:
- error: passing 'NSRect' to parameter of incompatible type 'CGFloat'
(and five "invalid operands" errors following it) in
RACompanionGrid -drawRect:. When the grid's fixed CC_GRID_THUMB
became the zoomable `thumb` ivar, the rename collided with the
method's existing local `NSRect thumb` (the thumbnail's box), so the
edge and the box became one identifier. The box is now `trect`; the
edge stays `thumb`.
- error: bad receiver type 'BOOL': [[window makeFirstResponder:grid]
self] messaged the BOOL that -makeFirstResponder: returns. Dropped the
outer message.
Also cleared the warnings the log shows in the same method:
-setFlipped: (deprecated 10.6) is now only used below the 10.6 SDK; on
10.6+ the draw call takes respectFlipped:YES instead, which is the
replacement Apple's notes describe. NSCompositeSourceOver goes through
the compat name the defines header already provides, and the two
NSTextAlignment* names are mapped to their pre-10.12 spellings under an
SDK check so the 10.5-SDK PowerPC build sees them too.
Re-checked: bracket balance by character scan; every selector sent to
self / owner declared; apple_mrc_ownership_check.py unchanged.
* ui/drivers: Win32 companion entry list goes virtual - grid builds instantly
Building the icon view took minutes on a large library where Qt is
instant. Three costs, all structural: the entry list was a retained
list view, so populating it was one LVM_INSERTITEM (plus a sub-item
set) per entry - 42k round trips through the control; LVM_ARRANGE then
laid out 42k icon cells; and thumbnails were decoded top-to-bottom at
one per frame regardless of what was on screen, so the visible screen
only filled in once everything above it had (42k entries: twelve
minutes). Qt's view is virtual: its model reports a count, cells are
drawn on demand, thumbnails load for the cells actually shown.
The entry list is now the Win32 equivalent, LVS_OWNERDATA (comctl32
4.70, Windows 95):
- populating is a filtered row map (rows[]: visible row -> entry index)
and one LVM_SETITEMCOUNT, whatever the size; no inserts, no arrange.
The search filter builds the same map, so run / delete / boxart / core
combo resolve through rows[] instead of a per-item lParam.
- the control asks for each row's text and image as it draws
(LVN_GETDISPINFOA - the ANSI notification, matching the ANSI control
even under a UNICODE build); the browse view is served the same way,
with the trailing backslash on directories.
- thumbnails are decoded only for rows the control has asked to draw:
GETDISPINFO queues a row that has no image yet, and the iterate hook
drains the queue newest-first (the rows most likely still on screen)
within a 4 ms budget, redrawing each row as its image lands. Nothing
is decoded for rows never scrolled to.
- memory is bounded: decoded thumbnails live in a ring of 512
image-list slots, recycled round-robin; an evicted row falls back to
the placeholder and re-queues if it comes into view again. Previously
the image list grew by one bitmap per entry (42k x 128 x 128 x 4 =
2.7 GB for a full pass).
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean), plus
a -DUNICODE syntax pass; companion_parity.py green. Not run here.
* ui/drivers: Win32 companion decodes thumbnails on a thread pool
Still slower than Qt after the virtual list. The remaining gap is where
the decode runs: Qt's ThumbnailLoader is a dedicated thread that runs
image_texture_load (the same decoder) with no per-frame budget, and its
UI thread only receives finished images. The Win32 companion decoded on
the UI thread under a 4 ms/frame budget - a boxart PNG takes 5-20 ms,
so about one thumbnail per frame, sharing that frame with emulation.
Now the decode is off the UI thread, and arranged to come out ahead of
Qt rather than level with it:
- a pool of decode threads (cores - 1, at least one, at most four;
libretro-common rthreads, so it builds wherever HAVE_THREADS does,
9x included) takes jobs newest-first - the rows most likely still on
screen - and decodes in parallel. Qt has one thread.
- each worker scales to thumbnail size itself and hands the UI thread a
T x T ARGB buffer; the UI thread's per-frame work is a DIB and an
image-list replace per finished thumbnail (~0.2 ms), never a decode.
Qt caches the full-size pixmap and rescales it on every paint.
- the request path resolves the file on the UI thread (the companion
core is single-threaded), so a job needs nothing from the core.
- a generation counter, bumped when the list, filter, zoom or thumbnail
type changes, makes in-flight results stale; they are dropped when
they land rather than blitted into the wrong row or size.
- all cross-thread state (queues, row map, thumb_idx, thumb_px) is read
and written under one lock; workers park on a condition and are woken
by requests and by ring space; shutdown joins them.
- without HAVE_THREADS the UI thread decodes under the old budget, so
the driver still builds and works.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean) with
and without HAVE_THREADS; companion_parity.py green. The pipeline
itself (queue, ready ring, worker loop, generation handling, shutdown)
was extracted into a Linux harness against the real rthreads and run
under ThreadSanitizer: no races, every decode installed exactly once,
stale results dropped, nothing leaked. The decode / GDI halves need a
Windows run.
* ui/drivers: Win32 companion - fix the quit hang; thumbnails cached across playlists
Two reports after the thread-pool commit: RetroArch hangs at close, and
the grid, while faster, is still not "instant" the way Qt's is.
The hang. ui_companion_win32_wimp_deinit freed the row map, thumb_idx
and the image list and only then called DestroyWindow. A virtual
(LVS_OWNERDATA) list view can ask for rows (LVN_GETDISPINFO) while it
is being torn down, so the handler read freed memory and a destroyed
image list during DestroyWindow - a fault inside the modal-clocked
teardown, which presents as a hang. Deinit now empties the list
(LVM_SETITEMCOUNT 0, image list detached) and destroys the windows
first, and frees the data after; the hwnd/entries pointers are cleared
so a late iterate or log call is a no-op. The pool shutdown is also
made hang-proof on its own: workers wait with a 100 ms timeout so a
lost wake-up on the Windows condition variable can never keep one
parked past quit, and stop broadcasts rather than signalling per
worker. (A TSan harness of the real pipeline code with four workers,
mid-decode and ring-blocked at quit, stops in 0 ms with no races.)
The "instant". The Qt companion keeps decoded pixmaps in a QCache keyed
by file path that survives switching playlists, so revisiting one draws
thumbnails with no decode at all. The Win32 slots were per row and
reset on every rebuild. They are now keyed by thumbnail path in an
open-addressed hash table and kept across list changes: only a new
thumbnail size or type drops them. A row whose file is already a slot
gets it on the spot, no decode. The slot budget follows the size to
stay near 64 MiB (a few hundred at 320 px, thousands at 64 px). Rows
whose thumbnail file does not exist are marked once (-2) so the
filesystem is not probed for them on every paint.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean) with
and without HAVE_THREADS; companion_parity.py green; the pipeline
harness under ThreadSanitizer (shutdown stress, 5 trials). GDI / window
teardown needs the Windows run.
* ui: Win32 File Browser laid out like Qt's; drive list on Windows
The File Browser tab on Win32 came up empty and did not work the way
Qt's does.
Empty: with no content directory configured, the core refused to open
a top level on Windows (I had ruled out a "bogus root"), so there was
nothing to list. On Windows the top level is the drive list: the core
now lists GetLogicalDrives() as directory entries ("C:\") for an empty
browse_dir, a drive root's ".." goes back to it, and the status bar
calls that level "Computer".
Layout: Qt's File Browser keeps the folder tree in the left pane and
shows the selected folder's files in the content view. Win32 had turned
the content view into a combined folder + file listing and left the
playlists in the left pane. Now, in the browser: the left list shows
the current folder's subfolders (".." first, folder icon), the content
view - list or grid - shows its files, a folder descends on double-
click / Enter, and a file loads (or opens the core picker) as before.
Leaving the tab, or picking a playlist, puts the playlists back in the
left pane; a playlist refresh that lands while browsing is deferred to
then. The core exposes the split (companion_core_browse_dir_count: the
listing is sorted folders first, so [0, dc) are folders and [dc, n)
files) for any backend that wants the same two-pane shape.
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); consumers of
companion_core.h pass; companion_core.o builds; companion_parity.py
green. Not run here (no Windows).
* ui: Win32 file browser - drive names shown, folder icon opaque
Two defects in the drive list the previous commit added:
- No names. companion_core_browse_name() took path_basename() of each
entry; a drive root "C:\" has no basename, so every row was blank.
When the basename is empty the name is the path itself.
- Black squares behind the folder icons. The fallback icon went into
the playlist image list raw (ImageList_AddIcon) and the list was
created with ILC_MASK; a masked list draws an alpha icon's transparent
pixels as black. The list is now unmasked and every image in it is an
opaque bitmap composited on the window colour: index 0 is the XMB
folder.png asset (what Qt shows) through the same compositing scaler
the playlist icons use, and only if the asset set is missing is the
shell folder icon used - drawn with DrawIconEx onto a window-coloured
bitmap, so it too is opaque. companion_core_folder_icon_path() gives
backends the asset's path.
Verified: companion_core.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean); consumers of
companion_core.h pass; companion_parity.py green. Not run here.
* ui/companion: shared thumbnail engine for every companion, with a regression test
Thumbnails in the Win32 grid only appeared for entries that were
clicked. Reading the Qt companion's pipeline end to end
(ThumbnailLoader, PlaylistModel::loadThumbnail, MainWindow::
updateVisibleItems, GridView::visibleIndexes) gives the model and, by
contrast, the bug:
Qt requests decodes for the rows its grid reports as visible, on a
50 ms scroll debounce, and never for anything else. Win32 requested
from LVN_GETDISPINFO - and comctl32 sends that for every item of a
virtual icon view while laying it out, so a 42k-entry list flooded
the 512-job queue, the oldest (the visible top) were dropped, the
workers decoded the bottom of the list, and a visible row was only
requested again when something repainted it: a click.
Rather than patch that in place, the whole pipeline moves into the
core as one engine every companion uses, ui/companion/companion_thumbs:
- cache of decoded, already-scaled thumbnails keyed by (path, edge),
byte budget (64 MiB default) with LRU eviction; survives switching
playlists, so a revisit draws with no decode (Qt's QCache behaviour)
- decode thread pool (cores - 1, 1..4; Qt has one), scaling on the
worker so the UI thread only ever copies finished pixels; a budgeted
UI-thread fallback without HAVE_THREADS
- two-lane request queue: urgent jobs newest-first (the rows on
screen, topmost first), then a prefetch lane oldest-first; keys are
de-duplicated against the cache and the queues
- cancel() empties the queues and keeps the cache; results in flight
still land and are cached; delivery carries the backend's tag, which
encodes its own row generation, so a stale result is dropped by the
backend, never blitted into the wrong list
- pixels are opaque ARGB8888: Windows' DIB order, a byte swap for Cocoa
Both natives now drive it the way Qt drives its loader:
Win32: each frame, the rows on screen are found from the list view's
own item rects (monotonic in row order, so a binary search), requested
urgently topmost-first, a screen either side prefetched; finished
pixels go into a recycled image-list slot ring; LVN_GETDISPINFO only
reads a row's slot. The local thread pool, hash table and rings are
gone.
Cocoa: the grid reports its visible rows from its visibleRect; the
same request / prefetch / poll cycle runs from iconTick; finished
pixels become an NSImage through an NSBitmapImageRep. The per-frame
synchronous NSImage load is gone.
Regression test: ui/companion/test/companion_thumbs_test.c, run by
tools/companion_thumbs_test.sh plain, under ThreadSanitizer and under
ASan+UBSan, against the real decoder (image_texture_load) with TGA
fixtures it writes itself. It checks a decode lands with the right
scaled / letterboxed pixels, cache hits without decode, LRU eviction
under budget, cancel keeping the cache and allowing re-requests, an
undecodable file delivered as NULL and forgotten, 300 keys over four
threads delivered exactly once, and free() with work in flight. The
engine is also compiled once as C89 (-ansi -pedantic, no threads).
Wired into Linux-libretro-common-tests.yml beside the parity check.
The test found one engine bug before it ever reached a backend
(re-request of a key whose decode was in flight across cancel()).
Verified: the test passes plain, TSan and ASan; companion_thumbs.c,
ui_win32_companion.c and the consumers of companion_thumbs.h pass
tools/mingw_syntax_check.sh (also with HAVE_THREADS off); full Qt 6
retroarch builds with the engine in and starts headless;
companion_parity.py green; apple_mrc_ownership_check.py unchanged.
Not run on Windows / macOS here.
* ui/companion: boxart panes on the engine; Cocoa two-pane browser; engine takes w x h
Follow-ups to the shared thumbnail engine, so both natives are on it
for everything and nothing decodes on a UI thread any more:
- The engine keys and scales by (path, w, h) rather than a square
edge, so the boxart pane can ask for its own rectangle and get an
aspect-fit, letterboxed image instead of a square. Grid cells pass
edge x edge. The test gains a rectangular case (20x80 into 60x30:
centre column image, corners letterbox).
- Boxart panes (Win32 and Cocoa) come from the engine: cached at once,
otherwise an urgent request tagged with the entry and a boxart bit,
delivered through the same per-frame poll, which now also runs in
list view so the pane fills in there too. The pane is cleared while
it waits, so a stale cover never sits under a new selection. Both
panes decoded synchronously per click before; Cocoa's per-frame
NSImage loader (cc_thumb_image) is gone.
- Cocoa File Browser is now two-pane like Qt's and Win32's: the left
table shows the folders (companion_core_browse_dir_count, ".." first,
XMB folder.png or the Finder folder) and the content table the files;
double-click a folder to descend, a file loads; leaving the tab or
picking a playlist restores the playlist pane. The row map serves the
browser too, so run / boxart / popup resolve files correctly.
- companion_parity.py requires the engine's request and poll calls and
the folder/file split on every backend (Qt waived: its own
ThumbnailLoader / QFileSystemModel), so a backend cannot quietly go
back to synchronous loading. 22 features, all three agree.
Verified: companion_thumbs_test.sh plain, TSan and ASan pass (ASan
caught a test-side index bug in the new rectangular case, fixed);
companion_thumbs.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (also with HAVE_THREADS off); consumers of
companion_thumbs.h pass; full Qt 6 retroarch builds and starts
headless; apple_mrc_ownership_check.py unchanged. Not run on Windows /
macOS here.
* ui: Qt on the shared thumbnail engine; Win32 / Cocoa file browser like Qt's
Qt joins the engine, so all three companions decode through one path:
- PlaylistModel drops ThumbnailLoader (its own QThread) and the QCache
of full-size pixmaps; it owns a companion_thumbs instance instead.
loadThumbnail() requests at the grid's cell size (fed from the zoom
slider), data(THUMBNAIL) converts the engine's pixels to a QPixmap
once per (path, size) into a small conversion cache, and a 16 ms
timer polls while anything is pending; thumbnailReady(path) is
emitted for the row's dataChanged and for other consumers. The
thumbnail-cache-limit setting becomes the engine's byte budget.
- The sidebar's four thumbnail widgets and the file-browser image
preview go through the same engine (imageAt / requestImage at the
widget's size), replacing the second loader thread and two
synchronous full-size decodes on the UI thread. ThumbnailLoader and
pixmapFromPathRA are gone; the previewLoader / m_thumbnailPixmaps
state with them.
- The engine gains set_budget(), forget(path) (a downloaded thumbnail
replaces its cached sizes) and pending() (queued + decoding + not
yet polled, so a poll timer never stops early). All three are in the
regression test.
The File Browser on Win32 now matches Qt's (screenshots side by side):
drive entries named "<label> (C:)" from GetVolumeInformation (the core
does it, so Cocoa would too); Up / Start Directory / Downloads buttons
under the tabs (Qt's toolbar); the content view is the folder's whole
listing as a table with Name / Size / Type / Date Modified, drawn with
the shell's own small image list so drives, folders and file types
have Explorer's icons (system image list: nothing of ours to
composite); size and date from FindFirstFile (Windows 95); the browser
is always a table like Qt's, and the playlist view type returns on
leaving. The boxart pane is cleared in the browser - Qt shows none for
a file selection - which the screenshot showed still holding the
previous playlist entry's cover. companion_core_browse_up() is the
"Up" action for any backend.
Cocoa gets the same: the three buttons, the whole listing with a Type
column, boxart cleared, Up / Start / Downloads.
companion_parity.py: Qt's engine waiver is gone - all three backends
reference the engine's request and poll for real.
Verified: companion_thumbs_test.sh plain, TSan, ASan pass with the
new cases; companion_core.c, ui_win32_companion.c and the consumers of
companion_core.h / companion_thumbs.h pass tools/mingw_syntax_check.sh;
full Qt 6 retroarch builds with the model on the engine and starts
headless with the qt companion; companion_parity.py green;
apple_mrc_ownership_check.py unchanged. Not run on Windows / macOS.
* ui/companion: regression test for the companion core; two bugs it found
A second regression test, this one for the toolkit-free model every
desktop companion drives (companion_core.c). It links the real core
and playlist.c against libretro-common with RetroArch's state replaced
by fixtures (companion_core_stubs.c: settings, runloop, path slots, an
empty core-info world, recording stand-ins for the load / scan tasks),
writes real .lpl files, and checks:
- the playlist listing: All Playlists first with the token path, the
configured specials next, then the files in order, with their paths
- selecting a playlist through the budgeted iterate and reading its
entries; each row's own file and index within it
- All Playlists: every file merged, sorted by label case-
insensitively, rows mapped back to their file and index
- the thumbnail path rule: the repository layout, label sanitising
(& * / : ` < > ? \ | -> _), the extension probe, the default path
for a missing file, image content as its own thumbnail
- the file browser: folders first with "..", the folder / file split,
descending, going up to the root, up refused at the root
- Run: a DETECT entry with nothing loaded asks for a core with its
path; an entry with a core pushes the load task with that core
- launch options: the entry's own core is offered, nothing duplicated
Run by tools/companion_core_test.sh, plain and under ASan+UBSan; wired
into Linux-libretro-common-tests.yml. On its first run it found two
bugs in the browser that no screenshot had shown:
- a use-after-free when descending into a folder: browse_open() was
handed a pointer into the current listing, freed that listing, then
copied the path from it. The path is copied before anything is
freed.
- "Up" could never reach the root on Unix: path_parent_dir() turns "/"
into "", which browse_open() took as "use the default directory", so
going up from the content directory looped back into it. The parent
step now maps "" to "/" and keeps browse_dir canonical (no trailing
separator below the root), so it compares and terminates.
tools/mingw_syntax_check.sh --consumers-of skips */test/ harnesses:
they are Linux-only by design and have their own scripts.
Verified: companion_core_test.sh plain and ASan pass;
companion_thumbs_test.sh passes; companion_core.c passes
tools/mingw_syntax_check.sh (mingw -Wall -Wextra + linux c89 pedantic)
and its consumers pass; companion_parity.py green.
* ui: abortable decodes (no exit hang), browser previews, no disk I/O on paint
Three reports: a thumbnail preview in the File Browser can take a very
long time to show, RetroArch can still hang on exit, and the Win32 /
Cocoa companions never preview in the browser at all. Traced, and the
traversal audited while at it:
Directory traversal is not the problem: dir_list_new gets each entry's
type from the enumeration itself (FindFirstFile attributes on Windows,
d_type elsewhere) - no per-file stat. The bottlenecks were these:
1. A decode could not be interrupted. image_texture_load runs both of
its stages incrementally (one chunk / one pass per step) but never
looked up between steps, so a worker decoding a large image ran to
completion whatever happened. On exit, free() joined that worker:
the hang. In the browser, clicking through large images queued
full decodes behind each other on the worker.
libretro-common gains image_texture_load_ex() with an abort hook
asked between chunks and between passes (image_texture_load is now
that with no hook). The engine's workers decode through it and
abort when the engine is shutting down or when their job's epoch is
stale - i.e. a cancel() happened since it was queued. Aborted jobs
are not delivered and their entries are dropped, so a later request
decodes again. Two new tests: cancel() during 8 x 16 MiB decodes
lets the re-requested key land first; free() with the same in
flight returns in well under a second.
2. Win32 did disk I/O while painting the browser table: FindFirstFile
per row per sub-item on every repaint, and SHGetFileInfo hitting
the shell and disk for every directory. Metadata (size, date, icon)
is now resolved once per row - one FindFirstFile, and the icon by
attributes alone (SHGFI_USEFILEATTRIBUTES; a drive keeps its real
icon) - and paints read the cache.
3. Qt's QFileSystemModel asks the shell for every folder's own icon
(a disk lookup per folder) and starts a QFileSystemWatcher on every
directory it has shown. Both are off now
(DontUseCustomDirectoryIcons, DontWatchForChanges): the generic
folder icon is what the natives show too, and the table is rebuilt
on navigation. Selecting an image in Qt's browser abandons the
decode of the previous one (abandonPending -> engine cancel).
4. Previews in the natives: Qt previews an image file selected in the
browser in its sidebar; Win32 and Cocoa cleared the pane in browse
mode. Both now show the selected image file through the engine
(cw_boxart_update_path / refreshBoxart's browse branch), cleared for
non-images. Since abandoned decodes leave grid rows marked
"requested", both natives re-ask for empty on-screen cells when the
engine goes idle.
Verified: companion_thumbs_test.sh plain, TSan and ASan pass with the
abort tests; companion_core_test.sh passes; image_texture.c and its
consumers, ui_win32_companion.c pass tools/mingw_syntax_check.sh;
full Qt 6 retroarch builds and starts headless; companion_parity.py
green; apple_mrc_ownership_check.py unchanged. Not run on Windows /
macOS.
* ui/companion: directory listings enumerate off the UI thread, for every backend
Going up into a large directory froze the Qt companion's File Browser
for seconds; the natives enumerated on the UI thread too. Nothing in
the browser may block, so the listing moves into the core as one
asynchronous, shared implementation, and each backend only paints it:
- companion_core_browse_open() now enumerates on a worker (rthreads;
synchronous fallback without HAVE_THREADS): dir_list_new, the
folders-first sort, and one stat per entry for size and mtime - all
off the UI thread. The result lands in companion_core_iterate() and
the new on_browse_changed callback fires (added last in the callback
table, so existing positional tables stay valid). The previous
listing stays readable until then. A newer open supersedes the one
running: it stops between entries, its result is discarded, and no
second thread is ever spawned alongside it. browse_busy() says when
"Loading..." applies.
- Size / Type / Date Modified are formatted by the core
(browse_size_str / _type_str / _date_str) from what it gathered, so
the three backends show the same strings and none of them touches
the disk to paint. The Win32 FindFirstFile-per-row cache is gone;
only the shell icon index stays local (by attributes, no lookup).
Qt: the file table drops QFileSystemModel + the sort/filter proxy.
That pair was the stall: the model kept every visited directory
loaded, the gatherer inserted rows in batches with the proxy
re-filtering and re-sorting on each one (O(n^2/100) on the UI
thread), and header sorting re-sorted the whole directory on every
navigation. BrowseTableModel paints the core's listing (Name / Size /
Type / Date, three stock icons resolved once, the search filter as a
row map) and resets when the listing lands. The directory tree keeps
QFileSystemModel (folders only) with its watcher and custom icons off.
Win32 / Cocoa: open / up / descend show "Loading..." and rebuild when
the listing lands, instead of right after open() (which would show the
old listing now).
companion_core_test covers the async path: the listing lands through
iterate(), busy() clears, size / type / date strings, supersession
(open A then B: only B delivers, once), Up to the root; run plain,
ASan and now TSan. companion_parity.py requires on_browse_changed on
every backend (Qt's two-pane waiver becomes its BrowseTableModel).
Verified: companion_core_test.sh plain / ASan / TSan and
companion_thumbs_test.sh pass; companion_core.c, ui_win32_companion.c
and the consumers of companion_core.h pass tools/mingw_syntax_check.sh;
full Qt 6 retroarch builds and starts headless; companion_parity.py
green; apple_mrc_ownership_check.py unchanged. Not run on Windows /
macOS.
* ui/drivers: clear the boxart pane the moment the File Browser is entered
Switching to the File Browser tab still left the previous playlist
entry's cover in the boxart pane on Win32. Two reasons:
- the clear had moved to the listing's landing (cw_browse_rebuild),
which is now asynchronous; until then the old cover stayed
- a static control does not repaint on STM_SETIMAGE with NULL: it
keeps drawing the image it had until something invalidates it, so
even once the clear ran, the cover remained on screen
Now cw_browse_enter clears the pane at once (and resets the core popup
and Core Info to the no-entry state, as Qt shows for the browser), and
the clear invalidates the control. Cocoa does the same on entry
(refreshBoxart sets nil, popup and info reset) so both natives match.
Verified: ui_win32_companion.c passes tools/mingw_syntax_check.sh
(mingw -Wall -Wextra clean); companion_parity.py green;
apple_mrc_ownership_check.py unchanged. Not run on Windows / macOS.
* ui/companion: header-click sorting in the file browser, once, for every backend
Clicking Name / Size / Type / Date Modified in the browser did nothing
(Win32, Cocoa) or nothing useful (Qt: the core-backed table had sorting
off). The sort lives in the core, so the three companions order the
listing identically:
- companion_core_browse_sort(column, ascending): folders always first
(".." first of all), then the files by name (case-insensitive), size,
type (extension) or modification time, ties broken by name. One qsort
over the already gathered arrays - no I/O. It applies to the current
listing at once (on_browse_changed fires) and is remembered, so every
listing that lands afterwards comes in the chosen order.
- Qt: BrowseTableModel::sort() forwards the header click; sorting is
on again, with the indicator on Name.
- Win32: LVN_COLUMNCLICK forwards it; the same column again flips the
direction, a new one starts ascending, as Qt's header does.
- Cocoa: the entries table gets sort descriptor prototypes (Name / Type
/ Size / Date; the Size and Date columns show only under the
browser) and sortDescriptorsDidChange: forwards them.
companion_core_test covers each column both ways, the folders-first
invariant, tie-breaking by name, and the order persisting across a
re-enumeration. companion_parity.py requires the sort call on every
backend (24 features).
Verified: companion_core_test.sh plain and ASan pass; companion_core.c,
ui_win32_companion.c and the consumers of companion_core.h pass
tools/mingw_syntax_check.sh; full Qt 6 retroarch builds and starts
headless; companion_parity.py green; apple_mrc_ownership_check.py
unchanged. Not run on Windows / macOS.
* ui/companion: fix the crash on the drive list after a sort; scenario regression tests
Clicking a drive in the File Browser crashed on Windows once the
browser had been sorted by Date (or Size). The drive-list branch of the
listing worker returned without allocating the size / mtime arrays
(only the Windows path did that), and the sort comparator indexed
mtime[] for the Date column unconditionally: NULL dereference in
companion_core_browse_cmp the moment the drive list landed and the
remembered sort was applied to it.
Both ends fixed: the drive list now goes through the same metadata
allocation as every other listing (a drive root is simply not stat'ed),
so there is one job path; and the comparator never indexes an array it
does not have.
Tests, in the shape that catches this class before it reaches a
Windows box:
- test_sort_without_metadata builds the drive-list shape directly (a
folders-only listing with no metadata arrays, via a COMPANION_CORE_
TESTING hook) and sorts it by every column both ways. On the old
comparator this SEGVs under ASan at the exact line; on the fix it
passes - verified both ways.
- test_sort_then_folders_only runs the real job path: every sort
setting, then open a folders-only directory, then sort the landed
listing by every column again.
- test_backend_scenario replays the click sequences the backends send
to the core in a user's order: enter the browser, click every header
both ways, select every row (name / path / size / type / date /
is-dir, as the panes and tables resolve them), descend, activate a
file, Up, Start Directory, rapid navigation without waiting, sort
again, back to a playlist. Any fault on the core side of any
companion trips it. Runs plain, ASan and TSan.
Verified: companion_core_test.sh plain / ASan / TSan pass;
companion_core.c passes tools/mingw_syntax_check.sh (mingw -Wall
-Wextra + linux c89 pedantic) and builds; companion_parity.py green.
* ui/companion: stop the reset -> sort -> changed -> reset recursion (Qt stack overflow)
Clicking a drive in the Qt File Browser blew the stack: the backtrace
is ui_companion_qt_core_on_browse_changed -> Qt -> the same, twelve
thousand frames deep. The loop:
the listing lands -> onBrowseChanged -> the model resets ->
QTableView re-applies its header sort on a reset -> model sort() ->
companion_core_browse_sort() -> on_browse_changed -> ...
companion_core_browse_sort() fired the callback even when the requested
order was the one already in place, so a view that re-applies its sort
on "changed" - which Qt's table does on every model reset - never
converged.
Fixed once in the core: a sort that changes nothing does nothing and
fires nothing. The Qt model's sort() is idempotent too, and
onBrowseChanged has a re-entrancy guard. companion_core_set_ud() is
added (a backend can create the core before the object its callbacks
act on).
Regression test: test_sort_callback_reentrancy registers a listener
that does what Qt's table does - re-applies the current sort on every
"changed" - with a depth counter that stops it at 3, so a loop is
reported rather than crashed in. On the previous core it reports depth
4 in every case; on this one, one callback per real change and none
for a repeat. Verified both ways.
Verified: companion_core_test.sh plain / ASan / TSan pass;
companion_core.c and the consumers of companion_core.h pass
tools/mingw_syntax_check.sh; full Qt 6 retroarch builds and starts
headless; companion_parity.py green.
* ui: browser header clicks sort, and stay sorted, on Qt / Win32; Date and Type proven
Header clicks in the Qt browser appeared to do nothing: every column
sorted the same. The core sorted correctly; the Qt window then undid
it. onBrowseChanged() restored the header state saved before the last
navigation - and that state carries a sort indicator (Name ascending),
so after each click's reload the view snapped its indicator back to
Name and re-sorted by it. Now the saved state (column widths) is
restored once, after a navigation, and the indicator is always set from
the core's actual order (signals blocked, so it never re-sorts by
itself).
Win32: the clicked column shows a sort arrow (HDF_SORTUP / SORTDOWN;
ignored by older comctl32), and a rebuild no longer resets the column
widths the user set (the browser rebuilds on every landing and every
sort). Cocoa's descriptor path re-read and left as is: it already
forwards the clicked column and direction.
The core test now proves each column orders differently, not just
Name and Size: Date with explicit, distinct mtimes (newest first
descending, oldest first ascending), Type across six extensions
(grouped and ordered by extension, names within a group, reversed when
descending), and an explicit check that the four sorts produce four
different first files.
Verified: companion_core_test.sh plain / ASan / TSan pass;
ui_win32_companion.c passes tools/mingw_syntax_check.sh; full Qt 6
retroarch builds and starts headless; companion_parity.py green;
apple_mrc_ownership_check.py unchanged. Not clicked on Windows / macOS.
* ui/drivers: browser header shows the sort direction on Win32 without comctl32 v6
The Win32 companion showed no arrow on the sorted column: it used
HDF_SORTUP / HDF_SORTDOWN, which only a themed (v6) comctl32 draws, and
this build carries no common-controls v6 manifest - the header is the
classic one, which ignores those bits.
The classic header shows a picture instead: the sorted column now gets
HDF_IMAGE with an image on the right of its caption, from a two-entry
image list (up, down) drawn with GDI on the button colour at creation.
The v6 bits are still set for a themed header, so either kind shows
the direction; leaving the browser clears the arrow off the playlist
columns. Qt explicitly turns its header's indicator on.
Verified: ui_win32_companion.c passes tools/mingw_syntax_check.sh
(mingw -Wall -Wextra clean); full Qt 6 retroarch builds;
companion_parity.py green. Not run on Windows.
* ui/drivers: Qt and Cocoa browser headers follow the core's sort like Win32's
One rule for the browser header on all three companions: a new column
starts ascending, the same column again flips, and the header's
highlighted column and arrow always show the order the core's listing
is actually in - whether it came from a click on this backend or was
remembered from before (a re-opened directory lands already sorted).
Cocoa: after every reload the table's sort descriptors, highlighted
column and indicator image are set from the core (syncSortIndicator;
the programmatic set is flagged so sortDescriptorsDidChange: does not
treat it as a click). Leaving the browser clears the highlight and
arrows off the playlist table. Qt: the initial indicator is taken from
the core rather than hard-coded to Name ascending; the per-landing sync
was already in place. Win32 already did both.
Verified: full Qt 6 retroarch builds; companion_parity.py green;
apple_mrc_ownership_check.py reports one new local autoreleased object
(the descriptor, retained by setSortDescriptors: within the call).
Not run on macOS.
* ui/drivers: Win32 browser header showed a document, not the sort arrow
A report-view list view hands its small image list to its header when
LVM_SETIMAGELIST(LVSIL_SMALL) is sent, replacing whatever the header
had. cw_browse_rebuild set the header's arrow image list first and the
rows' shell image list after, so the header's image 0 / 1 became the
shell's first two icons - a document. The arrow image list is now set
after the rows' one, every rebuild.
Verified: tools/mingw_syntax_check.sh (mingw -Wall -Wextra clean). Not
run on Windows.
* ui/companion: thumbnail engine use-after-free on a doubly-recorded key; test races
CI's TSan run of companion_thumbs_test failed at "re-requested decoded"
while the plain run passed. Two test defects and one engine bug behind
it:
- The waits were counting deliveries, not the delivery they meant. A
job popped before a cancel() still lands with its old epoch; with one
worker that stale delivery satisfied drain(1) before the re-requested
key had landed, and the following get() saw nothing. TSan's
scheduling made it hit. The tests now wait for the specific tag
(drain_tag) wherever a re-request is checked.
- strdup was implicitly declared under the script's -ansi pass (the
warning in the log); on a 64-bit host an implicit int return would
truncate the pointer. Replaced with strldup(path, strlen(path) + 1) -
and note the + 1: strldup(s, n) copies n - 1 characters, strlcpy
style. My first attempt passed strlen(path) and silently truncated
every path by one character, which made every decode fail and, with
the next point, exposed the engine bug.
- Engine: an entry could be freed while another finished record still
pointed at it. A failed decode's record freed the entry in poll()
("undecodable: forget it"); a second record for the same key - a job
taken before a cancel() and a re-request after it - then dereferenced
it (ct_find walked a freed chain link). Entries are now reference-
counted by the jobs and records that point at them (request +1, ring
drop / cancel pop / polled record -1) and freed only at zero.
Regression test: test_double_failure_no_uaf builds that shape twenty
times (request an undecodable file, cancel, request again, poll, look
it up). On the branch-tip engine it is a heap-use-after-free under
ASan five runs out of five; on this engine it passes, plain, TSan and
ASan, repeatedly.
Verified: companion_thumbs_test.sh plain / TSan / ASan pass (ASan x5);
companion_core_test.sh passes; companion_thumbs.c passes
tools/mingw_syntax_check.sh (mingw -Wall -Wextra + c89 pedantic) and
builds.
* ui/companion: animated previews (APNG, WEBP, WEBM, MP4) in every companion's pane
The File Browser preview showed only the first frame of an animated
file. RetroArch's own File Browser (gfx_thumbnail) plays the selected
thumbnail through libretro-common's animation stream API -
image_transfer_anim_stream_* over APNG (rpng_apng), animated WEBP, WEBM
and MP4, frames on the container's clock, no audio. The companions now
do the same, through the shared engine, once for all three:
- companion_thumbs_animate(path, w, h, tag, bg): one animation at a
time (the selected file). Its own thread reads the file, probes it
the way gfx_thumbnail does (a cheap type gate, then rpng_is_apng_ex
over the head of the buffer for PNG - an ordinary PNG costs one
4 KiB probe and nothing else), opens the stream, and loops: next
frame (honouring the loop count, rewinding at the end of a pass),
ARGB from the stream where it can supply it or a swizzle where it
cannot, scaled and letterboxed exactly like a still, pushed as a
delivery for (path, w x h, tag), then sleeps the frame's duration.
A still produces nothing. animate_stop(), a newer animate(), or
free() ends it within one frame duration; frames of a superseded
animation are dropped at poll. Files over 256 MiB are not animated.
Frames land through companion_thumbs_poll like any other delivery,
so a backend's existing "blit these bits into the pane" path draws
them; pending() and animating() keep its polling alive.
- Win32 / Cocoa: the boxart pane starts the animation for the selected
file after showing its still, and stops it when the selection moves.
Qt: the sidebar's four widgets play frames for a browser selection
(frameReady from the model, QT_TAG_ANIM_FRAME deliveries), stopped on
the next selection. Any previous animation stops first.
Regression test: test_animation writes a two-frame APNG by hand (IHDR,
acTL, fcTL, IDAT, fdAT - zlib + CRC), checks it decodes as a still
(frame 0, red), then that animate() delivers at least six frames in
four seconds with both colours seen, that animating() reports it, that
stop() ends it, that a still animates nothing, and that free() with an
animation running returns. Plain, TSan and ASan. The script's C89 pass
gains _GNU_SOURCE (as the real C89 gate has) for the POSIX types
libretro-common's headers use, and HAVE_RPNG for the APNG probe.
companion_parity.py requires the animate call on every backend (25
features).
Verified: companion_thumbs_test.sh plain / TSan / ASan and
companion_core_test.sh pass; companion_thumbs.c, ui_win32_companion.c
and the consumers of companion_thumbs.h pass tools/mingw_syntax_check.sh;
full Qt 6 retroarch builds and starts headless; companion_parity.py
green; apple_mrc_ownership_check.py unchanged. Not run on Windows /
macOS.
* ui/drivers: remove stale companion_preview references from the Win32 companion
The animated-previews commit left the Win32 companion with an include
of, and calls into, a companion_preview module from a direction I had
abandoned in the same session (the Qt and Cocoa files had been reset;
this one had not). The header does not exist: the Windows build failed
at the include. All of it is gone; the pane's animation goes through
companion_thumbs_animate like the other two backends.
The syntax gate should have caught it and did not: it forgave every
"No such file" error so that optional platform headers this box lacks
(d3dkmthk.h) do not fail unrelated files - which also forgave a missing
project header. It now forgives only a missing header named without a
path; one with a path component (../companion/x.h) fails the gate.
Probed both ways.
Verified: ui_win32_companion.c compiles to an object with mingw
(-Wall -Wextra, no warnings), and passes the fixed gate along with
companion_thumbs.c, companion_core.c and the 15 consumers of
ui_companion_driver.h; companion_parity.py green.
* gfx: share the File Browser's animated preview with the companions (gfx_anim_preview)
The companions' previews of an animated file were slow to start and
silent, while RetroArch's own File Browser thumbnail plays the same
file at once and with sound. The reason was that the companion engine
had its own playback path: read the whole file, open the stream, no
audio. The menu's path (gfx_thumbnail.c) does it right - a sliding-
window progressive open so frames start from the first resident bytes
and a tail-moov MP4 opens from a few MiB, memory admission that scales
with the heap, the container's audio track through the mixer over its
own window - so that is what everyone uses now.
gfx/gfx_anim_preview.{c,h}: the session that machinery becomes, moved
out of gfx_thumbnail.c with its reasoning comments - open (type gate,
APNG head probe, windowed progressive open with the moov-island jump
and the media-floor prime, admission), feed (keep the window
straddling the decoder's frontier under the per-tick I/O budget and
raise the demuxer's bound to what is resident), next / rewind with
the container's duration rules, and the preview audio (the second
window, moov head sizing, mixer stream, its feeder, stop). Nothing in
it knows about a thumbnail, a video driver or a toolkit.
gfx_thumbnail.c keeps its threaded upload path and now drives the
open, both feeders and the audio through a session it wraps around the
stream and mapping it owns (gfx_anim_preview_wrap / _release, non-
owning); ~430 lines of inline copies are gone. Both of its sample
suites pass on the result: gfx_thumbnail_anim (plain, ASan+UBSan,
TSan sweep) and gfx_thumbnail_preview (make check: windowed opens over
sparse tail-moov fixtures, audio-window islands, decode budgets).
The companion engine's animation thread is that session too: open,
feed, next, rewind, close; the UI thread starts the preview audio once
the session is published and feeds its window every poll (mixer calls
stay on the UI thread), stop() silences at once. A video's still is
now its first frame through the same windowed open instead of
image_texture_load reading the whole file - the other half of the
startup latency. So the companions get the menu's startup time and its
sound (honouring menu_thumbnail_preview_audio) from the same code.
One bug found by the engine test while doing this, in the shared code:
image_transfer_anim_stream_set_argb is honoured only before the first
frame, and APNG reports false to a repeat request afterwards although
the order stands. Asking per frame and trusting the answer swapped R
and B from the second frame on (a blue-tinted preview after the first
loop). The session decides the order once at open and remembers it.
The animation test now checks every frame is one of the fixture's two
colours over ten frames, which is what caught it.
Verified: companion_thumbs_test.sh plain / TSan / ASan pass (the module
linked in); companion_core_test.sh passes; both gfx_thumbnail sample
suites pass; gfx_anim_preview.c, gfx_thumbnail.c, companion_thumbs.c,
ui_win32_companion.c and the consumers of gfx_thumbnail.h pass
tools/mingw_syntax_check.sh; full Qt 6 retroarch builds and starts
headless; companion_parity.py green; apple_mrc_ownership_check.py
unchanged. Xcode and MSVC build through griffin, which includes the
new file. Not run on Windows / macOS.
* ui/companion: per-frame preview cost - fold the byte swap into the sampler, 4-tap downscale, no GDI churn
Measured per frame at pane size (320 x 400), -O2:
nearest full-canvas swizzle folded swizzle 4-tap (+swizzle)
3840x2160 source 0.35 ms 11.8 ms 0.22 ms 0.98 ms
1920x1080 0.13 ms 1.5 ms 0.16 ms 0.91 ms
640x480 0.09 ms 0.29 ms 0.12 ms 0.93 ms
So the scale to pane size was never the cost. What was: for a stream
that will not emit ARGB words (animated WEBP), the whole canvas was
byte-swapped into a fresh malloc before sampling - 12 ms a frame at
4K, a third of a 30 fps budget - to feed a sampler that reads a few
hundred thousand of those pixels. companion_thumbs_scale_ex takes the
source order as a flag and swaps the sampled pixels only: 0.2 ms, no
allocation. The animation thread and the video-still path use it.
(Handing the raw canvas to the toolkit and letting it scale would be
worse, not better: every toolkit here would copy the full canvas into
its own image per frame - 33 MB at 4K - and scale on the CPU anyway.)
Quality, the actual weakness: nearest-neighbour downscaling a video to
a pane aliases and shimmers on motion. When shrinking by two or more
in both directions the sampler now averages four taps per output
pixel, placed a third in from each edge of the source cell so they
always fall on rows and columns of different parity (a 1-px
checkerboard, the worst case, averages to grey instead of picking one
colour - the test caught the quarter-point placement getting that
wrong). Under 1 ms at any source size. Enlarging stays nearest.
UI-thread side, per frame: Win32 created and destroyed a DIB section
and re-set the static control's image every frame; it now keeps one
DIB for the pane, copies the frame into its pixels (after GdiFlush)
and invalidates. Cocoa allocated an NSBitmapImageRep and an NSImage
per frame; it keeps one rep and writes into its bitmapData. Qt did
img.copy() before QPixmap::fromImage(), which copies again; the copy
is gone.
test_scaler covers the R,G,B,A-order path (red in, ARGB red out; the
same words read as ARGB are blue), the 4-tap average on a checkerboard
and nearest on enlargement.
Verified: companion_thumbs_test.sh plain / TSan / ASan pass;
companion_thumbs.c and ui_win32_companion.c pass
tools/mingw_syntax_check.sh (the Win32 TU also compiled to an object
with mingw, no warnings); consumers of companion_thumbs.h pass; full
Qt 6 retroarch builds and starts headless; companion_parity.py green;
apple_mrc_ownership_check.py unchanged. Not run on Windows / macOS.
* ui/drivers: Cocoa - folders pane under the File Browser tab, grid layout on attach, focus back on close
Three reports from running the Cocoa companion:
- The File Browser was empty. The playlists table was tab item 0's
view, and tab item 1 (File Browser) had no view at all, so selecting
that tab showed an empty pane and hid the very table that lists the
folders in browse mode. The tab view is now only the strip; the table
sits under it in both modes and layoutViews places it.
- The grid view showed nothing. RACompanionGrid computed its column
count from its own bounds, which are zero until its first relayout
inside the scroll view, and it only relaid out when explicitly told
to; a zero-width layout stayed. It now takes the width from the clip
view when it has one and relays out on viewDidMoveToSuperview, so
becoming the document view lays it out on its own.
- Closing the companion (or loading content from it) left the keyboard
with no window: RetroArch's window is now made key when the companion
hides, on every path that hides it (close button, entry run, load
with the popup's core, load through the core picker).
Verified: static checks (bracket balance by character scan, every
selector sent to self declared and implemented,
apple_mrc_ownership_check.py unchanged); companion_parity.py green.
Not compiled here (no Apple toolchain): the Xcode CI build is the gate.
* ui/drivers: Cocoa - keyboard back to RetroArch's real window; grid paints visible rows; diagnostics
Focus. Closing the companion still left RetroArch without keyboard
control. hideAndFocusRetroArch made key the window of [CocoaView get]
- but on a Metal build the render view is not a CocoaView and that
object sits in no window, so the call went to nil. It now asks the
platform: the window hosting the render view (RetroArch_OSX
-hostWindow), activates the app, makes that window key and makes the
render view its first responder - without which key events reach the
window and nothing in it.
Grid. drawRect walked every entry of the list on every paint (42k
rectForRow calls per repaint); it now paints only the rows the dirty
rect covers. And, since the grid still shows nothing on a real Mac and
I have no Mac, it logs its first paint - count, frame, dirty rect,
thumbnail edge, columns, owner and wimp pointers - so a --verbose run
says which of those is wrong.
Folder pane. Names are missing while icons show; the data-source path
reads correctly, so it logs the first name it hands the table and
whether it is valid UTF-8 (a non-UTF-8 name makes stringWithUTF8String
return nil, i.e. an empty cell).
Verified: static checks (bracket balance, MRC lint unchanged);
companion_parity.py green. Not compiled here: the Xcode CI build is
the gate, and the two log lines are what I need from the next run.
* ui/companion: Cocoa regression harness on Linux (GNUstep AppKit, headless); focus hand-back after AppKit's close
Until now the Cocoa companion had never been compiled, let alone run,
anywhere I could observe; every change to it was made blind and judged
by static checks. GNUstep provides a real Foundation + AppKit on
Linux, so it can be:
tools/companion_cocoa_test.sh compiles the real
ui/drivers/ui_cocoa_companion.m against GNUstep's AppKit (Apple-only
headers - AvailabilityMacros.h, TargetConditionals.h, QuartzCore.h -
shimmed in GNUstep's own version scale), links it with the real
companion core, the core test's stubs and fixtures and a stub platform
(a window with a render view that takes first responder, as CocoaView
does), and runs it under Xvfb. companion_cocoa_test.m drives the
driver the way RetroArch and a user do - init, iterate until the
playlist lands, select Icons in the view popup, click the File Browser
tab, close the window through the delegate and through AppKit's own
performClose - and asserts on the AppKit objects: the grid is the
scroll view's document with a frame and the playlist's count and
paints; the folder table stays visible under the File Browser tab and
hands back names; the content table has the listing's rows; after
closing, RetroArch's window is key and main with the render view first
responder. Wired into CI beside the other two suites (apt-get in the
job).
What the harness found while being brought up: the core-test stub's
msg_hash returned one placeholder for every message, and a popup drops
a second item with the same title - the stub now returns a distinct
string per message; the driver's 10.4 open-panel branch calls
objc_msgSend, which the GNU runtime does not have (guarded, since that
runtime never lacks -URL).
What it did not reproduce, stated plainly: the grid and the focus
hand-back both pass under GNUstep on the previous driver too, so the
empty grid and the lost keyboard seen on a real Mac are AppKit-on-Mac
behaviour this harness does not model. For focus, the difference most
likely to matter is that AppKit re-arbitrates the key window as part of
closing the one that was key, after windowShouldClose: has returned -
so the hand-back (key, main, first responder on the render view) is
now repeated from windowWillClose: and once more on the next run-loop
pass, to win over that arbitration. The grid's first-paint log from
the previous patch remains the way to pin the grid.
Verified: companion_cocoa_test.sh passes; companion_core_test.sh
passes; companion_parity.py green; apple_mrc_ownership_check.py
unchanged. The Xcode CI build remains the Mac compile gate.
* tools: companion gap audit vs Qt; Cocoa harness action audit mode
Two audits, to answer "what does the Cocoa (and Win32) companion still
lack against Qt's":
- COMPANION_AUDIT=1 tools/companion_cocoa_test.sh: after the regression
checks, the harness fires every user action the Cocoa controller
implements (view switches, zoom, thumbnail and boxart types, the
three dock toggles, search focus / edit / clear, the browser's tab
and three buttons, folder double-click, core popup, picker Load /
Cancel) on the real AppKit objects under GNUstep and reports each as
implemented / missing and whether it ran. Actions that launch
content, open modal panels or delete are listed but not fired.
Result on this tip: every action implemented, none faults.
- tools/companion_gap_audit.py: a feature-by-feature table of what
Qt's window offers against evidence in the Cocoa and Win32 sources,
and the resulting gap lists.
Verified: companion_cocoa_test.sh passes (with and without the audit).
* ui/drivers: Qt parity wiring - Stop, Unload Core, Exit, About, Contributors, Load Custom Core, search Enter
From the gap audit, the items that are pure wiring of native widgets
to core calls Qt already uses:
Cocoa: a Stop button beside Run (companion_core_unload_core, like
Qt's), File > Unload Core and File > Exit RetroArch (CMD_EVENT_QUIT),
Help > About (version alert) and Help > About Contributors (the
AUTHORS list in a scrolling text window).
Win32: the same Stop button and Unload Core item; Help > About
Contributors (the list in a read-only edit); File > Load Custom Core
(a file picker for a core library, into companion_core_load_core);
and Enter in the search box runs the focused entry as Qt's
onSearchEnterPressed does (the EDIT is subclassed for the key).
AUTHORS.h is a C++11 raw string, which Qt can read and C / Objective-C
cannot: tools/gen_authors_c.py writes AUTHORS_c.h, the same list as a
plain C literal, and CI checks the two agree.
companion_parity.py now requires unload core, exit and the
contributors list on every backend (28 features). The gap audit's
Win32 patterns are corrected (Load Core, Exit and About were already
there; they were regex misses) - Cocoa's remaining gaps are 10 and
Win32's 8, all dialogs, drag-and-drop, rename, progress and theme.
The Cocoa harness checks the new wiring on a real AppKit: Stop reaches
the core (command_event observed by the stub), the contributors
window opens with the text, and the remaining selectors exist; its
audit mode lists them.
Verified: companion_cocoa_test.sh passes; ui_win32_companion.c
compiles to an object with mingw (no warnings) and passes
tools/mingw_syntax_check.sh; full Qt 6 retroarch builds;
companion_parity.py green; apple_mrc_ownership_check.py unchanged.
Not run on Windows / macOS.
* ui/companion: playlist rename, add files / file drop, thumbnail drop - in the core, on every backend
Three more of Qt's features, implemented once in the C89 core and bound
on both natives (Qt's rename now goes through the core too):
- companion_core_playlist_rename(): Qt's rules - only inside the
playlists directory (history / favorites refused), no path
separators, never over an existing name - then the move and a list
refresh.
- companion_core_playlist_add_files(): Qt's drop / "Add Files" for
paths - a file is pushed with label = name without extension and
db_name = the playlist, a directory is walked recursively, DETECT or
a given core; All Playlists refused; the shown playlist reloads.
- companion_core_thumbnail_install(): Qt's changeThumbnail for a
dropped image file - decoded, downscaled to
desktop_menu_thumbnail_max_size, written as PNG at the repository
path with the directory created.
Win32: Rename (in-place label edit on the playlist list, applied on
LVN_ENDLABELEDIT through the core), Add Files (multi-select picker),
WM_DROPFILES - an image over the boxart pane installs the thumbnail
of the pane's type, anything else goes into the selected playlist.
Cocoa: Rename (a sheet with a field), Add Files (open panel), file
drops on the entries table (data-source validate / accept) and an
image drop on the boxart pane (RACompanionBoxart). Both forget the
changed thumbnail in the engine and show it again.
Qt: renamePlaylistItem is the core's rename (72 lines -> 30); its Add
Files dialog (extension filter, names, core choice, progress) and its
QImage-based thumbnail drop stay, as waived in companion_parity.py.
Tests: companion_core_test covers the three (refusals, the move, the
list refresh; a file plus a walked directory with the label / db_name
/ DETECT of each entry; a PNG at the repository path downscaled to the
setting), plain and ASan. The Cocoa harness drives the controller: a
dropped file and directory add two entries, a dropped image installs
at the repository path, a rename shows in the reloaded table.
companion_parity.py: 31 features. The gap audit drops "status bar
progress": Qt's QProgressBar there is created, hidden and never driven.
Remaining gaps: the Core Options, Shader Params and Options dialogs,
and the dark theme on Cocoa.
Verified: companion_core_test.sh plain / ASan pass;
companion_cocoa_test.sh passes; ui_win32_companion.c compiles to an
object with mingw (no warnings) and passes tools/mingw_syntax_check.sh
with companion_core.c and the consumers of companion_core.h; full Qt 6
retroarch builds and starts headless; companion_parity.py green;
apple_mrc_ownership_check.py: one new local autoreleased object (the
rename field). Not run on Windows / macOS.
* ui/companion: Core Options, Shader Parameters and Options dialogs on both natives; Cocoa dark theme
The last of Qt's features the natives lacked, each as a flat table the
core exposes toolkit-free and a table window per backend:
- Core Options (companion_core_option_*): the running core's options
with description, info, value labels, current value; set, reset,
reset all - over runloop's core_option_manager, written when the
core flushes as the menu's are. Win32 / Cocoa: option | value,
double-click cycles, Reset / Reset All.
- Shader Parameters (companion_core_shader_param_*): the menu shader's
parameters with description (id when there is none), range, step,
current; set (clamped), reset to initial, apply
(CMD_EVENT_SHADERS_APPLY_CHANGES). Win32: parameter | value | range
with a field and Apply / Reset; Cocoa: the same with the Value column
editable in place.
- Options (companion_core_setting_*): the desktop-menu settings Qt's
View > Options edits, as typed rows (bool / uint / string / choice)
read and set from text with type checks. Win32: setting | value,
double-click toggles a bool or cycles a choice, a field and Apply
for the rest; Cocoa: editable Value column, double-click likewise.
- Cocoa dark theme: the Theme setting is honoured on 10.14+ by giving
the companion window the dark appearance (system default follows the
system).
Tests: companion_core_test builds a real core_option_manager from v2
definitions and a stub menu shader and checks every accessor, set /
reset / clamp / out-of-range, apply, and the settings table's read-back
and type refusals - plain and ASan. The Cocoa harness opens all three
windows on a real AppKit and drives them: rows and values, cycling and
reset, editing a shader value in the cell and applying, toggling a bool
and editing a number and the theme in the Options table.
companion_parity.py: 34 features (Qt's own three dialogs, which predate
the core, are waived with reasons). tools/companion_gap_audit.py now
reports zero gaps vs Qt for both Cocoa and Win32.
Verified: companion_core_test.sh plain / ASan pass;
companion_cocoa_test.sh passes; ui_win32_companion.c compiles to an
object with mingw (no warnings) and passes tools/mingw_syntax_check.sh
with companion_core.c and the consumers of companion_core.h; full Qt 6
retroarch builds and starts headless; companion_parity.py green;
apple_mrc_ownership_check.py: one more local autoreleased object. Not
run on Windows / macOS.
* ui/companion: Win32 regression harness on Linux (mingw + Wine, headless)
The Win32 companion gets the same net the Cocoa one has: the real
ui/drivers/ui_win32_companion.c, built with mingw and linked with the
real companion core, the core test's stubs and fixtures and a stub for
RetroArch's main window and modal helpers, runs under Wine on Xvfb
(tools/companion_win32_test.sh). Wine's comctl32 is not Microsoft's,
but the object graph, the messages and their side effects are the same
- which is where every Win32 bug so far has been.
companion_win32_test.c drives the driver as RetroArch and a user do -
init, iterate until the playlist lands, then the messages the widgets
send (the View combo's CBN_SELCHANGE and the menu's WM_COMMAND ids, the
tab's TCN_SELCHANGE, the header's LVN_COLUMNCLICK, list selections,
WM_CLOSE) - and checks the real controls: the playlist list's rows and
text; the entries list's count, its view style after switching to
Icons and back; the search filter and Clear; the File Browser - the
async listing landing, the folder pane's rows and "..", the content
list's rows and its four columns and the Type text, the empty boxart
pane, a header click sorting by Type and the same click flipping it,
Up and Start Directory; Stop reaching the core; the Core Options,
Shader Parameters and Options windows opening with the right rows,
value labels, a double-click cycling an option; the window hiding on
close. 33 checks, all green; with the browse-landed rebuild removed it
reports the four panes that go stale, so it catches the class of bug
it exists for.
The driver's control and menu ids move to ui_win32_companion_ids.h so
the harness sends exactly the commands the widgets send (its first
draft carried a copy of the enum, which had drifted). The core test's
fixtures gain the two Windows spellings they needed (mkdir, utime,
sleeping). Wired into CI beside the other suites.
Verified: companion_win32_test.sh passes; companion_cocoa_test.sh and
companion_core_test.sh pass; ui_win32_companion.c and the consumers of
the new header pass tools/mingw_syntax_check.sh; companion_parity.py
green.
* ui/drivers: fix the Xcode (ARC) build and the overlap-copy finding
Xcode, which builds the Cocoa companion with -fobjc-arc: the grid's
first-paint log cast an object pointer to void* without a bridge
(BRIDGE, as the rest of the file does), and the three table windows
passed the address of an ivar as the makeTableWindow out-parameter,
which ARC treats as an __autoreleasing write-back and refuses for a
non-local; each now goes through a local and assigns the ivar.
tools/overlap_copy_check.py: the Win32 Options list read buf[0] in the
source expression of a strlcpy into buf; the value is now read into a
bool before either literal is copied.
Verified: overlap_copy_check.py clean; companion_cocoa_test.sh and
companion_win32_test.sh pass; ui_win32_companion.c passes
tools/mingw_syntax_check.sh; apple_mrc_ownership_check.py unchanged.
The deprecated NSTitledWindowMask names in the log are the pre-10.12
spellings the file uses throughout for the 10.4 SDK; warnings only.
* ui/drivers: the Mac main loop never iterated the companion - "Loading playlist..." for ever
The screenshot says it: "Loading playlist..." in the status bar, the
entries pane empty in both views, the File Browser empty. Every one of
those is an asynchronous result that lands through
ui_companion_driver_wimp_iterate() - the playlist parse, the browser's
listing, decoded thumbnails, animation frames, status - and on a real
Mac that hook was never called.
The only call was in the Qt-era -rarch_main loop in ui_cocoa.m, which
is under #ifdef HAVE_QT. The Xcode build has no Qt: its whole main loop
is the CFRunLoop observer rarch_draw_observer in cocoa_common.m, which
called runloop_iterate() and task_queue_check() and nothing else. So
the Cocoa companion built its window, kicked off its work, and nothing
ever arrived. The observer now calls the hook each frame, as the
generic loop in retroarch.c does for the other platforms.
Why the harness did not catch it: it calls the driver's iterate itself,
standing in for the platform loop. companion_parity.py now also checks
that the platforms' real main loops call ui_companion_driver_wimp_
iterate() (rarch_draw_observer today; the generic loop covers Win32 and
Qt) - it fails on the previous cocoa_common.m and passes on this one.
This is also the most likely cause of the earlier "grid shows nothing"
and "browser is empty" reports, which the GNUstep harness could never
reproduce: it iterates.
Verified: companion_parity.py green (with the new check);
cocoa_common.m compiles under GNUstep's syntax check. Not run on macOS:
the Xcode CI build and your next run are the gate.
* ui/drivers: Cocoa - hand the keyboard back in every run-loop mode, and when the window resigns key
After closing the companion the mouse controls RetroArch again but the
keyboard does not. On macOS the mouse goes to the window under it,
while key events go to the key window through RAWindow -sendEvent:, so
this is the picture of RetroArch's window being main but not key after
the close.
Two things about the previous hand-back could let that happen. Its
deferred re-assert was a default-mode timer, and the close button's
click is dispatched in the event-tracking mode, so the re-assert could
wait until the mode changed; and it ran only from the delegate's close
methods, whereas AppKit's own choice of the next key window - made
while the close is in progress - is what has to be beaten.
Now: the re-assert is scheduled in the default, event-tracking and
modal-panel modes, three times over 40 ms (the arbitration can run
late); it also runs when the companion window resigns key while not
visible (the moment the close takes the key status away); and it does
nothing if the window has been shown again meanwhile. Each attempt
logs whether the host ended up key and main and what NSApp's key
window is, so a --verbose run says exactly where it lands if this is
still not it.
Verified: GNUstep compile; companion_cocoa_test.sh passes;
companion_parity.py green; MRC lint unchanged. Not run on macOS.
* ui/drivers: Cocoa - let the companion window actually close; the keyboard comes back
The keyboard stayed with a window that no longer existed on screen.
windowShouldClose: hid the companion itself and returned NO - so AppKit
was told the window was not closing. It stayed open in AppKit's eyes,
hidden but still the key window, and key events kept going to it while
mouse events went to the window under the pointer: exactly "mouse works,
keyboard does not". And since no close ever happened, windowWillClose:
and windowDidResignKey: - where every hand-back attempt of the last
three patches lived - never fired.
windowShouldClose: now returns YES. AppKit closes the window (kept
alive by setReleasedWhenClosed:NO; the driver's toggle orders it back),
resigns its key status, and the hand-back runs from the delegate
methods that now fire. The programmatic hide on loading content keeps
its own hand-back.
The harness asserts the delegate returns YES and closes the window
through AppKit, then shows it again through the driver's toggle and
checks it still lists the playlists.
Verified: companion_cocoa_test.sh passes; MRC lint unchanged. Not run
on macOS.
* ui/companion: run the Cocoa harness on Apple's AppKit in CI; assert a keystroke after the close
The keyboard still does not return to RetroArch after the companion
closes on a real Mac, and the GNUstep harness keeps passing: whatever
this is, it is in Apple's AppKit - key-window arbitration, activation -
which GNUstep only approximates. There is no Mac here to debug on; the
macOS CI runner has a window server and can run AppKit, so the harness
runs there now, built with Apple's clang against the real Cocoa
framework (tools/companion_cocoa_test_macos.sh, no shims), as a step of
the macOS workflow ahead of the Xcode build.
The harness also asks the actual question now. RetroArch reads the
keyboard in RAWindow -sendEvent:, which AppKit calls on the key window
for key events; the harness's stand-in for RetroArch's window counts
the key events reaching its -sendEvent:. After closing the companion
through AppKit (performClose:), it posts a keystroke through NSApp and
asserts it arrived - and prints which window NSApp holds as key if not.
The harness also becomes a regular, activatable app first, since
Apple's AppKit gives no key window to a background process.
Under GNUstep the new checks pass (NSApp's key window is RetroArch's;
the posted keystroke reaches -sendEvent:). The macOS job's log is the
answer for Apple's AppKit.
* ui/companion: Cocoa harness - report faults and exceptions with a backtrace
The first run on Apple's AppKit got through init, the playlist, the
grid (a real frame, painted), the File Browser, Stop, Contributors and
the menu items, then died with "Trace/BPT trap: 5" right after
"addPaths: implemented" - a SIGTRAP with no message. The harness now
installs handlers for SIGTRAP / SIGSEGV / SIGBUS / SIGABRT / SIGILL that
print a backtrace, and an uncaught-exception handler that prints the
exception's name, reason and call stack, so the next log names the
place. Methods returning size_t / BOOL are invoked through NSInvocation
rather than performSelector: (which is for id returns and undefined for
these on Apple's runtime), in case that was the trap.
Under GNUstep the harness still passes.
* ui/companion: overlapping strlcpy on a playlist reload (trapped on macOS); test builds trap it too
The harness on Apple's AppKit got through everything up to adding files
to the shown playlist, then trapped in __strlcpy_chk -> __chk_fail_
overlap inside companion_core_begin_playlist. The path: a backend adds
files to the playlist it is showing and hands the core the pointer it
got from companion_core_selected_playlist_path() - the core's own
selected_path buffer. add_files reloads that playlist through
select_playlist_path -> begin_playlist, which strlcpy'd the path into
selected_path: source and destination the same buffer. Undefined, and
macOS's fortified libc aborts on it; Linux's strlcpy (libretro-common's
own) silently did the copy, which is why every Linux suite passed.
begin_playlist now takes a copy of @path before it clears state or
writes selected_path.
So the Linux suites catch this class from now on: under
LIBRETRO_STRL_CHECK_OVERLAP, libretro-common's strlcpy aborts on an
overlapping copy exactly as Apple's does, and the four companion test
scripts build with it. companion_core_test adds the aliasing call the
backends make (add files through the selected-path pointer, reload,
count) - on the previous core it aborts with "strlcpy: overlapping copy";
on this one it passes. All four suites pass with the check on.
Verified: companion_core_test.sh plain / ASan, companion_thumbs_test.sh,
companion_cocoa_test.sh, companion_win32_test.sh pass;
companion_core.c and compat_strl.c pass tools/mingw_syntax_check.sh
and build; overlap_copy_check.py clean.
* ui/drivers: Cocoa - forget held keys when another window takes the keyboard (the dead keyboard)
The harness on Apple's AppKit settled the key-window question: after
the companion closes, RetroArch's window is key and main and a posted
keystroke reaches RAWindow -sendEvent:. So the keyboard was arriving,
and RetroArch was ignoring it.
The mechanism is RetroArch's own held-key state. The companion is
opened with a key (its hotkey, or Enter in the menu). The moment its
window becomes key, that key is still down; its release is delivered to
the companion window, so RetroArch's window never sees the key-up and
apple_key_state keeps the key "held". The menu's flush-and-wait-for-
release (menu_st->input_driver_flushing_input ->
INP_FLAG_WAIT_INPUT_RELEASE) then waits for that release - for ever.
Keyboard dead, mouse (which does not go through that gate) fine, and
closing the companion changes nothing because the key is still "down".
Deactivating the app clears it, which is why RetroArch already calls
apple_input_keyboard_reset() from applicationWillResignActive.
Same treatment for losing the keyboard to another window of our own:
RetroArch_OSX (RAWindow's delegate) resets the keyboard state in
windowDidResignKey:, and the companion's toggle resets it right after
taking the keyboard, covering a show from a non-key state. The harness
stubs apple_input_keyboard_reset and asserts the companion's show calls
it.
Verified: companion_cocoa_test.sh passes under GNUstep; MRC lint
unchanged. Apple's AppKit run of the harness (previous commit) is what
established the key-window half. Not run in the real app on macOS.
* ui/companion: keep the playlist config off the stack; guard the selected_path self-copy by pointer
companion_core_begin_playlist() no longer takes a PATH_MAX_LENGTH copy
of @path to survive being handed core->selected_path: the copy is
skipped when the pointer already is that buffer, the way path_set()
does it, and the buffer already holds the path. The playlist_config_t
that begin_playlist, all_next, playlist_open and playlist_open_private
each built on the stack now lives in companion_core_t; playlist_init()
and playlist_parse_begin() copy it, and all four run on the UI thread,
so one is enough. begin_playlist drops from 5184 to 32 bytes of frame
and the other three from ~3 KiB to under 64 bytes, within the 4 KiB
ceiling CODING-GUIDELINES sets.
* ui/drivers: Cocoa - the icon grid's prefetch read past the thumbnail marks (the crash)
Guard Malloc named it exactly: a byte read one past the end of a
MALLOC_TINY block in -[RACompanionController thumbWant:urgent:]. (The
earlier crash in MoltenVK was the same corruption, noticed later by an
unrelated allocation - the usual way an overrun surfaces.)
iconTick prefetches a screen either side of the visible rows, so it
calls thumbWant: with rows that do not exist. hasImageForRow: answers
NO for those - it means "no image", not "no row" - so thumbWant: went
on to read thumbNone[row], and thumbNone is only as long as the list.
Reading one byte past a heap block: harmless on glibc, fatal under
Apple's allocator.
thumbNone now carries its length (thumbNoneCount) and every access is
bounded by it: thumbWant: returns for a row outside the list, the idle
re-scan clamps, the delivery callback checks the array's length as well
as the current entry count (a delivery for the previous list), and the
two memsets use the array's own length rather than a count that may
have moved on since it was allocated.
Regression test, in the harness: drive iconTick repeatedly and call
thumbWant: with rows either side of the range, and run the whole
harness under ASan (tools/companion_cocoa_test.sh asan, wired into CI
beside the plain run). On the previous driver ASan reports
heap-buffer-overflow at ui_cocoa_companion.m:976 in thumbWant: and the
script exits 5; on this one both passes are clean. The script also
propagates the run's exit status now - the pipe through the log filter
was swallowing it, so a sanitizer abort would have looked like a pass.
Verified: companion_cocoa_test.sh plain and ASan pass (and fail as
described on the previous driver); companion_core_test.sh,
companion_thumbs_test.sh, companion_win32_test.sh pass;
companion_parity.py green; MRC lint unchanged.
---------
Co-authored-by: LibretroAdmin <[email protected]>
2106 lines
72 KiB
C
2106 lines
72 KiB
C
/* RetroArch - A frontend for libretro.
|
||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||
* Copyright (C) 2016-2019 - Brad Parker
|
||
*
|
||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||
* of the GNU General Public License as published by the Free Software Found-
|
||
* ation, either version 3 of the License, or (at your option) any later version.
|
||
*
|
||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
* PURPOSE. See the GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||
* If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#ifndef __CONFIG_DEF_H
|
||
#define __CONFIG_DEF_H
|
||
|
||
#include <boolean.h>
|
||
#include <audio/audio_resampler.h>
|
||
|
||
#ifdef __MACH__
|
||
#include <TargetConditionals.h>
|
||
#endif
|
||
|
||
#include "configuration.h"
|
||
#include "gfx/video_defines.h"
|
||
#include "input/input_defines.h"
|
||
|
||
#ifdef HAVE_CONFIG_H
|
||
#include "config.h"
|
||
#endif
|
||
|
||
#ifdef HAVE_NETWORKING
|
||
#include "network/netplay/netplay_defines.h"
|
||
#endif
|
||
|
||
/* Required for 3DS display mode setting */
|
||
#if defined(_3DS)
|
||
#include <3ds.h>
|
||
#include "gfx/common/ctr_defines.h"
|
||
#endif
|
||
|
||
/* Required for OpenDingux IPU filter + refresh
|
||
* rate settings */
|
||
#if defined(DINGUX)
|
||
#include "dingux/dingux_utils.h"
|
||
#endif
|
||
|
||
/* Required for 'show inputs on overlay' setting */
|
||
#if defined(HAVE_OVERLAY)
|
||
#include "../input/input_overlay.h"
|
||
#endif
|
||
|
||
/* Required for Steam enum settings */
|
||
#if defined(HAVE_MIST)
|
||
#include "steam/steam.h"
|
||
#endif
|
||
|
||
#if defined(HW_RVL)
|
||
#define MAX_GAMMA_SETTING 30
|
||
#elif defined(GEKKO)
|
||
#define MAX_GAMMA_SETTING 2
|
||
#else
|
||
#define MAX_GAMMA_SETTING 1
|
||
#endif
|
||
|
||
#if defined(XENON) || defined(_XBOX360) || defined(__PSL1GHT__) || defined(__PS3__)
|
||
#define DEFAULT_ASPECT_RATIO 1.7778f
|
||
#elif defined(_XBOX1) || defined(GEKKO) || defined(ANDROID)
|
||
#define DEFAULT_ASPECT_RATIO 1.3333f
|
||
#else
|
||
#define DEFAULT_ASPECT_RATIO 1.3333f
|
||
#endif
|
||
|
||
#define DEFAULT_VIEWPORT_BIAS_X 0.5
|
||
#define DEFAULT_VIEWPORT_BIAS_Y 0.5
|
||
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_VIEWPORT_BIAS_PORTRAIT_X 0.5
|
||
#define DEFAULT_VIEWPORT_BIAS_PORTRAIT_Y 0.0
|
||
#endif
|
||
|
||
#if defined(GEKKO)
|
||
#define DEFAULT_MOUSE_SCALE 1
|
||
#endif
|
||
|
||
#define DEFAULT_TOUCH_SCALE 1
|
||
|
||
#if defined(RARCH_MOBILE) || defined(HAVE_LIBNX) || defined(__WINRT__) || defined(__EMSCRIPTEN__) || defined (VITA)
|
||
#define DEFAULT_POINTER_ENABLE true
|
||
#else
|
||
#define DEFAULT_POINTER_ENABLE false
|
||
#endif
|
||
|
||
/* Certain platforms might have assets stored in the bundle that
|
||
* we need to extract to a user-writable directory on first boot.
|
||
*
|
||
* Examples include: Android, iOS/OSX) */
|
||
#if defined(ANDROID) || defined(__APPLE__)
|
||
#define DEFAULT_BUNDLE_ASSETS_EXTRACT_ENABLE true
|
||
#else
|
||
#define DEFAULT_BUNDLE_ASSETS_EXTRACT_ENABLE false
|
||
#endif
|
||
|
||
#ifdef HAVE_MATERIALUI
|
||
/* Show icons to the left of each menu entry */
|
||
#define DEFAULT_MATERIALUI_ICONS_ENABLE true
|
||
/* Show boolean option ON/OFF icons */
|
||
#define DEFAULT_MATERIALUI_SWITCH_ICONS true
|
||
/* Show system-specific icons in the playlists tab */
|
||
#define DEFAULT_MATERIALUI_PLAYLIST_ICONS_ENABLE true
|
||
#endif
|
||
|
||
/* Material UI colour theme */
|
||
#define DEFAULT_MATERIALUI_THEME MATERIALUI_THEME_OZONE_DARK
|
||
|
||
/* Type of animation to use when performing menu transitions
|
||
* > 'Auto' follows Material UI standards:
|
||
* - Slide when switching between parent menus (tabs)
|
||
* - Fade when changing levels in a menu
|
||
* Note: Not wrapping this with a HAVE_MATERIALUI ifdef
|
||
* because there's too much baggage involved... */
|
||
#define DEFAULT_MATERIALUI_TRANSITION_ANIM MATERIALUI_TRANSITION_ANIM_AUTO
|
||
|
||
/* Adjust menu padding etc. to better fit the
|
||
* screen when using landscape layouts */
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION_DISABLED
|
||
#else
|
||
#define DEFAULT_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION_ALWAYS
|
||
#endif
|
||
|
||
/* Show/hide navigation bar
|
||
* > When hidden, MaterialUI menu navigation
|
||
* behaves like RGUI */
|
||
#define DEFAULT_MATERIALUI_SHOW_NAV_BAR true
|
||
|
||
/* Reposition navigation bar to make better use
|
||
* of screen space when using landscape layouts */
|
||
#define DEFAULT_MATERIALUI_AUTO_ROTATE_NAV_BAR true
|
||
|
||
/* Default portrait/landscape playlist view modes
|
||
* (when thumbnails are enabled) */
|
||
#define DEFAULT_MATERIALUI_THUMBNAIL_VIEW_PORTRAIT MATERIALUI_THUMBNAIL_VIEW_PORTRAIT_LIST_SMALL
|
||
#define DEFAULT_MATERIALUI_THUMBNAIL_VIEW_LANDSCAPE MATERIALUI_THUMBNAIL_VIEW_LANDSCAPE_LIST_MEDIUM
|
||
|
||
/* Enable second thumbnail when using 'list view'
|
||
* thumbnail views
|
||
* Note: Second thumbnail will only be drawn if
|
||
* display has sufficient horizontal real estate */
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_MATERIALUI_DUAL_THUMBNAIL_LIST_VIEW_ENABLE false
|
||
#else
|
||
#define DEFAULT_MATERIALUI_DUAL_THUMBNAIL_LIST_VIEW_ENABLE true
|
||
#endif
|
||
|
||
/* Draw solid colour 4:3 background when rendering
|
||
* thumbnails
|
||
* > Helps to unify menu appearance when viewing
|
||
* thumbnails of different sizes */
|
||
#define DEFAULT_MATERIALUI_THUMBNAIL_BACKGROUND_ENABLE true
|
||
#define DEFAULT_MENU_THUMBNAIL_BACKGROUND_ENABLE false
|
||
|
||
/* Play the audio track of animated WebM thumbnails (menu preview). */
|
||
#define DEFAULT_MENU_THUMBNAIL_PREVIEW_AUDIO false
|
||
|
||
#define DEFAULT_SCREEN_BRIGHTNESS 100
|
||
|
||
#define DEFAULT_CRT_SWITCH_RESOLUTION CRT_SWITCH_NONE
|
||
|
||
#define DEFAULT_CRT_SWITCH_RESOLUTION_SUPER 2560
|
||
|
||
/* SDL display server: 0 never, 1 only when the native server cannot switch modes, 2 always */
|
||
#define DEFAULT_VIDEO_SDL_DISPLAY_SERVER VIDEO_SDL_DISPLAY_SERVER_AUTO
|
||
|
||
#define DEFAULT_CRT_SWITCH_CENTER_ADJUST 0
|
||
|
||
#define DEFAULT_CRT_SWITCH_PORCH_ADJUST 0
|
||
|
||
#define DEFAULT_CRT_SWITCH_VERTICAL_ADJUST 0
|
||
|
||
#define DEFAULT_CRT_SWITCH_HIRES_MENU true
|
||
|
||
#define DEFAULT_HISTORY_LIST_ENABLE true
|
||
|
||
#define DEFAULT_PLAYLIST_ENTRY_RENAME true
|
||
|
||
#define DEFAULT_WIFI_ENABLE true
|
||
|
||
#define DEFAULT_ACCESSIBILITY_ENABLE false
|
||
|
||
#define DEFAULT_ACCESSIBILITY_NARRATOR_SPEECH_SPEED 5
|
||
|
||
/* espeak is the default narrator engine so existing setups are
|
||
* unaffected. The enum lives in configuration.h. */
|
||
#define DEFAULT_ACCESSIBILITY_NARRATOR_ENGINE ACCESSIBILITY_NARRATOR_ENGINE_ESPEAK
|
||
|
||
#define DEFAULT_DRIVER_SWITCH_ENABLE true
|
||
|
||
#define DEFAULT_USER_LANGUAGE 0
|
||
|
||
#define DEFAULT_GAMEMODE_ENABLE true
|
||
|
||
#ifdef HAVE_LAKKA_SWITCH
|
||
#define DEFAULT_SWITCH_OC false
|
||
#define DEFAULT_SWITCH_CEC true
|
||
#define DEFAULT_BLUETOOTH_ERTM false
|
||
#endif
|
||
|
||
#if (defined(_WIN32) && !defined(_XBOX)) || (defined(__linux) && !defined(ANDROID) && !defined(HAVE_LAKKA)) || (defined(__MACH__) && !TARGET_OS_IPHONE) || defined(__EMSCRIPTEN__)
|
||
#define DEFAULT_MOUSE_ENABLE true
|
||
#else
|
||
#define DEFAULT_MOUSE_ENABLE false
|
||
#endif
|
||
|
||
#ifdef HAVE_CHEEVOS
|
||
#define DEFAULT_CHEEVOS_ENABLE false
|
||
#define DEFAULT_CHEEVOS_APPEARANCE_ANCHOR 0 /* CHEEVOS_APPEARANCE_ANCHOR_TOPLEFT */
|
||
#define DEFAULT_CHEEVOS_APPEARANCE_PADDING_AUTO true
|
||
#define DEFAULT_CHEEVOS_APPEARANCE_PADDING_H 0.0f
|
||
#define DEFAULT_CHEEVOS_APPEARANCE_PADDING_V 0.0f
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_SUMMARY 1 /* RCHEEVOS_SUMMARY_HASCHEEVOS */
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_UNLOCK true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_MASTERY true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_ACCOUNT true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_LBOARD_START true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_LBOARD_SUBMIT true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_LBOARD_CANCEL true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_LBOARD_TRACKERS true
|
||
#define DEFAULT_CHEEVOS_VISIBILITY_PROGRESS_TRACKER true
|
||
#endif
|
||
|
||
/* VIDEO */
|
||
|
||
#if defined(_XBOX360)
|
||
#define DEFAULT_GAMMA 1
|
||
#else
|
||
#define DEFAULT_GAMMA 0
|
||
#endif
|
||
|
||
/* Windowed
|
||
* Real x resolution = aspect * base_size * x scale
|
||
* Real y resolution = base_size * y scale
|
||
*/
|
||
#define DEFAULT_SCALE 3
|
||
|
||
/* Fullscreen */
|
||
|
||
/* To start in Fullscreen, or not. */
|
||
|
||
#if defined(HAVE_STEAM) || defined(DINGUX) || defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||
/* Start in fullscreen mode for Steam and Dingux
|
||
* WinRT and Winapi Family builds */
|
||
#define DEFAULT_FULLSCREEN true
|
||
#else
|
||
#define DEFAULT_FULLSCREEN false
|
||
#endif
|
||
|
||
/* To use windowed mode or not when going fullscreen. */
|
||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||
/* Do not use windowed mode for WinRT and Winapi Family builds on the Xbox UWP with fixed resolution shrinks the image into the left top corner of the screen with some libretro cores */
|
||
#define DEFAULT_WINDOWED_FULLSCREEN false
|
||
#else
|
||
#define DEFAULT_WINDOWED_FULLSCREEN true
|
||
#endif
|
||
|
||
/* Not platform-specific: how hard to push for exclusive fullscreen
|
||
* where the platform lets the application decide. */
|
||
#define DEFAULT_VIDEO_FSE_NEGOTIATION VIDEO_FSE_RELAXED
|
||
|
||
/* Enable automatic switching of the screen refresh rate when using the specified screen mode(s),
|
||
* based on running core/content */
|
||
#define DEFAULT_AUTOSWITCH_REFRESH_RATE AUTOSWITCH_REFRESH_RATE_EXCLUSIVE_FULLSCREEN
|
||
#define DEFAULT_AUTOSWITCH_PAL_THRESHOLD 54.50f
|
||
|
||
/* Which monitor to prefer. 0 is any monitor, 1 and up selects
|
||
* specific monitors, 1 being the first monitor. */
|
||
#define DEFAULT_MONITOR_INDEX 0
|
||
|
||
/* Window */
|
||
|
||
/* DEFAULT_WINDOW_DECORATIONS:
|
||
Whether to show the usual window decorations like border, titlebar etc. */
|
||
#ifdef WEBOS
|
||
#define DEFAULT_WINDOW_DECORATIONS false
|
||
#else
|
||
#define DEFAULT_WINDOW_DECORATIONS true
|
||
#endif
|
||
|
||
/* Amount of transparency to use for the main window.
|
||
* 1 is the most transparent while 100 is opaque. */
|
||
#define DEFAULT_WINDOW_OPACITY 100
|
||
|
||
/* DEFAULT_WINDOW_SAVE_POSITIONS:
|
||
* Whether to remember window positions
|
||
* NOTE: Only enabled for desktop Windows
|
||
* at present. */
|
||
#define DEFAULT_WINDOW_SAVE_POSITIONS false
|
||
|
||
/* Whether to use custom (fixed size)
|
||
* window dimensions in windowed mode. */
|
||
#ifdef WEBOS
|
||
#define DEFAULT_WINDOW_CUSTOM_SIZE_ENABLE true
|
||
#else
|
||
#define DEFAULT_WINDOW_CUSTOM_SIZE_ENABLE false
|
||
#endif
|
||
|
||
/* Window dimensions when using a fixed size
|
||
* window. A value of 0 disables fixed size
|
||
* windows, using nominal dimensions of
|
||
* window scale multiplied by the core
|
||
* framebuffer size. */
|
||
#if defined(WEBOS)
|
||
#define DEFAULT_WINDOW_WIDTH 1920
|
||
#define DEFAULT_WINDOW_HEIGHT 1080
|
||
#else
|
||
#define DEFAULT_WINDOW_WIDTH 1280
|
||
#define DEFAULT_WINDOW_HEIGHT 720
|
||
#endif
|
||
|
||
/* Maximum auto-set window dimensions
|
||
* when not using a fixed size window */
|
||
#define DEFAULT_WINDOW_AUTO_WIDTH_MAX 1920
|
||
#define DEFAULT_WINDOW_AUTO_HEIGHT_MAX 1080
|
||
|
||
/* Fullscreen resolution. A value of 0 uses the desktop
|
||
* resolution. */
|
||
#if defined(DINGUX)
|
||
#define DEFAULT_FULLSCREEN_X 320
|
||
#define DEFAULT_FULLSCREEN_Y 240
|
||
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||
#define DEFAULT_FULLSCREEN_X 1920
|
||
#define DEFAULT_FULLSCREEN_Y 1080
|
||
#else
|
||
#define DEFAULT_FULLSCREEN_X 0
|
||
#define DEFAULT_FULLSCREEN_Y 0
|
||
#endif
|
||
|
||
#if defined(HAVE_WINDOW_OFFSET)
|
||
/* Screen offsets to center content in CTRs */
|
||
#define DEFAULT_WINDOW_OFFSET_X 0
|
||
#define DEFAULT_WINDOW_OFFSET_Y 0
|
||
#endif
|
||
|
||
/* Number of threads to use for video recording */
|
||
#define DEFAULT_VIDEO_RECORD_THREADS 2
|
||
|
||
#if defined(RARCH_CONSOLE)
|
||
#define DEFAULT_LOAD_DUMMY_ON_CORE_SHUTDOWN false
|
||
#else
|
||
#define DEFAULT_LOAD_DUMMY_ON_CORE_SHUTDOWN true
|
||
#endif
|
||
|
||
/* Specifies whether cores are allowed to
|
||
* present core options in category submenus */
|
||
#define DEFAULT_CORE_OPTION_CATEGORY_ENABLE true
|
||
|
||
/* Specifies whether to cache core info
|
||
* into a single (compressed) file for improved
|
||
* load times on platforms with slow IO */
|
||
#if defined(__x86_64__) || defined(_M_X64)
|
||
#define DEFAULT_CORE_INFO_CACHE_ENABLE false
|
||
#else
|
||
#define DEFAULT_CORE_INFO_CACHE_ENABLE true
|
||
#endif
|
||
|
||
/* Specifies whether to ignore core info
|
||
* savestate capabilities, allowing to
|
||
* experiment with related features
|
||
* (run ahead, rewind, etc) */
|
||
#define DEFAULT_CORE_INFO_SAVESTATE_BYPASS false
|
||
|
||
/* Specifies whether to 'reload' (fork and quit)
|
||
* RetroArch when launching content with the
|
||
* currently loaded core
|
||
* > Only relevant on platforms without dynamic core
|
||
* loading support
|
||
* > Setting this to 'false' will decrease loading
|
||
* times when required core is already running,
|
||
* but may cause stability issues (if core misbehaves) */
|
||
#ifndef HAVE_DYNAMIC
|
||
#define DEFAULT_ALWAYS_RELOAD_CORE_ON_RUN_CONTENT true
|
||
#endif
|
||
|
||
/* Forcibly disable composition.
|
||
* Only valid on Windows Vista/7/8 for now. */
|
||
#define DEFAULT_DISABLE_COMPOSITION false
|
||
|
||
/* Video VSYNC (recommended) */
|
||
#define DEFAULT_VSYNC true
|
||
#define DEFAULT_SCANLINE_SYNC false
|
||
|
||
/* Vulkan specific */
|
||
#define DEFAULT_MAX_SWAPCHAIN_IMAGES 3
|
||
#define MINIMUM_MAX_SWAPCHAIN_IMAGES 2
|
||
#define MAXIMUM_MAX_SWAPCHAIN_IMAGES 4
|
||
|
||
/* D3D1x specific */
|
||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||
#define DEFAULT_WAITABLE_SWAPCHAINS false
|
||
#else
|
||
#define DEFAULT_WAITABLE_SWAPCHAINS true
|
||
#endif
|
||
#define DEFAULT_MAX_FRAME_LATENCY 1
|
||
#define MAXIMUM_MAX_FRAME_LATENCY 4
|
||
|
||
/* GL specific */
|
||
#define DEFAULT_ADAPTIVE_VSYNC false
|
||
|
||
/* Hands SPIR-V shaders straight to the driver through GL_ARB_gl_spirv
|
||
* rather than cross compiling them to GLSL. Off by default: the win is
|
||
* on a cold driver shader cache, and at least one implementation caches
|
||
* the cross compiled path far more effectively than the SPIR-V one, so
|
||
* this is opt-in until there is per-driver data to key off. */
|
||
#define DEFAULT_VIDEO_GL_DIRECT_SPIRV false
|
||
|
||
/* Attempts to hard-synchronize CPU and GPU.
|
||
* Can reduce latency at cost of performance. */
|
||
#define DEFAULT_HARD_SYNC false
|
||
|
||
/* Configures how many frames the GPU can run ahead of CPU.
|
||
* 0: Syncs to GPU immediately.
|
||
* 1: Syncs to previous frame.
|
||
* 2: Etc ...
|
||
*/
|
||
#define DEFAULT_HARD_SYNC_FRAMES 0
|
||
#define MINIMUM_HARD_SYNC_FRAMES 0
|
||
#define MAXIMUM_HARD_SYNC_FRAMES 3
|
||
|
||
/* Sets how many milliseconds to delay after VSync before running the core.
|
||
* Can reduce latency at cost of higher risk of stuttering.
|
||
*/
|
||
#define DEFAULT_FRAME_DELAY 0
|
||
#define MAXIMUM_FRAME_DELAY 99
|
||
#define DEFAULT_FRAME_DELAY_AUTO false
|
||
|
||
/* When true, the frame-time ring buffer that backs the "Estimated
|
||
* Screen Refresh Rate" diagnostic + the AUTO-apply menu action is
|
||
* sampled only when the runloop is in a "clean" steady state
|
||
* (content running, not paused, not in fast-forward, not in
|
||
* menu-with-paused-libretro, frame time within a sanity envelope
|
||
* around the expected period).
|
||
*
|
||
* Disabled by default to preserve the existing measurement
|
||
* behaviour and the reset toggles that depend on it. When
|
||
* enabled, the deviation in the diagnostic readout becomes a real
|
||
* signal again (the polluting samples from sleep / menu / save /
|
||
* load never enter the buffer in the first place), at the cost
|
||
* of slower convergence after content load. */
|
||
#define DEFAULT_FRAME_TIME_SAMPLE_GATED false
|
||
|
||
/* When true, drains the 'Estimated Screen Refresh Rate' sample
|
||
* buffer after fast-forward, save state, or load state -- events
|
||
* whose timing doesn't reflect normal frame cadence and would
|
||
* skew the deviation measurement. Best-effort cleanup for users
|
||
* who haven't enabled DEFAULT_FRAME_TIME_SAMPLE_GATED (which
|
||
* prevents the contamination at the source).
|
||
*
|
||
* Replaces three separate per-event reset toggles
|
||
* (frame_time_counter_reset_after_{fastforwarding,load_state,
|
||
* save_state}). Defaults to false to match the prior aggregate
|
||
* behaviour (all three off). */
|
||
#define DEFAULT_FRAME_TIME_COUNTER_AUTO_RESET false
|
||
|
||
/* Duplicates frames for the purposes of running Shaders at a higher framerate
|
||
* than content framerate. Requires running screen at multiple of 60hz, and
|
||
* don't combine with Swap_interval > 1, or BFI. (Though BFI can be done in a shader
|
||
* with multi-frame shaders.)
|
||
*/
|
||
#define DEFAULT_SHADER_SUBFRAMES 1
|
||
|
||
/* Divides implements basic rolling scanning of sub frames - does this simply by scrolling a
|
||
* a scissor rect down the screen according to how many sub frames there are
|
||
*/
|
||
#define DEFAULT_SCAN_SUBFRAMES false
|
||
|
||
/* Inserts black frame(s) inbetween frames.
|
||
* Useful for Higher Hz monitors (set to multiples of 60 Hz) who want to play 60 Hz
|
||
* material with CRT-like motion clarity.
|
||
*/
|
||
#define DEFAULT_BLACK_FRAME_INSERTION 0
|
||
|
||
/* Black Frame Insertion Dark Frames.
|
||
* Increase for more clarity at the cost of lower brightness. Adjusting can also eliminate
|
||
* any temporary image retention if noticed. Only useful at 180hz or higher 60hz multiples,
|
||
* as 120hz only has one total extra frame for BFI to work with.
|
||
*/
|
||
#define DEFAULT_BFI_DARK_FRAMES 1
|
||
|
||
/* Uses a custom swap interval for VSync.
|
||
* Set this to effectively halve monitor refresh rate.
|
||
*/
|
||
#define DEFAULT_SWAP_INTERVAL 1
|
||
|
||
/* Threaded video. Will possibly increase performance significantly
|
||
* at the cost of worse synchronization and latency.
|
||
*/
|
||
#if defined(HAVE_LIBNX)
|
||
#define DEFAULT_VIDEO_THREADED true
|
||
#else
|
||
#define DEFAULT_VIDEO_THREADED false
|
||
#endif
|
||
|
||
#if defined(HAVE_THREADS)
|
||
#if defined(GEKKO) || defined(PSP) || defined(PS2)
|
||
/* For single-core consoles right now it's best to have this be disabled. */
|
||
#define DEFAULT_THREADED_DATA_RUNLOOP_ENABLE false
|
||
#else
|
||
#define DEFAULT_THREADED_DATA_RUNLOOP_ENABLE true
|
||
#endif
|
||
#else
|
||
#define DEFAULT_THREADED_DATA_RUNLOOP_ENABLE false
|
||
#endif
|
||
|
||
/* Off everywhere: pinning the main and audio threads to the fast
|
||
* cores of a mixed-core part trades battery for latency, so it is
|
||
* the user's call. */
|
||
#define DEFAULT_THREAD_PREFER_FAST_CORES false
|
||
|
||
/* Set to true if HW render cores should get their private context. */
|
||
#define DEFAULT_VIDEO_SHARED_CONTEXT false
|
||
|
||
/* Sets GC/Wii screen width. */
|
||
#define DEFAULT_VIDEO_VI_WIDTH 640
|
||
|
||
#ifdef GEKKO
|
||
/* Removes 480i flicker, smooths picture a little. */
|
||
#define DEFAULT_VIDEO_VFILTER true
|
||
|
||
/* Allow overscan to be corrected on displays that
|
||
* do not have proper 'pixel perfect' scaling */
|
||
#define DEFAULT_VIDEO_OVERSCAN_CORRECTION_TOP 0
|
||
#define DEFAULT_VIDEO_OVERSCAN_CORRECTION_BOTTOM 0
|
||
#endif
|
||
|
||
/* Smooths picture. */
|
||
#if defined(_3DS) || defined(GEKKO) || defined(HW_RVL) || defined(PSP) || defined(VITA) || defined(SN_TARGET_PSP2) || defined(PS2) || defined(_XBOX) || defined(DINGUX)
|
||
#define DEFAULT_VIDEO_SMOOTH true
|
||
#else
|
||
#define DEFAULT_VIDEO_SMOOTH false
|
||
#endif
|
||
|
||
/* Graphics context specific scaling */
|
||
#define DEFAULT_VIDEO_CTX_SCALING false
|
||
|
||
/* On resize and fullscreen, rendering area will stay 4:3 */
|
||
#define DEFAULT_FORCE_ASPECT true
|
||
|
||
/* Only applies to Android 9.0 (API 28) and up */
|
||
/* Choose if the screen will be able to write around the notch or not */
|
||
#define DEFAULT_NOTCH_WRITE_OVER_ENABLE false
|
||
|
||
/* Enable use of shaders */
|
||
#define DEFAULT_SHADER_ENABLE true
|
||
|
||
/* When enabled, shaders compile one pass per frame instead of
|
||
* stalling for the entire preset. Disable to force the legacy
|
||
* synchronous (blocking) shader load path. */
|
||
#if defined(ANDROID)
|
||
#define DEFAULT_SHADER_DEFERRED_LOADING false
|
||
#else
|
||
#define DEFAULT_SHADER_DEFERRED_LOADING true
|
||
#endif
|
||
|
||
/* HDR output mode: 0 = off, 1 = HDR10, 2 = scRGB */
|
||
#define DEFAULT_VIDEO_HDR_MODE 0
|
||
|
||
/* Swapchain bit depth when HDR is off: 0 = auto (8), 1 = force 8, 2 = force 10.
|
||
* Only meaningful in SDR; HDR dictates its own swapchain format. */
|
||
#define DEFAULT_VIDEO_SWAPCHAIN_BIT_DEPTH 0
|
||
|
||
/* Brightness of the SDR menu/overlay when composited into the HDR backbuffer */
|
||
#define DEFAULT_MENU_HDR_BRIGHTNESS_NITS 200.0f
|
||
|
||
/* The number of nits that paper white is at */
|
||
#define DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS 200.0f
|
||
|
||
/* Peak luminance of the display, in nits. 1000 is the HDR10 reference peak and
|
||
* roughly what mid-range HDR panels reach, so it is a safe default for a value
|
||
* the frontend cannot query - no platform exposes it portably. */
|
||
#define DEFAULT_VIDEO_HDR_MAX_NITS 1000.0f
|
||
|
||
/* Should we expand the colour gamut when using hdr */
|
||
#define DEFAULT_VIDEO_HDR_EXPAND_GAMUT 0
|
||
|
||
/* Enable a basic HDR scanline implementation which is the main reason for using HDR in RetroArch */
|
||
#define DEFAULT_VIDEO_HDR_SCANLINES true
|
||
|
||
/* Default to the largely standard RGB layout */
|
||
#define DEFAULT_VIDEO_HDR_SUBPIXEL_LAYOUT 0
|
||
|
||
/* When presets are saved they will be saved using the #reference
|
||
* directive by default */
|
||
#define DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE true
|
||
|
||
#define DEFAULT_SHADER_DELAY 0
|
||
|
||
/* Only scale in integer steps.
|
||
* The base size depends on system-reported geometry and aspect ratio.
|
||
* If video_force_aspect is not set, X/Y will be integer scaled independently.
|
||
* Overscale rounds up instead of down, default is downscale.
|
||
*/
|
||
#define DEFAULT_SCALE_INTEGER false
|
||
#define DEFAULT_SCALE_INTEGER_AXIS 0
|
||
#define DEFAULT_SCALE_INTEGER_SCALING 0
|
||
|
||
/* Controls aspect ratio handling. */
|
||
|
||
/* 1:1 PAR */
|
||
#define DEFAULT_ASPECT_RATIO_AUTO false
|
||
|
||
#if defined(_XBOX360) || defined(__PS3__)
|
||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_16_9
|
||
#elif defined(PSP) || defined(_3DS) || defined(HAVE_LIBNX) || defined(VITA)
|
||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_CORE
|
||
#elif defined(RARCH_CONSOLE)
|
||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_4_3
|
||
#else
|
||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_CORE
|
||
#endif
|
||
|
||
#if defined(DINGUX)
|
||
/* Enables aspect ratio correction (1:1 PAR) when
|
||
* using the IPU hardware scaler in Dingux devices */
|
||
#define DEFAULT_DINGUX_IPU_KEEP_ASPECT true
|
||
/* Sets image filtering method when using the
|
||
* IPU hardware scaler in Dingux devices */
|
||
#if defined(RETROFW)
|
||
#define DEFAULT_DINGUX_IPU_FILTER_TYPE DINGUX_IPU_FILTER_NEAREST
|
||
#else
|
||
#define DEFAULT_DINGUX_IPU_FILTER_TYPE DINGUX_IPU_FILTER_BICUBIC
|
||
#endif
|
||
|
||
#if defined(DINGUX_BETA)
|
||
/* Sets refresh rate of integral LCD panel
|
||
* in Dingux devices */
|
||
#define DEFAULT_DINGUX_REFRESH_RATE DINGUX_REFRESH_RATE_60HZ
|
||
#endif
|
||
#if defined(RS90) || defined(MIYOO)
|
||
/* Sets image filtering method on the RS90
|
||
* when integer scaling is disabled */
|
||
#define DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE DINGUX_RS90_SOFTFILTER_POINT
|
||
#endif
|
||
#endif
|
||
|
||
/* Save configuration file on exit. */
|
||
#define DEFAULT_CONFIG_SAVE_ON_EXIT true
|
||
|
||
/* Save minimal configuration (only values that differ from defaults). */
|
||
#define DEFAULT_CONFIG_SAVE_MINIMAL false
|
||
|
||
/* Save active input remap file on exit/close content */
|
||
#define DEFAULT_REMAP_SAVE_ON_EXIT true
|
||
|
||
#define DEFAULT_SHOW_HIDDEN_FILES false
|
||
#define DEFAULT_CORE_SUGGEST_ALWAYS false
|
||
|
||
/* Initialise file browser with the last used start directory */
|
||
#define DEFAULT_USE_LAST_START_DIRECTORY false
|
||
|
||
#define DEFAULT_OVERLAY_BEHIND_MENU false
|
||
|
||
#define DEFAULT_OVERLAY_HIDE_IN_MENU true
|
||
|
||
/* Automatically disable overlays when a
|
||
* controller is connected in port 1 */
|
||
#define DEFAULT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED false
|
||
|
||
#define DEFAULT_OVERLAY_SHOW_MOUSE_CURSOR false
|
||
|
||
#ifdef HAKCHI
|
||
#define DEFAULT_INPUT_OVERLAY_OPACITY 0.5f
|
||
#else
|
||
#define DEFAULT_INPUT_OVERLAY_OPACITY 0.7f
|
||
#endif
|
||
|
||
#define DEFAULT_INPUT_OVERLAY_SCALE_LANDSCAPE 1.0f
|
||
#define DEFAULT_INPUT_OVERLAY_ASPECT_ADJUST_LANDSCAPE 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_X_SEPARATION_LANDSCAPE 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_Y_SEPARATION_LANDSCAPE 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_X_OFFSET_LANDSCAPE 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_Y_OFFSET_LANDSCAPE 0.0f
|
||
|
||
#define DEFAULT_INPUT_OVERLAY_SCALE_PORTRAIT 1.0f
|
||
#define DEFAULT_INPUT_OVERLAY_ASPECT_ADJUST_PORTRAIT 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_X_SEPARATION_PORTRAIT 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_Y_SEPARATION_PORTRAIT 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_X_OFFSET_PORTRAIT 0.0f
|
||
#define DEFAULT_INPUT_OVERLAY_Y_OFFSET_PORTRAIT 0.0f
|
||
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_OVERLAY_AUTO_ROTATE true
|
||
#else
|
||
#define DEFAULT_OVERLAY_AUTO_ROTATE false
|
||
#endif
|
||
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_INPUT_OVERLAY_AUTO_SCALE true
|
||
#else
|
||
#define DEFAULT_INPUT_OVERLAY_AUTO_SCALE false
|
||
#endif
|
||
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_INPUT_OVERLAY_POINTER_ENABLE true
|
||
#else
|
||
#define DEFAULT_INPUT_OVERLAY_POINTER_ENABLE false
|
||
#endif
|
||
|
||
#define DEFAULT_INPUT_OVERLAY_ANALOG_RECENTER_ZONE 0
|
||
|
||
#define DEFAULT_INPUT_OVERLAY_LIGHTGUN_PORT -1
|
||
#define DEFAULT_INPUT_OVERLAY_LIGHTGUN_TRIGGER_ON_TOUCH true
|
||
#define DEFAULT_INPUT_OVERLAY_LIGHTGUN_TRIGGER_DELAY 1
|
||
#define DEFAULT_INPUT_OVERLAY_LIGHTGUN_MULTI_TOUCH_INPUT 0
|
||
#define DEFAULT_INPUT_OVERLAY_LIGHTGUN_ALLOW_OFFSCREEN true
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_SPEED 1.0f
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_HOLD_TO_DRAG true
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_HOLD_MSEC 200
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_DTAP_TO_DRAG false
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_DTAP_MSEC 200
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_SWIPE_THRESHOLD 1.0f
|
||
#define DEFAULT_INPUT_OVERLAY_MOUSE_ALT_TWO_TOUCH_INPUT OVERLAY_MOUSE_BTN_NONE
|
||
|
||
#ifdef UDEV_TOUCH_SUPPORT
|
||
#define DEFAULT_INPUT_TOUCH_VMOUSE_POINTER true
|
||
#define DEFAULT_INPUT_TOUCH_VMOUSE_MOUSE true
|
||
#define DEFAULT_INPUT_TOUCH_VMOUSE_TOUCHPAD true
|
||
#define DEFAULT_INPUT_TOUCH_VMOUSE_TRACKBALL false
|
||
#define DEFAULT_INPUT_TOUCH_VMOUSE_GESTURE true
|
||
#endif
|
||
|
||
#include "runtime_file_defines.h"
|
||
#ifdef HAVE_MENU
|
||
#include "menu/menu_defines.h"
|
||
|
||
#ifdef HAVE_LIBNX
|
||
#define DEFAULT_MENU_USE_PREFERRED_SYSTEM_COLOR_THEME true
|
||
#else
|
||
#define DEFAULT_MENU_USE_PREFERRED_SYSTEM_COLOR_THEME false
|
||
#endif
|
||
|
||
#ifdef HAVE_OZONE
|
||
/* Ozone colour theme: 1 == Basic Black */
|
||
#define DEFAULT_OZONE_COLOR_THEME 1
|
||
#define DEFAULT_OZONE_PADDING_FACTOR 1.0f
|
||
#define DEFAULT_OZONE_HEADER_ICON 1
|
||
#define DEFAULT_OZONE_HEADER_SEPARATOR 1
|
||
#define DEFAULT_OZONE_COLLAPSE_SIDEBAR false
|
||
#define DEFAULT_OZONE_SHOW_SIDEBAR true
|
||
#define DEFAULT_OZONE_SCROLL_CONTENT_METADATA false
|
||
#define DEFAULT_OZONE_THUMBNAIL_SCALE_FACTOR 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE 0
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_GLOBAL 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_TITLE 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_SIDEBAR 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_LABEL 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_SUBLABEL 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_TIME 1.0f
|
||
#define DEFAULT_OZONE_FONT_SCALE_FACTOR_FOOTER 1.0f
|
||
#endif
|
||
|
||
#if defined(HAVE_OZONE) || defined(HAVE_XMB)
|
||
#define DEFAULT_OZONE_TRUNCATE_PLAYLIST_NAME true
|
||
#define DEFAULT_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME false
|
||
#endif
|
||
|
||
#define DEFAULT_SETTINGS_SHOW_DRIVERS true
|
||
#define DEFAULT_SETTINGS_SHOW_VIDEO true
|
||
#define DEFAULT_SETTINGS_SHOW_AUDIO true
|
||
#define DEFAULT_SETTINGS_SHOW_INPUT true
|
||
#define DEFAULT_SETTINGS_SHOW_LATENCY true
|
||
#define DEFAULT_SETTINGS_SHOW_CORE true
|
||
#define DEFAULT_SETTINGS_SHOW_CONFIGURATION true
|
||
#define DEFAULT_SETTINGS_SHOW_SAVING true
|
||
#define DEFAULT_SETTINGS_SHOW_LOGGING true
|
||
#define DEFAULT_SETTINGS_SHOW_FILE_BROWSER true
|
||
#define DEFAULT_SETTINGS_SHOW_FRAME_THROTTLE true
|
||
#define DEFAULT_SETTINGS_SHOW_RECORDING true
|
||
#define DEFAULT_SETTINGS_SHOW_ONSCREEN_DISPLAY true
|
||
#define DEFAULT_SETTINGS_SHOW_USER_INTERFACE true
|
||
#define DEFAULT_SETTINGS_SHOW_AI_SERVICE true
|
||
#define DEFAULT_SETTINGS_SHOW_ACCESSIBILITY true
|
||
#define DEFAULT_SETTINGS_SHOW_POWER_MANAGEMENT true
|
||
#define DEFAULT_SETTINGS_SHOW_ACHIEVEMENTS true
|
||
#define DEFAULT_SETTINGS_SHOW_NETWORK true
|
||
#define DEFAULT_SETTINGS_SHOW_PLAYLISTS true
|
||
#define DEFAULT_SETTINGS_SHOW_USER true
|
||
#define DEFAULT_SETTINGS_SHOW_DIRECTORY true
|
||
#define DEFAULT_SETTINGS_SHOW_STEAM true
|
||
#define DEFAULT_SETTINGS_SHOW_SMB_CLIENT true
|
||
|
||
#define DEFAULT_QUICK_MENU_SHOW_RESUME_CONTENT true
|
||
#define DEFAULT_QUICK_MENU_SHOW_RESTART_CONTENT true
|
||
#define DEFAULT_QUICK_MENU_SHOW_CLOSE_CONTENT true
|
||
#define DEFAULT_QUICK_MENU_SHOW_TAKE_SCREENSHOT true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SAVESTATE_SUBMENU true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SAVE_LOAD_STATE true
|
||
#define DEFAULT_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE true
|
||
#define DEFAULT_QUICK_MENU_SHOW_REPLAY false
|
||
#define DEFAULT_QUICK_MENU_SHOW_ADD_TO_FAVORITES true
|
||
#define DEFAULT_QUICK_MENU_SHOW_ADD_TO_PLAYLIST false
|
||
#define DEFAULT_QUICK_MENU_SHOW_START_RECORDING true
|
||
#define DEFAULT_QUICK_MENU_SHOW_START_STREAMING true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SET_CORE_ASSOCIATION true
|
||
#define DEFAULT_QUICK_MENU_SHOW_RESET_CORE_ASSOCIATION true
|
||
#define DEFAULT_QUICK_MENU_SHOW_CORE_OPTIONS true
|
||
#define DEFAULT_QUICK_MENU_SHOW_CORE_OPTIONS_FLUSH false
|
||
#define DEFAULT_QUICK_MENU_SHOW_CONTROLS true
|
||
#define DEFAULT_QUICK_MENU_SHOW_LATENCY true
|
||
#define DEFAULT_QUICK_MENU_SHOW_REWIND true
|
||
#define DEFAULT_QUICK_MENU_SHOW_OVERLAYS true
|
||
#define DEFAULT_QUICK_MENU_SHOW_CHEATS true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SHADERS true
|
||
#define DEFAULT_QUICK_MENU_SHOW_INFORMATION true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES true
|
||
#define DEFAULT_QUICK_MENU_SHOW_SAVE_CONTENT_DIR_OVERRIDES true
|
||
#ifdef HAVE_NETWORKING
|
||
#define DEFAULT_QUICK_MENU_SHOW_DOWNLOAD_THUMBNAILS true
|
||
#endif
|
||
|
||
#define DEFAULT_MENU_SHOW_ONLINE_UPDATER true
|
||
#if defined(HAVE_LAKKA) || defined(VITA)
|
||
#define DEFAULT_MENU_SHOW_CORE_UPDATER false
|
||
#else
|
||
#define DEFAULT_MENU_SHOW_CORE_UPDATER true
|
||
#endif
|
||
#define DEFAULT_MENU_SHOW_LOAD_CORE true
|
||
#define DEFAULT_MENU_SHOW_LOAD_CONTENT true
|
||
#ifdef HAVE_CDROM
|
||
#define DEFAULT_MENU_SHOW_LOAD_DISC true
|
||
#define DEFAULT_MENU_SHOW_DUMP_DISC true
|
||
#ifdef HAVE_LAKKA
|
||
#define DEFAULT_MENU_SHOW_EJECT_DISC true
|
||
#endif /* HAVE_LAKKA */
|
||
#endif
|
||
#define DEFAULT_MENU_SHOW_INFORMATION true
|
||
#define DEFAULT_MENU_SHOW_CONFIGURATIONS true
|
||
#define DEFAULT_MENU_SHOW_HELP true
|
||
#if defined(ANDROID)
|
||
/* Android's navigation model expects the user to leave via Home or the
|
||
* task switcher rather than an in-app control, and the Android TV
|
||
* guidelines state outright that an exit item should not appear in the
|
||
* menu. Default the entry off; the toggle stays available under
|
||
* Settings -> User Interface -> Menu Item Visibility for anyone who
|
||
* wants it back, and existing configs that already set the key are
|
||
* left untouched. */
|
||
#define DEFAULT_MENU_SHOW_QUIT false
|
||
#else
|
||
#define DEFAULT_MENU_SHOW_QUIT true
|
||
#endif
|
||
#define DEFAULT_MENU_SHOW_RESTART true
|
||
#define DEFAULT_MENU_SHOW_REBOOT true
|
||
#define DEFAULT_MENU_SHOW_SHUTDOWN true
|
||
#ifdef HAVE_MIST
|
||
#define DEFAULT_MENU_SHOW_CORE_MANAGER_STEAM true
|
||
#endif
|
||
#define DEFAULT_MENU_SHOW_SUBLABELS true
|
||
#define DEFAULT_MENU_SHOW_SUBLABELS_CURRENT_SELECTION_ONLY false
|
||
#define DEFAULT_MENU_SHOW_CONFIRM true
|
||
#define DEFAULT_MENU_DYNAMIC_WALLPAPER_ENABLE true
|
||
#define DEFAULT_MENU_SCROLL_FAST false
|
||
#define DEFAULT_MENU_SCROLL_DELAY 256
|
||
|
||
#define DEFAULT_KIOSK_MODE_ENABLE false
|
||
#define DEFAULT_MENU_HORIZONTAL_ANIMATION true
|
||
#define DEFAULT_MENU_SHOW_FULL_PATHS true
|
||
|
||
#define DEFAULT_MENU_TICKER_TYPE (TICKER_TYPE_LOOP)
|
||
#define DEFAULT_MENU_TICKER_SPEED 2.0f
|
||
#define DEFAULT_MENU_TICKER_SMOOTH true
|
||
|
||
/* Don't skip rendering assets based on the absence of other assets */
|
||
#define DEFAULT_MENU_IGNORE_MISSING_ASSETS false
|
||
|
||
#if defined(HAVE_THREADS)
|
||
#define DEFAULT_MENU_SAVESTATE_RESUME true
|
||
#else
|
||
#define DEFAULT_MENU_SAVESTATE_RESUME false
|
||
#endif
|
||
|
||
#define DEFAULT_MENU_INSERT_DISK_RESUME true
|
||
|
||
#define DEFAULT_QUIT_ON_CLOSE_CONTENT QUIT_ON_CLOSE_CONTENT_DISABLED
|
||
|
||
/* While the menu is active, supported drivers
|
||
* will display a screensaver after SCREENSAVER_TIMEOUT
|
||
* seconds of inactivity. A timeout of zero disables
|
||
* the screensaver */
|
||
#define DEFAULT_MENU_SCREENSAVER_TIMEOUT 0
|
||
|
||
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
|
||
/* When menu screensaver is enabled, specifies
|
||
* animation effect and animation speed */
|
||
#define DEFAULT_MENU_SCREENSAVER_ANIMATION MENU_SCREENSAVER_BLANK
|
||
#define DEFAULT_MENU_SCREENSAVER_ANIMATION_SPEED 1.0f
|
||
#endif
|
||
|
||
#define DEFAULT_CONTENT_SHOW_SETTINGS true
|
||
#define DEFAULT_CONTENT_SHOW_HISTORY true
|
||
#define DEFAULT_CONTENT_SHOW_FAVORITES true
|
||
#define DEFAULT_CONTENT_SHOW_FAVORITES_FIRST false
|
||
#ifdef HAVE_IMAGEVIEWER
|
||
#define DEFAULT_CONTENT_SHOW_IMAGES true
|
||
#endif
|
||
#define DEFAULT_CONTENT_SHOW_MUSIC false
|
||
#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
|
||
#define DEFAULT_CONTENT_SHOW_VIDEO true
|
||
#endif
|
||
|
||
#define DEFAULT_MENU_CONTENT_SHOW_ADD_ENTRY MENU_ADD_CONTENT_ENTRY_DISPLAY_PLAYLISTS_TAB
|
||
|
||
/* Share 'Import Content' values */
|
||
#if defined(HAVE_NETWORKING)
|
||
#if defined(_3DS)
|
||
#define DEFAULT_CONTENT_SHOW_NETPLAY MENU_ADD_CONTENT_ENTRY_DISPLAY_HIDDEN
|
||
#else
|
||
#define DEFAULT_CONTENT_SHOW_NETPLAY MENU_ADD_CONTENT_ENTRY_DISPLAY_PLAYLISTS_TAB
|
||
#endif
|
||
#endif
|
||
|
||
#define DEFAULT_CONTENT_SHOW_PLAYLISTS true
|
||
#define DEFAULT_CONTENT_SHOW_PLAYLIST_TABS true
|
||
|
||
#if defined(HAVE_LIBRETRODB)
|
||
#define DEFAULT_MENU_CONTENT_SHOW_EXPLORE true
|
||
#endif
|
||
#define DEFAULT_MENU_CONTENT_SHOW_CONTENTLESS_CORES MENU_CONTENTLESS_CORES_DISPLAY_SINGLE_PURPOSE
|
||
|
||
/* Shared with the Ozone driver. */
|
||
#if defined(HAVE_XMB) || defined(HAVE_OZONE)
|
||
#define DEFAULT_XMB_ANIMATION 0
|
||
#endif
|
||
#ifdef HAVE_XMB
|
||
#define DEFAULT_XMB_VERTICAL_FADE_FACTOR 100
|
||
#define DEFAULT_XMB_SHOW_HORIZONTAL_LIST true
|
||
#define DEFAULT_XMB_SHOW_TITLE_HEADER true
|
||
#define DEFAULT_XMB_ENTRY_ICONS true
|
||
#define DEFAULT_XMB_SWITCH_ICONS true
|
||
#define DEFAULT_XMB_CURRENT_MENU_ICON 1
|
||
#define DEFAULT_XMB_TITLE_MARGIN 3
|
||
#define DEFAULT_XMB_TITLE_MARGIN_HORIZONTAL_OFFSET 0
|
||
#define MAXIMUM_XMB_TITLE_MARGIN 12
|
||
#define DEFAULT_XMB_ALPHA_FACTOR 90
|
||
|
||
#define DEFAULT_MENU_FONT_COLOR_RED 255
|
||
#define DEFAULT_MENU_FONT_COLOR_GREEN 255
|
||
#define DEFAULT_MENU_FONT_COLOR_BLUE 255
|
||
#ifdef HAVE_ODROIDGO2
|
||
#define DEFAULT_XMB_MENU_LAYOUT 2
|
||
#else
|
||
#define DEFAULT_XMB_MENU_LAYOUT 0
|
||
#endif
|
||
#define DEFAULT_XMB_ICON_THEME XMB_ICON_THEME_MONOCHROME
|
||
#define DEFAULT_XMB_THEME XMB_THEME_ELECTRIC_BLUE
|
||
|
||
#if defined(HAVE_LAKKA) || defined(__arm__) || defined(__PPC64__) || defined(__ppc64__) || defined(__powerpc64__) || defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__)
|
||
#define DEFAULT_XMB_SHADOWS_ENABLE false
|
||
#else
|
||
#define DEFAULT_XMB_SHADOWS_ENABLE true
|
||
#endif
|
||
#endif
|
||
|
||
#define DEFAULT_MENU_FRAMEBUFFER_OPACITY 0.900f
|
||
#define DEFAULT_MENU_WALLPAPER_OPACITY 0.900f
|
||
#define DEFAULT_MENU_FOOTER_OPACITY 1.000f
|
||
#define DEFAULT_MENU_HEADER_OPACITY 1.000f
|
||
|
||
#if (defined(HAVE_OPENGLES2) && !defined(__EMSCRIPTEN__)) || (defined(__MACH__) && defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED < 101200))
|
||
#define DEFAULT_MENU_SHADER_PIPELINE 1
|
||
#else
|
||
#define DEFAULT_MENU_SHADER_PIPELINE 2
|
||
#endif
|
||
|
||
#define DEFAULT_SHOW_ADVANCED_SETTINGS true
|
||
|
||
#define DEFAULT_RGUI_COLOR_THEME RGUI_THEME_CLASSIC_GREEN
|
||
#define DEFAULT_RGUI_TRANSPARENCY true
|
||
|
||
#define DEFAULT_RGUI_INLINE_THUMBNAILS false
|
||
#define DEFAULT_RGUI_SWAP_THUMBNAILS false
|
||
|
||
/* Dithering trades banding for a fine pattern, which is the better
|
||
* bargain at normal menu scales. It is magnified by the menu's
|
||
* nearest-neighbour upscale though, so users running a large scale
|
||
* factor may prefer it off. */
|
||
#define DEFAULT_RGUI_THUMBNAIL_DITHER true
|
||
#define DEFAULT_RGUI_THUMBNAIL_DOWNSCALER RGUI_THUMB_SCALE_POINT
|
||
#define DEFAULT_RGUI_THUMBNAIL_DELAY 0
|
||
#define DEFAULT_RGUI_INTERNAL_UPSCALE_LEVEL RGUI_UPSCALE_NONE
|
||
#define DEFAULT_RGUI_FULL_WIDTH_LAYOUT true
|
||
#define DEFAULT_RGUI_ASPECT RGUI_ASPECT_RATIO_4_3
|
||
#define DEFAULT_RGUI_ASPECT_LOCK RGUI_ASPECT_RATIO_LOCK_NONE
|
||
#define DEFAULT_RGUI_SHADOWS false
|
||
#define DEFAULT_RGUI_PARTICLE_EFFECT RGUI_PARTICLE_EFFECT_NONE
|
||
#define DEFAULT_RGUI_PARTICLE_EFFECT_SPEED 1.0f
|
||
#define DEFAULT_RGUI_PARTICLE_EFFECT_SCREENSAVER true
|
||
#define DEFAULT_RGUI_EXTENDED_ASCII false
|
||
#define DEFAULT_RGUI_SWITCH_ICONS true
|
||
#endif
|
||
|
||
#ifdef HAVE_MENU
|
||
#define DEFAULT_BLOCK_CONFIG_READ true
|
||
#else
|
||
#define DEFAULT_BLOCK_CONFIG_READ false
|
||
#endif
|
||
|
||
#define DEFAULT_GAME_SPECIFIC_OPTIONS true
|
||
#define DEFAULT_AUTO_OVERRIDES_ENABLE true
|
||
#define DEFAULT_AUTO_REMAPS_ENABLE true
|
||
#define DEFAULT_INITIAL_DISK_CHANGE_ENABLE true
|
||
#define DEFAULT_GLOBAL_CORE_OPTIONS false
|
||
#define DEFAULT_AUTO_SHADERS_ENABLE true
|
||
|
||
#define DEFAULT_SORT_SAVEFILES_ENABLE true
|
||
#define DEFAULT_SORT_SAVESTATES_ENABLE true
|
||
#define DEFAULT_SORT_SAVEFILES_BY_CONTENT_ENABLE false
|
||
#define DEFAULT_SORT_SAVESTATES_BY_CONTENT_ENABLE false
|
||
#define DEFAULT_SORT_SCREENSHOTS_BY_CONTENT_ENABLE false
|
||
|
||
#define DEFAULT_SAVESTATES_IN_CONTENT_DIR false
|
||
#define DEFAULT_SAVEFILES_IN_CONTENT_DIR false
|
||
#define DEFAULT_SYSTEMFILES_IN_CONTENT_DIR false
|
||
#define DEFAULT_SCREENSHOTS_IN_CONTENT_DIR false
|
||
|
||
#if defined(RS90) || defined(RETROFW) || defined(MIYOO) || defined(SWITCH) || defined(ORBIS) || defined(__WINRT__)
|
||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_START_SELECT
|
||
#elif defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
|
||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_L3_R3
|
||
#elif defined(PS2) || defined(PSP)
|
||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_HOLD_START
|
||
#elif defined(VITA)
|
||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_L1_R1_START_SELECT
|
||
#elif TARGET_OS_TV
|
||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_DOWN_Y_L_R
|
||
#else
|
||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_NONE
|
||
#endif
|
||
|
||
#define DEFAULT_QUIT_GAMEPAD_COMBO INPUT_COMBO_NONE
|
||
|
||
#if defined(VITA)
|
||
#define DEFAULT_INPUT_BACKTOUCH_ENABLE false
|
||
#define DEFAULT_INPUT_BACKTOUCH_TOGGLE false
|
||
#endif
|
||
|
||
#if defined(ANDROID) || TARGET_OS_IPHONE
|
||
#define DEFAULT_OVERLAY_ENABLE_AUTOPREFERRED true
|
||
#else
|
||
#define DEFAULT_OVERLAY_ENABLE_AUTOPREFERRED false
|
||
#endif
|
||
|
||
#if defined(HAVE_OVERLAY)
|
||
#if defined(RARCH_MOBILE)
|
||
#define DEFAULT_OVERLAY_SHOW_INPUTS OVERLAY_SHOW_INPUT_TOUCHED
|
||
#else
|
||
#define DEFAULT_OVERLAY_SHOW_INPUTS OVERLAY_SHOW_INPUT_PHYSICAL
|
||
#endif
|
||
#endif
|
||
|
||
#define DEFAULT_OVERLAY_SHOW_INPUTS_PORT 0
|
||
|
||
#define DEFAULT_OVERLAY_DPAD_DIAGONAL_SENSITIVITY 80
|
||
#define DEFAULT_OVERLAY_ABXY_DIAGONAL_SENSITIVITY 50
|
||
|
||
#define DEFAULT_MENU_SWAP_OK_CANCEL_BUTTONS true
|
||
#define DEFAULT_MENU_SWAP_SCROLL_BUTTONS false
|
||
#define DEFAULT_MENU_SINGLECLICK_PLAYLISTS false
|
||
#define DEFAULT_MENU_ALLOW_TABS_BACK true
|
||
|
||
#if defined(WIIU)
|
||
#define DEFAULT_ALL_USERS_CONTROL_MENU true
|
||
#else
|
||
#define DEFAULT_ALL_USERS_CONTROL_MENU false
|
||
#endif
|
||
|
||
#define DEFAULT_CONFIRM_QUIT true
|
||
#define DEFAULT_CONFIRM_CLOSE true
|
||
#define DEFAULT_CONFIRM_RESET true
|
||
|
||
#define DEFAULT_LOG_TO_FILE false
|
||
#define DEFAULT_LOG_TO_FILE_TIMESTAMP false
|
||
|
||
/* Crop overscanned frames. */
|
||
#define DEFAULT_CROP_OVERSCAN true
|
||
|
||
/* Font size for on-screen messages. */
|
||
#if defined(DINGUX)
|
||
#define DEFAULT_FONT_SIZE 12
|
||
#elif defined(PS2)
|
||
#define DEFAULT_FONT_SIZE 16
|
||
#else
|
||
#define DEFAULT_FONT_SIZE 32
|
||
#endif
|
||
|
||
/* Offset for where messages will be placed on-screen.
|
||
* Values are in range [0.0, 1.0]. */
|
||
#define DEFAULT_MESSAGE_POS_OFFSET_X 0.05f
|
||
#define DEFAULT_MESSAGE_POS_OFFSET_Y 0.05f
|
||
|
||
/* Color of the message.
|
||
* RGB hex value. */
|
||
#define DEFAULT_MESSAGE_COLOR 0xffffff
|
||
|
||
#define DEFAULT_MESSAGE_BGCOLOR_ENABLE false
|
||
#define DEFAULT_MESSAGE_BGCOLOR_RED 0
|
||
#define DEFAULT_MESSAGE_BGCOLOR_GREEN 0
|
||
#define DEFAULT_MESSAGE_BGCOLOR_BLUE 0
|
||
#define DEFAULT_MESSAGE_BGCOLOR_OPACITY 1.0f
|
||
|
||
/* Record post-filtered (CPU filter) video,
|
||
* rather than raw game output. */
|
||
#define DEFAULT_POST_FILTER_RECORD false
|
||
|
||
/* Screenshots named automatically. */
|
||
#define DEFAULT_AUTO_SCREENSHOT_FILENAME true
|
||
|
||
/* Screenshots post-shaded GPU output if available. */
|
||
#define DEFAULT_GPU_SCREENSHOT false
|
||
|
||
/* Record post-shaded GPU output instead of raw game footage if available. */
|
||
#define DEFAULT_GPU_RECORD false
|
||
|
||
/* Watch shader files for changes and auto-apply as necessary. */
|
||
#define DEFAULT_VIDEO_SHADER_WATCH_FILES false
|
||
|
||
/* Initialise file browser with last used directory
|
||
* when selecting shader presets/passes via the menu */
|
||
#define DEFAULT_VIDEO_SHADER_REMEMBER_LAST_DIR false
|
||
|
||
/* OSD-messages. */
|
||
#define DEFAULT_FONT_ENABLE true
|
||
|
||
/* The accurate refresh rate of your monitor (Hz).
|
||
* This is used to calculate audio input rate with the formula:
|
||
* audio_input_rate = game_input_rate * display_refresh_rate /
|
||
* game_refresh_rate.
|
||
*
|
||
* If the implementation does not report any values,
|
||
* NTSC defaults will be assumed for compatibility.
|
||
* This value should stay close to 60Hz to avoid large pitch changes.
|
||
* If your monitor does not run at 60Hz, or something close to it,
|
||
* disable VSync, and leave this at its default. */
|
||
#ifdef _3DS
|
||
#define DEFAULT_REFRESH_RATE ((32730.0f * 8192.0f) / 4481134.0f)
|
||
#elif defined(RARCH_CONSOLE)
|
||
#define DEFAULT_REFRESH_RATE (60 / 1.001f)
|
||
#else
|
||
#define DEFAULT_REFRESH_RATE (60)
|
||
#endif
|
||
#define DEFAULT_CRT_REFRESH_RATE (DEFAULT_REFRESH_RATE)
|
||
|
||
/* Allow games to set rotation. If false, rotation requests are
|
||
* honored, but ignored.
|
||
* Used for setups where one manually rotates the monitor. */
|
||
#define DEFAULT_ALLOW_ROTATE true
|
||
|
||
#ifdef _3DS
|
||
/* Enable New3DS clock and L2 cache */
|
||
#define DEFAULT_NEW_3DS_SPEEDUP_ENABLE true
|
||
/* Enable bottom LCD screen */
|
||
#define DEFAULT_VIDEO_3DS_LCD_BOTTOM true
|
||
/* Sets video display mode (3D, 2D, etc.) */
|
||
#define DEFAULT_VIDEO_3DS_DISPLAY_MODE CTR_VIDEO_MODE_3D
|
||
|
||
#define DEFAULT_BOTTOM_FONT_ENABLE true
|
||
#define DEFAULT_BOTTOM_FONT_COLOR 255
|
||
#define DEFAULT_BOTTOM_FONT_SCALE 1.48f
|
||
#endif
|
||
|
||
#ifdef WIIU
|
||
/* On Wii U, whether to optimize for the native TV resolution
|
||
* or exactly 2x the Wii U GamePad resolution. */
|
||
#define DEFAULT_WIIU_PREFER_DRC false
|
||
#endif
|
||
|
||
/* AUDIO */
|
||
|
||
/* Will enable audio or not. */
|
||
#define DEFAULT_AUDIO_ENABLE true
|
||
|
||
/* Enable menu audio sounds. */
|
||
#define DEFAULT_AUDIO_ENABLE_MENU false
|
||
#define DEFAULT_AUDIO_ENABLE_MENU_OK false
|
||
#define DEFAULT_AUDIO_ENABLE_MENU_CANCEL false
|
||
#define DEFAULT_AUDIO_ENABLE_MENU_NOTICE false
|
||
#define DEFAULT_AUDIO_ENABLE_MENU_BGM false
|
||
#define DEFAULT_AUDIO_ENABLE_MENU_SCROLL false
|
||
|
||
#ifdef HAVE_GFX_WIDGETS
|
||
#define DEFAULT_MENU_ENABLE_WIDGETS true
|
||
#else
|
||
#define DEFAULT_MENU_ENABLE_WIDGETS false
|
||
#endif
|
||
|
||
/* Display an animation when loading content
|
||
* > Currently implemented only as a widget */
|
||
#define DEFAULT_MENU_SHOW_LOAD_CONTENT_ANIMATION DEFAULT_MENU_ENABLE_WIDGETS
|
||
|
||
/* Display a notification when successfully
|
||
* connecting/disconnecting an autoconfigured
|
||
* controller
|
||
* > Disabled by default on the Switch */
|
||
#if defined(HAVE_LIBNX) && defined(HAVE_GFX_WIDGETS)
|
||
#define DEFAULT_NOTIFICATION_SHOW_AUTOCONFIG false
|
||
#else
|
||
#define DEFAULT_NOTIFICATION_SHOW_AUTOCONFIG true
|
||
#endif
|
||
|
||
/* Display a notification when controller
|
||
* autoconfiguration fails. */
|
||
#define DEFAULT_NOTIFICATION_SHOW_AUTOCONFIG_FAILS true
|
||
|
||
/* Display a notification when cheats are being
|
||
* applied */
|
||
#define DEFAULT_NOTIFICATION_SHOW_CHEATS_APPLIED true
|
||
|
||
/* Display a notification when applying an
|
||
* IPS/BPS/UPS/Xdelta patch file */
|
||
#define DEFAULT_NOTIFICATION_SHOW_PATCH_APPLIED true
|
||
|
||
/* Display a notification when loading an
|
||
* input remap file */
|
||
#define DEFAULT_NOTIFICATION_SHOW_REMAP_LOAD true
|
||
|
||
/* Display a notification when loading a
|
||
* configuration override file */
|
||
#define DEFAULT_NOTIFICATION_SHOW_CONFIG_OVERRIDE_LOAD true
|
||
|
||
/* Display a notification when automatically restoring
|
||
* at launch the last used disk of multi-disk content */
|
||
#define DEFAULT_NOTIFICATION_SHOW_SET_INITIAL_DISK true
|
||
|
||
/* Display disc control notifications */
|
||
#define DEFAULT_NOTIFICATION_SHOW_DISK_CONTROL true
|
||
|
||
/* Display save state notifications */
|
||
#define DEFAULT_NOTIFICATION_SHOW_SAVE_STATE true
|
||
|
||
/* Display a notification when fast forwarding
|
||
* content */
|
||
#define DEFAULT_NOTIFICATION_SHOW_FAST_FORWARD true
|
||
|
||
#if defined(HAVE_SCREENSHOTS)
|
||
/*Display a notification when taking a screenshot*/
|
||
#define DEFAULT_NOTIFICATION_SHOW_SCREENSHOT true
|
||
|
||
/*Desired duration of the screenshot notification*/
|
||
#define DEFAULT_NOTIFICATION_SHOW_SCREENSHOT_DURATION 0
|
||
|
||
/* Display a white flashing effect with the desired
|
||
* duration when taking a screenshot*/
|
||
#define DEFAULT_NOTIFICATION_SHOW_SCREENSHOT_FLASH 0
|
||
#endif
|
||
|
||
/* Display a notification when setting the refresh rate*/
|
||
#if defined(_3DS) || (defined(DINGUX) && defined(DINGUX_BETA))
|
||
/* 3DS and OpenDingux Beta devices set refresh rate
|
||
* on gfx driver init - set default notification
|
||
* state to 'false' in order to avoid OSD log spam */
|
||
#define DEFAULT_NOTIFICATION_SHOW_REFRESH_RATE false
|
||
#else
|
||
#define DEFAULT_NOTIFICATION_SHOW_REFRESH_RATE true
|
||
#endif
|
||
|
||
#ifdef HAVE_NETWORKING
|
||
#define DEFAULT_NOTIFICATION_SHOW_NETPLAY_EXTRA false
|
||
#endif
|
||
|
||
#ifdef HAVE_MENU
|
||
#define DEFAULT_NOTIFICATION_SHOW_WHEN_MENU_IS_ALIVE false
|
||
#endif
|
||
|
||
/* Output samplerate. */
|
||
#if defined(GEKKO) || defined(MIYOO)
|
||
#define DEFAULT_OUTPUT_RATE 32000
|
||
#define DEFAULT_INPUT_RATE 32000
|
||
#elif defined(_3DS) || defined(RETROFW)
|
||
#define DEFAULT_OUTPUT_RATE 32730
|
||
#define DEFAULT_INPUT_RATE 32730
|
||
#elif defined(__EMSCRIPTEN__)
|
||
#define DEFAULT_OUTPUT_RATE 44100
|
||
#define DEFAULT_INPUT_RATE 44100
|
||
#else
|
||
#define DEFAULT_OUTPUT_RATE 48000
|
||
#define DEFAULT_INPUT_RATE 48000
|
||
#endif
|
||
|
||
/* Audio device (e.g. hw:0,0 or /dev/audio). If NULL, will use defaults. */
|
||
#define DEFAULT_AUDIO_DEVICE NULL
|
||
|
||
/* Desired audio latency in milliseconds. Might not be honored
|
||
* if driver can't provide given latency. */
|
||
#if defined(ANDROID) || defined(RETROFW) || defined(MIYOO) || (defined(__EMSCRIPTEN__) && defined(HAVE_AL))
|
||
/* For most Android devices, 64ms is way too low. */
|
||
#define DEFAULT_OUT_LATENCY 128
|
||
#define DEFAULT_IN_LATENCY 128
|
||
#else
|
||
#define DEFAULT_OUT_LATENCY 64
|
||
#define DEFAULT_IN_LATENCY 64
|
||
#endif
|
||
|
||
/* Will sync audio. (recommended) */
|
||
#define DEFAULT_AUDIO_SYNC true
|
||
|
||
/* Run the audio pipeline (convert, DSP, resample, volume) on the audio
|
||
* thread instead of inside the frame.
|
||
*
|
||
* On wherever there are threads to run it on. The latency is the same
|
||
* as the frame-synchronous path at any Audio Latency setting - the
|
||
* pipeline moves off the frame, it does not add a buffer - while rate
|
||
* control gets measured at the device's own pace instead of once a
|
||
* frame, and the resampler leaves the frame budget.
|
||
*
|
||
* Nothing here forces it on a driver that cannot take it: audio_driver
|
||
* requires wait_writable() and no core audio callback, and falls back
|
||
* to the inline path with a log line otherwise, so this is the default
|
||
* for the drivers that can and a no-op for the rest. */
|
||
#if defined(HAVE_THREADS)
|
||
#define DEFAULT_AUDIO_THREADED_PIPELINE true
|
||
#else
|
||
#define DEFAULT_AUDIO_THREADED_PIPELINE false
|
||
#endif
|
||
|
||
/* Ask the OS to schedule the audio thread ahead of the rest of the
|
||
* frontend. Best effort: a system that refuses keeps the default
|
||
* priority. On wherever there is an audio thread to raise. */
|
||
#if defined(HAVE_THREADS)
|
||
#define DEFAULT_AUDIO_THREAD_PRIORITY true
|
||
#else
|
||
#define DEFAULT_AUDIO_THREAD_PRIORITY false
|
||
#endif
|
||
|
||
/* Audio rate control. */
|
||
#if !defined(RARCH_CONSOLE)
|
||
#define DEFAULT_RATE_CONTROL true
|
||
#else
|
||
#define DEFAULT_RATE_CONTROL false
|
||
#endif
|
||
|
||
/* Rate control delta. Defines how much rate_control
|
||
* is allowed to adjust input rate. */
|
||
#define DEFAULT_RATE_CONTROL_DELTA 0.005f
|
||
|
||
/* Maximum timing skew. Defines how much adjust_system_rates
|
||
* is allowed to adjust input rate. */
|
||
#define DEFAULT_MAX_TIMING_SKEW 0.05f
|
||
|
||
/* Default audio volume in dB. (0.0 dB == unity gain). */
|
||
#define DEFAULT_AUDIO_VOLUME 0.0f
|
||
|
||
/* Default audio volume of the audio mixer in dB. (0.0 dB == unity gain). */
|
||
#define DEFAULT_AUDIO_MIXER_VOLUME 0.0f
|
||
|
||
#ifdef HAVE_WASAPI
|
||
/* WASAPI defaults */
|
||
#define DEFAULT_WASAPI_EXCLUSIVE_MODE false
|
||
#define DEFAULT_WASAPI_FLOAT_FORMAT false
|
||
/* Automatic shared mode buffer */
|
||
#define DEFAULT_WASAPI_SH_BUFFER_LENGTH 0
|
||
#endif
|
||
|
||
#if TARGET_OS_IOS
|
||
/* Respect silent mode (false will render audio in silent mode) */
|
||
#define DEFAULT_AUDIO_RESPECT_SILENT_MODE true
|
||
#endif
|
||
|
||
/* Automatically mute audio when fast forward is enabled. */
|
||
#define DEFAULT_AUDIO_FASTFORWARD_MUTE false
|
||
/* Speed up audio to match fast forward speed up. */
|
||
#define DEFAULT_AUDIO_FASTFORWARD_SPEEDUP false
|
||
/* When a core outputs 16-bit integer audio, the deterministic
|
||
* fixed-point (int16) resampler variant of the selected backend
|
||
* (sinc, nearest, or CC) can be preferred over the float one for any
|
||
* needed resampling, avoiding the s16<->float round-trip
|
||
* (bit-reproducible). Opt-in; the float path remains the default. */
|
||
#define DEFAULT_AUDIO_FASTPATH_S16 false
|
||
/* Requested output sample format for negotiable audio drivers:
|
||
* AUDIO_FORMAT_NEGOTIATION_INT16 (0) or AUDIO_FORMAT_NEGOTIATION_FLOAT (1).
|
||
* Float by default, matching RetroArch's historical driver behaviour. */
|
||
#define DEFAULT_AUDIO_FORMAT_NEGOTIATION AUDIO_FORMAT_NEGOTIATION_FLOAT
|
||
/* Automatically mute audio when rewind is enabled. */
|
||
#define DEFAULT_AUDIO_REWIND_MUTE false
|
||
|
||
#ifdef HAVE_MICROPHONE
|
||
/* Microphone support */
|
||
#define DEFAULT_MICROPHONE_ENABLE true
|
||
#define DEFAULT_MICROPHONE_DEVICE NULL
|
||
|
||
#ifdef HAVE_WASAPI
|
||
#define DEFAULT_WASAPI_MICROPHONE_SH_BUFFER_LENGTH 0
|
||
#endif
|
||
#endif
|
||
|
||
/* MISC */
|
||
|
||
/* Enables displaying the current frames per second. */
|
||
#define DEFAULT_FPS_SHOW false
|
||
|
||
/* FPS display will be updated at the set interval (in frames) */
|
||
#define DEFAULT_FPS_UPDATE_INTERVAL 256
|
||
|
||
/* Memory status display will be updated at the set interval (in frames) */
|
||
#define DEFAULT_MEMORY_UPDATE_INTERVAL 256
|
||
|
||
/* Enables displaying the current frame count. */
|
||
#define DEFAULT_FRAMECOUNT_SHOW false
|
||
|
||
/* Includes displaying the current memory usage/total with FPS/Frames. */
|
||
#define DEFAULT_MEMORY_SHOW false
|
||
|
||
/* Displays the current time in the preferred format. */
|
||
#define DEFAULT_TIME_SHOW TIME_SHOW_OFF
|
||
|
||
/* Enables displaying various timing statistics. */
|
||
#define DEFAULT_STATISTICS_SHOW false
|
||
|
||
/* Enables displaying the current netplay room ping. */
|
||
#define DEFAULT_NETPLAY_PING_SHOW false
|
||
|
||
/* Enables use of rewind. This will incur some memory footprint
|
||
* depending on the save state buffer. */
|
||
#define DEFAULT_REWIND_ENABLE false
|
||
|
||
/* When set, any time a cheat is toggled it is immediately applied. */
|
||
#define DEFAULT_APPLY_CHEATS_AFTER_TOGGLE false
|
||
|
||
/* When set, all enabled cheats are auto-applied when a game is loaded. */
|
||
#define DEFAULT_APPLY_CHEATS_AFTER_LOAD false
|
||
|
||
|
||
#if defined(RETROFW) || defined(MIYOO)
|
||
/*RETROFW jz4760 has significant slowdown with default settings */
|
||
#define DEFAULT_REWIND_BUFFER_SIZE (1 << 20)
|
||
#define DEFAULT_REWIND_BUFFER_SIZE_STEP 1
|
||
#define DEFAULT_REWIND_GRANULARITY 6
|
||
#else
|
||
/* The buffer size for the rewind buffer. This needs to be about
|
||
* 15-20MB per minute. Very game dependant. */
|
||
#define DEFAULT_REWIND_BUFFER_SIZE (20 << 20) /* 20MiB */
|
||
|
||
/* The amount of MB to increase/decrease the rewind_buffer_size when it is changed via the UI. */
|
||
#define DEFAULT_REWIND_BUFFER_SIZE_STEP 10 /* 10MB */
|
||
|
||
/* How many frames to rewind at a time. */
|
||
#define DEFAULT_REWIND_GRANULARITY 1
|
||
#endif
|
||
|
||
/* Pause gameplay when window loses focus. */
|
||
#define DEFAULT_PAUSE_NONACTIVE true
|
||
|
||
/* Pause gameplay when controller disconnects. */
|
||
#define DEFAULT_PAUSE_ON_DISCONNECT false
|
||
|
||
/* Saves non-volatile SRAM at a regular interval.
|
||
* It is measured in seconds. A value of 0 disables autosave. */
|
||
#if defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN32) || TARGET_OS_OSX || defined(ANDROID) || TARGET_OS_IPHONE || defined(DINGUX)
|
||
/* Flush to file every 10 seconds on modern platforms by default */
|
||
#define DEFAULT_AUTOSAVE_INTERVAL 10
|
||
#else
|
||
/* Default to disabled on I/O-constrained platforms */
|
||
#define DEFAULT_AUTOSAVE_INTERVAL 0
|
||
#endif
|
||
|
||
/* Netplay lobby filters */
|
||
#define DEFAULT_NETPLAY_SHOW_ONLY_CONNECTABLE true
|
||
#define DEFAULT_NETPLAY_SHOW_ONLY_INSTALLED_CORES false
|
||
#define DEFAULT_NETPLAY_SHOW_PASSWORDED true
|
||
|
||
/* Publicly announce netplay */
|
||
#define DEFAULT_NETPLAY_PUBLIC_ANNOUNCE true
|
||
|
||
/* Start netplay in spectator mode */
|
||
#define DEFAULT_NETPLAY_START_AS_SPECTATOR false
|
||
|
||
/* Netplay chat fading toggle */
|
||
#define DEFAULT_NETPLAY_FADE_CHAT true
|
||
|
||
/* Netplay chat colors */
|
||
#define DEFAULT_NETPLAY_CHAT_COLOR_NAME 0x008000
|
||
#define DEFAULT_NETPLAY_CHAT_COLOR_MSG 0xFFFFFF
|
||
|
||
/* Allow players to pause */
|
||
#define DEFAULT_NETPLAY_ALLOW_PAUSING false
|
||
|
||
/* Allow connections in slave mode */
|
||
#define DEFAULT_NETPLAY_ALLOW_SLAVES true
|
||
|
||
/* Require connections only in slave mode */
|
||
#define DEFAULT_NETPLAY_REQUIRE_SLAVES false
|
||
|
||
#define DEFAULT_NETPLAY_NAT_TRAVERSAL false
|
||
|
||
#define DEFAULT_NETPLAY_CHECK_FRAMES 600
|
||
|
||
#define DEFAULT_NETPLAY_USE_MITM_SERVER false
|
||
|
||
#define DEFAULT_NETPLAY_MITM_SERVER "nyc"
|
||
|
||
#ifdef HAVE_NETWORKING
|
||
#define DEFAULT_NETPLAY_MAX_CONNECTIONS 3
|
||
#define DEFAULT_NETPLAY_MAX_PING 0
|
||
|
||
#define DEFAULT_NETPLAY_SHARE_DIGITAL RARCH_NETPLAY_SHARE_DIGITAL_NO_SHARING
|
||
#define DEFAULT_NETPLAY_SHARE_ANALOG RARCH_NETPLAY_SHARE_ANALOG_NO_SHARING
|
||
#endif
|
||
|
||
/* On save state load, block SRAM from being overwritten.
|
||
* This could potentially lead to buggy games. */
|
||
#define DEFAULT_BLOCK_SRAM_OVERWRITE false
|
||
|
||
/* When saving savestates, state index is automatically
|
||
* incremented before saving.
|
||
* When the content is loaded, state index will be set
|
||
* to the highest existing value. */
|
||
#define DEFAULT_SAVESTATE_AUTO_INDEX false
|
||
|
||
/* Specifies the maximum number of savestates to keep
|
||
* when savestate auto index is enabled
|
||
* > When limit is exceeded, savestate with the lowest
|
||
* index will be deleted automatically when creating
|
||
* a new savestate
|
||
* > Setting value to zero disables the limit (no
|
||
* savestates will be deleted in this case) */
|
||
#define DEFAULT_SAVESTATE_MAX_KEEP 0
|
||
|
||
/* When recording replays, replay index is automatically
|
||
* incremented before recording starts.
|
||
* When the content is loaded, replay index will be set
|
||
* to the highest existing value. */
|
||
#define DEFAULT_REPLAY_AUTO_INDEX true
|
||
|
||
/* Specifies the maximum number of replays to keep
|
||
* when replay auto index is enabled
|
||
* > When limit is exceeded, replay with the lowest
|
||
* index will be deleted automatically when creating
|
||
* a new replay
|
||
* > Setting value to zero disables the limit (no
|
||
* replays will be deleted in this case) */
|
||
#define DEFAULT_REPLAY_MAX_KEEP 0
|
||
|
||
/* Specifies how often checkpoints will be saved to replay files during recording.
|
||
* > Setting value to zero disables recording checkpoints. */
|
||
#define DEFAULT_REPLAY_CHECKPOINT_INTERVAL 0
|
||
/* Specifies whether checkpoints in replay files should be loaded
|
||
* during playback. This can be helpful for cores that are not
|
||
* deterministic but in some cores produces janky results depending on
|
||
* when inputs are processed. */
|
||
#define DEFAULT_REPLAY_CHECKPOINT_DESERIALIZE true
|
||
|
||
/* Automatically saves a savestate at the end of RetroArch's lifetime.
|
||
* The path is $SRAM_PATH.auto.
|
||
* RetroArch will automatically load any savestate with this path on
|
||
* startup if savestate_auto_load is set. */
|
||
#define DEFAULT_SAVESTATE_AUTO_SAVE false
|
||
#define DEFAULT_SAVESTATE_AUTO_LOAD false
|
||
|
||
/* Automatically saves a savestate at a regular interval.
|
||
* It is measured in seconds. A value of 0 disables automatic savestate saving. */
|
||
#if defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN32) || TARGET_OS_OSX || defined(ANDROID) || TARGET_OS_IPHONE || defined(DINGUX)
|
||
/* Disabled by default but can be enabled by user */
|
||
#define DEFAULT_SAVESTATE_AUTOMATIC_INTERVAL 0
|
||
#else
|
||
/* Default to disabled on I/O-constrained platforms */
|
||
#define DEFAULT_SAVESTATE_AUTOMATIC_INTERVAL 0
|
||
#endif
|
||
|
||
/* Take screenshots for save states */
|
||
#if defined(__x86_64__) || defined(_M_X64)
|
||
#define DEFAULT_SAVESTATE_THUMBNAIL_ENABLE true
|
||
#else
|
||
#define DEFAULT_SAVESTATE_THUMBNAIL_ENABLE false
|
||
#endif
|
||
|
||
/* When creating save (srm) files, compress
|
||
* written data */
|
||
#define DEFAULT_SAVE_FILE_COMPRESSION false
|
||
|
||
/* When creating save state files, compress
|
||
* written data */
|
||
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||
#define DEFAULT_SAVESTATE_FILE_COMPRESSION false
|
||
#else
|
||
#define DEFAULT_SAVESTATE_FILE_COMPRESSION true
|
||
#endif
|
||
|
||
/* Slowmotion ratio. */
|
||
#define DEFAULT_SLOWMOTION_RATIO 3.0f
|
||
|
||
/* Maximum fast forward ratio. */
|
||
#define DEFAULT_FASTFORWARD_RATIO 0.0f
|
||
#define MAXIMUM_FASTFORWARD_RATIO 50.0f
|
||
|
||
/* Skip frames when fast forwarding. */
|
||
#define DEFAULT_FASTFORWARD_FRAMESKIP true
|
||
|
||
/* Enable runloop for variable refresh rate screens. Force x1 speed while handling fast forward too. */
|
||
#define DEFAULT_VRR_RUNLOOP_ENABLE false
|
||
|
||
/* Run core logic one or more frames ahead then load the state back to reduce perceived input lag. */
|
||
#define DEFAULT_RUN_AHEAD_FRAMES 1
|
||
|
||
/* When using the Run Ahead feature, use a secondary instance of the core. */
|
||
#define DEFAULT_RUN_AHEAD_SECONDARY_INSTANCE true
|
||
|
||
/* Hide warning messages when using the Run Ahead feature. */
|
||
#define DEFAULT_RUN_AHEAD_HIDE_WARNINGS false
|
||
|
||
/* Enable stdin/network command interface. */
|
||
#define DEFAULT_NETWORK_CMD_ENABLE false
|
||
#define DEFAULT_NETWORK_CMD_PORT 55355
|
||
#define DEFAULT_NETWORK_REMOTE_BASE_PORT 55400
|
||
#define DEFAULT_STDIN_CMD_ENABLE false
|
||
|
||
#define DEFAULT_NETWORK_BUILDBOT_AUTO_EXTRACT_ARCHIVE true
|
||
#define DEFAULT_NETWORK_BUILDBOT_SHOW_EXPERIMENTAL_CORES false
|
||
|
||
/* Automatically create a backup whenever a core is
|
||
* updated via the online updater
|
||
* > Enable by default on all modern platforms with
|
||
* online updater support */
|
||
#if defined(HAVE_ONLINE_UPDATER) && (defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN32) || TARGET_OS_OSX || defined(ANDROID) || TARGET_OS_IPHONE)
|
||
#define DEFAULT_CORE_UPDATER_AUTO_BACKUP true
|
||
#else
|
||
#define DEFAULT_CORE_UPDATER_AUTO_BACKUP false
|
||
#endif
|
||
/* Number of automatic core backups to retain
|
||
* (oldest backup will be deleted when creating
|
||
* a new one) */
|
||
#define DEFAULT_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE 1
|
||
|
||
#define DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS false
|
||
|
||
/* Number of entries that will be kept in content history playlist file. */
|
||
#define DEFAULT_CONTENT_HISTORY_SIZE 200
|
||
|
||
/* Number of entries that will be kept in content favorites playlist file.
|
||
* -1 == 'unlimited' (99999) */
|
||
#define DEFAULT_CONTENT_FAVORITES_SIZE 200
|
||
|
||
/* Sort all playlists (apart from histories) alphabetically */
|
||
#define DEFAULT_PLAYLIST_SORT_ALPHABETICAL true
|
||
|
||
/* File format to use when writing playlists to disk */
|
||
#define DEFAULT_PLAYLIST_USE_OLD_FORMAT false
|
||
|
||
/* When creating/updating playlists, compress written data */
|
||
#define DEFAULT_PLAYLIST_COMPRESSION false
|
||
|
||
#ifdef HAVE_MENU
|
||
/* Specify when to display 'core name' inline on playlist entries */
|
||
#define DEFAULT_PLAYLIST_SHOW_INLINE_CORE_NAME PLAYLIST_INLINE_CORE_DISPLAY_HIST_FAV
|
||
|
||
/* Specifies which runtime record to use on playlist sublabels */
|
||
#define DEFAULT_PLAYLIST_SUBLABEL_RUNTIME_TYPE PLAYLIST_RUNTIME_PER_CORE
|
||
|
||
/* Specifies time/date display format for runtime 'last played' data */
|
||
#define DEFAULT_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE PLAYLIST_LAST_PLAYED_STYLE_YMD_HM
|
||
|
||
#define DEFAULT_PLAYLIST_ENTRY_REMOVE_ENABLE PLAYLIST_ENTRY_REMOVE_ENABLE_ALL
|
||
#endif
|
||
|
||
#define DEFAULT_SCAN_WITHOUT_CORE_MATCH false
|
||
|
||
#define DEFAULT_SCAN_SERIAL_AND_CRC false
|
||
|
||
#ifdef __WINRT__
|
||
/* Be paranoid about WinRT file I/O performance, and leave this disabled by
|
||
* default */
|
||
#define DEFAULT_PLAYLIST_SHOW_SUBLABELS false
|
||
#else
|
||
#define DEFAULT_PLAYLIST_SHOW_SUBLABELS true
|
||
#endif
|
||
|
||
#define DEFAULT_PLAYLIST_SHOW_HISTORY_ICONS PLAYLIST_SHOW_HISTORY_ICONS_CONTENT
|
||
|
||
/* Show the indices of playlist entries in
|
||
* a menu-driver-specific fashion */
|
||
#define DEFAULT_PLAYLIST_SHOW_ENTRY_IDX true
|
||
|
||
#define DEFAULT_PLAYLIST_FUZZY_ARCHIVE_MATCH false
|
||
|
||
#define DEFAULT_PLAYLIST_PORTABLE_PATHS false
|
||
|
||
#define DEFAULT_PLAYLIST_USE_FILENAME false
|
||
|
||
#define DEFAULT_PLAYLIST_ALLOW_NON_PNG false
|
||
|
||
/* Show Menu start-up screen on boot. */
|
||
#define DEFAULT_MENU_SHOW_START_SCREEN true
|
||
|
||
/* Default scale factor for non-framebuffer-based display
|
||
* drivers and display widgets */
|
||
#if defined(VITA)
|
||
#define DEFAULT_MENU_SCALE_FACTOR 1.5f
|
||
#elif defined(__ANDROID__)
|
||
#define DEFAULT_MENU_SCALE_FACTOR 0.75f
|
||
#else
|
||
#define DEFAULT_MENU_SCALE_FACTOR 1.0f
|
||
#endif
|
||
/* Specifies whether menu images (icons, thumbnails,
|
||
* wallpapers) are uploaded with mip-mapped filtering.
|
||
* Keeps images smooth when drawn below their native size,
|
||
* at the cost of slightly higher video memory usage. */
|
||
#define DEFAULT_MENU_TEXTURE_MIPMAPPING true
|
||
/* Specifies whether display widgets should be scaled
|
||
* automatically using the default menu scale factor */
|
||
#define DEFAULT_MENU_WIDGET_SCALE_AUTO true
|
||
/* Default scale factor for display widgets when widget
|
||
* auto scaling is disabled (fullscreen mode) */
|
||
#define DEFAULT_MENU_WIDGET_SCALE_FACTOR 1.0f
|
||
/* Default scale factor for display widgets when widget
|
||
* auto scaling is disabled (windowed mode) */
|
||
#define DEFAULT_MENU_WIDGET_SCALE_FACTOR_WINDOWED 1.0f
|
||
|
||
/* Log level for the frontend */
|
||
#define DEFAULT_FRONTEND_LOG_LEVEL 1
|
||
|
||
/* Log level for libretro cores (GET_LOG_INTERFACE). */
|
||
#define DEFAULT_LIBRETRO_LOG_LEVEL 1
|
||
|
||
#ifndef RARCH_DEFAULT_PORT
|
||
#ifndef VITA
|
||
#define RARCH_DEFAULT_PORT 55435
|
||
#else
|
||
#define RARCH_DEFAULT_PORT 19492
|
||
#endif
|
||
#endif
|
||
|
||
#ifndef RARCH_STREAM_DEFAULT_PORT
|
||
#define RARCH_STREAM_DEFAULT_PORT 56400
|
||
#endif
|
||
|
||
/* KEYBINDS, JOYPAD */
|
||
|
||
/* Axis threshold (between 0.0 and 1.0)
|
||
* How far an axis must be tilted to result in a button press. */
|
||
#define DEFAULT_AXIS_THRESHOLD 0.5f
|
||
#define DEFAULT_ANALOG_DEADZONE 0.0f
|
||
#define DEFAULT_ANALOG_SENSITIVITY 1.0f
|
||
#define DEFAULT_SENSOR_ACCELEROMETER_SENSITIVITY 1.0f
|
||
#define DEFAULT_SENSOR_GYROSCOPE_SENSITIVITY 1.0f
|
||
|
||
|
||
/* Describes speed of which turbo-enabled buttons toggle. */
|
||
#define DEFAULT_TURBO_ENABLE true
|
||
#define DEFAULT_TURBO_PERIOD 6
|
||
#define DEFAULT_TURBO_DUTY_CYCLE 0
|
||
#define DEFAULT_TURBO_MODE 0
|
||
#define DEFAULT_TURBO_BIND -1
|
||
#define DEFAULT_TURBO_BUTTON RETRO_DEVICE_ID_JOYPAD_B
|
||
#define DEFAULT_TURBO_ALLOW_DPAD false
|
||
|
||
/* Enable automatic mouse grab by default
|
||
* only on Android */
|
||
#if defined(ANDROID)
|
||
#define DEFAULT_INPUT_AUTO_MOUSE_GRAB true
|
||
#else
|
||
#define DEFAULT_INPUT_AUTO_MOUSE_GRAB false
|
||
#endif
|
||
|
||
#if TARGET_OS_IPHONE
|
||
#define DEFAULT_INPUT_KEYBOARD_GAMEPAD_ENABLE false
|
||
#else
|
||
#define DEFAULT_INPUT_KEYBOARD_GAMEPAD_ENABLE true
|
||
#endif
|
||
|
||
/* Enable input auto-detection. Will attempt to autoconfigure
|
||
* gamepads, plug-and-play style. */
|
||
#define DEFAULT_INPUT_AUTODETECT_ENABLE true
|
||
|
||
/* Enables accelerometer/gyroscope/illuminance
|
||
* sensor input, if supported */
|
||
#define DEFAULT_INPUT_SENSORS_ENABLE true
|
||
|
||
/* Use the Android system (IME) keyboard for menu text entry instead of
|
||
* the built-in on-screen keyboard. Off by default so gamepad-only
|
||
* and no-touch devices keep the navigable on-screen keyboard at
|
||
* all times. */
|
||
#define DEFAULT_INPUT_ANDROID_SYSTEM_KEYBOARD false
|
||
|
||
/* Automatically enable game focus when running or
|
||
* resuming content */
|
||
#define DEFAULT_INPUT_AUTO_GAME_FOCUS AUTO_GAME_FOCUS_OFF
|
||
|
||
/* Make simultaneous buttons easier to hit on Android */
|
||
#if defined(ANDROID)
|
||
#define DEFAULT_INPUT_BLOCK_TIMEOUT 1
|
||
#endif
|
||
|
||
/* Show the input descriptors set by the core instead
|
||
* of the default ones. */
|
||
#define DEFAULT_INPUT_DESCRIPTOR_LABEL_SHOW true
|
||
#define DEFAULT_INPUT_DESCRIPTOR_HIDE_UNBOUND false
|
||
|
||
#if defined(DINGUX)
|
||
#define DEFAULT_INPUT_MAX_USERS 1
|
||
#else
|
||
#define DEFAULT_INPUT_MAX_USERS 8
|
||
#endif
|
||
|
||
#define DEFAULT_INPUT_BIND_TIMEOUT 3
|
||
#if defined(ANDROID)
|
||
#define DEFAULT_INPUT_BIND_HOLD 1
|
||
#else
|
||
#define DEFAULT_INPUT_BIND_HOLD 0
|
||
#endif
|
||
#define DEFAULT_INPUT_POLL_TYPE_BEHAVIOR 2
|
||
#define DEFAULT_INPUT_HOTKEY_BLOCK_DELAY 5
|
||
#define DEFAULT_INPUT_HOTKEY_DEVICE_MERGE false
|
||
#define DEFAULT_INPUT_HOTKEY_FOLLOWS_PLAYER1 false
|
||
|
||
#define DEFAULT_GFX_THUMBNAILS_DEFAULT 3
|
||
|
||
#define DEFAULT_MENU_LEFT_THUMBNAILS_DEFAULT 0
|
||
#define DEFAULT_MENU_ICON_THUMBNAILS_DEFAULT 0
|
||
|
||
#define DEFAULT_GFX_THUMBNAIL_UPSCALE_THRESHOLD 0
|
||
|
||
#ifdef HAVE_MENU
|
||
#if defined(RS90) || defined(MIYOO)
|
||
/* The RS-90 has a hardware clock that is neither
|
||
* configurable nor persistent, rendering it useless.
|
||
* We therefore hide it in the menu by default. */
|
||
#define DEFAULT_MENU_TIMEDATE_ENABLE false
|
||
#else
|
||
#define DEFAULT_MENU_TIMEDATE_ENABLE true
|
||
#endif
|
||
#define DEFAULT_MENU_TIMEDATE_STYLE MENU_TIMEDATE_STYLE_YMD_HM
|
||
#define DEFAULT_MENU_TIMEDATE_DATE_SEPARATOR MENU_TIMEDATE_DATE_SEPARATOR_HYPHEN
|
||
#define DEFAULT_MENU_REMEMBER_SELECTION MENU_REMEMBER_SELECTION_ALWAYS
|
||
#define DEFAULT_MENU_STARTUP_PAGE MENU_STARTUP_PAGE_MAIN_MENU
|
||
#endif
|
||
|
||
#define DEFAULT_XMB_VERTICAL_THUMBNAILS false
|
||
|
||
#define DEFAULT_XMB_THUMBNAIL_SCALE_FACTOR 100
|
||
|
||
#if TARGET_OS_IPHONE
|
||
#define DEFAULT_UI_COMPANION_START_ON_BOOT false
|
||
#else
|
||
#define DEFAULT_UI_COMPANION_START_ON_BOOT true
|
||
#endif
|
||
|
||
#define DEFAULT_UI_COMPANION_ENABLE false
|
||
/* Currently only used to show the WIMP UI on startup */
|
||
#define DEFAULT_UI_COMPANION_TOGGLE false
|
||
|
||
/* Only init the WIMP UI for this session if this is enabled */
|
||
#define DEFAULT_DESKTOP_MENU_ENABLE true
|
||
|
||
/* Desktop companion presentation settings, shared by the Qt, Win32 and
|
||
* Cocoa companions. */
|
||
#define DEFAULT_DESKTOP_MENU_VIEW_TYPE 0 /* 0 list, 1 icons */
|
||
#define DEFAULT_DESKTOP_MENU_THUMBNAIL_TYPE 0 /* 0 boxart, 1 screenshot, 2 title, 3 logo */
|
||
#define DEFAULT_DESKTOP_MENU_SUGGEST_LOADED_CORE_FIRST false
|
||
#define DEFAULT_DESKTOP_MENU_SAVE_LAST_TAB false
|
||
#define DEFAULT_DESKTOP_MENU_LAST_TAB 0
|
||
#define DEFAULT_DESKTOP_MENU_SAVE_GEOMETRY false
|
||
#define DEFAULT_DESKTOP_MENU_SHOW_WELCOME_SCREEN true
|
||
#define DEFAULT_DESKTOP_MENU_SCAN_FINISH_CONFIRM true
|
||
#define DEFAULT_DESKTOP_MENU_THUMBNAIL_CACHE_LIMIT 500
|
||
#define DEFAULT_DESKTOP_MENU_THUMBNAIL_MAX_SIZE 0 /* 0 = unlimited */
|
||
#define DEFAULT_DESKTOP_MENU_THUMBNAIL_QUALITY 0 /* 0 = default */
|
||
#define DEFAULT_DESKTOP_MENU_ICON_VIEW_ZOOM 50
|
||
#define DEFAULT_DESKTOP_MENU_ALL_PLAYLISTS_LIST_MAX_COUNT 0
|
||
#define DEFAULT_DESKTOP_MENU_ALL_PLAYLISTS_GRID_MAX_COUNT 0
|
||
#define DEFAULT_DESKTOP_MENU_THEME 0 /* 0 system, 1 dark, 2 custom */
|
||
|
||
/* Keep track of how long each core+content has been running for over time */
|
||
|
||
#ifdef __WINRT__
|
||
/* Be paranoid about WinRT file I/O performance, and leave this disabled by
|
||
* default */
|
||
#define DEFAULT_CONTENT_RUNTIME_LOG false
|
||
#else
|
||
#define DEFAULT_CONTENT_RUNTIME_LOG true
|
||
#endif
|
||
|
||
/* Keep track of how long each content has been running
|
||
* for over time (ignores core) */
|
||
#define DEFAULT_CONTENT_RUNTIME_LOG_AGGREGATE false
|
||
|
||
#define DEFAULT_UI_MENUBAR_ENABLE true
|
||
|
||
#if defined(__QNX__) || defined(_XBOX1) || defined(_XBOX360) || (defined(__MACH__) && TARGET_OS_IPHONE) || defined(ANDROID) || defined(WIIU) || defined(HAVE_NEON) || defined(GEKKO) || defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__PS3__)
|
||
#define DEFAULT_AUDIO_RESAMPLER_QUALITY_LEVEL RESAMPLER_QUALITY_LOWER
|
||
#elif defined(PSP) || defined(_3DS) || defined(VITA) || defined(PS2) || defined(DINGUX)
|
||
#define DEFAULT_AUDIO_RESAMPLER_QUALITY_LEVEL RESAMPLER_QUALITY_LOWEST
|
||
#else
|
||
#define DEFAULT_AUDIO_RESAMPLER_QUALITY_LEVEL RESAMPLER_QUALITY_NORMAL
|
||
#endif
|
||
|
||
/* MIDI */
|
||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
|
||
#define DEFAULT_MIDI_OUTPUT "Microsoft GS Wavetable Synth"
|
||
#else
|
||
#define DEFAULT_MIDI_OUTPUT "OFF"
|
||
#endif
|
||
#define DEFAULT_MIDI_INPUT "OFF"
|
||
#define DEFAULT_MIDI_VOLUME 100
|
||
|
||
#ifdef HAVE_MIST
|
||
/* Steam */
|
||
#define DEFAULT_STEAM_RICH_PRESENCE_FORMAT STEAM_RICH_PRESENCE_FORMAT_CONTENT_SYSTEM
|
||
#endif
|
||
|
||
/* Only applies to Android 7.0 (API 24) and up */
|
||
#define DEFAULT_SUSTAINED_PERFORMANCE_MODE false
|
||
|
||
#if defined(ANDROID) || TARGET_OS_IPHONE
|
||
#define DEFAULT_VIBRATE_ON_KEYPRESS true
|
||
#else
|
||
#define DEFAULT_VIBRATE_ON_KEYPRESS false
|
||
#endif
|
||
|
||
#if TARGET_OS_IPHONE
|
||
#define DEFAULT_ENABLE_DEVICE_VIBRATION true
|
||
#else
|
||
#define DEFAULT_ENABLE_DEVICE_VIBRATION false
|
||
#endif
|
||
|
||
/* Defines the strength of rumble effects
|
||
* on OpenDingux devices */
|
||
#if defined(DINGUX) && defined(HAVE_LIBSHAKE)
|
||
#define DEFAULT_RUMBLE_GAIN 50
|
||
#else
|
||
#define DEFAULT_RUMBLE_GAIN 100
|
||
#endif
|
||
|
||
#ifdef HAVE_VULKAN
|
||
#define DEFAULT_VULKAN_GPU_INDEX 0
|
||
#endif
|
||
|
||
#ifdef HAVE_D3D10
|
||
#define DEFAULT_D3D10_GPU_INDEX 0
|
||
#endif
|
||
|
||
#ifdef HAVE_D3D11
|
||
#define DEFAULT_D3D11_GPU_INDEX 0
|
||
#endif
|
||
|
||
#ifdef HAVE_D3D12
|
||
#define DEFAULT_D3D12_GPU_INDEX 0
|
||
#endif
|
||
|
||
#ifdef HAVE_METAL
|
||
#define DEFAULT_METAL_GPU_INDEX 0
|
||
#endif
|
||
|
||
#if defined(HAKCHI)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://hakchicloud.com/Libretro_Cores/"
|
||
#elif defined(WEBOS)
|
||
#if defined(__arm__)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/webos/armv7a/latest/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://retroarch-cores.webosbrew.org/aarch64/"
|
||
#endif
|
||
#elif defined(ANDROID)
|
||
#if defined(ANDROID_ARM_V7)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/android/latest/armeabi-v7a/"
|
||
#elif defined(ANDROID_ARM)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/android/latest/armeabi/"
|
||
#elif defined(ANDROID_AARCH64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/android/latest/arm64-v8a/"
|
||
#elif defined(ANDROID_X86)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/android/latest/x86/"
|
||
#elif defined(ANDROID_X64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/android/latest/x86_64/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL ""
|
||
#endif
|
||
#elif defined(__QNX__)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/blackberry/latest/"
|
||
#elif TARGET_OS_IPHONE
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/apple/ios/latest/"
|
||
#elif TARGET_OS_OSX
|
||
#if defined(__x86_64__)
|
||
#if defined(HAVE_SSL)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "https://buildbot.libretro.com/nightly/apple/osx/x86_64/latest/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/apple/osx/x86_64/latest/"
|
||
#endif
|
||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://bot.libretro.com/nightly/apple/osx/x86/latest/"
|
||
#elif defined(__aarch64__)
|
||
#if defined(HAVE_SSL)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "https://buildbot.libretro.com/nightly/apple/osx/arm64/latest/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/apple/osx/arm64/latest/"
|
||
#endif
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/apple/osx/ppc/latest/"
|
||
#endif
|
||
#elif defined(_WIN32) && !defined(_XBOX)
|
||
#if _MSC_VER >= 1910
|
||
#ifndef __WINRT__
|
||
#if defined(__x86_64__) || defined(_M_X64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows/x86_64/latest/"
|
||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(_M_IX86) || defined(_M_IA64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2017-desktop/x86/latest/"
|
||
#elif defined(__arm__) || defined(_M_ARM)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2017-desktop/arm/latest/"
|
||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2017-desktop/arm64/latest/"
|
||
#endif
|
||
#else
|
||
#if defined(__x86_64__) || defined(_M_X64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows/x86_64/latest/"
|
||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(_M_IX86) || defined(_M_IA64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows/x86/latest/"
|
||
#elif defined(__arm__) || defined(_M_ARM)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2017-uwp/arm/latest/"
|
||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2017-uwp/arm64/latest/"
|
||
#endif
|
||
#endif
|
||
#elif _MSC_VER == 1600
|
||
#if defined(__x86_64__) || defined(_M_X64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2010/x86_64/latest/"
|
||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(_M_IX86) || defined(_M_IA64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2010/x86/latest/"
|
||
#endif
|
||
#elif _MSC_VER == 1400
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2005/x86/latest/"
|
||
#elif _MSC_VER == 1310
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows-msvc2003/x86/latest/"
|
||
#else
|
||
#if defined(__x86_64__) || defined(_M_X64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows/x86_64/latest/"
|
||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(_M_IX86) || defined(_M_IA64)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/windows/x86/latest/"
|
||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||
/* No official MinGW/clang ARM64 buildbot yet – use empty default */
|
||
#define DEFAULT_BUILDBOT_SERVER_URL ""
|
||
#endif
|
||
#endif
|
||
#elif defined(__linux__)
|
||
#if defined(__x86_64__)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/linux/x86_64/latest/"
|
||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/linux/x86/latest/"
|
||
#elif defined(__aarch64__)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/linux/aarch64/latest/"
|
||
#elif defined(__arm__) && __ARM_ARCH == 7 && defined(__ARM_PCS_VFP)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/linux/armhf/latest/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL ""
|
||
#endif
|
||
#elif defined(WIIU)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/nintendo/wiiu/latest/"
|
||
#elif defined(HAVE_LIBNX)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL "http://buildbot.libretro.com/nightly/nintendo/switch/libnx/latest/"
|
||
#elif defined(_3DS)
|
||
#define DEFAULT_BUILDBOT_SERVER_URL envIsHomebrew() ? "http://buildbot.libretro.com/nightly/nintendo/3ds/latest/3dsx/" : "http://buildbot.libretro.com/nightly/nintendo/3ds/latest/cia/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_SERVER_URL ""
|
||
#endif
|
||
|
||
#ifdef __EMSCRIPTEN__
|
||
#define DEFAULT_BUILDBOT_ASSETS_SERVER_URL "https://buildbot.libretro.com/assets/"
|
||
#else
|
||
#define DEFAULT_BUILDBOT_ASSETS_SERVER_URL "http://buildbot.libretro.com/assets/"
|
||
#endif
|
||
|
||
#define DEFAULT_DISCORD_APP_ID "475456035851599874"
|
||
|
||
#define DEFAULT_AI_SERVICE_SOURCE_LANG 0
|
||
|
||
#define DEFAULT_AI_SERVICE_TARGET_LANG 0
|
||
|
||
#define DEFAULT_AI_SERVICE_ENABLE false
|
||
|
||
#define DEFAULT_AI_SERVICE_PAUSE false
|
||
|
||
#define DEFAULT_AI_SERVICE_MODE 1
|
||
|
||
#define DEFAULT_AI_SERVICE_URL "http://localhost:4404/"
|
||
|
||
#if defined(HAVE_FFMPEG) || defined(HAVE_MPV) || defined(HAVE_WEBMPLAYER)
|
||
#define DEFAULT_BUILTIN_MEDIAPLAYER_ENABLE true
|
||
#else
|
||
#define DEFAULT_BUILTIN_MEDIAPLAYER_ENABLE false
|
||
#endif
|
||
|
||
#if defined(HAVE_IMAGEVIEWER)
|
||
#define DEFAULT_BUILTIN_IMAGEVIEWER_ENABLE true
|
||
#else
|
||
#define DEFAULT_BUILTIN_IMAGEVIEWER_ENABLE false
|
||
#endif
|
||
|
||
#define DEFAULT_FILTER_BY_CURRENT_CORE false
|
||
|
||
#endif
|
||
|
||
#ifdef HAVE_SMBCLIENT
|
||
#define DEFAULT_SMB_CLIENT_AUTH_MODE 1
|
||
#define DEFAULT_SMB_CLIENT_NUM_CONTEXTS 4
|
||
#define DEFAULT_SMB_CLIENT_MAX_CONTEXTS 20
|
||
#define DEFAULT_SMB_CLIENT_TIMEOUT 5
|
||
#define DEFAULT_SMB_CLIENT_MAX_TIMEOUT 20
|
||
#endif
|