mirror of
https://github.com/libretro/RetroArch
synced 2025-03-17 10:21:26 +00:00
commit
1d2dd8f400
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,6 +1,6 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [twinaphex]
|
||||
github: [libretro]
|
||||
patreon: libretro
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -174,7 +174,7 @@ retroarch_switch.nso
|
||||
|
||||
# PS2
|
||||
ps2/irx/*.c
|
||||
ps2/libcdvd/lib/
|
||||
*.irx
|
||||
|
||||
# Wayland
|
||||
gfx/common/wayland/idle-inhibit-unstable-v1.c
|
||||
|
16
.travis.yml
16
.travis.yml
@ -40,12 +40,16 @@ matrix:
|
||||
env: CXX_BUILD=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_MENU=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_NETWORKING=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_OVERLAY=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_CDROM=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_VIDEO_LAYOUT=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_THREADS=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_AUDIOMIXER=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
@ -105,6 +109,10 @@ matrix:
|
||||
- cd pkg/android/phoenix
|
||||
- ./gradlew assembleNormalRelease
|
||||
|
||||
jobs:
|
||||
allow_failure:
|
||||
- os: osx
|
||||
|
||||
before_install:
|
||||
- |
|
||||
if [[ "$CC" =~ ^gcc-8.* ]]; then
|
||||
@ -132,6 +140,10 @@ before_script:
|
||||
if [ -n "$DISABLE_OVERLAY" ]; then
|
||||
ARGS="$ARGS --disable-overlay"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DISABLE_NETWORKING" ]; then
|
||||
ARGS="$ARGS --disable-networking"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DISABLE_CDROM" ]; then
|
||||
ARGS="$ARGS --disable-cdrom"
|
||||
@ -140,6 +152,10 @@ before_script:
|
||||
if [ -n "$DISABLE_VIDEO_LAYOUT" ]; then
|
||||
ARGS="$ARGS --disable-video_layout"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DISABLE_THREADS" ]; then
|
||||
ARGS="$ARGS --disable-threads --disable-glslang"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DISABLE_AUDIOMIXER" ]; then
|
||||
ARGS="$ARGS --disable-audiomixer"
|
||||
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,15 +1,15 @@
|
||||
{
|
||||
"terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
|
||||
"terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
|
||||
"terminal.integrated.env.windows": {
|
||||
"PATH": "/mingw64/lib/ccache/bin:/mingw64/lib/ccache/bin:/mingw64/lib/ccache/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:$PATH",
|
||||
"MSYSTEM": "MINGW64",
|
||||
},
|
||||
"terminal.integrated.cursorBlinking": true,
|
||||
|
||||
"editor.tabSize": 3,
|
||||
"editor.detectIndentation": false,
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.insertSpaces": true,
|
||||
"editor.formatOnSave": false,
|
||||
"files.associations": {
|
||||
"frontend_driver.h": "c",
|
||||
"*.in": "c",
|
||||
|
207
CHANGES.md
207
CHANGES.md
@ -1,9 +1,208 @@
|
||||
# Future
|
||||
|
||||
# 1.8.9
|
||||
- AUTO SAVESTATES: Ensure save states are correctly flushed to disk when quitting RetroArch (fixes broken save states when exiting RetroArch - without first closing content - with 'Auto Save State' enabled)
|
||||
- BUILTIN CORES: Builtin cores like ffmpeg and imageviewer would previously try to erroneously load a dynamic core named 'builtin' - this would fail and would just be a wasteful operation - this now skips dylib loading in libretro_get_system_info for builtin cores
|
||||
- CHEEVOS: Report API errors when unlocking achievements or submitting leaderboards
|
||||
- CHEEVOS: Support less common file extensions
|
||||
- CHEEVOS: Disable hardcore mode when playing BSV file
|
||||
- CHEEVOS: Correctly report unlocked non-hardcore achievements when hardcore is paused
|
||||
- CHEEVOS/M3U: Bugfix - did not handle absolute/relative paths in M3U files correctly before
|
||||
- CHEEVOS/M3U: Bugfix - it didn't handle comments/directives
|
||||
- CHEEVOS/M3U: Bugfix - it doesn't handle trailing whitespace
|
||||
- CHEEVOS/M3U: Bugfix - failed when loading M3U files with certain line endings
|
||||
- CORE MANAGEMENT: Add 'core management' menu (Settings -> Core)
|
||||
- CORE MANAGEMENT: Add option to backup/restore installed cores
|
||||
- CORE MANAGEMENT: Improved core selection logic
|
||||
- CORE INFO: Search search optimisations
|
||||
- CORE DOWNLOADER: Rename 'Core Updater' to 'Core Downloader'
|
||||
- CORE DOWNLOADER: Add 'Show Experimental Cores' setting under Settings > Network > Updater
|
||||
- CORE DOWNLOADER: Core licenses are now shown for all entries in the Core Updater menu
|
||||
- CORE DOWNLOADER: Pressing RetroPad select on a Core Updater entry will now display any text in the description field of its info file
|
||||
- CORE DOWNLOADER: Installed cores are now highlighted via a [#] symbol
|
||||
- CORE DOWNLOADER: Pressing RetroPad start on a selected, installed entry opens the Core Information menu (when using Material UI, swiping left or right triggers the same action). This means we can now view bios info etc. - and more importantly delete cores - without jumping through all the hoops of loading a core first and navigating all over the place
|
||||
- CORE DOWNLOADER/UPDATER: Add option to automatically backup cores when updating
|
||||
- DISK CONTROL: Enable 'Load New Disc' while disk tray is open
|
||||
- INPUT: Added a hotkey delay option to allow hotkey input to work properly when it is assigned to another action
|
||||
- INPUT: Remove 'All Users Control Menu' setting, was buggy and will be properly reintroduced after input overhaul
|
||||
- LINUX: Set default saves/save states/system paths
|
||||
- LOCALIZATION: Add Persian language
|
||||
- LOCALIZATION: Add Hebrew language
|
||||
- LOCALIZATION: Add Asturian language
|
||||
- MENU: Proper line wrapping for message dialog boxes
|
||||
- MENU/HOTKEYS: Add sublabels to all hotkey bind entries
|
||||
- MENU/QUICK MENU: Suppress the display of 'empty' quick menu listings when closing content
|
||||
- MENU/OZONE: Performance improvements
|
||||
- MENU/SDL: Add mouse controls
|
||||
- OPENGL1/VITA: Initial changes for HW context without FBO
|
||||
- OVERLAYS: Add options for moving the on-screen overlay
|
||||
- PLAYLISTS/WINDOWS: Fix core path entries in image/video/music history playlists
|
||||
- PS2: Add back CDFS support
|
||||
- SDL/GL: Advertise GLSL support
|
||||
- VIDEO/WIDGETS: Fix heap-use-after-free errors, leading to memory corruption
|
||||
- VITA: Added custom bubbles support
|
||||
- VITA: VitaGL update
|
||||
- VULKAN/WSI: Better frame pacing
|
||||
- VULKAN/WSI: Fix Intel Mesa being broken when using Fences, we have to use Semaphores to acquire the swapchain or the entire GPU stalls
|
||||
- VULKAN/WSI: Add support for either using fences or semaphores when syncing
|
||||
- VULKAN/WSI: Prefer using semaphores for integrated GPUs as it promotes better throughput over fences
|
||||
- VULKAN/WSI/ANDROID: Do not use mailbox emulation on Android
|
||||
- UWP/XBOX: Potentially improve performance by enabling 'Game Mode'
|
||||
|
||||
# 1.8.8
|
||||
- AUDIO/JACK: Fix regression introduced after 1.8.4 - would hang at startup
|
||||
- CHEEVOS: Disable hardcore when cheats are enabled
|
||||
- CHD: Return false when special track cannot be found
|
||||
- DISCORD/MATCHMAKING: Fix Discord 'Ask To Join' functionality
|
||||
- FILE PATH: Various file path handling optimisations
|
||||
- FONT: Fix Arabic, Chinese and Korean font rendering
|
||||
- INPUT MAPPING/REMAPPING: Restore broken 'reset to default' functionality with RetroPad 'start' button
|
||||
- INPUT MAPPING/REMAPPING: Fix 'reset to default' action for analog sticks and undefined core inputs
|
||||
- LOCALIZATION: Update Arabic translation
|
||||
- LOCALIZATION: Update Chinese (Simplified) translation
|
||||
- LOCALIZATION: Update Chinese (Traditional) translation
|
||||
- LOCALIZATION: Update German translation
|
||||
- LOCALIZATION: Update Greek translation
|
||||
- LOCALIZATION: Update Spanish translation
|
||||
- LOCALIZATION: Update French translation
|
||||
- LOCALIZATION: Update Italian translation
|
||||
- LOCALIZATION: Update Japanese translation
|
||||
- LOCALIZATION: Update Korean translation
|
||||
- LOCALIZATION: Update Dutch translation
|
||||
- LOCALIZATION: Update Polish translation
|
||||
- LOCALIZATION: Update Portuguese Brazilian translation
|
||||
- LOCALIZATION: Update Russian translation
|
||||
- LOCALIZATION: Update Turkish translation
|
||||
- LOCALIZATION: Update Vietnamese translation
|
||||
- LOCALIZATION: Add Slovak translation
|
||||
- MENU: Small buffer optimizations
|
||||
- MENU/THUMBNAILS/BUGFIX: Fix heap-use-after-free error
|
||||
- MENU/OZONE: Add option to sort playlists after name truncation
|
||||
- MENU/OZONE/ANDROIDTV: Default to Ozone menu driver
|
||||
- MENU/OZONE/ANDROID: Gamepad-like devices default to Ozone now (Shield Portable)
|
||||
- NETPLAY: Lower announcement rate
|
||||
- OVERLAYS: Fix memory leak when loading overlays
|
||||
- SHADER PRESETS: Improved shader preset dirs
|
||||
- TIME/DATE: Enable configuration of date seperator in clock and runtime 'last played' displays
|
||||
- VITA: Fix upside-down vertical games
|
||||
- UWP: Enable playlist and savefile compression by default (because of slow file I/O)
|
||||
- WIIU: Gamepad hotplugging support
|
||||
- WIIU: Theoretical multi-gamepad support
|
||||
- VIDEO/WIDGETS: Fix overlapping text when simultaneous pop-up notifications and core/shader messages are being displayed
|
||||
- X11: Fix crash in x11_display_server_get_screen_orientation
|
||||
- X11/XSHM: Allow X11/XHSM video driver to operate without SHM extension
|
||||
- X11/XSHM: Fix compatibility with X11 input driver
|
||||
- XVIDEO: Fix keyboard input initialization
|
||||
- XVIDEO/XWAYLAND: Fix XVideo support on xwayland (by supporting I420 and YZ12)
|
||||
|
||||
# 1.8.7
|
||||
- 3DS: Add IDs for Frodo
|
||||
- 3DS: Enable basic networking / cheevos
|
||||
- CHEEVOS/BUGFIX: Opening achievements list would crash RetroArch with badges enabled (on new games)
|
||||
- CHEEVOS: Option to start a session with all achievements active
|
||||
- CHEEVOS: Don't perform unnecessary cheevos initialisation when cheevos are disabled. Should reduce startup times when loading content.
|
||||
- CORE OPTIONS: Disable 'Use Global Core Options File' by default
|
||||
- DOS/DJGPP: Add 32bit color support for cores
|
||||
- GLCORE: Switch to glcore video driver when requested by a core
|
||||
- LINUX/XDG: Use GenericName correctly in desktop entry
|
||||
- MAC/COCOA: Fix mouse cursor tracking
|
||||
- MENU/MATERIALUI: Add desktop-style playlist view mode
|
||||
- MENU/MATERIALUI/DESKTOPVIEW: When scrolling playlists, show last selected thumbnails while waiting for next entry to load
|
||||
- MENU/MATERIALUI: Limit tab switch rate when input repeat is active
|
||||
- MENU/OZONE: Fix sidebar playlist sort order when 'Truncate Playlist Names' is enabled
|
||||
- MENU/RGUI: Adjusted menu defaults, adjusted default scrolling speed
|
||||
- MENU/RGUI: Enable custom wallpaper when menu size is reduced at low resolutions
|
||||
- MENU/XMB: Limit tab switch rate when input repeat is active
|
||||
- NETPLAY: Fix regressions introduced in 1.8.5
|
||||
- RGUI: Add option to always stretch menu to fill the screen
|
||||
- WIIU: Enable graphics widgets
|
||||
|
||||
# 1.8.6
|
||||
- 3DS: Add IDs for UZEM, TGB Dual, and NeoCD
|
||||
- 3DS: Fix font driver horizontal text alignment
|
||||
- 3DS: Allow button presses up to INPUT_MAX_USERS - this enables the 3DS to bind and use buttons and axis for users up to the maximum set by 'Max Users' in the input settings menu.
|
||||
- 3DS: Disable video filter if upscaled resolution exceeds hardware limits. The 3DS has a maximum video buffer size of 2048x2048. This is sufficient for every core that it supports, but when using software video filters the core output resolution is doubled. This is made worse by the fact that the video filter upscaling buffer size is dependent upon the maximum output resolution of the core - which in some cases is very large indeed (e.g. pcsx-rearmed sets a maximum width of 1024, for enhanced resolution support). The 3DS has very limited 'linear memory' for graphics buffer purposes, and a large base core buffer + video filter buffer can easily exceed this - which may also disable video output, or cause a crash. This PR very simply adds a 3DS-specific check to the video filter initialisation: if the resultant upscaling buffer exceeds the hardware limitation, then the filter is automatically disabled.
|
||||
- 3DS/FONT/BUGFIX: Text colour was wrong: the RGBA channels were muddled, and R was always set to 255
|
||||
- 3DS/FONT/BUGFIX: When drawing multiline strings, the line spacing was completely incorrect
|
||||
- 3DS/FONT: Improves the appearance of the drop shadow effect on notification text.
|
||||
- 3DS/ARCHIVE/7Z: Re-enable 7zip support.
|
||||
- ARCHIVE/ZIP: Expand functionality of 'rzip_stream' interface. This PR expands the functionality of the new rzip_stream archived stream interface such that it now has almost complete feature parity with the standard file_stream interface, and can therefore be used as a drop-in replacement in most situations
|
||||
- AI SERVICE: Hide redundant entries when service is disabled
|
||||
- AI SERVICE: Added in auto-translate support
|
||||
- AI SERVICE: support for NVDA and SAPI narration
|
||||
- AUTOCONFIG: Use correct port index in input device configured/disconnected notifications
|
||||
- BUGFIX: Fix race condition where task could momentarily not be in the queue when reordering
|
||||
- CHEEVOS/BUGFIX: Prevent null reference rendering achievement list while closing application
|
||||
- CHEEVOS/BUGFIX: Report non-memorymap GBA cores as unsupported
|
||||
- COMMANDLINE: Advise against using -s and -S variables on the command line. …
|
||||
- CONFIG FILE: Only write config files to disk when parameters change
|
||||
- CONFIG FILE/BUGFIX: RetroArch no longer crashes when attempting to save a config file after 'unsetting' a parameter (currently, this can be triggered quite easily by manipulating input remaps)
|
||||
- CONFIG FILE/BUGFIX: When using Material UI, RetroArch no longer modifies the wrong setting (or segfaults...) when tapping entries in the Quick Menu > Controls input remapping submenu
|
||||
- CONFIG FILE/BUGFIX: Quite a few real and potential memory leaks have been fixed.
|
||||
- CHD: Fixes a crash caused by ignoring the return value from one of the CHD library functions
|
||||
- FASTFORWARDING: A new Mute When Fast-Forwarding option has been added under Settings > Audio. When enabled, users can fast forward without having to listen to distorted audio.
|
||||
- GLCORE/SLANG: Set filter and wrap mode correctly when intialising shader textures. Before, the glcore shader driver did not correctly initialise loaded textures. The texture filtering and wrap mode were forced on texture creation, but these settings were not recorded - subsequent updates would set garbage values, that would resolve to linear filtering OFF and wrap mode = CLAMP_TO_EDGE.
|
||||
- LOCALIZATION: Update Japanese translation
|
||||
- LOCALIZATION: Update Spanish translation
|
||||
- LOCALIZATION: Update Portuguese Brazilian translation
|
||||
- IOS: Set audio session category to ambient so sound does not get cut off on interruption (phone call/playing back audio)
|
||||
- MAC/IOHIDMANAGER/BUGFIX: Fix for Mayflash N64 adapter. In case last hatswitch does not match cookie. For the mayflash N64 adapter, I was getting a BAD EXC ADDRESS (in mac OS 10.13) for this line (tmp was NULL). Retroarch would crash in the gui if I pressed a button from the DPAD on controller 2. With this change, it no longer crashes in the gui and still registers the button push.
|
||||
- MAC/COCOA: Fix mouse input - this brings back two lines of code that have been removed over time but
|
||||
appear to be required in order for mouse input to work on macOS
|
||||
- METAL/BUGFIX: GPU capture on Metal/OSX/NVidia could crash
|
||||
- METAL/BUGFIX: Taking screenshots could capture black frames. Resulting PNG screenshots were black.
|
||||
- METAL/BUGFIX: Corrupted image due to incorrect viewport copy when taking screenshot
|
||||
- MENU: Prevent font-related segfaults when using extremely small scales/window sizes
|
||||
- MENU: Fix 'gfx_display_draw_texture_slice()'
|
||||
- MENU/FONT: Enable correct vertical alignment of text (+ font rendering fixes)
|
||||
- MENU/RGUI: Enable automatic menu size reduction when running at low resolutions (down to 256x192)
|
||||
- MENU/OZONE: Update timedate style options for Last Played sublabel metadata
|
||||
- MENU/OZONE: Hide 'Menu Color Theme' setting when 'Use preferred system color theme' is enabled
|
||||
- MENU/OZONE: Fix thumbnail switching via 'scan' button functionality
|
||||
- MENU/OZONE: Prevent glitches when rendering Ozone's selection cursor
|
||||
- MENU/OZONE: Enable proper vertical text alignment + thumbnail display improvements
|
||||
- MENU/OZONE: Enable second thumbnail/content metadata toggle using RetroPad 'select'
|
||||
- MENU/OZONE: Refactor footer display
|
||||
- MENU/OZONE: Hide thumbnail button hints when viewing file browser lists
|
||||
- MENU/OZONE/INPUT/BUGFIX: Fix undefined behaviour when using touch screen to change input remaps
|
||||
- MENU/OZONE/INPUT/BUGFIX: It turns out that Windows reports negative pointer coordinates when the mouse cursor goes beyond the left hand edge of the RetroArch window (this doesn't happen on Linux, so I never encountered this issue before!). As a result, if Ozone is currently not showing the sidebar (menu depth > 1), moving the cursor off the left edge of the window generates a false positive 'cursor in sidebar' event - which breaks menu navigation, as described in #10419. With this PR, we now handle 'cursor in sidebar' status correctly in all cases
|
||||
- MENU/OZONE/INPUT/BUGFIX: Pointer input is now correctly disabled when message boxes are displayed
|
||||
- MENU/XMB: Fix thumbnail switching via 'scan' button functionality
|
||||
- ODROID GO ADVANCE: Add DRM HW context driver
|
||||
- PSL1GHT: Initial port
|
||||
- PSL1GHT/KEYBOARD: Implement PSL1GHT keyboard
|
||||
- PLAYLIST/BUGFIX: Improve handling of 'broken' playlists - RetroArch will no longer segfault when attempting to run content via a playlist entry with missing path or core path fields.
|
||||
- PLAYLIST/BUGFIX: Improve handling of 'broken' playlists - when a playlist entry has either core path and/or core name set to NULL, DETECT or an empty string, attempting to load content will fallback to the normal 'core selection' code (currently this happens only if both core path and core name are DETECT - this is wholly inadequate!)
|
||||
- PLAYLIST/BUGFIX: RetroArch will no longer segfault when attempting to fetch content runtime information when core path is NULL
|
||||
- PLAYLIST/BUGFIX: Core name + runtime info will only be displayed on playlists and in the Information submenu if both the core path and core name fields are 'valid' (i.e. not NULL or DETECT)
|
||||
- PLAYLIST/BUGFIX: When handling entries with missing path fields, the menu sorting order now matches that of the playlist sorting order (at present, everything goes out of sync when paths are empty). Moreover, entries with missing path fields can now be 'selected', so users can remove them (currently, hitting A on such an entry immediately tries - and fails - to load the content, so the only way to remove the broken entry is via the Playlist Management > Clean Playlist feature)
|
||||
- PLAYLIST: Add optional per-playlist alphabetical sorting
|
||||
- PLAYLIST: Omit whitespace when writing compressed JSON format playlists
|
||||
- PLAYLIST: Add optional playlist compression
|
||||
- QNX: Support analog sticks
|
||||
- SAVESTATES: Add optional save state compression (enabled by default now)
|
||||
- SRAM: Add optional save (SRAM) file compression
|
||||
- SCANNER: Prevent redundant playlist entries when handling M3U content
|
||||
- SCANNER/ANDROID: Fix content scanner being unable to identify certain games from CHD images (raw data sector/subcode)
|
||||
- TASKS/BUGFIX: Fix task deadlocks
|
||||
- TASKS/SCREENSHOT/BUGFIX: Fix heap-use-after-free error when widgets are disabled
|
||||
- TVOS: Disable overlays for tvOS, fix app icon
|
||||
- VIDEO/WIDGETS/BUGFIX: The font ascender/descender metrics added in #10375 are now used to achieve 'pixel perfect' vertical text alignment
|
||||
- VIDEO/WIDGETS/BUGFIX: Message queue text now uses its own dedicated font. Previously, a single (larger) font was used for all active widgets, and this was scaled down for message queue items. This 'squished' the text a little; more importantly, when using the stb font renderers (on Android. etc.) it caused ugly artefacts around the edges of glyphs due to pixel interpolation errors. Now that a correctly sized font is used, the message queue is always rendered cleanly.
|
||||
- VIDEO/WIDGETS/BUGFIX: Previously, each widget font was 'flushed' (font_driver_flush()) at least once a frame. This is quite a slow operation. Now we only flush fonts if they have actually been used.
|
||||
- VULKAN/BUGFIX: Fix display of statistics text
|
||||
- UNIX/BUGFIX: Fix overflow when computing total memory on i386
|
||||
- WIIU/BUGFIX: Fix font driver horizontal text alignment
|
||||
- WIIU/BUGFIX: Fix non-vertex coordinates in draws using tex shader
|
||||
- WIIU/BUGFIX: Update and fix meta.xml file for the WiiU release. This change makes it so the information from the meta.xml file parsed for the WiiU's Homebrew Launcher is displayed properly.
|
||||
|
||||
# 1.8.5
|
||||
- 3DS: Keep the bottom screen hidden on sleep/wakeup. When the 3DS wakes back up after being closed, the bottom screen needs to be reinitialized. Adding the condition here will cause the screen to be turned on or off based on the state of ctr_bottom_screen_enabled, as you'd expect
|
||||
- ANDROID/CHROMEBOOK/CRASH: Fix Chromebook crashes (on x86 x64) when touching the screen
|
||||
- BUGFIX: Prevent double input when using 'return' key (hardware) to close on-screen keyboard
|
||||
- BUGFIX: Fix mouse capture hotkey not working
|
||||
- BUGFIX: Avoid overflow when calculating multiplying performance counter
|
||||
- BUGFIX: Retroarch overlay displaying "Game remap file loaded." on the overlay instead of "Core remap file loaded." when only a core remap file is present
|
||||
- CHEEVOS/BUGFIX: Achievement triggers could cause Retroarch to Crash
|
||||
- CHEEVOS: Don't block Sameboy core because it only exposes some memory
|
||||
- CHEEVOS: Support for extended Sega CD memory
|
||||
@ -21,14 +220,19 @@
|
||||
- FFMPEG CORE: Fix crash on seeking when using HW decoding in some cases
|
||||
- LIBRETRO: Add disk control interface API extension
|
||||
- LINUX: Avoid possible crash when running retroarch at startup
|
||||
- LINUX/GLX: Fix threaded video crashes/instability because of GLX OML sync callbacks
|
||||
- LOCALIZATION: Update French translation
|
||||
- LOCALIZATION: Update Korean translation
|
||||
- LOCALIZATION: Update Polish translation
|
||||
- LOCALIZATION: Update Spanish translation
|
||||
- LOCALIZATION: Update Portuguese Brazilian translation
|
||||
- MENU: Add Menu Scroll Acceleration option
|
||||
- MENU: Automatically select currently checked item when opening drop-down lists
|
||||
- MENU: Fix smooth (vertical) line ticker scroll speed
|
||||
- MENU: Don't flush on override/remap messages
|
||||
- MENU/DATETIME: Adds some new timedate styles that follow the DD/MM/YYYY format, found in several European countries
|
||||
- MENU/DATETIME: Modifies the existing translation files in order to accommodate the new options that are now available
|
||||
- MENU/DATETIME: Reorders the timedate view options based on a decreasing order of the quantity of information displayed, so that they are more convenient to switch around and easily categorized
|
||||
- MENU/BUGFIX: Fix bug - if you were in XMB and you would set menu driver to RGUI, you could no longer go to the left or right tab
|
||||
- MENU/MATERIALUI: Add option to remove navigation bar
|
||||
- MENU/OZONE: Add DPI-based scaling
|
||||
@ -47,6 +251,8 @@
|
||||
- ODROID GO ADVANCE: Rotation support
|
||||
- NETPLAY/ROOMS/BUGFIX: Prevent out-of-bounds array indexing when displaying/selecting netplay rooms in menus
|
||||
- SCANNER: Add 'Arcade DAT Filter' Option
|
||||
- SCANNER: Add scanning Korea and Asia PS1 discs
|
||||
- SCANNER: Add support for scanning PSP Korean
|
||||
- VIDEO: Set hardware 'Bilinear filtering' off by default
|
||||
- VIDEO/WIDGETS: Widgets are now menu-independent
|
||||
- VIDEO/WIDGETS: Allow notifications to use full screen width when not displaying menu
|
||||
@ -54,6 +260,7 @@
|
||||
- VIDEO/WIDGETS: Fix volume widget scaling
|
||||
- VIDEO/WIDGETS: Add independent widget scale override settings for fullscreen/windowed modes
|
||||
- VIDEO/WIDGETS/BUGFIX: Prevent improper display of (old style) OSD text when widgets are enabled
|
||||
- VIDEO/WIDGETS/THREADED/BUGFIX: Fix issue - corruption of menu widgets when running some cores (e.g. VICE) with threaded video enabled
|
||||
- WIFI/CONNMANCTL: Display more characters from SSID
|
||||
|
||||
# 1.8.4
|
||||
|
118
Makefile.common
118
Makefile.common
@ -19,6 +19,12 @@ ifeq ($(HAVE_CXX11), 1)
|
||||
CXXFLAGS += $(CXX11_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SAPI), 1)
|
||||
LIBS += sapi.dll
|
||||
endif
|
||||
|
||||
|
||||
|
||||
ifeq ($(HAVE_GL_CONTEXT),)
|
||||
HAVE_GL_CONTEXT = 0
|
||||
HAVE_GL_MODERN = 0
|
||||
@ -176,6 +182,7 @@ OBJ += frontend/frontend_driver.o \
|
||||
tasks/task_image.o \
|
||||
tasks/task_playlist_manager.o \
|
||||
tasks/task_manual_content_scan.o \
|
||||
tasks/task_core_backup.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_base64.o \
|
||||
@ -219,7 +226,6 @@ OBJ += \
|
||||
file_path_str.o \
|
||||
$(LIBRETRO_COMM_DIR)/hash/rhash.o \
|
||||
input/common/input_hid_common.o \
|
||||
input/input_mapper.o \
|
||||
led/led_driver.o \
|
||||
gfx/video_coord_array.o \
|
||||
gfx/video_crt_switch.o \
|
||||
@ -241,6 +247,7 @@ OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.o \
|
||||
managers/cheat_manager.o \
|
||||
core_info.o \
|
||||
core_backup.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/config_file.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/config_file_userdata.o \
|
||||
runtime_file.o \
|
||||
@ -260,9 +267,9 @@ OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/utils/md5.o \
|
||||
playlist.o \
|
||||
$(LIBRETRO_COMM_DIR)/features/features_cpu.o \
|
||||
performance_counters.o \
|
||||
verbosity.o \
|
||||
$(LIBRETRO_COMM_DIR)/playlists/label_sanitization.o \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.o \
|
||||
manual_content_scan.o \
|
||||
disk_control_interface.o
|
||||
|
||||
@ -317,7 +324,11 @@ ifeq ($(HAVE_LANGEXTRA), 1)
|
||||
intl/msg_hash_cht.o \
|
||||
intl/msg_hash_ar.o \
|
||||
intl/msg_hash_el.o \
|
||||
intl/msg_hash_tr.o
|
||||
intl/msg_hash_tr.o \
|
||||
intl/msg_hash_sk.o \
|
||||
intl/msg_hash_fa.o \
|
||||
intl/msg_hash_he.o \
|
||||
intl/msg_hash_ast.o
|
||||
endif
|
||||
|
||||
ifneq ($(HAVE_GETOPT_LONG), 1)
|
||||
@ -426,6 +437,8 @@ ifeq ($(HAVE_QT), 1)
|
||||
|
||||
ifneq ($(findstring Linux,$(OS)),)
|
||||
DEF_FLAGS += -fPIC
|
||||
else ifneq ($(findstring BSD,$(OS)),)
|
||||
DEF_FLAGS += -fPIC
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -805,18 +818,11 @@ ifeq ($(HAVE_LAKKA_SWITCH), 1)
|
||||
DEFINES += -DHAVE_LAKKA_SWITCH
|
||||
endif
|
||||
|
||||
# Does not depend on HAVE_MENU
|
||||
ifeq ($(HAVE_SHADERS_COMMON), 1)
|
||||
OBJ += menu/menu_shader.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
OBJ += menu/menu_driver.o \
|
||||
menu/menu_setting.o \
|
||||
OBJ += menu/menu_setting.o \
|
||||
menu/widgets/menu_filebrowser.o \
|
||||
menu/widgets/menu_dialog.o \
|
||||
menu/widgets/menu_input_bind_dialog.o \
|
||||
menu/menu_cbs.o \
|
||||
menu/cbs/menu_cbs_ok.o \
|
||||
menu/cbs/menu_cbs_cancel.o \
|
||||
menu/cbs/menu_cbs_select.o \
|
||||
@ -837,10 +843,15 @@ ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
menu/menu_displaylist.o
|
||||
endif
|
||||
|
||||
OBJ += input/input_osk.o
|
||||
|
||||
ifeq ($(HAVE_GFX_WIDGETS), 1)
|
||||
OBJ += gfx/gfx_widgets.o
|
||||
OBJ += gfx/gfx_widgets.o \
|
||||
gfx/widgets/gfx_widget_screenshot.o \
|
||||
gfx/widgets/gfx_widget_volume.o \
|
||||
gfx/widgets/gfx_widget_generic_message.o \
|
||||
gfx/widgets/gfx_widget_libretro_message.o
|
||||
ifeq ($(HAVE_CHEEVOS), 1)
|
||||
OBJ += gfx/widgets/gfx_widget_achievement_popup.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OVERLAY), 1)
|
||||
@ -1114,7 +1125,12 @@ OBJ += gfx/drivers_context/gfx_null_ctx.o
|
||||
|
||||
ifeq ($(HAVE_KMS), 1)
|
||||
HAVE_AND_WILL_USE_DRM = 1
|
||||
|
||||
ifeq ($(HAVE_ODROIDGO2), 1)
|
||||
OBJ += gfx/drivers_context/drm_go2_ctx.o
|
||||
else
|
||||
OBJ += gfx/drivers_context/drm_ctx.o
|
||||
endif
|
||||
DEF_FLAGS += $(GBM_CFLAGS) $(DRM_CFLAGS)
|
||||
LIBS += $(GBM_LIBS) $(DRM_LIBS)
|
||||
endif
|
||||
@ -1670,7 +1686,8 @@ endif
|
||||
|
||||
ifeq ($(HAVE_ZLIB_COMMON), 1)
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/file/archive_file_zlib.o \
|
||||
$(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.o
|
||||
$(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.o \
|
||||
$(LIBRETRO_COMM_DIR)/streams/rzip_stream.o
|
||||
DEFINES += -DHAVE_ZLIB
|
||||
HAVE_COMPRESSION = 1
|
||||
|
||||
@ -1729,7 +1746,8 @@ endif
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/formats/bmp/rbmp_encode.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/json/jsonsax.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/json/jsonsax_full.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/image_transfer.o
|
||||
$(LIBRETRO_COMM_DIR)/formats/image_transfer.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/m3u/m3u_file.o
|
||||
|
||||
# Gong embedded core
|
||||
ifeq ($(HAVE_GONG),1)
|
||||
@ -1752,7 +1770,16 @@ endif
|
||||
# Accessibility
|
||||
ifeq ($(HAVE_ACCESSIBILITY), 1)
|
||||
DEFINES += -DHAVE_ACCESSIBILITY
|
||||
|
||||
ifeq ($(HAVE_SAPI), 1)
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
LIBS += -lsapi
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
|
||||
# Things that depend on network availability
|
||||
|
||||
@ -1798,38 +1825,41 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
# Netplay
|
||||
DEFINES += -DHAVE_NETWORK_CMD
|
||||
OBJ += network/netplay/netplay_delta.o \
|
||||
network/netplay/netplay_handshake.o \
|
||||
network/netplay/netplay_init.o \
|
||||
network/netplay/netplay_io.o \
|
||||
network/netplay/netplay_keyboard.o \
|
||||
network/netplay/netplay_sync.o \
|
||||
network/netplay/netplay_discovery.o \
|
||||
network/netplay/netplay_buf.o \
|
||||
network/netplay/netplay_room_parse.o
|
||||
network/netplay/netplay_handshake.o \
|
||||
network/netplay/netplay_init.o \
|
||||
network/netplay/netplay_io.o \
|
||||
network/netplay/netplay_keyboard.o \
|
||||
network/netplay/netplay_sync.o \
|
||||
network/netplay/netplay_discovery.o \
|
||||
network/netplay/netplay_buf.o \
|
||||
network/netplay/netplay_room_parse.o
|
||||
|
||||
# RetroAchievements
|
||||
ifeq ($(HAVE_CHEEVOS), 1)
|
||||
DEFINES += -DHAVE_CHEEVOS
|
||||
INCLUDE_DIRS += -Ideps/rcheevos/include
|
||||
|
||||
OBJ += cheevos-new/cheevos.o \
|
||||
cheevos-new/badges.o \
|
||||
cheevos-new/fixup.o \
|
||||
cheevos-new/parser.o \
|
||||
cheevos-new/hash.o \
|
||||
OBJ += cheevos/cheevos.o \
|
||||
cheevos/badges.o \
|
||||
cheevos/fixup.o \
|
||||
cheevos/parser.o \
|
||||
cheevos/hash.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/cdfs/cdfs.o \
|
||||
deps/rcheevos/src/rcheevos/trigger.o \
|
||||
deps/rcheevos/src/rcheevos/condset.o \
|
||||
deps/rcheevos/src/rcheevos/condition.o \
|
||||
deps/rcheevos/src/rcheevos/operand.o \
|
||||
deps/rcheevos/src/rcheevos/term.o \
|
||||
deps/rcheevos/src/rcheevos/expression.o \
|
||||
deps/rcheevos/src/rcheevos/value.o \
|
||||
deps/rcheevos/src/rcheevos/lboard.o \
|
||||
deps/rcheevos/src/rcheevos/alloc.o \
|
||||
deps/rcheevos/src/rcheevos/compat.o \
|
||||
deps/rcheevos/src/rcheevos/condition.o \
|
||||
deps/rcheevos/src/rcheevos/condset.o \
|
||||
deps/rcheevos/src/rcheevos/consoleinfo.o \
|
||||
deps/rcheevos/src/rcheevos/format.o \
|
||||
deps/rcheevos/src/rcheevos/lboard.o \
|
||||
deps/rcheevos/src/rcheevos/memref.o \
|
||||
deps/rcheevos/src/rcheevos/operand.o \
|
||||
deps/rcheevos/src/rcheevos/richpresence.o \
|
||||
deps/rcheevos/src/rcheevos/runtime.o \
|
||||
deps/rcheevos/src/rcheevos/runtime_progress.o \
|
||||
deps/rcheevos/src/rcheevos/trigger.o \
|
||||
deps/rcheevos/src/rcheevos/value.o \
|
||||
deps/rcheevos/src/rhash/hash.o \
|
||||
deps/rcheevos/src/rurl/url.o
|
||||
|
||||
ifeq ($(HAVE_LUA), 1)
|
||||
@ -1878,7 +1908,8 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
ifeq ($(HAVE_DISCORD), 1)
|
||||
NEED_CXX_LINKER = 1
|
||||
DEFINES += -DHAVE_DISCORD
|
||||
INCLUDE_DIRS += -Ideps/discord-rpc/include/ -Ideps/discord-rpc/thirdparty/rapidjson-1.1.0/include/
|
||||
INCLUDE_DIRS += -Ideps/discord-rpc/include \
|
||||
-Ideps/discord-rpc/thirdparty/rapidjson-1.1.0/include/
|
||||
|
||||
ifneq ($(HAVE_THREADS), 1)
|
||||
DEFINES += -DDISCORD_DISABLE_IO_THREAD
|
||||
@ -1886,8 +1917,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
|
||||
OBJ += deps/discord-rpc/src/discord_rpc.o \
|
||||
deps/discord-rpc/src/rpc_connection.o \
|
||||
deps/discord-rpc/src/serialization.o \
|
||||
discord/discord.o
|
||||
deps/discord-rpc/src/serialization.o
|
||||
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
OBJ += deps/discord-rpc/src/discord_register_win.o \
|
||||
@ -1936,8 +1966,7 @@ endif
|
||||
|
||||
ifneq ($(findstring FPGA,$(OS)),)
|
||||
OBJ += gfx/drivers/fpga_gfx.o \
|
||||
gfx/drivers_context/fpga_ctx.o \
|
||||
gfx/drivers_font/fpga_font.o
|
||||
gfx/drivers_context/fpga_ctx.o
|
||||
endif
|
||||
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
@ -2064,7 +2093,7 @@ ifeq ($(HAVE_MATH_NEON), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VITAGL), 1)
|
||||
DEFINES += -DHAVE_VITAGL -DTRANSPOSE_MATRICES
|
||||
DEFINES += -DHAVE_VITAGL -DSTB_DXT_IMPLEMENTATION -DSKIP_ERROR_HANDLING
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/vitaGL/source
|
||||
SOURCES := $(DEPS_DIR)/vitaGL/source $(DEPS_DIR)/vitaGL/source/utils
|
||||
OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)))
|
||||
@ -2113,6 +2142,7 @@ ifeq ($(HAVE_ODROIDGO2), 1)
|
||||
LIBS += -lrga -lpng -lz
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/libgo2/include
|
||||
OBJ += $(DEPS_DIR)/libgo2/src/display.o \
|
||||
$(DEPS_DIR)/libgo2/src/queue.o
|
||||
$(DEPS_DIR)/libgo2/src/queue.o \
|
||||
gfx/drivers/oga_gfx.o
|
||||
endif
|
||||
##################################
|
||||
|
@ -51,8 +51,9 @@ DEFINES :=
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
OBJ += griffin/griffin.o
|
||||
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB -DHAVE_CC_RESAMPLER
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA
|
||||
#DEFINES += -DHAVE_NETWORKING -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_SOCKET_LEGACY -DHAVE_THREADS
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_7ZIP -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA
|
||||
DEFINES += -DHAVE_NETWORKING -DHAVE_CHEEVOS -DRC_DISABLE_LUA
|
||||
#DEFINES += -DHAVE_SOCKET_LEGACY -DHAVE_THREADS
|
||||
#-DHAVE_SSL -DHAVE_BUILTINMBEDTLS -DMBEDTLS_SSL_DEBUG_ALL
|
||||
#ssl is currently incompatible with griffin due to use of the "static" flag on repeating functions that will conflict when included in one file
|
||||
else
|
||||
@ -135,6 +136,7 @@ CFLAGS += -I. \
|
||||
-Ideps \
|
||||
-Ideps/7zip \
|
||||
-Ideps/stb \
|
||||
-Ideps/rcheevos/include \
|
||||
-Ilibretro-common/include \
|
||||
-Ilibretro-common/include/compat/zlib
|
||||
|
||||
|
@ -38,6 +38,7 @@ OBJ := ctr/ctr_system.o \
|
||||
libretro-common/streams/file_stream.o \
|
||||
libretro-common/vfs/vfs_implementation.o \
|
||||
libretro-common/hash/rhash.o \
|
||||
libretro-common/time/rtime.o \
|
||||
file_path_str.o \
|
||||
verbosity.o
|
||||
|
||||
|
112
Makefile.griffin
112
Makefile.griffin
@ -75,15 +75,22 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
WHOLE_END := -Wl,--no-whole-archive
|
||||
endif
|
||||
|
||||
STATIC_BUILD = 1
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
LIBS := $(WHOLE_START) $(WHOLE_END)
|
||||
else
|
||||
STATIC_BUILD = 0
|
||||
endif
|
||||
ifneq (,$(findstring unix,$(platform)))
|
||||
STATIC_BUILD = 0
|
||||
endif
|
||||
ifeq (qnx, $(platform))
|
||||
STATIC_BUILD = 0
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC_BUILD), 0)
|
||||
LIBS := $(WHOLE_START) $(WHOLE_END)
|
||||
else
|
||||
LIBS := $(WHOLE_START) -lretro_$(platform) $(WHOLE_END)
|
||||
endif
|
||||
endif
|
||||
|
||||
libogc_platform :=
|
||||
|
||||
@ -148,7 +155,7 @@ else ifeq ($(libogc_platform), 1)
|
||||
endif
|
||||
|
||||
LIBDIRS += -L.
|
||||
MACHDEP += -DGEKKO -mcpu=750 -meabi -mhard-float -DMSB_FIRST
|
||||
MACHDEP += -DGEKKO -mcpu=750 -meabi -mhard-float
|
||||
|
||||
ifeq ($(platform), ngc)
|
||||
LDFLAGS += $(MACHDEP) -Wl,-Map,$(notdir $(EXT_INTER_TARGET)).map
|
||||
@ -791,6 +798,44 @@ else ifneq (,$(findstring windows_msvc2015,$(platform)))
|
||||
export INCLUDE := $(INCLUDE);libretro-common\include;libretro-common\include\compat\msvc;gfx\include;deps;deps\stb
|
||||
export LIB := $(LIB)
|
||||
endif
|
||||
else ifeq (qnx,$(platform))
|
||||
HAVE_AUDIOMIXER := 1
|
||||
HAVE_RPNG := 1
|
||||
HAVE_RJPEG := 1
|
||||
HAVE_RBMP := 1
|
||||
HAVE_RTGA := 1
|
||||
HAVE_ZLIB := 1
|
||||
HAVE_7ZIP := 1
|
||||
HAVE_NETWORKING := 1
|
||||
HAVE_NETWORK_CMD := 1
|
||||
HAVE_NETPLAYDISCOVERY := 1
|
||||
HAVE_OVERLAY := 1
|
||||
HAVE_VIDEO_LAYOUT := 0
|
||||
HAVE_MATERIALUI := 1
|
||||
HAVE_XMB := 1
|
||||
HAVE_STB_FONT := 1
|
||||
HAVE_THREADS := 1
|
||||
HAVE_LIBRETRODB := 1
|
||||
HAVE_COMMAND := 1
|
||||
HAVE_STDIN_CMD := 1
|
||||
HAVE_CMD := 1
|
||||
HAVE_DYLIB := 1
|
||||
HAVE_DYNAMIC := 1
|
||||
HAVE_GRIFFIN_CPP := 0
|
||||
WANT_GLSLANG := 0
|
||||
HAVE_CONFIGFILE := 1
|
||||
CC=qcc -Vgcc_ntoarmv7le
|
||||
CXX=QCC -Vgcc_ntoarmv7le
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
LDFLAGS += -g
|
||||
endif
|
||||
|
||||
PLATCFLAGS += -DHAVE_SHADERPIPELINE -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_GL_SYNC -DHAVE_GLSLANG -DHAVE_BUILTINGLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_XCB -DHAVE_EGL -DHAVE_BB10 -DHAVE_GLSL -DHAVE_AL -DRARCH_MOBILE
|
||||
EXT_TARGET := $(TARGET_NAME)
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/rcheevos/include -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
LIBS += -lEGL -lbps -lscreen -lsocket -lm -lGLESv2 -lOpenAL
|
||||
else ifneq (,$(findstring unix,$(platform)))
|
||||
HAVE_AUDIOMIXER := 1
|
||||
HAVE_RPNG := 1
|
||||
@ -823,6 +868,46 @@ else ifneq (,$(findstring unix,$(platform)))
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/rcheevos/include -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
LIBS += -ldl -lm -lpthread -lGL -ludev -lpulse -lX11 -lX11-xcb -lXxf86vm
|
||||
else ifeq (dos,$(platform))
|
||||
HAVE_AUDIOMIXER := 1
|
||||
HAVE_RPNG := 1
|
||||
HAVE_RJPEG := 1
|
||||
HAVE_RBMP := 1
|
||||
HAVE_RTGA := 1
|
||||
HAVE_ZLIB := 1
|
||||
HAVE_7ZIP := 1
|
||||
HAVE_NETWORKING := 0
|
||||
HAVE_NETWORK_CMD := 0
|
||||
HAVE_NETPLAYDISCOVERY := 0
|
||||
HAVE_OVERLAY := 1
|
||||
HAVE_VIDEO_LAYOUT := 0
|
||||
HAVE_MATERIALUI := 1
|
||||
HAVE_XMB := 0
|
||||
HAVE_STB_FONT := 1
|
||||
HAVE_THREADS := 0
|
||||
HAVE_LIBRETRODB := 1
|
||||
HAVE_COMMAND := 1
|
||||
HAVE_STDIN_CMD := 1
|
||||
HAVE_CMD := 1
|
||||
HAVE_DYLIB := 0
|
||||
HAVE_DYNAMIC := 0
|
||||
HAVE_GRIFFIN_CPP := 0
|
||||
WANT_GLSLANG := 0
|
||||
HAVE_CONFIGFILE := 1
|
||||
CC=i586-pc-msdosdjgpp-gcc
|
||||
CXX=i586-pc-msdosdjgpp-g++
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
LDFLAGS += -g
|
||||
endif
|
||||
|
||||
PLATCFLAGS += -DHAVE_SHADERPIPELINE -DHAVE_CC_RESAMPLER -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DRARCH_INTERNAL -DHAVE_XCB
|
||||
TARGET_NAME := retrodos
|
||||
EXT_TARGET := $(TARGET_NAME).exe
|
||||
EXT_INTER_TARGET := $(TARGET_NAME).exe
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
LIBS += -lm
|
||||
LIBDIRS += -L.
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
@ -1096,7 +1181,12 @@ $(APP_BOOTER_DIR)/app_booter.bin:
|
||||
$(MAKE) -C $(APP_BOOTER_DIR)
|
||||
|
||||
pkg: all
|
||||
ifeq ($(platform), wii)
|
||||
ifeq ($(platform), qnx)
|
||||
mkdir -p pkg/qnx/pkg
|
||||
cp -r $(EXT_TARGET) pkg/qnx/pkg/RetroArch
|
||||
cp -r media/canvas.png pkg/qnx/pkg/canvas.png
|
||||
cp -r media/retroarch-96x96.png pkg/qnx/pkg/retroarch-96x96.png
|
||||
else ifeq ($(platform), wii)
|
||||
cp -r $(EXT_TARGET) pkg/wii/CORE.dol
|
||||
else ifeq ($(platform), ngc)
|
||||
cp -r $(EXT_TARGET) pkg/ngc/CORE.dol
|
||||
@ -1104,6 +1194,18 @@ else ifeq ($(platform), psp1)
|
||||
psp-fixup-imports$(EXT) $(EXT_TARGET)
|
||||
endif
|
||||
|
||||
ifeq ($(platform), qnx)
|
||||
retroarch-dev.bar: pkg
|
||||
ifeq ($(QNX_DEBUGTOKEN),)
|
||||
blackberry-nativepackager -package $@ -devMode pkg/qnx/bar-descriptor.xml -C pkg/qnx/pkg pkg/qnx/pkg/*
|
||||
else
|
||||
blackberry-nativepackager -package $@ -devMode -debugToken $(QNX_DEBUGTOKEN) pkg/qnx/bar-descriptor.xml -C pkg/qnx/pkg pkg/qnx/pkg/*
|
||||
endif
|
||||
|
||||
retroarch-release.bar: pkg
|
||||
blackberry-nativepackager -package $@ pkg/qnx/bar-descriptor.xml -C pkg/qnx/pkg pkg/qnx/pkg/*
|
||||
endif
|
||||
|
||||
shaders-checkout:
|
||||
@if test -d $(SHADER_CG_DIR); then \
|
||||
echo "[SHADER CHECKOUT::] Git pulling common-shaders..."; \
|
||||
|
@ -133,7 +133,7 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs $(ARCH) -Wl,--allow-multiple-de
|
||||
# add things from Makefile.common
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
|
||||
LIBS := -lswresample -lavformat -lavcodec -lavutil -lswscale -lstdc++ -lbz2 -lpng -lz -lnx -lm
|
||||
LIBS := -lswresample -lavformat -lavcodec -lavutil -lswscale -lstdc++ -lbz2 -lpng -lz -lnx -lvpx -lopus -llzma -lm
|
||||
|
||||
ifeq ($(HAVE_OPENGL), 1)
|
||||
LIBS := -lEGL -lglapi -ldrm_nouveau $(LIBS)
|
||||
|
49
Makefile.ps2
49
Makefile.ps2
@ -1,19 +1,14 @@
|
||||
BUILD_FOR_PCSX2 = 0
|
||||
DEBUG = 0
|
||||
HAVE_KERNEL_PRX = 0
|
||||
HAVE_LOGGER = 0
|
||||
HAVE_FILE_LOGGER = 0
|
||||
HAVE_THREADS = 0
|
||||
BIG_STACK = 0
|
||||
MUTE_WARNINGS = 1
|
||||
PS2_IP = 192.168.1.150
|
||||
|
||||
TARGET = retroarchps2.elf
|
||||
TARGET_RELEASE = retroarchps2-release.elf
|
||||
|
||||
# Lib CDVD
|
||||
CDVD_DIR = ps2/libcdvd
|
||||
|
||||
# Compile the IRXs first
|
||||
IRX_DIR = ps2/irx
|
||||
IRX_FILES = $(wildcard ps2/irx/*.c)
|
||||
@ -22,7 +17,7 @@ ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_LV := -O0 -g
|
||||
RARCH_DEFINES += -DDEBUG
|
||||
else
|
||||
OPTIMIZE_LV := -O2
|
||||
OPTIMIZE_LV := -O3
|
||||
LDFLAGS := -s
|
||||
endif
|
||||
|
||||
@ -30,20 +25,18 @@ ifeq ($(MUTE_WARNINGS), 1)
|
||||
DISABLE_WARNINGS := -Wno-sign-compare -Wno-unused -Wno-parentheses
|
||||
endif
|
||||
|
||||
INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include -I$(CDVD_DIR)/ee
|
||||
INCDIR += -Ips2 -Ips2/include -Ilibretro-common/include -Ideps -Ideps/stb -Ideps/7zip
|
||||
INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include
|
||||
INCDIR += -Ips2/include -Ilibretro-common/include -Ideps -Ideps/stb -Ideps/7zip
|
||||
INCDIR += -Ideps/pthreads -Ideps/pthreads/platform/ps2 -Ideps/pthreads/platform/helper
|
||||
GPVAL = -G0
|
||||
CFLAGS = $(OPTIMIZE_LV) $(DISABLE_WARNINGS) -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES += -DPS2 -DUSE_IOP_CTYPE_MACRO -D_MIPS_ARCH_R5900 -DHAVE_ZLIB -DHAVE_NO_BUILTINZLIB -DHAVE_RPNG -DHAVE_RJPEG
|
||||
RARCH_DEFINES += -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
|
||||
RARCH_DEFINES += -DPS2 -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI
|
||||
RARCH_DEFINES += -DHAVE_ZLIB -DHAVE_NO_BUILTINZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS += -L$(PS2SDK)/ports/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ee/lib -L$(CDVD_DIR)/lib -L.
|
||||
LIBS += -lretro_ps2 -lgskit -ldmakit -lgskit_toolkit -laudsrv -lmf -lpadx -lmtap -lmc -lhdd -lsdl -lfileXio -lz
|
||||
LIBS += -lcdvdfs -lpatches -lpoweroff
|
||||
LDFLAGS += -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -L.
|
||||
# Lib cdvd is needed to get proper time
|
||||
LIBS += -lretro_ps2 -lpatches -lpoweroff -lgskit -ldmakit -laudsrv -lpadx -lmtap -lz -lcdvd
|
||||
|
||||
ifeq ($(BUILD_FOR_PCSX2), 1)
|
||||
RARCH_DEFINES += -DBUILD_FOR_PCSX2
|
||||
@ -57,27 +50,17 @@ ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_FILE_LOGGER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_KERNEL_PRX), 1)
|
||||
CFLAGS += -DHAVE_KERNEL_PRX
|
||||
endif
|
||||
|
||||
ifeq ($(BIG_STACK), 1)
|
||||
CFLAGS += -DBIG_STACK
|
||||
endif
|
||||
|
||||
CFLAGS += $(RARCH_DEFINES)
|
||||
|
||||
# All the IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/freemtap_irx.o $(IRX_DIR)/freepad_irx.o $(IRX_DIR)/freesio2_irx.o $(IRX_DIR)/iomanX_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/fileXio_irx.o $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o $(IRX_DIR)/usbd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbhdfsd_irx.o $(IRX_DIR)/freesd_irx.o $(IRX_DIR)/audsrv_irx.o $(IRX_DIR)/poweroff_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdvd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
|
||||
# Missing objecst on the PS2SDK
|
||||
EE_OBJS += ps2/compat_files/compat_ctype.o ps2/compat_files/time.o ps2/compat_files/ps2_devices.o
|
||||
EE_OBJS += ps2/compat_files/fileXio_cdvd.o ps2/compat_files/ps2_descriptor.o
|
||||
EE_OBJS += ps2/compat_files/ps2_devices.o
|
||||
|
||||
#EE_OBJS = griffin/griffin.o bootstrap/ps2/kernel_functions.o
|
||||
EE_OBJS += griffin/griffin.o
|
||||
|
||||
EE_CFLAGS = $(CFLAGS)
|
||||
@ -106,7 +89,10 @@ prepare:
|
||||
run:
|
||||
ps2client -h $(PS2_IP) execee host:$(EE_BIN)
|
||||
|
||||
debug: clean prepare all run
|
||||
sim:
|
||||
PCSX2 --elf=$(PWD)/$(EE_BIN) --nogui
|
||||
|
||||
debug: clean all run
|
||||
|
||||
package:
|
||||
ps2-packer $(EE_BIN) $(TARGET_RELEASE)
|
||||
@ -115,9 +101,4 @@ release: clean all package
|
||||
|
||||
#Include preferences
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
||||
|
||||
#Linking with C++
|
||||
$(EE_BIN): $(EE_OBJS) $(PS2SDK)/ee/startup/crt0.o
|
||||
$(EE_CXX) $(EE_NO_CRT) -T$(PS2SDK)/ee/startup/linkfile $(EE_CXXFLAGS) \
|
||||
-o $(EE_BIN) $(PS2SDK)/ee/startup/crt0.o $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(EE_OBJS) $(CRTEND_OBJ) $(CRTN_OBJ) $(EE_LDFLAGS) $(EE_LIBS)
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal_cpp
|
||||
|
@ -70,7 +70,7 @@ endif
|
||||
PPU_SRCS = griffin/griffin.c
|
||||
|
||||
DEFINES += -DHAVE_VIDEO_LAYOUT
|
||||
DEFINES += -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_GFX_WIDGETS -DHAVE_RGUI -DHAVE_XMB -DHAVE_OZONE -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DMSB_FIRST -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS -DHAVE_STB_FONT -DHAVE_RUNAHEAD -DHAVE_DR_MP3 -DHAVE_DR_FLAC
|
||||
DEFINES += -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_GFX_WIDGETS -DHAVE_RGUI -DHAVE_XMB -DHAVE_OZONE -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS -DHAVE_STB_FONT -DHAVE_RUNAHEAD -DHAVE_DR_MP3 -DHAVE_DR_FLAC
|
||||
DEFINES += -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES
|
||||
|
||||
ifeq ($(DEX_BUILD), 1)
|
||||
|
@ -59,6 +59,7 @@ PPU_SRCS = frontend/frontend_salamander.c \
|
||||
libretro-common/streams/file_stream.c \
|
||||
libretro-common/vfs/vfs_implementation.c \
|
||||
libretro-common/file/config_file.c \
|
||||
libretro-common/time/rtime.c \
|
||||
file_path_str.c \
|
||||
verbosity.c
|
||||
|
||||
|
@ -1,29 +1,39 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(PSL1GHT)),)
|
||||
$(error "Please set PSL1GHT in your environment. export PSL1GHT=<path>")
|
||||
endif
|
||||
|
||||
include $(PSL1GHT)/ppu_rules
|
||||
|
||||
include version.all
|
||||
|
||||
DEBUG = 0
|
||||
HAVE_LOGGER = 0
|
||||
HAVE_FILE_LOGGER = 0
|
||||
HAVE_FILE_LOGGER = 1
|
||||
|
||||
PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7"
|
||||
PC_DEVELOPMENT_UDP_PORT = 3490
|
||||
|
||||
CC = $(PS3DEV)/ppu/bin/ppu-gcc
|
||||
CXX = $(PS3DEV)/ppu/bin/ppu-g++
|
||||
LD = $(PS3DEV)/ppu/bin/ppu-ld
|
||||
|
||||
CONTENT_ID_FULL = UP0001-SSNE10000_00-0000000000000001
|
||||
CONTENTID = UP0001-SSNE10001_00-0000000000000001
|
||||
APPID = SSNE10001
|
||||
TITLE = Retroarch PSL1GHT
|
||||
PACKAGE_BASENAME := retroarch_psl1ght
|
||||
|
||||
ELF_TARGET := retroarch_psl1ght.elf
|
||||
EBOOT_PATH = pkg/ps3/USRDIR/EBOOT.BIN
|
||||
CORE_PATH = pkg/ps3/USRDIR/cores/CORE.SELF
|
||||
SELF_TARGET := $(ELF_TARGET:.elf=.self)
|
||||
CORE_PATH = pkg/psl1ght/pkg/USRDIR/cores/CORE.SELF
|
||||
|
||||
INCLUDE := -I. -I$(PS3DEV)/ppu/include -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib
|
||||
LIBDIRS := -L$(PS3DEV)/ppu/lib -L$(PS3DEV)/portlibs/ppu/lib -L.
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude
|
||||
LIBDIRS += -L.
|
||||
|
||||
MACHDEP := -D__CELLOS_LV2__ -D__PSL1GHT__
|
||||
MACHDEP := -D__CELLOS_LV2__ -D__PSL1GHT__ -mcpu=cell
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lrgl_ps3 -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl
|
||||
LIBS := -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
@ -38,46 +48,10 @@ endif
|
||||
|
||||
PKG_SCRIPT = tools/ps3/ps3py/pkg.py
|
||||
ifeq ($(shell uname), Linux)
|
||||
PKG_FINALIZE = package_finalize
|
||||
MAKE_SELF_WC = make_self_wc
|
||||
MAKE_SELF = make_self_npdrm
|
||||
PYTHON2 = python2
|
||||
GIT = git
|
||||
else
|
||||
PKG_FINALIZE = package_finalize.exe
|
||||
MAKE_SELF_WC = make_self_wc.exe
|
||||
MAKE_SELF = make_self_npdrm.exe
|
||||
PYTHON2 = python2.exe
|
||||
GIT = git.exe
|
||||
endif
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
PKG_SCRIPT = tools/ps3/ps3py/pkg.py
|
||||
ifeq ($(shell uname), Linux)
|
||||
PKG_FINALIZE = package_finalize
|
||||
MAKE_SELF_WC = make_self_wc
|
||||
MAKE_SELF = make_self_npdrm
|
||||
PYTHON2 = python2
|
||||
GIT = git
|
||||
else
|
||||
PKG_FINALIZE = package_finalize.exe
|
||||
MAKE_SELF_WC = make_self_wc.exe
|
||||
MAKE_SELF = make_self_npdrm.exe
|
||||
PYTHON2 = python2.exe
|
||||
GIT = git.exe
|
||||
endif
|
||||
|
||||
MAKE_FSELF_NPDRM = $(CELL_SDK)/host-win32/bin/make_fself_npdrm.exe
|
||||
MAKE_PACKAGE_NPDRM = $(CELL_SDK)/host-win32/bin/make_package_npdrm.exe
|
||||
|
||||
OBJ = griffin/griffin.o
|
||||
|
||||
@ -92,7 +66,7 @@ endif
|
||||
SHARED_FLAGS :=
|
||||
|
||||
SHARED_FLAGS += -DHAVE_VIDEO_LAYOUT
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DRARCH_CONSOLE -DHAVE_OPENGL -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_OPENGLES -DHAVE_OPENGLES1 -DHAVE_PSGL -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_GCMGL -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DRARCH_CONSOLE -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_GCMGL -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER -DRARCH_INTERNAL -DHAVE_MULTIMAN -DHAVE_RGUI
|
||||
CFLAGS += -std=gnu99 $(SHARED_FLAGS)
|
||||
CXXFLAGS += $(SHARED_FLAGS)
|
||||
|
||||
@ -103,28 +77,18 @@ else
|
||||
CXXFLAGS += -03 -g
|
||||
endif
|
||||
|
||||
all: $(ELF_TARGET)
|
||||
all: $(SELF_TARGET)
|
||||
|
||||
$(ELF_TARGET): $(OBJ)
|
||||
$(CXX) -o $@ $(LDFLAGS) $(LIBDIRS) $(OBJ) $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
create-core: $(SELF_TARGET)
|
||||
cp $(SELF_TARGET) $(CORE_PATH)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
create-npdrm-core:
|
||||
$(MAKE_FSELF_NPDRM) $(ELF_TARGET) $(CORE_PATH)
|
||||
|
||||
create-core:
|
||||
$(MAKE_SELF_WC) $(ELF_TARGET) $(CORE_PATH)
|
||||
|
||||
pkg: $(ELF_TARGET) create-npdrm-core
|
||||
$(MAKE_PACKAGE_NPDRM) pkg/ps3/package.conf ps3/pkg
|
||||
|
||||
pkg-signed: $(ELF_TARGET) create-core
|
||||
$(PYTHON2) $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) pkg/ps3 retroarch-ps3-cfw-$(PACKAGE_VERSION).pkg
|
||||
pkg: create-core
|
||||
$(PKG) --contentid $(CONTENTID) pkg/psl1ght/pkg/ $(PACKAGE_BASENAME).pkg
|
||||
# cp $(PACKAGE_BASENAME).pkg $(PACKAGE_BASENAME).gnpdrm.pkg
|
||||
# $(PACKAGE_FINALIZE) $(PACKAGE_BASENAME).gnpdrm.pkg
|
||||
|
||||
clean:
|
||||
rm -f $(ELF_TARGET)
|
||||
|
120
Makefile.psl1ght.salamander
Normal file
120
Makefile.psl1ght.salamander
Normal file
@ -0,0 +1,120 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(PSL1GHT)),)
|
||||
$(error "Please set PSL1GHT in your environment. export PSL1GHT=<path>")
|
||||
endif
|
||||
|
||||
include $(PSL1GHT)/ppu_rules
|
||||
|
||||
include version.all
|
||||
|
||||
DEBUG = 0
|
||||
HAVE_LOGGER = 0
|
||||
HAVE_FILE_LOGGER = 1
|
||||
|
||||
PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7"
|
||||
PC_DEVELOPMENT_UDP_PORT = 3490
|
||||
|
||||
CONTENTID = UP0001-SSNE10001_00-0000000000000001
|
||||
APPID = SSNE10001
|
||||
TITLE = Retroarch PSL1GHT
|
||||
PACKAGE_BASENAME := retroarch_psl1ght
|
||||
|
||||
ELF_TARGET := retroarch_psl1ght_salamander.elf
|
||||
ELF_TARGET_NONSTRIPPED := retroarch_psl1ght_salamander_nonstripped.elf
|
||||
EBOOT_PATH = pkg/psl1ght/pkg/USRDIR/EBOOT.BIN
|
||||
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude
|
||||
LIBDIRS += -L.
|
||||
|
||||
MACHDEP := -D__CELLOS_LV2__ -D__PSL1GHT__ -mcpu=cell -mhard-float -fmodulo-sched -ffunction-sections -fdata-sections
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lgcm_sys -lrsx -lsysutil -lio -lnet -lsysmodule -lrt -llv2 -lm
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
PKG_SCRIPT = tools/ps3/ps3py/pkg.py
|
||||
ifeq ($(shell uname), Linux)
|
||||
GIT = git
|
||||
else
|
||||
GIT = git.exe
|
||||
endif
|
||||
|
||||
OBJ = frontend/frontend_salamander.o \
|
||||
frontend/frontend_driver.o \
|
||||
frontend/drivers/platform_ps3.o \
|
||||
libretro-common/file/file_path.o \
|
||||
libretro-common/file/file_path_io.o \
|
||||
libretro-common/lists/dir_list.o \
|
||||
libretro-common/lists/string_list.o \
|
||||
libretro-common/file/retro_dirent.o \
|
||||
libretro-common/hash/rhash.o \
|
||||
libretro-common/string/stdstring.o \
|
||||
libretro-common/encodings/encoding_utf.o \
|
||||
libretro-common/compat/compat_strl.o \
|
||||
libretro-common/compat/compat_strcasestr.o \
|
||||
libretro-common/compat/fopen_utf8.o \
|
||||
libretro-common/streams/file_stream.o \
|
||||
libretro-common/vfs/vfs_implementation.o \
|
||||
libretro-common/file/config_file.o \
|
||||
libretro-common/time/rtime.c \
|
||||
file_path_str.o \
|
||||
verbosity.o
|
||||
|
||||
ifeq ($(HAVE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_LOGGER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_FILE_LOGGER
|
||||
endif
|
||||
|
||||
SHARED_FLAGS :=
|
||||
|
||||
SHARED_FLAGS += -DHAVE_VIDEO_LAYOUT
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DRARCH_CONSOLE -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_GCMGL -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER -DHAVE_MULTIMAN -DHAVE_RGUI -DIS_SALAMANDER
|
||||
CFLAGS += -std=gnu99 $(SHARED_FLAGS)
|
||||
CXXFLAGS += $(SHARED_FLAGS)
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
CFLAGS += -O3 -g
|
||||
CXXFLAGS += -03 -g
|
||||
endif
|
||||
|
||||
all: create-salamander
|
||||
|
||||
$(ELF_TARGET_NONSTRIPPED): $(OBJ)
|
||||
$(CXX) -o $@ $(LDFLAGS) $(LIBDIRS) $(OBJ) $(LIBS)
|
||||
|
||||
$(ELF_TARGET): $(ELF_TARGET_NONSTRIPPED)
|
||||
$(STRIP) $< -o $@
|
||||
$(SPRX) $@
|
||||
|
||||
create-salamander: $(ELF_TARGET)
|
||||
$(SELF_NPDRM) $(ELF_TARGET) $(EBOOT_PATH) $(CONTENTID)
|
||||
|
||||
pkg: create-salamander
|
||||
$(PKG) --contentid $(CONTENTID) pkg/psl1ght/pkg/ $(PACKAGE_BASENAME).pkg
|
||||
# cp $(PACKAGE_BASENAME).pkg $(PACKAGE_BASENAME).gnpdrm.pkg
|
||||
# $(PACKAGE_FINALIZE) $(PACKAGE_BASENAME).gnpdrm.pkg
|
||||
|
||||
clean:
|
||||
rm -f $(ELF_TARGET)
|
||||
rm -f $(OBJ)
|
||||
|
||||
.PHONY: clean
|
@ -25,7 +25,7 @@ INCDIR = deps deps/stb deps/7zip deps/pthreads deps/pthreads/platform/psp deps/p
|
||||
CFLAGS = $(OPTIMIZE_LV) -G0 -std=gnu99 -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES = -DPSP -D_MIPS_ARCH_ALLEGREX -DHAVE_LANGEXTRA -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
|
||||
RARCH_DEFINES = -DPSP -D_MIPS_ARCH_ALLEGREX -DHAVE_LANGEXTRA -DHAVE_ZLIB -DHAVE_AUDIOMIXER -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
|
@ -49,6 +49,7 @@ OBJS = frontend/frontend_salamander.o \
|
||||
libretro-common/streams/file_stream.o \
|
||||
libretro-common/vfs/vfs_implementation.o \
|
||||
libretro-common/hash/rhash.o \
|
||||
libretro-common/time/rtime.o \
|
||||
file_path_str.o \
|
||||
verbosity.o \
|
||||
bootstrap/psp1/kernel_functions.o
|
||||
|
@ -1,5 +1,6 @@
|
||||
TARGET := retroarch_vita
|
||||
DEBUG ?= 0
|
||||
HAVE_FILE_LOGGER = 1
|
||||
GRIFFIN_BUILD = 0
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
|
||||
@ -59,6 +60,7 @@ else
|
||||
RARCH_CONSOLE := 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_AUDIOMIXER := 1
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
HAVE_NETLOGGER = 1
|
||||
@ -86,7 +88,7 @@ AR := $(PREFIX)ar
|
||||
OBJCOPY := $(PREFIX)objcopy
|
||||
STRIP := $(PREFIX)strip
|
||||
NM := $(PREFIX)nm
|
||||
LD := $(CXX)
|
||||
LD := $(CC)
|
||||
|
||||
LIBDIRS := -L.
|
||||
|
||||
@ -121,7 +123,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
VITA_LIBS := -lSceDisplay_stub -lSceGxm_stub -lSceNet_stub -lSceNetCtl_stub -lSceAppUtil_stub \
|
||||
-lSceSysmodule_stub -lSceCtrl_stub -lSceHid_stub -lSceTouch_stub -lSceAudio_stub \
|
||||
-lScePower_stub -lSceRtc_stub -lSceCommonDialog_stub -lScePgf_stub -lSceMotion_stub \
|
||||
-lSceFiber_stub -lSceMotion_stub -lSceAppMgr_stub -lpthread -lpng -lz
|
||||
-lSceFiber_stub -lSceMotion_stub -lSceAppMgr_stub -lstdc++ -lpthread -lpng -lz
|
||||
|
||||
LIBS := $(WHOLE_START) -lretro_vita $(WHOLE_END) $(VITA_LIBS) -lm -lc
|
||||
|
||||
@ -180,6 +182,10 @@ vpksend: $(TARGET).vpk
|
||||
send: $(TARGET).self
|
||||
curl -T $< ftp://$(PSVITAIP):1337/ux0:/app/$(VITA_TITLE_ID)/eboot.bin
|
||||
|
||||
launch: $(TARGET).self
|
||||
curl -T $< ftp://$(PSVITAIP):1337/ux0:/app/$(VITA_TITLE_ID)/eboot.bin
|
||||
echo "launch $(VITA_TITLE_ID)" | nc ${PSVITAIP} 1338
|
||||
|
||||
.PHONY: clean all send vpksend
|
||||
.PRECIOUS: %.depend
|
||||
|
||||
|
@ -49,6 +49,7 @@ OBJS = frontend/frontend_salamander.o \
|
||||
libretro-common/streams/file_stream.o \
|
||||
libretro-common/vfs/vfs_implementation.o \
|
||||
libretro-common/hash/rhash.o \
|
||||
libretro-common/time/rtime.o \
|
||||
file_path_str.o \
|
||||
verbosity.o
|
||||
|
||||
|
@ -69,6 +69,7 @@ OBJ = frontend/frontend_salamander.o \
|
||||
libretro-common/compat/compat_strcasestr.o \
|
||||
libretro-common/compat/fopen_utf8.o \
|
||||
libretro-common/file/config_file.o \
|
||||
libretro-common/time/rtime.o \
|
||||
file_path_str.o \
|
||||
verbosity.o \
|
||||
$(APP_BOOTER_DIR)/app_booter.binobj
|
||||
|
@ -67,6 +67,7 @@ ifeq ($(SALAMANDER_BUILD),1)
|
||||
OBJ += libretro-common/streams/file_stream.o
|
||||
OBJ += libretro-common/vfs/vfs_implementation.o
|
||||
OBJ += libretro-common/hash/rhash.o
|
||||
OBJ += libretro-common/time/rtime.o
|
||||
OBJ += file_path_str.o
|
||||
OBJ += verbosity.o
|
||||
|
||||
@ -97,7 +98,7 @@ endif
|
||||
OBJ += gfx/drivers/gx2_shaders/snowflake.o
|
||||
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
OBJ += griffin/griffin.o
|
||||
OBJ += griffin/griffin.o griffin/griffin_cpp.o
|
||||
|
||||
INCDIRS += -Ilibretro-common/include/compat/zlib
|
||||
# for stb, libfat, iosuhax
|
||||
@ -107,7 +108,7 @@ endif
|
||||
INCDIRS += -Ideps/SPIRV-Cross
|
||||
|
||||
DEFINES += -DHAVE_AUDIOMIXER
|
||||
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_LIBRETRODB
|
||||
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_LIBRETRODB
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_CC_RESAMPLER
|
||||
DEFINES += -DHAVE_SPIRV_CROSS -DHAVE_SLANG
|
||||
DEFINES += -DHAVE_STB_FONT -DHAVE_STB_VORBIS -DHAVE_LANGEXTRA -DHAVE_LIBRETRODB -DHAVE_NETWORKING -DHAVE_NETPLAYDISCOVERY
|
||||
@ -122,6 +123,7 @@ endif
|
||||
else
|
||||
HAVE_AUDIOMIXER = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_GFX_WIDGETS = 1
|
||||
HAVE_RTGA = 1
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RJPEG = 1
|
||||
@ -163,7 +165,7 @@ OBJ := $(addprefix $(BUILD_DIR)/,$(OBJ))
|
||||
#-----------------------------
|
||||
# Compile flags
|
||||
|
||||
DEFINES += -DWIIU -DMSB_FIRST -D__WUT__ -DHW_WUP -D__wiiu__
|
||||
DEFINES += -DWIIU -D__WUT__ -DHW_WUP -D__wiiu__
|
||||
DEFINES += -DHAVE_MAIN
|
||||
DEFINES += -DRARCH_CONSOLE
|
||||
|
||||
@ -184,7 +186,7 @@ CFLAGS := -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS += -ffast-math -Werror=implicit-function-declaration
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
#CFLAGS += -fomit-frame-pointer -mword-relocations
|
||||
#CFLAGS += -Wall
|
||||
CFLAGS += -Wall
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
|
@ -1,5 +1,6 @@
|
||||
[](https://travis-ci.org/libretro/RetroArch)
|
||||
[](https://scan.coverity.com/projects/retroarch)
|
||||
[](https://crowdin.com/project/retroarch)
|
||||
|
||||
# RetroArch
|
||||
|
||||
@ -18,7 +19,7 @@ These programs are instantiated as dynamic libraries. We refer to these as "libr
|
||||
|
||||
## libretro
|
||||
|
||||
[libretro](http://libretro.com) is an API that exposes generic audio/video/input callbacks.
|
||||
[libretro](https://www.libretro.com) is an API that exposes generic audio/video/input callbacks.
|
||||
A frontend for libretro (such as RetroArch) handles video output, audio output, input and application lifecycle.
|
||||
A libretro core written in portable C or C++ can run seamlessly on many platforms with very little to no porting effort.
|
||||
|
||||
@ -33,7 +34,7 @@ Latest binaries are currently hosted on the [buildbot](http://buildbot.libretro.
|
||||
|
||||
## Support
|
||||
|
||||
To reach developers, either make an issue here on GitHub, make a thread on the [forum](http://www.libretro.com/forums/), chat on [discord](https://discord.gg/C4amCeV), or visit our IRC channel: #retroarch @ irc.freenode.org. You could create a post in [Reddit](https://www.reddit.com/r/RetroArch/) with *Technical Support* flair.
|
||||
To reach developers, either make an issue here on GitHub, make a thread on the [forum](https://www.libretro.com/forums/), chat on [discord](https://discord.gg/C4amCeV), or visit our IRC channel: #retroarch @ irc.freenode.org. You could create a post in [Reddit](https://www.reddit.com/r/RetroArch/) with *Technical Support* flair.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
@ -30,13 +30,4 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
bool is_accessibility_enabled(void);
|
||||
|
||||
bool accessibility_speak_priority(const char* speak_text, int priority);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <boolean.h>
|
||||
#include <rthreads/rthreads.h>
|
||||
|
||||
#include "../../configuration.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
@ -96,13 +97,13 @@ static void shutdown_cb(void *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int parse_ports(const char *audio_device,
|
||||
char **dest_ports, const char **jports)
|
||||
static int parse_ports(char **dest_ports, const char **jports)
|
||||
{
|
||||
int i;
|
||||
char *save = NULL;
|
||||
int parsed = 0;
|
||||
char *audio_device_cpy = strdup(audio_device);
|
||||
settings_t *settings = config_get_ptr();
|
||||
char *audio_device_cpy = strdup(settings->arrays.audio_device);
|
||||
const char *con = strtok_r(audio_device_cpy, ",", &save);
|
||||
|
||||
if (con)
|
||||
@ -203,7 +204,7 @@ static void *ja_init(const char *device,
|
||||
}
|
||||
}
|
||||
|
||||
parsed = parse_ports(device, dest_ports, jports);
|
||||
parsed = parse_ports(dest_ports, jports);
|
||||
|
||||
if (jack_activate(jd->client) < 0)
|
||||
{
|
||||
|
@ -105,8 +105,11 @@ static bool ra_alive(void *data)
|
||||
static void ra_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
roar_t *roar = (roar_t*)data;
|
||||
|
||||
if (roar_vs_blocking(roar->vss, (state) ? ROAR_VS_FALSE : ROAR_VS_TRUE, NULL) < 0)
|
||||
fprintf(stderr, "RetroArch [ERROR]: Can't set nonblocking. Will not be able to fast-forward.\n");
|
||||
{
|
||||
RARCH_ERR("Can't set nonblocking. Will not be able to fast-forward.\n");
|
||||
}
|
||||
roar->nonblocking = state;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size)
|
||||
num = 0;
|
||||
|
||||
#ifdef HAVE_LIBNX
|
||||
if (audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX) != 0) { }
|
||||
if (audoutWaitPlayFinish(&swa->current_buffer, &num, UINT64_MAX) != 0) { }
|
||||
#else
|
||||
svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333);
|
||||
svcResetSignal(swa->event);
|
||||
|
@ -46,6 +46,10 @@ typedef AudioOutBuffer compat_audio_out_buffer;
|
||||
#define switch_audio_ipc_output_stop(a) audoutStopAudioOut()
|
||||
#define switch_audio_ipc_output_start(a) audoutStartAudioOut()
|
||||
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX U64_MAX
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* libtransistor definitions */
|
||||
|
@ -86,7 +86,7 @@ static void mainLoop(void* data)
|
||||
if (!released_out_buffer)
|
||||
{
|
||||
#ifdef HAVE_LIBNX
|
||||
rc = audoutWaitPlayFinish(&released_out_buffer, &released_out_count, U64_MAX);
|
||||
rc = audoutWaitPlayFinish(&released_out_buffer, &released_out_count, UINT64_MAX);
|
||||
#else
|
||||
uint32_t handle_idx = 0;
|
||||
svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333);
|
||||
|
@ -1525,7 +1525,7 @@ static struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
|
||||
fd = open(fn, O_RDWR|O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
{
|
||||
fprintf(stderr, "cannot open device '%s'\n", fn);
|
||||
RARCH_ERR("[TINYALSA] Cannot open device '%s'\n", fn);
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
@ -1538,7 +1538,7 @@ static struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
|
||||
param_init(params);
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params))
|
||||
{
|
||||
fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
|
||||
RARCH_ERR("[TINYALSA] SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
|
||||
goto err_hw_refine;
|
||||
}
|
||||
|
||||
@ -2019,7 +2019,7 @@ static int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int b
|
||||
avail = pcm_avail_update(pcm);
|
||||
if (avail < 0)
|
||||
{
|
||||
fprintf(stderr, "cannot determine available mmap frames");
|
||||
RARCH_ERR("[TINYALSA] Cannot determine available mmap frames");
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2029,7 +2029,7 @@ static int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int b
|
||||
{
|
||||
if (pcm_start(pcm) < 0)
|
||||
{
|
||||
fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n",
|
||||
RARCH_ERR("[TINYALSA] Start error: hw 0x%x app 0x%x avail 0x%x\n",
|
||||
(unsigned int)pcm->mmap_status->hw_ptr,
|
||||
(unsigned int)pcm->mmap_control->appl_ptr,
|
||||
avail);
|
||||
@ -2052,7 +2052,7 @@ static int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int b
|
||||
{
|
||||
pcm->prepared = 0;
|
||||
pcm->running = 0;
|
||||
fprintf(stderr, "wait error: hw 0x%x app 0x%x avail 0x%x\n",
|
||||
RARCH_ERR("[TINYALSA] Wait error: hw 0x%x app 0x%x avail 0x%x\n",
|
||||
(unsigned int)pcm->mmap_status->hw_ptr,
|
||||
(unsigned int)pcm->mmap_control->appl_ptr,
|
||||
avail);
|
||||
@ -2073,7 +2073,7 @@ static int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int b
|
||||
frames = pcm_mmap_transfer_areas(pcm, (void *)buffer, offset, frames);
|
||||
if (frames < 0)
|
||||
{
|
||||
fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n",
|
||||
RARCH_ERR("[TINYALSA] Write error: hw 0x%x app 0x%x avail 0x%x\n",
|
||||
(unsigned int)pcm->mmap_status->hw_ptr,
|
||||
(unsigned int)pcm->mmap_control->appl_ptr,
|
||||
avail);
|
||||
|
@ -402,7 +402,7 @@ static bool v4l_poll(void *data,
|
||||
|
||||
if (preprocess_image(data))
|
||||
{
|
||||
if (frame_raw_cb != NULL)
|
||||
if (frame_raw_cb)
|
||||
frame_raw_cb(v4l->buffer_output, v4l->width,
|
||||
v4l->height, v4l->width * 4);
|
||||
return true;
|
||||
|
@ -1,301 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "fixup.h"
|
||||
#include "cheevos.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../core.h"
|
||||
|
||||
#include "../deps/rcheevos/include/rcheevos.h"
|
||||
|
||||
static int rcheevos_cmpaddr(const void* e1, const void* e2)
|
||||
{
|
||||
const rcheevos_fixup_t* f1 = (const rcheevos_fixup_t*)e1;
|
||||
const rcheevos_fixup_t* f2 = (const rcheevos_fixup_t*)e2;
|
||||
|
||||
if (f1->address < f2->address)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (f1->address > f2->address)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t rcheevos_var_reduce(size_t addr, size_t mask)
|
||||
{
|
||||
while (mask)
|
||||
{
|
||||
size_t tmp = (mask - 1) & ~mask;
|
||||
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
|
||||
mask = (mask & (mask - 1)) >> 1;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static size_t rcheevos_var_highest_bit(size_t n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
|
||||
return n ^ (n >> 1);
|
||||
}
|
||||
|
||||
void rcheevos_fixup_init(rcheevos_fixups_t* fixups)
|
||||
{
|
||||
fixups->elements = NULL;
|
||||
fixups->capacity = fixups->count = 0;
|
||||
fixups->dirty = false;
|
||||
}
|
||||
|
||||
void rcheevos_fixup_destroy(rcheevos_fixups_t* fixups)
|
||||
{
|
||||
CHEEVOS_FREE(fixups->elements);
|
||||
rcheevos_fixup_init(fixups);
|
||||
}
|
||||
|
||||
const uint8_t* rcheevos_fixup_find(rcheevos_fixups_t* fixups, unsigned address, int console)
|
||||
{
|
||||
rcheevos_fixup_t key;
|
||||
rcheevos_fixup_t* found;
|
||||
const uint8_t* location;
|
||||
|
||||
if (fixups->dirty)
|
||||
{
|
||||
qsort(fixups->elements, fixups->count, sizeof(rcheevos_fixup_t), rcheevos_cmpaddr);
|
||||
fixups->dirty = false;
|
||||
}
|
||||
|
||||
key.address = address;
|
||||
found = (rcheevos_fixup_t*)bsearch(&key, fixups->elements, fixups->count, sizeof(rcheevos_fixup_t), rcheevos_cmpaddr);
|
||||
|
||||
if (found != NULL)
|
||||
{
|
||||
return found->location;
|
||||
}
|
||||
|
||||
if (fixups->count == fixups->capacity)
|
||||
{
|
||||
unsigned new_capacity = fixups->capacity == 0 ? 16 : fixups->capacity * 2;
|
||||
rcheevos_fixup_t* new_elements = (rcheevos_fixup_t*)
|
||||
realloc(fixups->elements, new_capacity * sizeof(rcheevos_fixup_t));
|
||||
|
||||
if (new_elements == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fixups->elements = new_elements;
|
||||
fixups->capacity = new_capacity;
|
||||
}
|
||||
|
||||
fixups->elements[fixups->count].address = address;
|
||||
fixups->elements[fixups->count++].location = location =
|
||||
rcheevos_patch_address(address, console);
|
||||
fixups->dirty = true;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
const uint8_t* rcheevos_patch_address(unsigned address, int console)
|
||||
{
|
||||
rarch_system_info_t* system = runloop_get_system_info();
|
||||
const void* pointer = NULL;
|
||||
unsigned original_address = address;
|
||||
|
||||
if (console == RC_CONSOLE_NINTENDO)
|
||||
{
|
||||
if (address >= 0x0800 && address < 0x2000)
|
||||
{
|
||||
/* Address in the mirrorred RAM, adjust to real RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", address, address & 0x07ff);
|
||||
address &= 0x07ff;
|
||||
}
|
||||
}
|
||||
else if (console == RC_CONSOLE_GAMEBOY_COLOR)
|
||||
{
|
||||
if (address >= 0xe000 && address <= 0xfdff)
|
||||
{
|
||||
/* Address in the echo RAM, adjust to real RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", address, address - 0x2000);
|
||||
address -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
{
|
||||
/* We have memory descriptors, use it. */
|
||||
const rarch_memory_descriptor_t* desc = NULL;
|
||||
const rarch_memory_descriptor_t* end = NULL;
|
||||
|
||||
/* Patch the address to correctly map it to the mmaps. */
|
||||
if (console == RC_CONSOLE_GAMEBOY_ADVANCE)
|
||||
{
|
||||
if (address < 0x8000)
|
||||
{
|
||||
/* Internal RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x3000000);
|
||||
address += 0x3000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Work RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x2000000 - 0x8000);
|
||||
address += 0x2000000 - 0x8000;
|
||||
}
|
||||
}
|
||||
else if (console == RC_CONSOLE_PC_ENGINE)
|
||||
{
|
||||
if (address < 0x002000)
|
||||
{
|
||||
/* RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1f0000);
|
||||
address += 0x1f0000;
|
||||
}
|
||||
else if (address < 0x012000)
|
||||
{
|
||||
/* CD-ROM RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x100000 - 0x002000);
|
||||
address += 0x100000 - 0x002000;
|
||||
}
|
||||
else if (address < 0x042000)
|
||||
{
|
||||
/* Super System Card RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x0d0000 - 0x012000);
|
||||
address += 0x0d0000 - 0x012000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CD-ROM battery backed RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1ee000 - 0x042000);
|
||||
address += 0x1ee000 - 0x042000;
|
||||
}
|
||||
}
|
||||
else if (console == RC_CONSOLE_SUPER_NINTENDO)
|
||||
{
|
||||
if (address < 0x020000)
|
||||
{
|
||||
/* Work RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x7e0000);
|
||||
address += 0x7e0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x006000 - 0x020000);
|
||||
address += 0x006000 - 0x020000;
|
||||
}
|
||||
}
|
||||
else if (console == RC_CONSOLE_SEGA_CD)
|
||||
{
|
||||
if (address < 0x010000)
|
||||
{
|
||||
/* Work RAM. */
|
||||
address += 0xFF0000;
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Sega CD memory address %X adjusted to %X\n", original_address, address);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CD-ROM peripheral RAM - exposed at virtual address to avoid banking */
|
||||
address += 0x80020000 - 0x010000;
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Sega CD memory address %X adjusted to %X\n", original_address, address);
|
||||
}
|
||||
}
|
||||
|
||||
desc = system->mmaps.descriptors;
|
||||
end = desc + system->mmaps.num_descriptors;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (((desc->core.start ^ address) & desc->core.select) == 0)
|
||||
{
|
||||
pointer = desc->core.ptr;
|
||||
address -= desc->core.start;
|
||||
|
||||
if (desc->disconnect_mask)
|
||||
address = (unsigned)rcheevos_var_reduce(address & desc->disconnect_mask, desc->core.disconnect);
|
||||
|
||||
if (address >= desc->core.len)
|
||||
address -= rcheevos_var_highest_bit(address);
|
||||
|
||||
address += desc->core.offset;
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", original_address, (int)((desc - system->mmaps.descriptors) + 1), address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
break;
|
||||
case 1:
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
break;
|
||||
case 2:
|
||||
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
break;
|
||||
case 3:
|
||||
meminfo.id = RETRO_MEMORY_RTC;
|
||||
break;
|
||||
}
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
|
||||
if (address < meminfo.size)
|
||||
{
|
||||
pointer = meminfo.data;
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* HACK Subtract the correct amount of bytes to reach the save RAM as
|
||||
* it's size is not always set correctly in the core.
|
||||
*/
|
||||
if (i == 0 && console == RC_CONSOLE_NINTENDO)
|
||||
address -= 0x6000;
|
||||
else
|
||||
address -= meminfo.size;
|
||||
}
|
||||
}
|
||||
|
||||
if (pointer == NULL)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "address %X not supported\n", original_address);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (const uint8_t*)pointer + address;
|
||||
}
|
@ -24,6 +24,7 @@
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#define CHEEVOS_MENU_BADGE_LIMIT 256
|
||||
/* TODO/FIXME - public global variables */
|
||||
static uintptr_t cheevos_badge_menu_texture_list[CHEEVOS_MENU_BADGE_LIMIT] = { 0 };
|
||||
|
||||
void cheevos_reset_menu_badges(void)
|
||||
@ -54,7 +55,7 @@ void cheevos_set_menu_badge(int index, const char *badge, bool locked)
|
||||
uintptr_t cheevos_get_menu_badge_texture(int index)
|
||||
{
|
||||
if (index < CHEEVOS_MENU_BADGE_LIMIT)
|
||||
return cheevos_badge_menu_texture_list[index];
|
||||
return cheevos_badge_menu_texture_list[index];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -65,19 +66,23 @@ uintptr_t cheevos_get_badge_texture(const char *badge, bool locked)
|
||||
{
|
||||
char badge_file[24];
|
||||
char fullpath[PATH_MAX_LENGTH];
|
||||
uintptr_t tex;
|
||||
uintptr_t tex = 0;
|
||||
|
||||
if (!badge)
|
||||
return 0;
|
||||
|
||||
snprintf(badge_file, sizeof(badge_file), "%s%s.png", badge, locked ? "_lock" : "");
|
||||
strlcpy(badge_file, badge, sizeof(badge_file));
|
||||
if (locked)
|
||||
strlcat(badge_file, "_lock", sizeof(badge_file));
|
||||
strlcat(badge_file, ".png", sizeof(badge_file));
|
||||
|
||||
fill_pathname_application_special(fullpath,
|
||||
PATH_MAX_LENGTH * sizeof(char),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL);
|
||||
if (!gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
|
||||
tex = 0;
|
||||
|
||||
return tex;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -49,7 +49,7 @@ void rcheevos_get_achievement_state(unsigned index, char* buffer, size_t buffer_
|
||||
|
||||
bool rcheevos_get_description(rcheevos_ctx_desc_t *desc);
|
||||
|
||||
bool rcheevos_apply_cheats(bool *data_bool);
|
||||
void rcheevos_pause_hardcore();
|
||||
|
||||
bool rcheevos_unload(void);
|
||||
|
||||
@ -57,8 +57,6 @@ bool rcheevos_toggle_hardcore_mode(void);
|
||||
|
||||
void rcheevos_test(void);
|
||||
|
||||
bool rcheevos_set_cheats(void);
|
||||
|
||||
void rcheevos_set_support_cheevos(bool state);
|
||||
|
||||
bool rcheevos_get_support_cheevos(void);
|
||||
@ -73,8 +71,6 @@ extern bool rcheevos_loaded;
|
||||
extern bool rcheevos_hardcore_active;
|
||||
extern bool rcheevos_hardcore_paused;
|
||||
extern bool rcheevos_state_loaded_flag;
|
||||
extern int rcheevos_cheats_are_enabled;
|
||||
extern int rcheevos_cheats_were_enabled;
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
314
cheevos/fixup.c
Normal file
314
cheevos/fixup.c
Normal file
@ -0,0 +1,314 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "fixup.h"
|
||||
#include "cheevos.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../core.h"
|
||||
|
||||
#include "../deps/rcheevos/include/rcheevos.h"
|
||||
#include "../deps/rcheevos/include/rconsoles.h"
|
||||
|
||||
static int rcheevos_cmpaddr(const void* e1, const void* e2)
|
||||
{
|
||||
const rcheevos_fixup_t* f1 = (const rcheevos_fixup_t*)e1;
|
||||
const rcheevos_fixup_t* f2 = (const rcheevos_fixup_t*)e2;
|
||||
|
||||
if (f1->address < f2->address)
|
||||
return -1;
|
||||
else if (f1->address > f2->address)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t rcheevos_var_reduce(size_t addr, size_t mask)
|
||||
{
|
||||
while (mask)
|
||||
{
|
||||
size_t tmp = (mask - 1) & ~mask;
|
||||
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
|
||||
mask = (mask & (mask - 1)) >> 1;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static size_t rcheevos_var_highest_bit(size_t n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
|
||||
return n ^ (n >> 1);
|
||||
}
|
||||
|
||||
void rcheevos_fixup_init(rcheevos_fixups_t* fixups)
|
||||
{
|
||||
fixups->elements = NULL;
|
||||
fixups->capacity = fixups->count = 0;
|
||||
fixups->dirty = false;
|
||||
}
|
||||
|
||||
void rcheevos_fixup_destroy(rcheevos_fixups_t* fixups)
|
||||
{
|
||||
CHEEVOS_FREE(fixups->elements);
|
||||
rcheevos_fixup_init(fixups);
|
||||
}
|
||||
|
||||
const uint8_t* rcheevos_fixup_find(
|
||||
rcheevos_fixups_t* fixups, unsigned address, int console)
|
||||
{
|
||||
rcheevos_fixup_t key;
|
||||
rcheevos_fixup_t* found;
|
||||
const uint8_t* location;
|
||||
|
||||
if (fixups->dirty)
|
||||
{
|
||||
qsort(fixups->elements, fixups->count,
|
||||
sizeof(rcheevos_fixup_t), rcheevos_cmpaddr);
|
||||
fixups->dirty = false;
|
||||
}
|
||||
|
||||
key.address = address;
|
||||
found = (rcheevos_fixup_t*)bsearch(&key,
|
||||
fixups->elements, fixups->count,
|
||||
sizeof(rcheevos_fixup_t), rcheevos_cmpaddr);
|
||||
|
||||
if (found)
|
||||
return found->location;
|
||||
|
||||
if (fixups->count == fixups->capacity)
|
||||
{
|
||||
unsigned new_capacity = fixups->capacity == 0 ? 16 : fixups->capacity * 2;
|
||||
rcheevos_fixup_t* new_elements = (rcheevos_fixup_t*)
|
||||
realloc(fixups->elements, new_capacity * sizeof(rcheevos_fixup_t));
|
||||
|
||||
if (!new_elements)
|
||||
return NULL;
|
||||
|
||||
fixups->elements = new_elements;
|
||||
fixups->capacity = new_capacity;
|
||||
}
|
||||
|
||||
fixups->elements[fixups->count].address = address;
|
||||
fixups->elements[fixups->count++].location = location =
|
||||
rcheevos_patch_address(address, console);
|
||||
fixups->dirty = true;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
const uint8_t* rcheevos_patch_address(unsigned address, int console)
|
||||
{
|
||||
rarch_system_info_t* system = runloop_get_system_info();
|
||||
const void* pointer = NULL;
|
||||
unsigned original_address = address;
|
||||
|
||||
switch (console)
|
||||
{
|
||||
case RC_CONSOLE_NINTENDO:
|
||||
if (address >= 0x0800 && address < 0x2000)
|
||||
{
|
||||
/* Address in the mirrorred RAM,
|
||||
* adjust to real RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", address, address & 0x07ff);
|
||||
address &= 0x07ff;
|
||||
}
|
||||
break;
|
||||
case RC_CONSOLE_GAMEBOY_COLOR:
|
||||
if (address >= 0xe000 && address <= 0xfdff)
|
||||
{
|
||||
/* Address in the echo RAM, adjust to real RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", address, address - 0x2000);
|
||||
address -= 0x2000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
{
|
||||
/* We have memory descriptors, use it. */
|
||||
const rarch_memory_descriptor_t* desc = NULL;
|
||||
const rarch_memory_descriptor_t* end = NULL;
|
||||
|
||||
/* Patch the address to correctly map it to the mmaps. */
|
||||
switch (console)
|
||||
{
|
||||
case RC_CONSOLE_GAMEBOY_ADVANCE:
|
||||
if (address < 0x8000)
|
||||
{
|
||||
/* Internal RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x3000000);
|
||||
address += 0x3000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Work RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GBA memory address %X adjusted to %X\n", address, address + 0x2000000 - 0x8000);
|
||||
address += 0x2000000 - 0x8000;
|
||||
}
|
||||
break;
|
||||
case RC_CONSOLE_PC_ENGINE:
|
||||
if (address < 0x002000)
|
||||
{
|
||||
/* RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1f0000);
|
||||
address += 0x1f0000;
|
||||
}
|
||||
else if (address < 0x012000)
|
||||
{
|
||||
/* CD-ROM RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x100000 - 0x002000);
|
||||
address += 0x100000 - 0x002000;
|
||||
}
|
||||
else if (address < 0x042000)
|
||||
{
|
||||
/* Super System Card RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x0d0000 - 0x012000);
|
||||
address += 0x0d0000 - 0x012000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CD-ROM battery backed RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1ee000 - 0x042000);
|
||||
address += 0x1ee000 - 0x042000;
|
||||
}
|
||||
break;
|
||||
case RC_CONSOLE_SUPER_NINTENDO:
|
||||
if (address < 0x020000)
|
||||
{
|
||||
/* Work RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x7e0000);
|
||||
address += 0x7e0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "SNES memory address %X adjusted to %X\n", address, address + 0x006000 - 0x020000);
|
||||
address += 0x006000 - 0x020000;
|
||||
}
|
||||
break;
|
||||
case RC_CONSOLE_SEGA_CD:
|
||||
if (address < 0x010000)
|
||||
{
|
||||
/* Work RAM. */
|
||||
address += 0xFF0000;
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Sega CD memory address %X adjusted to %X\n", original_address, address);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CD-ROM peripheral RAM - exposed at virtual address to avoid banking */
|
||||
address += 0x80020000 - 0x010000;
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Sega CD memory address %X adjusted to %X\n", original_address, address);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
desc = system->mmaps.descriptors;
|
||||
end = desc + system->mmaps.num_descriptors;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (((desc->core.start ^ address) & desc->core.select) == 0)
|
||||
{
|
||||
pointer = desc->core.ptr;
|
||||
address -= desc->core.start;
|
||||
|
||||
if (desc->disconnect_mask)
|
||||
address = (unsigned)rcheevos_var_reduce(
|
||||
address & desc->disconnect_mask, desc->core.disconnect);
|
||||
|
||||
if (address >= desc->core.len)
|
||||
address -= rcheevos_var_highest_bit(address);
|
||||
|
||||
address += desc->core.offset;
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", original_address,
|
||||
(int)((desc - system->mmaps.descriptors) + 1), address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (console == RC_CONSOLE_GAMEBOY_ADVANCE)
|
||||
{
|
||||
/* The RetroAchievements implementation of memory access
|
||||
* for GBA puts the save RAM first,
|
||||
* so the default looping behavior below is backwards.
|
||||
*
|
||||
* If the core doesn't expose a
|
||||
* memory map, say it isn't supported.
|
||||
*/
|
||||
pointer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
break;
|
||||
case 1:
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
break;
|
||||
case 2:
|
||||
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
break;
|
||||
case 3:
|
||||
meminfo.id = RETRO_MEMORY_RTC;
|
||||
break;
|
||||
}
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
|
||||
if (address < meminfo.size)
|
||||
{
|
||||
pointer = meminfo.data;
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* HACK Subtract the correct amount of bytes to
|
||||
* reach the save RAM as its size is not always
|
||||
* set correctly in the core.
|
||||
*/
|
||||
if (i == 0 && console == RC_CONSOLE_NINTENDO)
|
||||
address -= 0x6000;
|
||||
else
|
||||
address -= meminfo.size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pointer)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "address %X not supported\n", original_address);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (const uint8_t*)pointer + address;
|
||||
}
|
@ -349,12 +349,10 @@ static char* rcheevos_unescape_string(const char* string, size_t length)
|
||||
*buffer_it++ = escaped_char;
|
||||
string += 2;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_it++ = *string++;
|
||||
}
|
||||
}
|
||||
*buffer_it = '\0';
|
||||
|
@ -32,7 +32,7 @@ End of setup
|
||||
*****************************************************************************/
|
||||
|
||||
#define RCHEEVOS_TAG "[RCHEEVOS]: "
|
||||
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q != NULL) free(q); } while (0)
|
||||
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q) free(q); } while (0)
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
|
102
config.def.h
102
config.def.h
@ -340,6 +340,9 @@
|
||||
#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
|
||||
|
||||
@ -406,8 +409,11 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OZONE
|
||||
/* Ozone colour theme: 1 == Basic Black */
|
||||
#define DEFAULT_OZONE_COLOR_THEME 1
|
||||
#define DEFAULT_OZONE_COLLAPSE_SIDEBAR false
|
||||
#define DEFAULT_OZONE_TRUNCATE_PLAYLIST_NAME true
|
||||
#define DEFAULT_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME true
|
||||
#define DEFAULT_OZONE_SCROLL_CONTENT_METADATA false
|
||||
#endif
|
||||
|
||||
@ -510,8 +516,10 @@ static const bool menu_show_core_updater = true;
|
||||
static const bool menu_show_legacy_thumbnail_updater = false;
|
||||
static const bool menu_show_sublabels = true;
|
||||
|
||||
#define DEFAULT_MENU_TICKER_TYPE (TICKER_TYPE_BOUNCE)
|
||||
static const float menu_ticker_speed = 1.0f;
|
||||
static const bool menu_scroll_fast = false;
|
||||
|
||||
#define DEFAULT_MENU_TICKER_TYPE (TICKER_TYPE_LOOP)
|
||||
static const float menu_ticker_speed = 2.0f;
|
||||
|
||||
#define DEFAULT_MENU_TICKER_SMOOTH true
|
||||
|
||||
@ -532,11 +540,15 @@ static const bool content_show_music = true;
|
||||
#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
|
||||
static const bool content_show_video = true;
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
#if defined(HAVE_NETWORKING)
|
||||
#if defined(_3DS)
|
||||
static const bool content_show_netplay = false;
|
||||
#else
|
||||
static const bool content_show_netplay = true;
|
||||
#endif
|
||||
#endif
|
||||
static const bool content_show_history = true;
|
||||
static const bool content_show_add = true;
|
||||
static const bool content_show_add = true;
|
||||
static const bool content_show_playlists = true;
|
||||
|
||||
#ifdef HAVE_XMB
|
||||
@ -544,7 +556,11 @@ static const unsigned xmb_alpha_factor = 75;
|
||||
static const unsigned menu_font_color_red = 255;
|
||||
static const unsigned menu_font_color_green = 255;
|
||||
static const unsigned menu_font_color_blue = 255;
|
||||
#ifdef HAVE_ODROIDGO2
|
||||
static const unsigned xmb_menu_layout = 2;
|
||||
#else
|
||||
static const unsigned xmb_menu_layout = 0;
|
||||
#endif
|
||||
static const unsigned xmb_icon_theme = XMB_ICON_THEME_MONOCHROME;
|
||||
static const unsigned xmb_theme = XMB_THEME_ELECTRIC_BLUE;
|
||||
|
||||
@ -599,7 +615,7 @@ static const bool rgui_extended_ascii = false;
|
||||
static const bool default_game_specific_options = true;
|
||||
static const bool default_auto_overrides_enable = true;
|
||||
static const bool default_auto_remaps_enable = true;
|
||||
static const bool default_global_core_options = true;
|
||||
static const bool default_global_core_options = false;
|
||||
static const bool default_auto_shaders_enable = true;
|
||||
|
||||
static const bool default_sort_savefiles_enable = false;
|
||||
@ -792,6 +808,10 @@ static const bool audio_enable_menu_bgm = false;
|
||||
#define DEFAULT_WASAPI_SH_BUFFER_LENGTH -16
|
||||
#endif
|
||||
|
||||
/* Automatically mute audio when fast forward
|
||||
* is enabled */
|
||||
#define DEFAULT_AUDIO_FASTFORWARD_MUTE false
|
||||
|
||||
/* MISC */
|
||||
|
||||
/* Enables displaying the current frames per second. */
|
||||
@ -900,6 +920,23 @@ static const bool savestate_auto_load = false;
|
||||
|
||||
static const bool savestate_thumbnail_enable = false;
|
||||
|
||||
/* When creating save (srm) files, compress
|
||||
* written data */
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
#define DEFAULT_SAVE_FILE_COMPRESSION true
|
||||
#else
|
||||
#define DEFAULT_SAVE_FILE_COMPRESSION false
|
||||
#endif
|
||||
|
||||
/* When creating save state files, compress
|
||||
* written data */
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* TODO/FIXME Apparently this is an issue on UWP for now, so disable it for now */
|
||||
#define DEFAULT_SAVESTATE_FILE_COMPRESSION false
|
||||
#else
|
||||
#define DEFAULT_SAVESTATE_FILE_COMPRESSION true
|
||||
#endif
|
||||
|
||||
/* Slowmotion ratio. */
|
||||
#define DEFAULT_SLOWMOTION_RATIO 3.0
|
||||
|
||||
@ -925,10 +962,27 @@ static const bool stdin_cmd_enable = false;
|
||||
|
||||
static const uint16_t network_remote_base_port = 55400;
|
||||
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
static const bool network_on_demand_thumbnails = true;
|
||||
#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) || defined(OSX) || defined(ANDROID) || defined(IOS))
|
||||
#define DEFAULT_CORE_UPDATER_AUTO_BACKUP true
|
||||
#else
|
||||
static const bool network_on_demand_thumbnails = false;
|
||||
#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
|
||||
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
#define DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS true
|
||||
#else
|
||||
#define DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS false
|
||||
#endif
|
||||
|
||||
/* Number of entries that will be kept in content history playlist file. */
|
||||
@ -939,22 +993,29 @@ static const unsigned default_content_history_size = 200;
|
||||
static const int default_content_favorites_size = 200;
|
||||
|
||||
/* Sort all playlists (apart from histories) alphabetically */
|
||||
static const bool playlist_sort_alphabetical = true;
|
||||
#define DEFAULT_PLAYLIST_SORT_ALPHABETICAL true
|
||||
|
||||
/* File format to use when writing playlists to disk */
|
||||
static const bool playlist_use_old_format = false;
|
||||
#define DEFAULT_PLAYLIST_USE_OLD_FORMAT false
|
||||
|
||||
/* When creating/updating playlists, compress written data */
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
#define DEFAULT_PLAYLIST_COMPRESSION true
|
||||
#else
|
||||
#define DEFAULT_PLAYLIST_COMPRESSION false
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
/* Specify when to display 'core name' inline on playlist entries */
|
||||
static const unsigned playlist_show_inline_core_name = PLAYLIST_INLINE_CORE_DISPLAY_HIST_FAV;
|
||||
#define DEFAULT_PLAYLIST_SHOW_INLINE_CORE_NAME PLAYLIST_INLINE_CORE_DISPLAY_HIST_FAV
|
||||
|
||||
/* Specifies which runtime record to use on playlist sublabels */
|
||||
static const unsigned playlist_sublabel_runtime_type = PLAYLIST_RUNTIME_PER_CORE;
|
||||
#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_HMS
|
||||
|
||||
static const unsigned playlist_entry_remove_enable = PLAYLIST_ENTRY_REMOVE_ENABLE_ALL;
|
||||
#define DEFAULT_PLAYLIST_ENTRY_REMOVE_ENABLE PLAYLIST_ENTRY_REMOVE_ENABLE_ALL
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SCAN_WITHOUT_CORE_MATCH false
|
||||
@ -972,16 +1033,16 @@ static const unsigned playlist_entry_remove_enable = PLAYLIST_ENTRY_REMOVE_ENABL
|
||||
/* Show Menu start-up screen on boot. */
|
||||
#define DEFAULT_MENU_SHOW_START_SCREEN true
|
||||
|
||||
/* Default scale factor for non-frambuffer-based menu
|
||||
* drivers and menu widgets */
|
||||
/* Default scale factor for non-frambuffer-based display
|
||||
* drivers and display widgets */
|
||||
#define DEFAULT_MENU_SCALE_FACTOR 1.0f
|
||||
/* Specifies whether menu widgets should be scaled
|
||||
/* 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 menu widgets when widget
|
||||
/* 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 menu widgets when widget
|
||||
/* Default scale factor for display widgets when widget
|
||||
* auto scaling is disabled (windowed mode) */
|
||||
#define DEFAULT_MENU_WIDGET_SCALE_FACTOR_WINDOWED 1.0f
|
||||
|
||||
@ -1033,6 +1094,8 @@ static const unsigned input_bind_timeout = 5;
|
||||
|
||||
static const unsigned input_bind_hold = 2;
|
||||
|
||||
#define DEFAULT_INPUT_HOTKEY_BLOCK_DELAY 5
|
||||
|
||||
static const unsigned gfx_thumbnails_default = 3;
|
||||
|
||||
static const unsigned menu_left_thumbnails_default = 0;
|
||||
@ -1040,7 +1103,8 @@ static const unsigned menu_left_thumbnails_default = 0;
|
||||
static const unsigned gfx_thumbnail_upscale_threshold = 0;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
static const unsigned menu_timedate_style = MENU_TIMEDATE_STYLE_DM_HM;
|
||||
#define DEFAULT_MENU_TIMEDATE_STYLE MENU_TIMEDATE_STYLE_DDMM_HM
|
||||
#define DEFAULT_MENU_TIMEDATE_DATE_SEPARATOR MENU_TIMEDATE_DATE_SEPARATOR_HYPHEN
|
||||
#endif
|
||||
|
||||
static const bool xmb_vertical_thumbnails = false;
|
||||
|
377
configuration.c
377
configuration.c
@ -314,276 +314,276 @@ enum midi_driver_enum
|
||||
};
|
||||
|
||||
#if defined(HAVE_METAL)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
|
||||
#elif defined(HAVE_VITA2D)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VITA2D;
|
||||
#elif (defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__)) && !defined(__WINRT__)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
|
||||
#elif defined(HAVE_OPENGL_CORE)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL_CORE;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VITA2D;
|
||||
#elif (defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__)) && !defined(__WINRT__) && !defined(__HAIKU__)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
|
||||
#elif defined(HAVE_OPENGL_CORE) && !defined(__HAIKU__)
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL_CORE;
|
||||
#elif defined(HAVE_OPENGL1)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL1;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL1;
|
||||
#elif defined(GEKKO)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WII;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WII;
|
||||
#elif defined(WIIU)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WIIU;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WIIU;
|
||||
#elif defined(XENON)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_XENON360;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_XENON360;
|
||||
#elif defined(HAVE_D3D11)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D11;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D11;
|
||||
#elif defined(HAVE_D3D12)
|
||||
/* FIXME/WARNING: DX12 performance on Xbox is horrible for
|
||||
/* FIXME/WARNING: DX12 performance on Xbox is horrible for
|
||||
* some reason. For now, we will default to D3D11 when possible. */
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D12;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D12;
|
||||
#elif defined(HAVE_D3D10)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D10;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D10;
|
||||
#elif defined(HAVE_D3D9)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D9;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D9;
|
||||
#elif defined(HAVE_D3D8)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D8;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D8;
|
||||
#elif defined(HAVE_VG)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VG;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VG;
|
||||
#elif defined(PSP)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PSP1;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PSP1;
|
||||
#elif defined(PS2)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PS2;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PS2;
|
||||
#elif defined(_3DS)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_CTR;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_CTR;
|
||||
#elif defined(SWITCH)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SWITCH;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SWITCH;
|
||||
#elif defined(HAVE_XVIDEO)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_XVIDEO;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_XVIDEO;
|
||||
#elif defined(HAVE_SDL) && !defined(HAVE_SDL_DINGUX)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL;
|
||||
#elif defined(HAVE_SDL2)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL2;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL2;
|
||||
#elif defined(HAVE_SDL_DINGUX)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_DINGUX;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_DINGUX;
|
||||
#elif defined(_WIN32) && !defined(_XBOX)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GDI;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GDI;
|
||||
#elif defined(DJGPP)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VGA;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VGA;
|
||||
#elif defined(HAVE_FPGA)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_FPGA;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_FPGA;
|
||||
#elif defined(HAVE_DYLIB) && !defined(ANDROID)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_EXT;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_EXT;
|
||||
#else
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_NULL;
|
||||
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS3;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS3;
|
||||
#elif defined(XENON)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_XENON360;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_XENON360;
|
||||
#elif defined(GEKKO)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WII;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WII;
|
||||
#elif defined(WIIU)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WIIU;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WIIU;
|
||||
#elif defined(PSP) || defined(VITA) || defined(ORBIS)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PSP;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PSP;
|
||||
#elif defined(PS2)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS2;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS2;
|
||||
#elif defined(_3DS)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_CTR;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_CTR;
|
||||
#elif defined(SWITCH)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SWITCH;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SWITCH;
|
||||
#elif defined(HAVE_PULSE)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PULSE;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PULSE;
|
||||
#elif defined(HAVE_ALSA) && defined(HAVE_VIDEOCORE)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSATHREAD;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSATHREAD;
|
||||
#elif defined(HAVE_ALSA)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSA;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSA;
|
||||
#elif defined(HAVE_TINYALSA)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_TINYALSA;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_TINYALSA;
|
||||
#elif defined(HAVE_AUDIOIO)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AUDIOIO;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AUDIOIO;
|
||||
#elif defined(HAVE_OSS)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_OSS;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_OSS;
|
||||
#elif defined(HAVE_JACK)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_JACK;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_JACK;
|
||||
#elif defined(HAVE_COREAUDIO) && !defined(HAVE_COCOA_METAL)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO;
|
||||
#elif defined(HAVE_COREAUDIO3)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO3;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO3;
|
||||
#elif defined(HAVE_XAUDIO)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_XAUDIO;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_XAUDIO;
|
||||
#elif defined(HAVE_DSOUND)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_DSOUND;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_DSOUND;
|
||||
#elif defined(HAVE_WASAPI)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WASAPI;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WASAPI;
|
||||
#elif defined(HAVE_AL)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AL;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AL;
|
||||
#elif defined(HAVE_SL)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SL;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SL;
|
||||
#elif defined(EMSCRIPTEN)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_RWEBAUDIO;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_RWEBAUDIO;
|
||||
#elif defined(HAVE_SDL)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL;
|
||||
#elif defined(HAVE_SDL2)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL2;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL2;
|
||||
#elif defined(HAVE_RSOUND)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_RSOUND;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_RSOUND;
|
||||
#elif defined(HAVE_ROAR)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ROAR;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ROAR;
|
||||
#elif defined(HAVE_DYLIB) && !defined(ANDROID)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_EXT;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_EXT;
|
||||
#else
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_NULL;
|
||||
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(PSP) || defined(EMSCRIPTEN)
|
||||
static enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_CC;
|
||||
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_CC;
|
||||
#else
|
||||
static enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_SINC;
|
||||
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_SINC;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FFMPEG)
|
||||
static enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_FFMPEG;
|
||||
static const enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_FFMPEG;
|
||||
#else
|
||||
static enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_NULL;
|
||||
static const enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINMM
|
||||
static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_WINMM;
|
||||
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_WINMM;
|
||||
#elif defined(HAVE_ALSA) && !defined(HAVE_HAKCHI) && !defined(HAVE_SEGAM)
|
||||
static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_ALSA;
|
||||
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_ALSA;
|
||||
#else
|
||||
static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_NULL;
|
||||
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UWP;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UWP;
|
||||
#elif defined(XENON)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XENON360;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XENON360;
|
||||
#elif defined(_XBOX360) || defined(_XBOX) || defined(HAVE_XINPUT2) || defined(HAVE_XINPUT_XBOX1)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XINPUT;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XINPUT;
|
||||
#elif defined(ANDROID)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_ANDROID;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_ANDROID;
|
||||
#elif defined(EMSCRIPTEN) && defined(HAVE_SDL2)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
|
||||
#elif defined(EMSCRIPTEN)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_RWEBINPUT;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_RWEBINPUT;
|
||||
#elif defined(_WIN32) && defined(HAVE_DINPUT)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DINPUT;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DINPUT;
|
||||
#elif defined(_WIN32) && !defined(HAVE_DINPUT) && _WIN32_WINNT >= 0x0501
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WINRAW;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WINRAW;
|
||||
#elif defined(ORBIS)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS4;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS4;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS3;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS3;
|
||||
#elif defined(PSP) || defined(VITA)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PSP;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PSP;
|
||||
#elif defined(PS2)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS2;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS2;
|
||||
#elif defined(_3DS)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_CTR;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_CTR;
|
||||
#elif defined(SWITCH)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SWITCH;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SWITCH;
|
||||
#elif defined(GEKKO)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WII;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WII;
|
||||
#elif defined(WIIU)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WIIU;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WIIU;
|
||||
#elif defined(HAVE_X11)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_X;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_X;
|
||||
#elif defined(HAVE_UDEV)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UDEV;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UDEV;
|
||||
#elif defined(__linux__) && !defined(ANDROID)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_LINUXRAW;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_LINUXRAW;
|
||||
#elif defined(HAVE_WAYLAND)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WAYLAND;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WAYLAND;
|
||||
#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_COCOA;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_COCOA;
|
||||
#elif defined(__QNX__)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_QNX;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_QNX;
|
||||
#elif defined(HAVE_SDL)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL;
|
||||
#elif defined(HAVE_SDL2)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
|
||||
#elif defined(DJGPP)
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DOS;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DOS;
|
||||
#else
|
||||
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_NULL;
|
||||
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS3;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS3;
|
||||
#elif defined(HAVE_XINPUT)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XINPUT;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XINPUT;
|
||||
#elif defined(GEKKO)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_GX;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_GX;
|
||||
#elif defined(WIIU)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WIIU;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WIIU;
|
||||
#elif defined(_XBOX)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XDK;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XDK;
|
||||
#elif defined(ORBIS)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS4;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS4;
|
||||
#elif defined(PSP) || defined(VITA)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PSP;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PSP;
|
||||
#elif defined(PS2)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS2;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS2;
|
||||
#elif defined(_3DS)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_CTR;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_CTR;
|
||||
#elif defined(SWITCH)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SWITCH;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SWITCH;
|
||||
#elif defined(HAVE_DINPUT)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DINPUT;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DINPUT;
|
||||
#elif defined(HAVE_UDEV)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_UDEV;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_UDEV;
|
||||
#elif defined(__linux) && !defined(ANDROID)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_LINUXRAW;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_LINUXRAW;
|
||||
#elif defined(ANDROID)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_ANDROID;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_ANDROID;
|
||||
#elif defined(HAVE_SDL) || defined(HAVE_SDL2)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SDL;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SDL;
|
||||
#elif defined(DJGPP)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DOS;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DOS;
|
||||
#elif defined(IOS)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_MFI;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_MFI;
|
||||
#elif defined(HAVE_HID)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_HID;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_HID;
|
||||
#elif defined(__QNX__)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_QNX;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_QNX;
|
||||
#elif defined(EMSCRIPTEN)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_RWEBPAD;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_RWEBPAD;
|
||||
#else
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_NULL;
|
||||
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_V4L2)
|
||||
static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_V4L2;
|
||||
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_V4L2;
|
||||
#elif defined(EMSCRIPTEN)
|
||||
static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_RWEBCAM;
|
||||
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_RWEBCAM;
|
||||
#elif defined(ANDROID)
|
||||
static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_ANDROID;
|
||||
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_ANDROID;
|
||||
#else
|
||||
static enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_NULL;
|
||||
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LAKKA)
|
||||
static enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_CONNMANCTL;
|
||||
static const enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_CONNMANCTL;
|
||||
#else
|
||||
static enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_NULL;
|
||||
static const enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
static enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_ANDROID;
|
||||
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_ANDROID;
|
||||
#else
|
||||
static enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL;
|
||||
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(_3DS) && defined(HAVE_RGUI)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
|
||||
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
|
||||
#else
|
||||
#if defined(HAVE_MATERIALUI) && defined(RARCH_MOBILE)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_MATERIALUI;
|
||||
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_MATERIALUI;
|
||||
#elif defined(HAVE_OZONE)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_OZONE;
|
||||
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_OZONE;
|
||||
#elif defined(HAVE_XMB) && !defined(_XBOX)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XMB;
|
||||
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XMB;
|
||||
#elif defined(HAVE_RGUI)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
|
||||
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
|
||||
#else
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL;
|
||||
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1180,7 +1180,8 @@ static struct config_array_setting *populate_settings_array(settings_t *settings
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct config_path_setting *populate_settings_path(settings_t *settings, int *size)
|
||||
static struct config_path_setting *populate_settings_path(
|
||||
settings_t *settings, int *size)
|
||||
{
|
||||
unsigned count = 0;
|
||||
struct config_path_setting *tmp = (struct config_path_setting*)calloc(1, (*size + 1) * sizeof(struct config_path_setting));
|
||||
@ -1326,7 +1327,8 @@ static struct config_path_setting *populate_settings_path(settings_t *settings,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct config_bool_setting *populate_settings_bool(settings_t *settings, int *size)
|
||||
static struct config_bool_setting *populate_settings_bool(
|
||||
settings_t *settings, int *size)
|
||||
{
|
||||
struct config_bool_setting *tmp = (struct config_bool_setting*)calloc(1, (*size + 1) * sizeof(struct config_bool_setting));
|
||||
unsigned count = 0;
|
||||
@ -1343,7 +1345,6 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("desktop_menu_enable", &settings->bools.desktop_menu_enable, true, DEFAULT_DESKTOP_MENU_ENABLE, false);
|
||||
SETTING_BOOL("video_gpu_record", &settings->bools.video_gpu_record, true, DEFAULT_GPU_RECORD, false);
|
||||
SETTING_BOOL("input_remap_binds_enable", &settings->bools.input_remap_binds_enable, true, true, false);
|
||||
SETTING_BOOL("all_users_control_menu", &settings->bools.input_all_users_control_menu, true, DEFAULT_ALL_USERS_CONTROL_MENU, false);
|
||||
SETTING_BOOL("menu_swap_ok_cancel_buttons", &settings->bools.input_menu_swap_ok_cancel_buttons, true, DEFAULT_MENU_SWAP_OK_CANCEL_BUTTONS, false);
|
||||
#ifdef HAVE_NETWORKING
|
||||
SETTING_BOOL("netplay_public_announce", &settings->bools.netplay_public_announce, true, DEFAULT_NETPLAY_PUBLIC_ANNOUNCE, false);
|
||||
@ -1369,7 +1370,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("netplay_request_device_p14", &settings->bools.netplay_request_devices[13], true, false, false);
|
||||
SETTING_BOOL("netplay_request_device_p15", &settings->bools.netplay_request_devices[14], true, false, false);
|
||||
SETTING_BOOL("netplay_request_device_p16", &settings->bools.netplay_request_devices[15], true, false, false);
|
||||
SETTING_BOOL("network_on_demand_thumbnails", &settings->bools.network_on_demand_thumbnails, true, network_on_demand_thumbnails, false);
|
||||
SETTING_BOOL("network_on_demand_thumbnails", &settings->bools.network_on_demand_thumbnails, true, DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS, false);
|
||||
#endif
|
||||
SETTING_BOOL("input_descriptor_label_show", &settings->bools.input_descriptor_label_show, true, input_descriptor_label_show, false);
|
||||
SETTING_BOOL("input_descriptor_hide_unbound", &settings->bools.input_descriptor_hide_unbound, true, input_descriptor_hide_unbound, false);
|
||||
@ -1402,6 +1403,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("video_crop_overscan", &settings->bools.video_crop_overscan, true, DEFAULT_CROP_OVERSCAN, false);
|
||||
SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, DEFAULT_SCALE_INTEGER, false);
|
||||
SETTING_BOOL("video_smooth", &settings->bools.video_smooth, true, DEFAULT_VIDEO_SMOOTH, false);
|
||||
SETTING_BOOL("video_ctx_scaling", &settings->bools.video_ctx_scaling, true, DEFAULT_VIDEO_CTX_SCALING, false);
|
||||
SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, DEFAULT_FORCE_ASPECT, false);
|
||||
SETTING_BOOL("video_threaded", video_driver_get_threaded(), true, DEFAULT_VIDEO_THREADED, false);
|
||||
SETTING_BOOL("video_shared_context", &settings->bools.video_shared_context, true, DEFAULT_VIDEO_SHARED_CONTEXT, false);
|
||||
@ -1431,9 +1433,12 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
#ifdef HAVE_AUDIOMIXER
|
||||
SETTING_BOOL("audio_mixer_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MIXER_MUTE_ENABLE), true, false, false);
|
||||
#endif
|
||||
SETTING_BOOL("audio_fastforward_mute", &settings->bools.audio_fastforward_mute, true, DEFAULT_AUDIO_FASTFORWARD_MUTE, false);
|
||||
SETTING_BOOL("location_allow", &settings->bools.location_allow, true, false, false);
|
||||
SETTING_BOOL("video_font_enable", &settings->bools.video_font_enable, true, DEFAULT_FONT_ENABLE, false);
|
||||
SETTING_BOOL("core_updater_auto_extract_archive", &settings->bools.network_buildbot_auto_extract_archive, true, true, false);
|
||||
SETTING_BOOL("core_updater_auto_extract_archive", &settings->bools.network_buildbot_auto_extract_archive, true, DEFAULT_NETWORK_BUILDBOT_AUTO_EXTRACT_ARCHIVE, false);
|
||||
SETTING_BOOL("core_updater_show_experimental_cores", &settings->bools.network_buildbot_show_experimental_cores, true, DEFAULT_NETWORK_BUILDBOT_SHOW_EXPERIMENTAL_CORES, false);
|
||||
SETTING_BOOL("core_updater_auto_backup", &settings->bools.core_updater_auto_backup, true, DEFAULT_CORE_UPDATER_AUTO_BACKUP, false);
|
||||
SETTING_BOOL("camera_allow", &settings->bools.camera_allow, true, false, false);
|
||||
SETTING_BOOL("discord_allow", &settings->bools.discord_enable, true, false, false);
|
||||
#if defined(VITA)
|
||||
@ -1452,7 +1457,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
#ifdef HAVE_MENU
|
||||
SETTING_BOOL("menu_unified_controls", &settings->bools.menu_unified_controls, true, false, false);
|
||||
SETTING_BOOL("menu_throttle_framerate", &settings->bools.menu_throttle_framerate, true, true, false);
|
||||
SETTING_BOOL("menu_linear_filter", &settings->bools.menu_linear_filter, true, true, false);
|
||||
SETTING_BOOL("menu_linear_filter", &settings->bools.menu_linear_filter, true, DEFAULT_VIDEO_SMOOTH, false);
|
||||
SETTING_BOOL("menu_horizontal_animation", &settings->bools.menu_horizontal_animation, true, DEFAULT_MENU_HORIZONTAL_ANIMATION, false);
|
||||
SETTING_BOOL("menu_pause_libretro", &settings->bools.menu_pause_libretro, true, true, false);
|
||||
SETTING_BOOL("menu_savestate_resume", &settings->bools.menu_savestate_resume, true, menu_savestate_resume, false);
|
||||
@ -1465,6 +1470,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("menu_show_sublabels", &settings->bools.menu_show_sublabels, true, menu_show_sublabels, false);
|
||||
SETTING_BOOL("menu_dynamic_wallpaper_enable", &settings->bools.menu_dynamic_wallpaper_enable, true, false, false);
|
||||
SETTING_BOOL("menu_ticker_smooth", &settings->bools.menu_ticker_smooth, true, DEFAULT_MENU_TICKER_SMOOTH, false);
|
||||
SETTING_BOOL("menu_scroll_fast", &settings->bools.menu_scroll_fast, true, false, false);
|
||||
SETTING_BOOL("settings_show_drivers", &settings->bools.settings_show_drivers, true, DEFAULT_SETTINGS_SHOW_DRIVERS, false);
|
||||
SETTING_BOOL("settings_show_video", &settings->bools.settings_show_video, true, DEFAULT_SETTINGS_SHOW_VIDEO, false);
|
||||
SETTING_BOOL("settings_show_audio", &settings->bools.settings_show_audio, true, DEFAULT_SETTINGS_SHOW_AUDIO, false);
|
||||
@ -1585,6 +1591,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("cheevos_verbose_enable", &settings->bools.cheevos_verbose_enable, true, false, false);
|
||||
SETTING_BOOL("cheevos_auto_screenshot", &settings->bools.cheevos_auto_screenshot, true, false, false);
|
||||
SETTING_BOOL("cheevos_badges_enable", &settings->bools.cheevos_badges_enable, true, false, false);
|
||||
SETTING_BOOL("cheevos_start_active", &settings->bools.cheevos_start_active, true, false, false);
|
||||
#endif
|
||||
#ifdef HAVE_OVERLAY
|
||||
SETTING_BOOL("input_overlay_enable", &settings->bools.input_overlay_enable, true, config_overlay_enable_default(), false);
|
||||
@ -1612,6 +1619,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("savestate_auto_save", &settings->bools.savestate_auto_save, true, savestate_auto_save, false);
|
||||
SETTING_BOOL("savestate_auto_load", &settings->bools.savestate_auto_load, true, savestate_auto_load, false);
|
||||
SETTING_BOOL("savestate_thumbnail_enable", &settings->bools.savestate_thumbnail_enable, true, savestate_thumbnail_enable, false);
|
||||
SETTING_BOOL("save_file_compression", &settings->bools.save_file_compression, true, DEFAULT_SAVE_FILE_COMPRESSION, false);
|
||||
SETTING_BOOL("savestate_file_compression", &settings->bools.savestate_file_compression, true, DEFAULT_SAVESTATE_FILE_COMPRESSION, false);
|
||||
SETTING_BOOL("history_list_enable", &settings->bools.history_list_enable, true, DEFAULT_HISTORY_LIST_ENABLE, false);
|
||||
SETTING_BOOL("playlist_entry_rename", &settings->bools.playlist_entry_rename, true, DEFAULT_PLAYLIST_ENTRY_RENAME, false);
|
||||
SETTING_BOOL("game_specific_options", &settings->bools.game_specific_options, true, default_game_specific_options, false);
|
||||
@ -1646,11 +1655,12 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("video_3ds_lcd_bottom", &settings->bools.video_3ds_lcd_bottom, true, video_3ds_lcd_bottom, false);
|
||||
#endif
|
||||
|
||||
SETTING_BOOL("playlist_use_old_format", &settings->bools.playlist_use_old_format, true, playlist_use_old_format, false);
|
||||
SETTING_BOOL("playlist_use_old_format", &settings->bools.playlist_use_old_format, true, DEFAULT_PLAYLIST_USE_OLD_FORMAT, false);
|
||||
SETTING_BOOL("playlist_compression", &settings->bools.playlist_compression, true, DEFAULT_PLAYLIST_COMPRESSION, false);
|
||||
SETTING_BOOL("content_runtime_log", &settings->bools.content_runtime_log, true, DEFAULT_CONTENT_RUNTIME_LOG, false);
|
||||
SETTING_BOOL("content_runtime_log_aggregate", &settings->bools.content_runtime_log_aggregate, true, DEFAULT_CONTENT_RUNTIME_LOG_AGGREGATE, false);
|
||||
SETTING_BOOL("playlist_show_sublabels", &settings->bools.playlist_show_sublabels, true, DEFAULT_PLAYLIST_SHOW_SUBLABELS, false);
|
||||
SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, playlist_sort_alphabetical, false);
|
||||
SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, DEFAULT_PLAYLIST_SORT_ALPHABETICAL, false);
|
||||
SETTING_BOOL("playlist_fuzzy_archive_match", &settings->bools.playlist_fuzzy_archive_match, true, DEFAULT_PLAYLIST_FUZZY_ARCHIVE_MATCH, false);
|
||||
|
||||
SETTING_BOOL("quit_press_twice", &settings->bools.quit_press_twice, true, DEFAULT_QUIT_PRESS_TWICE, false);
|
||||
@ -1660,6 +1670,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
#ifdef HAVE_OZONE
|
||||
SETTING_BOOL("ozone_collapse_sidebar", &settings->bools.ozone_collapse_sidebar, true, DEFAULT_OZONE_COLLAPSE_SIDEBAR, false);
|
||||
SETTING_BOOL("ozone_truncate_playlist_name", &settings->bools.ozone_truncate_playlist_name, true, DEFAULT_OZONE_TRUNCATE_PLAYLIST_NAME, false);
|
||||
SETTING_BOOL("ozone_sort_after_truncate_playlist_name", &settings->bools.ozone_sort_after_truncate_playlist_name, true, DEFAULT_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME, false);
|
||||
SETTING_BOOL("ozone_scroll_content_metadata",&settings->bools.ozone_scroll_content_metadata, true, DEFAULT_OZONE_SCROLL_CONTENT_METADATA, false);
|
||||
#endif
|
||||
SETTING_BOOL("log_to_file", &settings->bools.log_to_file, true, DEFAULT_LOG_TO_FILE, false);
|
||||
@ -1673,7 +1684,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct config_float_setting *populate_settings_float(settings_t *settings, int *size)
|
||||
static struct config_float_setting *populate_settings_float(
|
||||
settings_t *settings, int *size)
|
||||
{
|
||||
unsigned count = 0;
|
||||
struct config_float_setting *tmp = (struct config_float_setting*)calloc(1, (*size + 1) * sizeof(struct config_float_setting));
|
||||
@ -1694,11 +1706,15 @@ static struct config_float_setting *populate_settings_float(settings_t *settings
|
||||
#ifdef HAVE_OVERLAY
|
||||
SETTING_FLOAT("input_overlay_opacity", &settings->floats.input_overlay_opacity, true, DEFAULT_INPUT_OVERLAY_OPACITY, false);
|
||||
SETTING_FLOAT("input_overlay_scale", &settings->floats.input_overlay_scale, true, 1.0f, false);
|
||||
SETTING_FLOAT("input_overlay_center_x", &settings->floats.input_overlay_center_x, true, 0.5f, false);
|
||||
SETTING_FLOAT("input_overlay_center_y", &settings->floats.input_overlay_center_y, true, 0.5f, false);
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
SETTING_FLOAT("menu_scale_factor", &settings->floats.menu_scale_factor, true, DEFAULT_MENU_SCALE_FACTOR, false);
|
||||
SETTING_FLOAT("menu_widget_scale_factor", &settings->floats.menu_widget_scale_factor, true, DEFAULT_MENU_WIDGET_SCALE_FACTOR, false);
|
||||
#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
|
||||
SETTING_FLOAT("menu_widget_scale_factor_windowed", &settings->floats.menu_widget_scale_factor_windowed, true, DEFAULT_MENU_WIDGET_SCALE_FACTOR_WINDOWED, false);
|
||||
#endif
|
||||
SETTING_FLOAT("menu_wallpaper_opacity", &settings->floats.menu_wallpaper_opacity, true, menu_wallpaper_opacity, false);
|
||||
SETTING_FLOAT("menu_framebuffer_opacity", &settings->floats.menu_framebuffer_opacity, true, menu_framebuffer_opacity, false);
|
||||
SETTING_FLOAT("menu_footer_opacity", &settings->floats.menu_footer_opacity, true, menu_footer_opacity, false);
|
||||
@ -1721,7 +1737,8 @@ static struct config_float_setting *populate_settings_float(settings_t *settings
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct config_uint_setting *populate_settings_uint(settings_t *settings, int *size)
|
||||
static struct config_uint_setting *populate_settings_uint(
|
||||
settings_t *settings, int *size)
|
||||
{
|
||||
unsigned count = 0;
|
||||
struct config_uint_setting *tmp = (struct config_uint_setting*)calloc(1, (*size + 1) * sizeof(struct config_uint_setting));
|
||||
@ -1743,6 +1760,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("input_max_users", input_driver_get_uint(INPUT_ACTION_MAX_USERS), true, input_max_users, false);
|
||||
SETTING_UINT("fps_update_interval", &settings->uints.fps_update_interval, true, DEFAULT_FPS_UPDATE_INTERVAL, false);
|
||||
SETTING_UINT("input_menu_toggle_gamepad_combo", &settings->uints.input_menu_toggle_gamepad_combo, true, menu_toggle_gamepad_combo, false);
|
||||
SETTING_UINT("input_hotkey_block_delay", &settings->uints.input_hotkey_block_delay, true, DEFAULT_INPUT_HOTKEY_BLOCK_DELAY, false);
|
||||
#ifdef GEKKO
|
||||
SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false);
|
||||
#endif
|
||||
@ -1782,7 +1800,8 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("menu_thumbnails", &settings->uints.gfx_thumbnails, true, gfx_thumbnails_default, false);
|
||||
SETTING_UINT("menu_left_thumbnails", &settings->uints.menu_left_thumbnails, true, menu_left_thumbnails_default, false);
|
||||
SETTING_UINT("menu_thumbnail_upscale_threshold", &settings->uints.gfx_thumbnail_upscale_threshold, true, gfx_thumbnail_upscale_threshold, false);
|
||||
SETTING_UINT("menu_timedate_style", &settings->uints.menu_timedate_style, true, menu_timedate_style, false);
|
||||
SETTING_UINT("menu_timedate_style", &settings->uints.menu_timedate_style, true, DEFAULT_MENU_TIMEDATE_STYLE, false);
|
||||
SETTING_UINT("menu_timedate_date_separator", &settings->uints.menu_timedate_date_separator, true, DEFAULT_MENU_TIMEDATE_DATE_SEPARATOR, false);
|
||||
SETTING_UINT("menu_ticker_type", &settings->uints.menu_ticker_type, true, DEFAULT_MENU_TICKER_TYPE, false);
|
||||
#ifdef HAVE_RGUI
|
||||
SETTING_UINT("rgui_menu_color_theme", &settings->uints.menu_rgui_color_theme, true, DEFAULT_RGUI_COLOR_THEME, false);
|
||||
@ -1823,7 +1842,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("materialui_landscape_layout_optimization", &settings->uints.menu_materialui_landscape_layout_optimization, true, DEFAULT_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION, false);
|
||||
SETTING_UINT("menu_shader_pipeline", &settings->uints.menu_xmb_shader_pipeline, true, DEFAULT_MENU_SHADER_PIPELINE, false);
|
||||
#ifdef HAVE_OZONE
|
||||
SETTING_UINT("ozone_menu_color_theme", &settings->uints.menu_ozone_color_theme, true, 1, false);
|
||||
SETTING_UINT("ozone_menu_color_theme", &settings->uints.menu_ozone_color_theme, true, DEFAULT_OZONE_COLOR_THEME, false);
|
||||
#endif
|
||||
#endif
|
||||
SETTING_UINT("audio_out_rate", &settings->uints.audio_out_rate, true, DEFAULT_OUTPUT_RATE, false);
|
||||
@ -1890,18 +1909,21 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
SETTING_UINT("playlist_entry_remove_enable", &settings->uints.playlist_entry_remove_enable, true, playlist_entry_remove_enable, false);
|
||||
SETTING_UINT("playlist_show_inline_core_name", &settings->uints.playlist_show_inline_core_name, true, playlist_show_inline_core_name, false);
|
||||
SETTING_UINT("playlist_sublabel_runtime_type", &settings->uints.playlist_sublabel_runtime_type, true, playlist_sublabel_runtime_type, false);
|
||||
SETTING_UINT("playlist_entry_remove_enable", &settings->uints.playlist_entry_remove_enable, true, DEFAULT_PLAYLIST_ENTRY_REMOVE_ENABLE, false);
|
||||
SETTING_UINT("playlist_show_inline_core_name", &settings->uints.playlist_show_inline_core_name, true, DEFAULT_PLAYLIST_SHOW_INLINE_CORE_NAME, false);
|
||||
SETTING_UINT("playlist_sublabel_runtime_type", &settings->uints.playlist_sublabel_runtime_type, true, DEFAULT_PLAYLIST_SUBLABEL_RUNTIME_TYPE, false);
|
||||
SETTING_UINT("playlist_sublabel_last_played_style", &settings->uints.playlist_sublabel_last_played_style, true, DEFAULT_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE, false);
|
||||
#endif
|
||||
|
||||
SETTING_UINT("core_updater_auto_backup_history_size", &settings->uints.core_updater_auto_backup_history_size, true, DEFAULT_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE, false);
|
||||
|
||||
*size = count;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct config_size_setting *populate_settings_size(settings_t *settings, int *size)
|
||||
static struct config_size_setting *populate_settings_size(
|
||||
settings_t *settings, int *size)
|
||||
{
|
||||
unsigned count = 0;
|
||||
struct config_size_setting *tmp = (struct config_size_setting*)calloc((*size + 1), sizeof(struct config_size_setting));
|
||||
@ -1916,7 +1938,8 @@ static struct config_size_setting *populate_settings_size(settings_t *settings,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct config_int_setting *populate_settings_int(settings_t *settings, int *size)
|
||||
static struct config_int_setting *populate_settings_int(
|
||||
settings_t *settings, int *size)
|
||||
{
|
||||
unsigned count = 0;
|
||||
struct config_int_setting *tmp = (struct config_int_setting*)calloc((*size + 1), sizeof(struct config_int_setting));
|
||||
@ -2492,20 +2515,30 @@ static bool check_menu_driver_compatibility(settings_t *settings)
|
||||
return true;
|
||||
|
||||
/* TODO/FIXME - maintenance hazard */
|
||||
if (string_is_equal(video_driver, "d3d9") ||
|
||||
string_is_equal(video_driver, "d3d10") ||
|
||||
string_is_equal(video_driver, "d3d11") ||
|
||||
string_is_equal(video_driver, "d3d12") ||
|
||||
if (string_starts_with(video_driver, "d3d"))
|
||||
if (
|
||||
string_is_equal(video_driver, "d3d9") ||
|
||||
string_is_equal(video_driver, "d3d10") ||
|
||||
string_is_equal(video_driver, "d3d11") ||
|
||||
string_is_equal(video_driver, "d3d12")
|
||||
)
|
||||
return true;
|
||||
if (string_starts_with(video_driver, "gl"))
|
||||
if (
|
||||
string_is_equal(video_driver, "gl") ||
|
||||
string_is_equal(video_driver, "gl1") ||
|
||||
string_is_equal(video_driver, "glcore")
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
string_is_equal(video_driver, "caca") ||
|
||||
string_is_equal(video_driver, "gdi") ||
|
||||
string_is_equal(video_driver, "gl") ||
|
||||
string_is_equal(video_driver, "gl1") ||
|
||||
string_is_equal(video_driver, "gx2") ||
|
||||
string_is_equal(video_driver, "vulkan") ||
|
||||
string_is_equal(video_driver, "glcore") ||
|
||||
string_is_equal(video_driver, "metal") ||
|
||||
string_is_equal(video_driver, "ctr") ||
|
||||
string_is_equal(video_driver, "vita2d"))
|
||||
string_is_equal(video_driver, "vita2d")
|
||||
)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -2666,7 +2699,7 @@ static config_file_t *open_default_config_file(void)
|
||||
|
||||
skeleton_conf[0] = '\0';
|
||||
|
||||
/* Build a retroarch.cfg path from the
|
||||
/* Build a retroarch.cfg path from the
|
||||
* global config directory (/etc). */
|
||||
fill_pathname_join(skeleton_conf, GLOBAL_CONFIG_DIR,
|
||||
file_path_str(FILE_PATH_MAIN_CONFIG), path_size);
|
||||
@ -2681,7 +2714,7 @@ static config_file_t *open_default_config_file(void)
|
||||
|
||||
if (conf)
|
||||
{
|
||||
/* Since this is a clean config file, we can
|
||||
/* Since this is a clean config file, we can
|
||||
* safely use config_save_on_exit. */
|
||||
config_set_bool(conf, "config_save_on_exit", true);
|
||||
saved = config_file_write(conf, conf_path, true);
|
||||
@ -3342,7 +3375,7 @@ bool config_load_override(void *data)
|
||||
/* Create a new config file from core_path */
|
||||
if (config_file_exists(core_path))
|
||||
{
|
||||
RARCH_LOG("[Overrides] core-specific overrides found at %s.\n",
|
||||
RARCH_LOG("[Overrides]: Core-specific overrides found at %s.\n",
|
||||
core_path);
|
||||
|
||||
path_set(RARCH_PATH_CONFIG_APPEND, core_path);
|
||||
@ -3350,7 +3383,7 @@ bool config_load_override(void *data)
|
||||
should_append = true;
|
||||
}
|
||||
else
|
||||
RARCH_LOG("[Overrides] no core-specific overrides found at %s.\n",
|
||||
RARCH_LOG("[Overrides]: No core-specific overrides found at %s.\n",
|
||||
core_path);
|
||||
|
||||
/* per-content-dir overrides */
|
||||
@ -3361,12 +3394,12 @@ bool config_load_override(void *data)
|
||||
|
||||
temp_path[0] = '\0';
|
||||
|
||||
RARCH_LOG("[Overrides] content-dir-specific overrides found at %s.\n",
|
||||
RARCH_LOG("[Overrides]: Content dir-specific overrides found at %s.\n",
|
||||
game_path);
|
||||
|
||||
if (should_append)
|
||||
{
|
||||
RARCH_LOG("[Overrides] content-dir-specific overrides stacking on top of previous overrides.\n");
|
||||
RARCH_LOG("[Overrides]: Content dir-specific overrides stacking on top of previous overrides.\n");
|
||||
strlcpy(temp_path, path_get(RARCH_PATH_CONFIG_APPEND), path_size);
|
||||
strlcat(temp_path, "|", path_size);
|
||||
strlcat(temp_path, content_path, path_size);
|
||||
@ -3381,7 +3414,7 @@ bool config_load_override(void *data)
|
||||
should_append = true;
|
||||
}
|
||||
else
|
||||
RARCH_LOG("[Overrides] no content-dir-specific overrides found at %s.\n",
|
||||
RARCH_LOG("[Overrides]: No content-dir-specific overrides found at %s.\n",
|
||||
content_path);
|
||||
|
||||
/* per-game overrides */
|
||||
@ -3392,12 +3425,12 @@ bool config_load_override(void *data)
|
||||
|
||||
temp_path[0] = '\0';
|
||||
|
||||
RARCH_LOG("[Overrides] game-specific overrides found at %s.\n",
|
||||
RARCH_LOG("[Overrides]: Game-specific overrides found at %s.\n",
|
||||
game_path);
|
||||
|
||||
if (should_append)
|
||||
{
|
||||
RARCH_LOG("[Overrides] game-specific overrides stacking on top of previous overrides\n");
|
||||
RARCH_LOG("[Overrides]: game-specific overrides stacking on top of previous overrides\n");
|
||||
strlcpy(temp_path, path_get(RARCH_PATH_CONFIG_APPEND), path_size);
|
||||
strlcat(temp_path, "|", path_size);
|
||||
strlcat(temp_path, game_path, path_size);
|
||||
@ -3412,7 +3445,7 @@ bool config_load_override(void *data)
|
||||
should_append = true;
|
||||
}
|
||||
else
|
||||
RARCH_LOG("[Overrides] no game-specific overrides found at %s.\n",
|
||||
RARCH_LOG("[Overrides]: No game-specific overrides found at %s.\n",
|
||||
game_path);
|
||||
|
||||
if (!should_append)
|
||||
@ -3481,7 +3514,7 @@ bool config_unload_override(void)
|
||||
path_get(RARCH_PATH_CONFIG), config_get_ptr()))
|
||||
return false;
|
||||
|
||||
RARCH_LOG("[Overrides] configuration overrides unloaded, original configuration restored.\n");
|
||||
RARCH_LOG("[Overrides]: Configuration overrides unloaded, original configuration restored.\n");
|
||||
|
||||
/* Reset save paths */
|
||||
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
|
||||
@ -3516,6 +3549,7 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
const char *core_name = system ? system->info.library_name : NULL;
|
||||
const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME);
|
||||
const char *game_name = path_basename(rarch_path_basename);
|
||||
enum msg_hash_enums msg_remap_loaded = MSG_GAME_REMAP_FILE_LOADED;
|
||||
char content_dir_name[PATH_MAX_LENGTH];
|
||||
|
||||
if (string_is_empty(core_name) || string_is_empty(game_name))
|
||||
@ -3577,6 +3611,8 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
if (input_remapping_load_file(new_conf, game_path))
|
||||
{
|
||||
rarch_ctl(RARCH_CTL_SET_REMAPS_GAME_ACTIVE, NULL);
|
||||
/* msg_remap_loaded is set to MSG_GAME_REMAP_FILE_LOADED
|
||||
* by default - no need to change it here */
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
@ -3588,6 +3624,7 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
if (input_remapping_load_file(new_conf, content_path))
|
||||
{
|
||||
rarch_ctl(RARCH_CTL_SET_REMAPS_CONTENT_DIR_ACTIVE, NULL);
|
||||
msg_remap_loaded = MSG_DIRECTORY_REMAP_FILE_LOADED;
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
@ -3599,6 +3636,7 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
if (input_remapping_load_file(new_conf, core_path))
|
||||
{
|
||||
rarch_ctl(RARCH_CTL_SET_REMAPS_CORE_ACTIVE, NULL);
|
||||
msg_remap_loaded = MSG_CORE_REMAP_FILE_LOADED;
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
@ -3612,8 +3650,8 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
return false;
|
||||
|
||||
success:
|
||||
runloop_msg_queue_push(msg_hash_to_str(
|
||||
MSG_GAME_REMAP_FILE_LOADED), 1, 100, false,
|
||||
runloop_msg_queue_push(
|
||||
msg_hash_to_str(msg_remap_loaded), 1, 100, false,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
free(content_path);
|
||||
free(remap_directory);
|
||||
@ -4110,7 +4148,7 @@ bool config_save_overrides(enum override_type type, void *data)
|
||||
tmp_i = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
|
||||
path_overrides = populate_settings_path (overrides, &tmp_i);
|
||||
|
||||
RARCH_LOG("[Overrides] looking for changed settings... \n");
|
||||
RARCH_LOG("[Overrides]: Looking for changed settings... \n");
|
||||
|
||||
if (conf)
|
||||
{
|
||||
@ -4184,15 +4222,15 @@ bool config_save_overrides(enum override_type type, void *data)
|
||||
switch (type)
|
||||
{
|
||||
case OVERRIDE_CORE:
|
||||
RARCH_LOG ("[Overrides] path %s\n", core_path);
|
||||
RARCH_LOG ("[Overrides]: path %s\n", core_path);
|
||||
ret = config_file_write(conf, core_path, true);
|
||||
break;
|
||||
case OVERRIDE_GAME:
|
||||
RARCH_LOG ("[Overrides] path %s\n", game_path);
|
||||
RARCH_LOG ("[Overrides]: path %s\n", game_path);
|
||||
ret = config_file_write(conf, game_path, true);
|
||||
break;
|
||||
case OVERRIDE_CONTENT_DIR:
|
||||
RARCH_LOG ("[Overrides] path %s\n", content_path);
|
||||
RARCH_LOG ("[Overrides]: path %s\n", content_path);
|
||||
ret = config_file_write(conf, content_path, true);
|
||||
break;
|
||||
case OVERRIDE_NONE:
|
||||
@ -4236,6 +4274,7 @@ bool config_save_overrides(enum override_type type, void *data)
|
||||
free(override_directory);
|
||||
free(core_path);
|
||||
free(game_path);
|
||||
free(content_path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ typedef struct settings
|
||||
bool video_black_frame_insertion;
|
||||
bool video_vfilter;
|
||||
bool video_smooth;
|
||||
bool video_ctx_scaling;
|
||||
bool video_force_aspect;
|
||||
bool video_crop_overscan;
|
||||
bool video_aspect_ratio_auto;
|
||||
@ -130,6 +131,7 @@ typedef struct settings
|
||||
bool audio_rate_control;
|
||||
bool audio_wasapi_exclusive_mode;
|
||||
bool audio_wasapi_float_format;
|
||||
bool audio_fastforward_mute;
|
||||
|
||||
/* Input */
|
||||
bool input_remap_binds_enable;
|
||||
@ -142,7 +144,6 @@ typedef struct settings
|
||||
bool input_overlay_auto_rotate;
|
||||
bool input_descriptor_label_show;
|
||||
bool input_descriptor_hide_unbound;
|
||||
bool input_all_users_control_menu;
|
||||
bool input_menu_swap_ok_cancel_buttons;
|
||||
bool input_backtouch_enable;
|
||||
bool input_backtouch_toggle;
|
||||
@ -176,6 +177,7 @@ typedef struct settings
|
||||
bool menu_throttle_framerate;
|
||||
bool menu_linear_filter;
|
||||
bool menu_horizontal_animation;
|
||||
bool menu_scroll_fast;
|
||||
bool menu_show_online_updater;
|
||||
bool menu_show_core_updater;
|
||||
bool menu_show_load_core;
|
||||
@ -282,7 +284,9 @@ typedef struct settings
|
||||
|
||||
/* Network */
|
||||
bool network_buildbot_auto_extract_archive;
|
||||
bool network_buildbot_show_experimental_cores;
|
||||
bool network_on_demand_thumbnails;
|
||||
bool core_updater_auto_backup;
|
||||
|
||||
/* UI */
|
||||
bool ui_menubar_enable;
|
||||
@ -301,6 +305,7 @@ typedef struct settings
|
||||
bool cheevos_badges_enable;
|
||||
bool cheevos_verbose_enable;
|
||||
bool cheevos_auto_screenshot;
|
||||
bool cheevos_start_active;
|
||||
|
||||
/* Camera */
|
||||
bool camera_allow;
|
||||
@ -342,6 +347,8 @@ typedef struct settings
|
||||
bool savestate_auto_save;
|
||||
bool savestate_auto_load;
|
||||
bool savestate_thumbnail_enable;
|
||||
bool save_file_compression;
|
||||
bool savestate_file_compression;
|
||||
bool network_cmd_enable;
|
||||
bool stdin_cmd_enable;
|
||||
bool keymapper_enable;
|
||||
@ -375,6 +382,7 @@ typedef struct settings
|
||||
|
||||
bool sustained_performance_mode;
|
||||
bool playlist_use_old_format;
|
||||
bool playlist_compression;
|
||||
bool content_runtime_log;
|
||||
bool content_runtime_log_aggregate;
|
||||
|
||||
@ -387,6 +395,7 @@ typedef struct settings
|
||||
bool enable_device_vibration;
|
||||
bool ozone_collapse_sidebar;
|
||||
bool ozone_truncate_playlist_name;
|
||||
bool ozone_sort_after_truncate_playlist_name;
|
||||
bool ozone_scroll_content_metadata;
|
||||
|
||||
bool log_to_file;
|
||||
@ -429,6 +438,8 @@ typedef struct settings
|
||||
|
||||
float input_overlay_opacity;
|
||||
float input_overlay_scale;
|
||||
float input_overlay_center_x;
|
||||
float input_overlay_center_y;
|
||||
|
||||
float slowmotion_ratio;
|
||||
float fastforward_ratio;
|
||||
@ -483,6 +494,7 @@ typedef struct settings
|
||||
#ifdef GEKKO
|
||||
unsigned input_mouse_scale;
|
||||
#endif
|
||||
unsigned input_hotkey_block_delay;
|
||||
unsigned input_menu_toggle_gamepad_combo;
|
||||
unsigned input_keyboard_gamepad_mapping_type;
|
||||
unsigned input_poll_type_behavior;
|
||||
@ -538,6 +550,7 @@ typedef struct settings
|
||||
unsigned accessibility_narrator_speech_speed;
|
||||
|
||||
unsigned menu_timedate_style;
|
||||
unsigned menu_timedate_date_separator;
|
||||
unsigned gfx_thumbnails;
|
||||
unsigned menu_left_thumbnails;
|
||||
unsigned gfx_thumbnail_upscale_threshold;
|
||||
@ -609,6 +622,8 @@ typedef struct settings
|
||||
unsigned ai_service_mode;
|
||||
unsigned ai_service_target_lang;
|
||||
unsigned ai_service_source_lang;
|
||||
|
||||
unsigned core_updater_auto_backup_history_size;
|
||||
} uints;
|
||||
|
||||
struct
|
||||
|
@ -43,7 +43,7 @@ typedef struct content_ctx_info
|
||||
bool content_load_ram_file(unsigned slot);
|
||||
|
||||
/* Save a RAM state from memory to disk. */
|
||||
bool content_save_ram_file(unsigned slot);
|
||||
bool content_save_ram_file(unsigned slot, bool compress);
|
||||
|
||||
/* Load a state from disk to memory. */
|
||||
bool content_load_state(const char* path, bool load_to_backup_buffer, bool autoload);
|
||||
@ -51,6 +51,9 @@ bool content_load_state(const char* path, bool load_to_backup_buffer, bool autol
|
||||
/* Save a state from memory to disk. */
|
||||
bool content_save_state(const char *path, bool save_to_disk, bool autosave);
|
||||
|
||||
/* Returns true if a save state task is in progress */
|
||||
bool content_save_state_in_progress(void);
|
||||
|
||||
/* Copy a save state. */
|
||||
bool content_rename_state(const char *origin, const char *dest);
|
||||
|
||||
@ -82,9 +85,6 @@ bool content_reset_savestate_backups(void);
|
||||
bool content_undo_load_buf_is_empty(void);
|
||||
bool content_undo_save_buf_is_empty(void);
|
||||
|
||||
/* Checks if launched from the commandline */
|
||||
bool content_launched_from_cli(void);
|
||||
|
||||
/* Clears the pending subsystem rom buffer */
|
||||
bool content_is_subsystem_pending_load(void);
|
||||
|
||||
|
764
core_backup.c
Normal file
764
core_backup.c
Normal file
@ -0,0 +1,764 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2016-2019 - Brad Parker
|
||||
* Copyright (C) 2019-2020 - James Leaver
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/interface_stream.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <lists/dir_list.h>
|
||||
#include <time/rtime.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#include "frontend/frontend_driver.h"
|
||||
#include "file_path_special.h"
|
||||
#include "verbosity.h"
|
||||
|
||||
#include "core_backup.h"
|
||||
|
||||
/* Holds all entries in a core backup list */
|
||||
struct core_backup_list
|
||||
{
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
core_backup_list_entry_t *entries;
|
||||
};
|
||||
|
||||
/*********************/
|
||||
/* Utility Functions */
|
||||
/*********************/
|
||||
|
||||
/* Generates backup directory path for specified core.
|
||||
* Returns false if 'core_path' and/or 'dir_core_assets'
|
||||
* are invalid, or a filesystem error occurs */
|
||||
static bool core_backup_get_backup_dir(
|
||||
const char *dir_libretro, const char *dir_core_assets,
|
||||
const char *core_filename,
|
||||
char *backup_dir, size_t len)
|
||||
{
|
||||
char *last_underscore = NULL;
|
||||
char core_file_id[PATH_MAX_LENGTH];
|
||||
char tmp[PATH_MAX_LENGTH];
|
||||
|
||||
core_file_id[0] = '\0';
|
||||
tmp[0] = '\0';
|
||||
|
||||
/* Extract core file 'ID' (name without extension + suffix)
|
||||
* from core path */
|
||||
if (string_is_empty(dir_libretro) ||
|
||||
string_is_empty(core_filename) ||
|
||||
(len < 1))
|
||||
return false;
|
||||
|
||||
strlcpy(core_file_id, core_filename, sizeof(core_file_id));
|
||||
|
||||
/* > Remove file extension */
|
||||
path_remove_extension(core_file_id);
|
||||
|
||||
if (string_is_empty(core_file_id))
|
||||
return false;
|
||||
|
||||
/* > Remove platform-specific file name suffix,
|
||||
* if required */
|
||||
last_underscore = strrchr(core_file_id, '_');
|
||||
|
||||
if (!string_is_empty(last_underscore))
|
||||
if (!string_is_equal(last_underscore, "_libretro"))
|
||||
*last_underscore = '\0';
|
||||
|
||||
if (string_is_empty(core_file_id))
|
||||
return false;
|
||||
|
||||
/* Get core backup directory
|
||||
* > If no assets directory is defined, use
|
||||
* core directory as a base */
|
||||
fill_pathname_join(tmp, string_is_empty(dir_core_assets) ?
|
||||
dir_libretro : dir_core_assets,
|
||||
"core_backups", sizeof(tmp));
|
||||
|
||||
fill_pathname_join(backup_dir, tmp,
|
||||
core_file_id, len);
|
||||
|
||||
if (string_is_empty(backup_dir))
|
||||
return false;
|
||||
|
||||
/* > Create directory, if required */
|
||||
if (!path_is_directory(backup_dir))
|
||||
{
|
||||
if (!path_mkdir(backup_dir))
|
||||
{
|
||||
RARCH_ERR("[core backup] Failed to create backup directory: %s.\n", backup_dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Generates a timestamped core backup file path from
|
||||
* the specified core path. Returns true if successful */
|
||||
bool core_backup_get_backup_path(
|
||||
const char *core_path, uint32_t crc, enum core_backup_mode backup_mode,
|
||||
const char *dir_core_assets, char *backup_path, size_t len)
|
||||
{
|
||||
int n;
|
||||
time_t current_time;
|
||||
struct tm time_info;
|
||||
const char *core_filename = NULL;
|
||||
char core_dir[PATH_MAX_LENGTH];
|
||||
char backup_dir[PATH_MAX_LENGTH];
|
||||
char backup_filename[PATH_MAX_LENGTH];
|
||||
|
||||
core_dir[0] = '\0';
|
||||
backup_dir[0] = '\0';
|
||||
backup_filename[0] = '\0';
|
||||
|
||||
/* Get core filename and parent directory */
|
||||
if (string_is_empty(core_path))
|
||||
return false;
|
||||
|
||||
core_filename = path_basename(core_path);
|
||||
|
||||
if (string_is_empty(core_filename))
|
||||
return false;
|
||||
|
||||
fill_pathname_parent_dir(core_dir, core_path, sizeof(core_dir));
|
||||
|
||||
if (string_is_empty(core_dir))
|
||||
return false;
|
||||
|
||||
/* Get backup directory */
|
||||
if (!core_backup_get_backup_dir(core_dir, dir_core_assets, core_filename,
|
||||
backup_dir, sizeof(backup_dir)))
|
||||
return false;
|
||||
|
||||
/* Get current time */
|
||||
time(¤t_time);
|
||||
rtime_localtime(¤t_time, &time_info);
|
||||
|
||||
/* Generate backup filename */
|
||||
n = snprintf(backup_filename, sizeof(backup_filename),
|
||||
"%s.%04u%02u%02uT%02u%02u%02u.%08x.%u%s",
|
||||
core_filename,
|
||||
(unsigned)time_info.tm_year + 1900,
|
||||
(unsigned)time_info.tm_mon + 1,
|
||||
(unsigned)time_info.tm_mday,
|
||||
(unsigned)time_info.tm_hour,
|
||||
(unsigned)time_info.tm_min,
|
||||
(unsigned)time_info.tm_sec,
|
||||
crc,
|
||||
(unsigned)backup_mode,
|
||||
file_path_str(FILE_PATH_CORE_BACKUP_EXTENSION));
|
||||
|
||||
if ((n < 0) || (n >= 128))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
|
||||
/* Build final path */
|
||||
fill_pathname_join(backup_path, backup_dir,
|
||||
backup_filename, len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns detected type of specified core backup file */
|
||||
enum core_backup_type core_backup_get_backup_type(const char *backup_path)
|
||||
{
|
||||
const char *backup_ext = NULL;
|
||||
struct string_list *metadata_list = NULL;
|
||||
char core_ext[255];
|
||||
|
||||
core_ext[0] = '\0';
|
||||
|
||||
if (string_is_empty(backup_path) || !path_is_valid(backup_path))
|
||||
goto error;
|
||||
|
||||
/* Get backup file extension */
|
||||
backup_ext = path_get_extension(backup_path);
|
||||
|
||||
if (string_is_empty(backup_ext))
|
||||
goto error;
|
||||
|
||||
/* Get platform-specific dynamic library extension */
|
||||
if (!frontend_driver_get_core_extension(core_ext, sizeof(core_ext)))
|
||||
goto error;
|
||||
|
||||
/* Check if this is an archived backup */
|
||||
if (string_is_equal_noncase(backup_ext,
|
||||
file_path_str(FILE_PATH_CORE_BACKUP_EXTENSION_NO_DOT)))
|
||||
{
|
||||
const char *backup_filename = NULL;
|
||||
const char *src_ext = NULL;
|
||||
|
||||
/* Split the backup filename into its various
|
||||
* metadata components */
|
||||
backup_filename = path_basename(backup_path);
|
||||
|
||||
if (string_is_empty(backup_filename))
|
||||
goto error;
|
||||
|
||||
metadata_list = string_split(backup_filename, ".");
|
||||
|
||||
if (!metadata_list || (metadata_list->size != 6))
|
||||
goto error;
|
||||
|
||||
/* Get extension of source core file */
|
||||
src_ext = metadata_list->elems[1].data;
|
||||
|
||||
if (string_is_empty(src_ext))
|
||||
goto error;
|
||||
|
||||
/* Check whether extension is valid */
|
||||
if (!string_is_equal_noncase(src_ext, core_ext))
|
||||
goto error;
|
||||
|
||||
string_list_free(metadata_list);
|
||||
metadata_list = NULL;
|
||||
|
||||
return CORE_BACKUP_TYPE_ARCHIVE;
|
||||
}
|
||||
|
||||
/* Check if this is a plain dynamic library file */
|
||||
if (string_is_equal_noncase(backup_ext, core_ext))
|
||||
return CORE_BACKUP_TYPE_LIB;
|
||||
|
||||
error:
|
||||
if (metadata_list)
|
||||
{
|
||||
string_list_free(metadata_list);
|
||||
metadata_list = NULL;
|
||||
}
|
||||
|
||||
return CORE_BACKUP_TYPE_INVALID;
|
||||
}
|
||||
|
||||
/* Fetches crc value of specified core backup file.
|
||||
* Returns true if successful */
|
||||
bool core_backup_get_backup_crc(char *backup_path, uint32_t *crc)
|
||||
{
|
||||
struct string_list *metadata_list = NULL;
|
||||
enum core_backup_type backup_type;
|
||||
|
||||
if (string_is_empty(backup_path) || !crc)
|
||||
goto error;
|
||||
|
||||
/* Get backup type */
|
||||
backup_type = core_backup_get_backup_type(backup_path);
|
||||
|
||||
switch (backup_type)
|
||||
{
|
||||
case CORE_BACKUP_TYPE_ARCHIVE:
|
||||
{
|
||||
const char *backup_filename = NULL;
|
||||
const char *crc_str = NULL;
|
||||
|
||||
/* Split the backup filename into its various
|
||||
* metadata components */
|
||||
backup_filename = path_basename(backup_path);
|
||||
|
||||
if (string_is_empty(backup_filename))
|
||||
goto error;
|
||||
|
||||
metadata_list = string_split(backup_filename, ".");
|
||||
|
||||
if (!metadata_list || (metadata_list->size != 6))
|
||||
goto error;
|
||||
|
||||
/* Get crc string */
|
||||
crc_str = metadata_list->elems[3].data;
|
||||
|
||||
if (string_is_empty(crc_str))
|
||||
goto error;
|
||||
|
||||
/* Convert to an integer */
|
||||
*crc = (uint32_t)string_hex_to_unsigned(crc_str);
|
||||
|
||||
if (*crc == 0)
|
||||
goto error;
|
||||
|
||||
string_list_free(metadata_list);
|
||||
metadata_list = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case CORE_BACKUP_TYPE_LIB:
|
||||
{
|
||||
intfstream_t *backup_file = NULL;
|
||||
|
||||
/* This is a plain dynamic library file,
|
||||
* have to read file data to determine crc */
|
||||
|
||||
/* Open backup file */
|
||||
backup_file = intfstream_open_file(
|
||||
backup_path, RETRO_VFS_FILE_ACCESS_READ,
|
||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
|
||||
if (backup_file)
|
||||
{
|
||||
bool success;
|
||||
|
||||
/* Get crc value */
|
||||
success = intfstream_get_crc(backup_file, crc);
|
||||
|
||||
/* Close backup file */
|
||||
intfstream_close(backup_file);
|
||||
free(backup_file);
|
||||
backup_file = NULL;
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Backup is invalid */
|
||||
break;
|
||||
}
|
||||
|
||||
error:
|
||||
if (metadata_list)
|
||||
{
|
||||
string_list_free(metadata_list);
|
||||
metadata_list = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetches core path associated with specified core
|
||||
* backup file. Returns detected type of backup
|
||||
* file - CORE_BACKUP_TYPE_INVALID indicates that
|
||||
* backup file cannot be restored/installed, or
|
||||
* arguments are otherwise invalid */
|
||||
enum core_backup_type core_backup_get_core_path(
|
||||
const char *backup_path, const char *dir_libretro,
|
||||
char *core_path, size_t len)
|
||||
{
|
||||
const char *backup_filename = NULL;
|
||||
char *core_filename = NULL;
|
||||
enum core_backup_type backup_type = CORE_BACKUP_TYPE_INVALID;
|
||||
|
||||
if (string_is_empty(backup_path) || string_is_empty(dir_libretro))
|
||||
return backup_type;
|
||||
|
||||
backup_filename = path_basename(backup_path);
|
||||
|
||||
if (string_is_empty(backup_filename))
|
||||
return backup_type;
|
||||
|
||||
/* Check backup type */
|
||||
switch (core_backup_get_backup_type(backup_path))
|
||||
{
|
||||
case CORE_BACKUP_TYPE_ARCHIVE:
|
||||
{
|
||||
char *period = NULL;
|
||||
|
||||
/* This is an archived backup with timestamp/crc
|
||||
* metadata in the filename */
|
||||
core_filename = strdup(backup_filename);
|
||||
|
||||
/* Find the location of the second period */
|
||||
period = strchr(core_filename, '.');
|
||||
if (!period || (*(++period) == '\0'))
|
||||
break;
|
||||
|
||||
period = strchr(period, '.');
|
||||
if (!period)
|
||||
break;
|
||||
|
||||
/* Trim everything after (and including) the
|
||||
* second period */
|
||||
*period = '\0';
|
||||
|
||||
if (string_is_empty(core_filename))
|
||||
break;
|
||||
|
||||
/* All good - build core path */
|
||||
fill_pathname_join(core_path, dir_libretro,
|
||||
core_filename, len);
|
||||
|
||||
backup_type = CORE_BACKUP_TYPE_ARCHIVE;
|
||||
}
|
||||
break;
|
||||
case CORE_BACKUP_TYPE_LIB:
|
||||
/* This is a plain dynamic library file */
|
||||
fill_pathname_join(core_path, dir_libretro,
|
||||
backup_filename, len);
|
||||
backup_type = CORE_BACKUP_TYPE_LIB;
|
||||
break;
|
||||
default:
|
||||
/* Backup is invalid */
|
||||
break;
|
||||
}
|
||||
|
||||
if (core_filename)
|
||||
{
|
||||
free(core_filename);
|
||||
core_filename = NULL;
|
||||
}
|
||||
|
||||
return backup_type;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* Backup List Functions */
|
||||
/*************************/
|
||||
|
||||
/**************************************/
|
||||
/* Initialisation / De-Initialisation */
|
||||
/**************************************/
|
||||
|
||||
/* Parses backup file name and adds to backup list, if valid */
|
||||
static bool core_backup_add_entry(core_backup_list_t *backup_list,
|
||||
const char *core_filename, const char *backup_path)
|
||||
{
|
||||
char *backup_filename = NULL;
|
||||
core_backup_list_entry_t *entry = NULL;
|
||||
unsigned backup_mode = 0;
|
||||
|
||||
if (!backup_list ||
|
||||
string_is_empty(core_filename) ||
|
||||
string_is_empty(backup_path) ||
|
||||
(backup_list->size >= backup_list->capacity))
|
||||
goto error;
|
||||
|
||||
backup_filename = strdup(path_basename(backup_path));
|
||||
|
||||
if (string_is_empty(backup_filename))
|
||||
goto error;
|
||||
|
||||
/* Ensure base backup filename matches core */
|
||||
if (!string_starts_with(backup_filename, core_filename))
|
||||
goto error;
|
||||
|
||||
/* Remove backup file extension */
|
||||
path_remove_extension(backup_filename);
|
||||
|
||||
/* Parse backup filename metadata
|
||||
* - <core_filename>.<timestamp>.<crc>.<backup_mode>
|
||||
* - timestamp: YYYYMMDDTHHMMSS */
|
||||
entry = &backup_list->entries[backup_list->size];
|
||||
|
||||
if (sscanf(backup_filename + strlen(core_filename),
|
||||
".%04u%02u%02uT%02u%02u%02u.%08x.%u",
|
||||
&entry->date.year, &entry->date.month, &entry->date.day,
|
||||
&entry->date.hour, &entry->date.minute, &entry->date.second,
|
||||
&entry->crc, &backup_mode) != 8)
|
||||
goto error;
|
||||
|
||||
entry->backup_mode = (enum core_backup_mode)backup_mode;
|
||||
|
||||
/* Cache backup path */
|
||||
entry->backup_path = strdup(backup_path);
|
||||
backup_list->size++;
|
||||
|
||||
free(backup_filename);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (backup_filename)
|
||||
free(backup_filename);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Creates a new core backup list containing entries
|
||||
* for all existing backup files.
|
||||
* Returns a handle to a new core_backup_list_t object
|
||||
* on success, otherwise returns NULL. */
|
||||
core_backup_list_t *core_backup_list_init(
|
||||
const char *core_path, const char *dir_core_assets)
|
||||
{
|
||||
size_t i;
|
||||
const char *core_filename = NULL;
|
||||
struct string_list *dir_list = NULL;
|
||||
core_backup_list_t *backup_list = NULL;
|
||||
core_backup_list_entry_t *entries = NULL;
|
||||
char core_dir[PATH_MAX_LENGTH];
|
||||
char backup_dir[PATH_MAX_LENGTH];
|
||||
|
||||
core_dir[0] = '\0';
|
||||
backup_dir[0] = '\0';
|
||||
|
||||
/* Get core filename and parent directory */
|
||||
if (string_is_empty(core_path))
|
||||
goto error;
|
||||
|
||||
core_filename = path_basename(core_path);
|
||||
|
||||
if (string_is_empty(core_filename))
|
||||
goto error;
|
||||
|
||||
fill_pathname_parent_dir(core_dir, core_path, sizeof(core_dir));
|
||||
|
||||
if (string_is_empty(core_dir))
|
||||
goto error;
|
||||
|
||||
/* Get backup directory */
|
||||
if (!core_backup_get_backup_dir(core_dir, dir_core_assets, core_filename,
|
||||
backup_dir, sizeof(backup_dir)))
|
||||
goto error;
|
||||
|
||||
/* Get backup file list */
|
||||
dir_list = dir_list_new(
|
||||
backup_dir,
|
||||
file_path_str(FILE_PATH_CORE_BACKUP_EXTENSION),
|
||||
false, /* include_dirs */
|
||||
false, /* include_hidden */
|
||||
false, /* include_compressed */
|
||||
false /* recursive */
|
||||
);
|
||||
|
||||
/* Sanity check */
|
||||
if (!dir_list)
|
||||
goto error;
|
||||
|
||||
if (dir_list->size < 1)
|
||||
goto error;
|
||||
|
||||
/* Ensure list is sorted in alphabetical order
|
||||
* > This corresponds to 'timestamp' order */
|
||||
dir_list_sort(dir_list, true);
|
||||
|
||||
/* Create core backup list */
|
||||
backup_list = (core_backup_list_t*)calloc(1, sizeof(*backup_list));
|
||||
|
||||
if (!backup_list)
|
||||
goto error;
|
||||
|
||||
/* Create entries array
|
||||
* (Note: Set this to the full size of the directory
|
||||
* list - this may be larger than we need, but saves
|
||||
* many inefficiencies later) */
|
||||
entries = (core_backup_list_entry_t*)calloc(dir_list->size, sizeof(*entries));
|
||||
|
||||
if (!entries)
|
||||
goto error;
|
||||
|
||||
backup_list->entries = entries;
|
||||
backup_list->capacity = dir_list->size;
|
||||
backup_list->size = 0;
|
||||
|
||||
/* Loop over backup files and parse file names */
|
||||
for (i = 0; i < dir_list->size; i++)
|
||||
{
|
||||
const char *backup_path = dir_list->elems[i].data;
|
||||
core_backup_add_entry(backup_list, core_filename, backup_path);
|
||||
}
|
||||
|
||||
if (backup_list->size == 0)
|
||||
goto error;
|
||||
|
||||
string_list_free(dir_list);
|
||||
|
||||
return backup_list;
|
||||
|
||||
error:
|
||||
if (dir_list)
|
||||
string_list_free(dir_list);
|
||||
|
||||
if (backup_list)
|
||||
core_backup_list_free(backup_list);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Frees specified core backup list */
|
||||
void core_backup_list_free(core_backup_list_t *backup_list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!backup_list)
|
||||
return;
|
||||
|
||||
if (backup_list->entries)
|
||||
{
|
||||
for (i = 0; i < backup_list->size; i++)
|
||||
{
|
||||
core_backup_list_entry_t *entry = &backup_list->entries[i];
|
||||
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
if (entry->backup_path)
|
||||
{
|
||||
free(entry->backup_path);
|
||||
entry->backup_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(backup_list->entries);
|
||||
backup_list->entries = NULL;
|
||||
}
|
||||
|
||||
free(backup_list);
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* Getters */
|
||||
/***********/
|
||||
|
||||
/* Returns number of entries in core backup list */
|
||||
size_t core_backup_list_size(core_backup_list_t *backup_list)
|
||||
{
|
||||
if (!backup_list)
|
||||
return 0;
|
||||
|
||||
return backup_list->size;
|
||||
}
|
||||
|
||||
/* Returns number of entries of specified 'backup mode'
|
||||
* (manual or automatic) in core backup list */
|
||||
size_t core_backup_list_get_num_backups(
|
||||
core_backup_list_t *backup_list,
|
||||
enum core_backup_mode backup_mode)
|
||||
{
|
||||
size_t i;
|
||||
size_t num_backups = 0;
|
||||
|
||||
if (!backup_list || !backup_list->entries)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < backup_list->size; i++)
|
||||
{
|
||||
core_backup_list_entry_t *current_entry = &backup_list->entries[i];
|
||||
|
||||
if (current_entry &&
|
||||
(current_entry->backup_mode == backup_mode))
|
||||
num_backups++;
|
||||
}
|
||||
|
||||
return num_backups;
|
||||
}
|
||||
|
||||
/* Fetches core backup list entry corresponding
|
||||
* to the specified entry index.
|
||||
* Returns false if index is invalid. */
|
||||
bool core_backup_list_get_index(
|
||||
core_backup_list_t *backup_list,
|
||||
size_t idx,
|
||||
const core_backup_list_entry_t **entry)
|
||||
{
|
||||
if (!backup_list || !backup_list->entries || !entry)
|
||||
return false;
|
||||
|
||||
if (idx >= backup_list->size)
|
||||
return false;
|
||||
|
||||
*entry = &backup_list->entries[idx];
|
||||
|
||||
if (*entry)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetches core backup list entry corresponding
|
||||
* to the specified core crc checksum value.
|
||||
* Note that 'manual' and 'auto' backups are
|
||||
* considered independent - we only compare
|
||||
* crc values for the specified backup_mode.
|
||||
* Returns false if entry is not found. */
|
||||
bool core_backup_list_get_crc(
|
||||
core_backup_list_t *backup_list,
|
||||
uint32_t crc, enum core_backup_mode backup_mode,
|
||||
const core_backup_list_entry_t **entry)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!backup_list || !backup_list->entries || !entry)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < backup_list->size; i++)
|
||||
{
|
||||
core_backup_list_entry_t *current_entry = &backup_list->entries[i];
|
||||
|
||||
if (current_entry &&
|
||||
(current_entry->crc == crc) &&
|
||||
(current_entry->backup_mode == backup_mode))
|
||||
{
|
||||
*entry = current_entry;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetches a string representation of a backup
|
||||
* list entry timestamp.
|
||||
* Returns false in the event of an error */
|
||||
bool core_backup_list_get_entry_timestamp_str(
|
||||
const core_backup_list_entry_t *entry,
|
||||
enum core_backup_date_separator_type date_separator,
|
||||
char *timestamp, size_t len)
|
||||
{
|
||||
int n;
|
||||
const char *format_str = "";
|
||||
|
||||
if (!entry || (len < 20))
|
||||
return false;
|
||||
|
||||
/* Get time format string */
|
||||
switch (date_separator)
|
||||
{
|
||||
case CORE_BACKUP_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%04u/%02u/%02u %02u:%02u:%02u";
|
||||
break;
|
||||
case CORE_BACKUP_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%04u.%02u.%02u %02u:%02u:%02u";
|
||||
break;
|
||||
default:
|
||||
format_str = "%04u-%02u-%02u %02u:%02u:%02u";
|
||||
break;
|
||||
}
|
||||
|
||||
n = snprintf(timestamp, len,
|
||||
format_str,
|
||||
entry->date.year,
|
||||
entry->date.month,
|
||||
entry->date.day,
|
||||
entry->date.hour,
|
||||
entry->date.minute,
|
||||
entry->date.second);
|
||||
|
||||
if ((n < 0) || (n >= 32))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fetches a string representation of a backup
|
||||
* list entry crc value.
|
||||
* Returns false in the event of an error */
|
||||
bool core_backup_list_get_entry_crc_str(
|
||||
const core_backup_list_entry_t *entry,
|
||||
char *crc, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!entry || (len < 9))
|
||||
return false;
|
||||
|
||||
n = snprintf(crc, len, "%08x", entry->crc);
|
||||
|
||||
if ((n < 0) || (n >= 32))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
|
||||
return true;
|
||||
}
|
177
core_backup.h
Normal file
177
core_backup.h
Normal file
@ -0,0 +1,177 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2014-2017 - Jean-André Santoni
|
||||
* Copyright (C) 2016-2019 - Brad Parker
|
||||
* Copyright (C) 2019-2020 - James Leaver
|
||||
*
|
||||
* 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 __CORE_BACKUP_H
|
||||
#define __CORE_BACKUP_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* Defines the various types of supported core backup
|
||||
* file. Allows us to handle manual core installs
|
||||
* (via downloaded/compiled dynamic libraries dropped
|
||||
* in the 'downloads' folder) using the same task
|
||||
* interface as 'managed'/archived backups */
|
||||
enum core_backup_type
|
||||
{
|
||||
CORE_BACKUP_TYPE_INVALID = 0,
|
||||
CORE_BACKUP_TYPE_ARCHIVE,
|
||||
CORE_BACKUP_TYPE_LIB
|
||||
};
|
||||
|
||||
/* Used to distinguish manual and automatic
|
||||
* core backups */
|
||||
enum core_backup_mode
|
||||
{
|
||||
CORE_BACKUP_MODE_MANUAL = 0,
|
||||
CORE_BACKUP_MODE_AUTO
|
||||
};
|
||||
|
||||
/* Note: These must be kept synchronised with
|
||||
* 'enum menu_timedate_date_separator_type' in
|
||||
* 'menu_defines.h' */
|
||||
enum core_backup_date_separator_type
|
||||
{
|
||||
CORE_BACKUP_DATE_SEPARATOR_HYPHEN = 0,
|
||||
CORE_BACKUP_DATE_SEPARATOR_SLASH,
|
||||
CORE_BACKUP_DATE_SEPARATOR_PERIOD,
|
||||
CORE_BACKUP_DATE_SEPARATOR_LAST
|
||||
};
|
||||
|
||||
/* Holds all timestamp info for a core backup file */
|
||||
typedef struct
|
||||
{
|
||||
unsigned year;
|
||||
unsigned month;
|
||||
unsigned day;
|
||||
unsigned hour;
|
||||
unsigned minute;
|
||||
unsigned second;
|
||||
} core_backup_list_date_t;
|
||||
|
||||
/* Holds all info related to a core backup file */
|
||||
typedef struct
|
||||
{
|
||||
char *backup_path;
|
||||
core_backup_list_date_t date;
|
||||
uint32_t crc;
|
||||
enum core_backup_mode backup_mode;
|
||||
} core_backup_list_entry_t;
|
||||
|
||||
/* Prevent direct access to core_backup_list_t
|
||||
* members */
|
||||
typedef struct core_backup_list core_backup_list_t;
|
||||
|
||||
/*********************/
|
||||
/* Utility Functions */
|
||||
/*********************/
|
||||
|
||||
/* Generates a timestamped core backup file path from
|
||||
* the specified core path. Returns true if successful */
|
||||
bool core_backup_get_backup_path(
|
||||
const char *core_path, uint32_t crc, enum core_backup_mode backup_mode,
|
||||
const char *dir_core_assets, char *backup_path, size_t len);
|
||||
|
||||
/* Returns detected type of specified core backup file */
|
||||
enum core_backup_type core_backup_get_backup_type(const char *backup_path);
|
||||
|
||||
/* Fetches crc value of specified core backup file.
|
||||
* Returns true if successful */
|
||||
bool core_backup_get_backup_crc(char *backup_path, uint32_t *crc);
|
||||
|
||||
/* Fetches core path associated with specified core
|
||||
* backup file. Returns detected type of backup
|
||||
* file - CORE_BACKUP_TYPE_INVALID indicates that
|
||||
* backup file cannot be restored/installed, or
|
||||
* arguments are otherwise invalid */
|
||||
enum core_backup_type core_backup_get_core_path(
|
||||
const char *backup_path, const char *dir_libretro,
|
||||
char *core_path, size_t len);
|
||||
|
||||
/*************************/
|
||||
/* Backup List Functions */
|
||||
/*************************/
|
||||
|
||||
/**************************************/
|
||||
/* Initialisation / De-Initialisation */
|
||||
/**************************************/
|
||||
|
||||
/* Creates a new core backup list containing entries
|
||||
* for all existing backup files.
|
||||
* Returns a handle to a new core_backup_list_t object
|
||||
* on success, otherwise returns NULL. */
|
||||
core_backup_list_t *core_backup_list_init(
|
||||
const char *core_path, const char *dir_core_assets);
|
||||
|
||||
/* Frees specified core backup list */
|
||||
void core_backup_list_free(core_backup_list_t *backup_list);
|
||||
|
||||
/***********/
|
||||
/* Getters */
|
||||
/***********/
|
||||
|
||||
/* Returns number of entries in core backup list */
|
||||
size_t core_backup_list_size(core_backup_list_t *backup_list);
|
||||
|
||||
/* Returns number of entries of specified 'backup mode'
|
||||
* (manual or automatic) in core backup list */
|
||||
size_t core_backup_list_get_num_backups(
|
||||
core_backup_list_t *backup_list,
|
||||
enum core_backup_mode backup_mode);
|
||||
|
||||
/* Fetches core backup list entry corresponding
|
||||
* to the specified entry index.
|
||||
* Returns false if index is invalid. */
|
||||
bool core_backup_list_get_index(
|
||||
core_backup_list_t *backup_list,
|
||||
size_t idx,
|
||||
const core_backup_list_entry_t **entry);
|
||||
|
||||
/* Fetches core backup list entry corresponding
|
||||
* to the specified core crc checksum value.
|
||||
* Note that 'manual' and 'auto' backups are
|
||||
* considered independent - we only compare
|
||||
* crc values for the specified backup_mode.
|
||||
* Returns false if entry is not found. */
|
||||
bool core_backup_list_get_crc(
|
||||
core_backup_list_t *backup_list,
|
||||
uint32_t crc, enum core_backup_mode backup_mode,
|
||||
const core_backup_list_entry_t **entry);
|
||||
|
||||
/* Fetches a string representation of a backup
|
||||
* list entry timestamp.
|
||||
* Returns false in the event of an error */
|
||||
bool core_backup_list_get_entry_timestamp_str(
|
||||
const core_backup_list_entry_t *entry,
|
||||
enum core_backup_date_separator_type date_separator,
|
||||
char *timestamp, size_t len);
|
||||
|
||||
/* Fetches a string representation of a backup
|
||||
* list entry crc value.
|
||||
* Returns false in the event of an error */
|
||||
bool core_backup_list_get_entry_crc_str(
|
||||
const core_backup_list_entry_t *entry,
|
||||
char *crc, size_t len);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
545
core_info.c
545
core_info.c
@ -19,6 +19,7 @@
|
||||
#include <string/stdstring.h>
|
||||
#include <file/config_file.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <lists/dir_list.h>
|
||||
#include <file/archive_file.h>
|
||||
|
||||
@ -45,25 +46,6 @@ enum compare_op
|
||||
COMPARE_OP_GREATER_EQUAL
|
||||
};
|
||||
|
||||
struct core_info_state
|
||||
{
|
||||
#ifdef HAVE_COMPRESSION
|
||||
const struct string_list *tmp_list;
|
||||
#endif
|
||||
const char *tmp_path;
|
||||
core_info_t *current;
|
||||
core_info_list_t *curr_list;
|
||||
};
|
||||
|
||||
typedef struct core_info_state core_info_state_t;
|
||||
|
||||
static core_info_state_t core_info_st;
|
||||
|
||||
static core_info_state_t *coreinfo_get_ptr(void)
|
||||
{
|
||||
return &core_info_st;
|
||||
}
|
||||
|
||||
static void core_info_list_resolve_all_extensions(
|
||||
core_info_list_t *core_info_list)
|
||||
{
|
||||
@ -140,15 +122,17 @@ static void core_info_list_resolve_all_firmware(
|
||||
snprintf(desc_key, sizeof(desc_key), "firmware%u_desc", c);
|
||||
snprintf(opt_key, sizeof(opt_key), "firmware%u_opt", c);
|
||||
|
||||
if (config_get_string(config, path_key, &tmp) && !string_is_empty(tmp))
|
||||
if (config_get_string(config, path_key, &tmp))
|
||||
{
|
||||
info->firmware[c].path = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
info->firmware[c].path = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
if (config_get_string(config, desc_key, &tmp) && !string_is_empty(tmp))
|
||||
if (config_get_string(config, desc_key, &tmp))
|
||||
{
|
||||
info->firmware[c].desc = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
info->firmware[c].desc = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
@ -187,6 +171,7 @@ static void core_info_list_free(core_info_list_t *core_info_list)
|
||||
free(info->databases);
|
||||
free(info->notes);
|
||||
free(info->required_hw_api);
|
||||
free(info->description);
|
||||
string_list_free(info->supported_extensions_list);
|
||||
string_list_free(info->authors_list);
|
||||
string_list_free(info->note_list);
|
||||
@ -203,6 +188,8 @@ static void core_info_list_free(core_info_list_t *core_info_list)
|
||||
free(info->firmware[j].desc);
|
||||
}
|
||||
free(info->firmware);
|
||||
|
||||
free(info->core_file_id.str);
|
||||
}
|
||||
|
||||
free(core_info_list->all_ext);
|
||||
@ -230,7 +217,7 @@ static config_file_t *core_info_list_iterate(
|
||||
current_path,
|
||||
info_path_base_size);
|
||||
|
||||
#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(PS2) && !defined(HW_WUP))
|
||||
#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(HW_WUP))
|
||||
{
|
||||
char *substr = strrchr(info_path_base, '_');
|
||||
if (substr)
|
||||
@ -254,6 +241,36 @@ static config_file_t *core_info_list_iterate(
|
||||
return conf;
|
||||
}
|
||||
|
||||
/* Returned path must be free()'d */
|
||||
static char *core_info_get_core_lock_file_path(const char *core_path)
|
||||
{
|
||||
char *lock_file_path = NULL;
|
||||
const char *lock_file_ext = file_path_str(FILE_PATH_LOCK_EXTENSION);
|
||||
size_t len;
|
||||
|
||||
if (string_is_empty(core_path))
|
||||
return NULL;
|
||||
|
||||
/* Note: We follow the common 'core_info' trend of
|
||||
* allocating all strings dynamically... */
|
||||
|
||||
/* Get path length */
|
||||
len = (strlen(core_path) + strlen(lock_file_ext) + 1) * sizeof(char);
|
||||
|
||||
/* Allocate string */
|
||||
lock_file_path = (char*)malloc(len);
|
||||
if (!lock_file_path)
|
||||
return NULL;
|
||||
|
||||
lock_file_path[0] = '\0';
|
||||
|
||||
/* Lock file is just core path + 'lock' extension */
|
||||
strlcpy(lock_file_path, core_path, len);
|
||||
strlcat(lock_file_path, lock_file_ext, len);
|
||||
|
||||
return lock_file_path;
|
||||
}
|
||||
|
||||
static core_info_list_t *core_info_list_new(const char *path,
|
||||
const char *libretro_info_dir,
|
||||
const char *exts,
|
||||
@ -315,48 +332,48 @@ static core_info_list_t *core_info_list_new(const char *path,
|
||||
{
|
||||
char *tmp = NULL;
|
||||
|
||||
if (config_get_string(conf, "display_name", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "display_name", &tmp))
|
||||
{
|
||||
core_info[i].display_name = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].display_name = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
if (config_get_string(conf, "display_version", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "display_version", &tmp))
|
||||
{
|
||||
core_info[i].display_version = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].display_version = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
if (config_get_string(conf, "corename", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "corename", &tmp))
|
||||
{
|
||||
core_info[i].core_name = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].core_name = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "systemname", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "systemname", &tmp))
|
||||
{
|
||||
core_info[i].systemname = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].systemname = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "systemid", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "systemid", &tmp))
|
||||
{
|
||||
core_info[i].system_id = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].system_id = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "manufacturer", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "manufacturer", &tmp))
|
||||
{
|
||||
core_info[i].system_manufacturer = strdup(tmp);
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].system_manufacturer = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
@ -367,92 +384,116 @@ static core_info_list_t *core_info_list_new(const char *path,
|
||||
core_info[i].firmware_count = count;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "supported_extensions", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "supported_extensions", &tmp))
|
||||
{
|
||||
core_info[i].supported_extensions = strdup(tmp);
|
||||
core_info[i].supported_extensions_list =
|
||||
string_split(core_info[i].supported_extensions, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].supported_extensions = strdup(tmp);
|
||||
core_info[i].supported_extensions_list =
|
||||
string_split(core_info[i].supported_extensions, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "authors", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "authors", &tmp))
|
||||
{
|
||||
core_info[i].authors = strdup(tmp);
|
||||
core_info[i].authors_list =
|
||||
string_split(core_info[i].authors, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].authors = strdup(tmp);
|
||||
core_info[i].authors_list =
|
||||
string_split(core_info[i].authors, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "permissions", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "permissions", &tmp))
|
||||
{
|
||||
core_info[i].permissions = strdup(tmp);
|
||||
core_info[i].permissions_list =
|
||||
string_split(core_info[i].permissions, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].permissions = strdup(tmp);
|
||||
core_info[i].permissions_list =
|
||||
string_split(core_info[i].permissions, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "license", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "license", &tmp))
|
||||
{
|
||||
core_info[i].licenses = strdup(tmp);
|
||||
core_info[i].licenses_list =
|
||||
string_split(core_info[i].licenses, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].licenses = strdup(tmp);
|
||||
core_info[i].licenses_list =
|
||||
string_split(core_info[i].licenses, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "categories", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "categories", &tmp))
|
||||
{
|
||||
core_info[i].categories = strdup(tmp);
|
||||
core_info[i].categories_list =
|
||||
string_split(core_info[i].categories, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].categories = strdup(tmp);
|
||||
core_info[i].categories_list =
|
||||
string_split(core_info[i].categories, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "database", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "database", &tmp))
|
||||
{
|
||||
core_info[i].databases = strdup(tmp);
|
||||
core_info[i].databases_list =
|
||||
string_split(core_info[i].databases, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].databases = strdup(tmp);
|
||||
core_info[i].databases_list =
|
||||
string_split(core_info[i].databases, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "notes", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "notes", &tmp))
|
||||
{
|
||||
core_info[i].notes = strdup(tmp);
|
||||
core_info[i].note_list = string_split(core_info[i].notes, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].notes = strdup(tmp);
|
||||
core_info[i].note_list = string_split(core_info[i].notes, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "required_hw_api", &tmp)
|
||||
&& !string_is_empty(tmp))
|
||||
if (config_get_string(conf, "required_hw_api", &tmp))
|
||||
{
|
||||
core_info[i].required_hw_api = strdup(tmp);
|
||||
core_info[i].required_hw_api_list = string_split(core_info[i].required_hw_api, "|");
|
||||
if (!string_is_empty(tmp))
|
||||
{
|
||||
core_info[i].required_hw_api = strdup(tmp);
|
||||
core_info[i].required_hw_api_list = string_split(core_info[i].required_hw_api, "|");
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (config_get_string(conf, "description", &tmp))
|
||||
{
|
||||
if (!string_is_empty(tmp))
|
||||
core_info[i].description = strdup(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
@ -466,17 +507,56 @@ static core_info_list_t *core_info_list_new(const char *path,
|
||||
if (config_get_bool(conf, "database_match_archive_member",
|
||||
&tmp_bool))
|
||||
core_info[i].database_match_archive_member = tmp_bool;
|
||||
|
||||
if (config_get_bool(conf, "is_experimental",
|
||||
&tmp_bool))
|
||||
core_info[i].is_experimental = tmp_bool;
|
||||
}
|
||||
|
||||
core_info[i].config_data = conf;
|
||||
}
|
||||
|
||||
if (!string_is_empty(base_path))
|
||||
{
|
||||
const char *core_filename = path_basename(base_path);
|
||||
|
||||
/* Cache core path */
|
||||
core_info[i].path = strdup(base_path);
|
||||
|
||||
if (!core_info[i].display_name)
|
||||
core_info[i].display_name =
|
||||
strdup(path_basename(core_info[i].path));
|
||||
/* Cache core file 'id'
|
||||
* > Filename without extension or platform-specific suffix */
|
||||
if (!string_is_empty(core_filename))
|
||||
{
|
||||
char *core_file_id = strdup(core_filename);
|
||||
path_remove_extension(core_file_id);
|
||||
|
||||
if (!string_is_empty(core_file_id))
|
||||
{
|
||||
#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(HW_WUP))
|
||||
char *last_underscore = strrchr(core_file_id, '_');
|
||||
if (last_underscore)
|
||||
*last_underscore = '\0';
|
||||
#endif
|
||||
core_info[i].core_file_id.str = core_file_id;
|
||||
core_info[i].core_file_id.len = strlen(core_file_id);
|
||||
|
||||
core_file_id = NULL;
|
||||
}
|
||||
|
||||
if (core_file_id)
|
||||
{
|
||||
free(core_file_id);
|
||||
core_file_id = NULL;
|
||||
}
|
||||
|
||||
/* Get fallback display name, if required */
|
||||
if (!core_info[i].display_name)
|
||||
core_info[i].display_name = strdup(core_filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get core lock status */
|
||||
core_info[i].is_locked = core_info_get_core_lock(core_info[i].path, false);
|
||||
}
|
||||
|
||||
if (core_info_list)
|
||||
@ -497,7 +577,13 @@ bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
core_info_t *out_info, const char *path)
|
||||
{
|
||||
size_t i;
|
||||
if (!core_info_list || !out_info)
|
||||
const char *core_filename = NULL;
|
||||
|
||||
if (!core_info_list || !out_info || string_is_empty(path))
|
||||
return false;
|
||||
|
||||
core_filename = path_basename(path);
|
||||
if (string_is_empty(core_filename))
|
||||
return false;
|
||||
|
||||
memset(out_info, 0, sizeof(*out_info));
|
||||
@ -506,8 +592,10 @@ bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
{
|
||||
const core_info_t *info = &core_info_list->list[i];
|
||||
|
||||
if (string_is_equal(path_basename(info->path),
|
||||
path_basename(path)))
|
||||
if (!info || (info->core_file_id.len == 0))
|
||||
continue;
|
||||
|
||||
if (!strncmp(info->core_file_id.str, core_filename, info->core_file_id.len))
|
||||
{
|
||||
*out_info = *info;
|
||||
return true;
|
||||
@ -573,15 +661,23 @@ static core_info_t *core_info_find_internal(
|
||||
const char *core)
|
||||
{
|
||||
size_t i;
|
||||
const char *core_path_basename = path_basename(core);
|
||||
const char *core_filename = NULL;
|
||||
|
||||
if (!list || string_is_empty(core))
|
||||
return NULL;
|
||||
|
||||
core_filename = path_basename(core);
|
||||
if (string_is_empty(core_filename))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < list->count; i++)
|
||||
{
|
||||
core_info_t *info = core_info_get(list, i);
|
||||
|
||||
if (!info || !info->path)
|
||||
if (!info || (info->core_file_id.len == 0))
|
||||
continue;
|
||||
if (string_is_equal(path_basename(info->path), core_path_basename))
|
||||
|
||||
if (!strncmp(info->core_file_id.str, core_filename, info->core_file_id.len))
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -630,9 +726,8 @@ static bool core_info_list_update_missing_firmware_internal(
|
||||
return true;
|
||||
}
|
||||
|
||||
void core_info_free_current_core(void)
|
||||
void core_info_free_current_core(core_info_state_t *p_coreinfo)
|
||||
{
|
||||
core_info_state_t *p_coreinfo = coreinfo_get_ptr();
|
||||
if (p_coreinfo->current)
|
||||
free(p_coreinfo->current);
|
||||
p_coreinfo->current = NULL;
|
||||
@ -698,10 +793,11 @@ bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info,
|
||||
set_missing_bios);
|
||||
}
|
||||
|
||||
bool core_info_load(core_info_ctx_find_t *info)
|
||||
bool core_info_load(
|
||||
core_info_ctx_find_t *info,
|
||||
core_info_state_t *p_coreinfo)
|
||||
{
|
||||
core_info_t *core_info = NULL;
|
||||
core_info_state_t *p_coreinfo = coreinfo_get_ptr();
|
||||
|
||||
if (!info)
|
||||
return false;
|
||||
@ -721,14 +817,18 @@ bool core_info_load(core_info_ctx_find_t *info)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool core_info_find(core_info_ctx_find_t *info, const char *core_path)
|
||||
bool core_info_find(core_info_ctx_find_t *info)
|
||||
{
|
||||
core_info_state_t *p_coreinfo = coreinfo_get_ptr();
|
||||
|
||||
if (!info || !p_coreinfo->curr_list)
|
||||
return false;
|
||||
info->inf = core_info_find_internal(p_coreinfo->curr_list, core_path);
|
||||
|
||||
info->inf = core_info_find_internal(p_coreinfo->curr_list, info->path);
|
||||
|
||||
if (!info->inf)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -946,22 +1046,30 @@ bool core_info_list_get_display_name(core_info_list_t *core_info_list,
|
||||
const char *path, char *s, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
const char *core_filename = NULL;
|
||||
|
||||
if (!core_info_list)
|
||||
if (!core_info_list || string_is_empty(path))
|
||||
return false;
|
||||
|
||||
core_filename = path_basename(path);
|
||||
if (string_is_empty(core_filename))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
const core_info_t *info = &core_info_list->list[i];
|
||||
|
||||
if (!string_is_equal(path_basename(info->path), path_basename(path)))
|
||||
if (!info || (info->core_file_id.len == 0))
|
||||
continue;
|
||||
|
||||
if (!info->display_name)
|
||||
continue;
|
||||
if (!strncmp(info->core_file_id.str, core_filename, info->core_file_id.len))
|
||||
{
|
||||
if (string_is_empty(info->display_name))
|
||||
break;
|
||||
|
||||
strlcpy(s, info->display_name, len);
|
||||
return true;
|
||||
strlcpy(s, info->display_name, len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -985,6 +1093,100 @@ bool core_info_get_display_name(const char *path, char *s, size_t len)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns core_info parameters required for
|
||||
* core updater tasks, read from specified file.
|
||||
* Returned core_updater_info_t object must be
|
||||
* freed using core_info_free_core_updater_info().
|
||||
* Returns NULL if 'path' is invalid. */
|
||||
core_updater_info_t *core_info_get_core_updater_info(const char *path)
|
||||
{
|
||||
char *tmp_str = NULL;
|
||||
bool tmp_bool = false;
|
||||
core_updater_info_t *info = NULL;
|
||||
config_file_t *conf = NULL;
|
||||
|
||||
if (string_is_empty(path))
|
||||
return NULL;
|
||||
|
||||
/* Read config file */
|
||||
conf = config_file_new_from_path_to_string(path);
|
||||
|
||||
if (!conf)
|
||||
return NULL;
|
||||
|
||||
/* Create info struct */
|
||||
info = (core_updater_info_t*)calloc(1, sizeof(*info));
|
||||
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
/* Fetch required parameters */
|
||||
|
||||
/* > is_experimental */
|
||||
info->is_experimental = false;
|
||||
if (config_get_bool(conf, "is_experimental", &tmp_bool))
|
||||
info->is_experimental = tmp_bool;
|
||||
|
||||
/* > display_name */
|
||||
info->display_name = NULL;
|
||||
if (config_get_string(conf, "display_name", &tmp_str))
|
||||
{
|
||||
if (!string_is_empty(tmp_str))
|
||||
info->display_name = tmp_str;
|
||||
else
|
||||
free(tmp_str);
|
||||
|
||||
tmp_str = NULL;
|
||||
}
|
||||
|
||||
/* > description */
|
||||
info->description = NULL;
|
||||
if (config_get_string(conf, "description", &tmp_str))
|
||||
{
|
||||
if (!string_is_empty(tmp_str))
|
||||
info->description = tmp_str;
|
||||
else
|
||||
free(tmp_str);
|
||||
|
||||
tmp_str = NULL;
|
||||
}
|
||||
|
||||
/* > licenses */
|
||||
info->licenses = NULL;
|
||||
if (config_get_string(conf, "license", &tmp_str))
|
||||
{
|
||||
if (!string_is_empty(tmp_str))
|
||||
info->licenses = tmp_str;
|
||||
else
|
||||
free(tmp_str);
|
||||
|
||||
tmp_str = NULL;
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
config_file_free(conf);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void core_info_free_core_updater_info(core_updater_info_t *info)
|
||||
{
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (info->display_name)
|
||||
free(info->display_name);
|
||||
|
||||
if (info->description)
|
||||
free(info->description);
|
||||
|
||||
if (info->licenses)
|
||||
free(info->licenses);
|
||||
|
||||
free(info);
|
||||
info = NULL;
|
||||
}
|
||||
|
||||
static int core_info_qsort_func_path(const core_info_t *a,
|
||||
const core_info_t *b)
|
||||
{
|
||||
@ -1337,3 +1539,144 @@ bool core_info_hw_api_supported(core_info_t *info)
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sets 'locked' status of specified core
|
||||
* > Returns true if successful
|
||||
* > Like all functions that access the cached
|
||||
* core info list this is *not* thread safe */
|
||||
bool core_info_set_core_lock(const char *core_path, bool lock)
|
||||
{
|
||||
char *lock_file_path = NULL;
|
||||
RFILE *lock_file = NULL;
|
||||
bool lock_file_exists = false;
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
if (string_is_empty(core_path))
|
||||
goto error;
|
||||
|
||||
/* Search for specified core */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (!core_info_find(&core_info))
|
||||
goto error;
|
||||
|
||||
/* Get associated lock file path */
|
||||
lock_file_path = core_info_get_core_lock_file_path(core_info.inf->path);
|
||||
|
||||
if (string_is_empty(lock_file_path))
|
||||
goto error;
|
||||
|
||||
/* Check whether lock file exists */
|
||||
lock_file_exists = path_is_valid(lock_file_path);
|
||||
|
||||
/* Create or delete lock file, as required */
|
||||
if (lock && !lock_file_exists)
|
||||
{
|
||||
lock_file = filestream_open(
|
||||
lock_file_path,
|
||||
RETRO_VFS_FILE_ACCESS_WRITE,
|
||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
|
||||
if (!lock_file)
|
||||
goto error;
|
||||
|
||||
/* We have to write something - just output
|
||||
* a single character */
|
||||
if (filestream_putc(lock_file, 0) != 0)
|
||||
goto error;
|
||||
|
||||
filestream_close(lock_file);
|
||||
lock_file = NULL;
|
||||
}
|
||||
else if (!lock && lock_file_exists)
|
||||
if (filestream_delete(lock_file_path) != 0)
|
||||
goto error;
|
||||
|
||||
/* Clean up */
|
||||
free(lock_file_path);
|
||||
lock_file_path = NULL;
|
||||
|
||||
/* File operations were successful - update
|
||||
* core info entry */
|
||||
core_info.inf->is_locked = lock;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (lock_file_path)
|
||||
{
|
||||
free(lock_file_path);
|
||||
lock_file_path = NULL;
|
||||
}
|
||||
|
||||
if (lock_file)
|
||||
{
|
||||
filestream_close(lock_file);
|
||||
lock_file = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetches 'locked' status of specified core
|
||||
* > If 'validate_path' is 'true', will search
|
||||
* cached core info list for a corresponding
|
||||
* 'sanitised' core file path. This is *not*
|
||||
* thread safe
|
||||
* > If 'validate_path' is 'false', performs a
|
||||
* direct filesystem check. This *is* thread
|
||||
* safe, but validity of specified core path
|
||||
* must be checked externally */
|
||||
bool core_info_get_core_lock(const char *core_path, bool validate_path)
|
||||
{
|
||||
const char *core_file_path = NULL;
|
||||
char *lock_file_path = NULL;
|
||||
bool is_locked = false;
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
if (string_is_empty(core_path))
|
||||
goto end;
|
||||
|
||||
/* Check whether core path is to be validated */
|
||||
if (validate_path)
|
||||
{
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
if (core_info_find(&core_info))
|
||||
core_file_path = core_info.inf->path;
|
||||
}
|
||||
else
|
||||
core_file_path = core_path;
|
||||
|
||||
/* A core cannot be locked if it does not exist... */
|
||||
if (string_is_empty(core_file_path) ||
|
||||
!path_is_valid(core_file_path))
|
||||
goto end;
|
||||
|
||||
/* Get lock file path */
|
||||
lock_file_path = core_info_get_core_lock_file_path(core_file_path);
|
||||
|
||||
if (string_is_empty(lock_file_path))
|
||||
goto end;
|
||||
|
||||
/* Check whether lock file exists */
|
||||
is_locked = path_is_valid(lock_file_path);
|
||||
|
||||
/* If core path has been validated (and a
|
||||
* core info object is available), ensure
|
||||
* that core info 'is_locked' field is
|
||||
* up to date */
|
||||
if (validate_path && core_info.inf)
|
||||
core_info.inf->is_locked = is_locked;
|
||||
|
||||
end:
|
||||
if (lock_file_path)
|
||||
{
|
||||
free(lock_file_path);
|
||||
lock_file_path = NULL;
|
||||
}
|
||||
|
||||
return is_locked;
|
||||
}
|
||||
|
77
core_info.h
77
core_info.h
@ -35,10 +35,29 @@ typedef struct
|
||||
bool optional;
|
||||
} core_info_firmware_t;
|
||||
|
||||
/* Simple container/convenience struct for
|
||||
* holding the 'id' of a core file
|
||||
* > 'id' is the filename without extension or
|
||||
* platform-specific suffix
|
||||
* > 'id' is used for core info searches - enables
|
||||
* matching regardless of core file base path,
|
||||
* and is platform-independent (e.g. an Android
|
||||
* core file will be correctly identified on Linux)
|
||||
* > 'len' is used to cache the length of 'str', for
|
||||
* improved performance when performing string
|
||||
* comparisons */
|
||||
typedef struct
|
||||
{
|
||||
char *str;
|
||||
size_t len;
|
||||
} core_file_id_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool supports_no_game;
|
||||
bool database_match_archive_member;
|
||||
bool is_experimental;
|
||||
bool is_locked;
|
||||
size_t firmware_count;
|
||||
char *path;
|
||||
void *config_data;
|
||||
@ -56,6 +75,7 @@ typedef struct
|
||||
char *databases;
|
||||
char *notes;
|
||||
char *required_hw_api;
|
||||
char *description;
|
||||
struct string_list *categories_list;
|
||||
struct string_list *databases_list;
|
||||
struct string_list *note_list;
|
||||
@ -65,9 +85,20 @@ typedef struct
|
||||
struct string_list *licenses_list;
|
||||
struct string_list *required_hw_api_list;
|
||||
core_info_firmware_t *firmware;
|
||||
core_file_id_t core_file_id;
|
||||
void *userdata;
|
||||
} core_info_t;
|
||||
|
||||
/* A subset of core_info parameters required for
|
||||
* core updater tasks */
|
||||
typedef struct
|
||||
{
|
||||
bool is_experimental;
|
||||
char *display_name;
|
||||
char *description;
|
||||
char *licenses;
|
||||
} core_updater_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
core_info_t *list;
|
||||
@ -98,6 +129,18 @@ enum core_info_list_qsort_type
|
||||
CORE_INFO_LIST_SORT_SYSTEM_NAME
|
||||
};
|
||||
|
||||
struct core_info_state
|
||||
{
|
||||
#ifdef HAVE_COMPRESSION
|
||||
const struct string_list *tmp_list;
|
||||
#endif
|
||||
const char *tmp_path;
|
||||
core_info_t *current;
|
||||
core_info_list_t *curr_list;
|
||||
};
|
||||
|
||||
typedef struct core_info_state core_info_state_t;
|
||||
|
||||
size_t core_info_list_num_info_files(core_info_list_t *list);
|
||||
|
||||
/* Non-reentrant, does not allocate. Returns pointer to internal state. */
|
||||
@ -109,6 +152,14 @@ bool core_info_list_get_display_name(core_info_list_t *list,
|
||||
|
||||
bool core_info_get_display_name(const char *path, char *s, size_t len);
|
||||
|
||||
/* Returns core_info parameters required for
|
||||
* core updater tasks, read from specified file.
|
||||
* Returned core_updater_info_t object must be
|
||||
* freed using core_info_free_core_updater_info().
|
||||
* Returns NULL if 'path' is invalid. */
|
||||
core_updater_info_t *core_info_get_core_updater_info(const char *path);
|
||||
void core_info_free_core_updater_info(core_updater_info_t *info);
|
||||
|
||||
void core_info_get_name(const char *path, char *s, size_t len,
|
||||
const char *path_info, const char *dir_cores,
|
||||
const char *exts, bool show_hidden_files,
|
||||
@ -116,7 +167,7 @@ void core_info_get_name(const char *path, char *s, size_t len,
|
||||
|
||||
core_info_t *core_info_get(core_info_list_t *list, size_t i);
|
||||
|
||||
void core_info_free_current_core(void);
|
||||
void core_info_free_current_core(core_info_state_t *p_coreinfo);
|
||||
|
||||
bool core_info_init_current_core(void);
|
||||
|
||||
@ -132,9 +183,11 @@ bool core_info_get_list(core_info_list_t **core);
|
||||
bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info,
|
||||
bool *set_missing_bios);
|
||||
|
||||
bool core_info_find(core_info_ctx_find_t *info, const char *name);
|
||||
bool core_info_find(core_info_ctx_find_t *info);
|
||||
|
||||
bool core_info_load(core_info_ctx_find_t *info);
|
||||
bool core_info_load(
|
||||
core_info_ctx_find_t *info,
|
||||
core_info_state_t *p_coreinfo);
|
||||
|
||||
bool core_info_database_supports_content_path(const char *database_path, const char *path);
|
||||
|
||||
@ -149,6 +202,24 @@ bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
|
||||
bool core_info_hw_api_supported(core_info_t *info);
|
||||
|
||||
/* Sets 'locked' status of specified core
|
||||
* > Returns true if successful
|
||||
* > Like all functions that access the cached
|
||||
* core info list this is *not* thread safe */
|
||||
bool core_info_set_core_lock(const char *core_path, bool lock);
|
||||
/* Fetches 'locked' status of specified core
|
||||
* > If 'validate_path' is 'true', will search
|
||||
* cached core info list for a corresponding
|
||||
* 'sanitised' core file path. This is *not*
|
||||
* thread safe
|
||||
* > If 'validate_path' is 'false', performs a
|
||||
* direct filesystem check. This *is* thread
|
||||
* safe, but validity of specified core path
|
||||
* must be checked externally */
|
||||
bool core_info_get_core_lock(const char *core_path, bool validate_path);
|
||||
|
||||
core_info_state_t *coreinfo_get_ptr(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* CORE_INFO_H_ */
|
||||
|
@ -82,6 +82,18 @@ static void core_updater_list_free_entry(core_updater_list_entry_t *entry)
|
||||
free(entry->display_name);
|
||||
entry->display_name = NULL;
|
||||
}
|
||||
|
||||
if (entry->description)
|
||||
{
|
||||
free(entry->description);
|
||||
entry->description = NULL;
|
||||
}
|
||||
|
||||
if (entry->licenses_list)
|
||||
{
|
||||
string_list_free(entry->licenses_list);
|
||||
entry->licenses_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Creates a new, empty core updater list.
|
||||
@ -410,13 +422,11 @@ static bool core_updater_list_set_paths(
|
||||
char remote_core_path[PATH_MAX_LENGTH];
|
||||
char local_core_path[PATH_MAX_LENGTH];
|
||||
char local_info_path[PATH_MAX_LENGTH];
|
||||
char display_name[255];
|
||||
bool is_archive;
|
||||
|
||||
remote_core_path[0] = '\0';
|
||||
local_core_path[0] = '\0';
|
||||
local_info_path[0] = '\0';
|
||||
display_name[0] = '\0';
|
||||
|
||||
if (!entry || string_is_empty(filename_str))
|
||||
return false;
|
||||
@ -499,10 +509,8 @@ static bool core_updater_list_set_paths(
|
||||
last_underscore = (char*)strrchr(local_info_path, '_');
|
||||
|
||||
if (!string_is_empty(last_underscore))
|
||||
{
|
||||
if (string_is_not_equal_fast(last_underscore, "_libretro", 9))
|
||||
if (!string_is_equal(last_underscore, "_libretro"))
|
||||
*last_underscore = '\0';
|
||||
}
|
||||
|
||||
/* > Add proper file extension */
|
||||
strlcat(
|
||||
@ -518,29 +526,94 @@ static bool core_updater_list_set_paths(
|
||||
|
||||
entry->local_info_path = strdup(local_info_path);
|
||||
|
||||
/* display_name
|
||||
* > Note: It's a bit rubbish that we have to
|
||||
* read the actual core info files here...
|
||||
* Would be better to cache this globally
|
||||
* (at present, we only cache info for
|
||||
* *installed* cores...) */
|
||||
if (path_is_valid(local_info_path))
|
||||
if (!core_info_get_display_name(
|
||||
local_info_path, display_name, sizeof(display_name)))
|
||||
display_name[0] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
/* > If info file does not exist, just use
|
||||
* core filename */
|
||||
if (string_is_empty(display_name))
|
||||
strlcpy(display_name, filename_str, sizeof(display_name));
|
||||
/* Reads info file associated with core and
|
||||
* adds relevant information to updater list
|
||||
* entry */
|
||||
static bool core_updater_list_set_core_info(
|
||||
core_updater_list_entry_t *entry,
|
||||
const char *local_info_path,
|
||||
const char *filename_str)
|
||||
{
|
||||
core_updater_info_t *core_info = NULL;
|
||||
|
||||
if (!entry ||
|
||||
string_is_empty(local_info_path) ||
|
||||
string_is_empty(filename_str))
|
||||
return false;
|
||||
|
||||
/* Clear any existing core info */
|
||||
if (entry->display_name)
|
||||
{
|
||||
free(entry->display_name);
|
||||
entry->display_name = NULL;
|
||||
}
|
||||
|
||||
entry->display_name = strdup(display_name);
|
||||
if (entry->description)
|
||||
{
|
||||
free(entry->description);
|
||||
entry->description = NULL;
|
||||
}
|
||||
|
||||
if (entry->licenses_list)
|
||||
{
|
||||
/* Note: We can safely leave this as NULL if
|
||||
* the core info file is invalid */
|
||||
string_list_free(entry->licenses_list);
|
||||
entry->licenses_list = NULL;
|
||||
}
|
||||
|
||||
entry->is_experimental = false;
|
||||
|
||||
/* Read core info file
|
||||
* > Note: It's a bit rubbish that we have to
|
||||
* read the actual core info files here...
|
||||
* Would be better to cache this globally
|
||||
* (at present, we only cache info for
|
||||
* *installed* cores...) */
|
||||
core_info = core_info_get_core_updater_info(local_info_path);
|
||||
|
||||
if (core_info)
|
||||
{
|
||||
/* display_name + is_experimental */
|
||||
if (!string_is_empty(core_info->display_name))
|
||||
{
|
||||
entry->display_name = strdup(core_info->display_name);
|
||||
entry->is_experimental = core_info->is_experimental;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If display name is blank, use core filename and
|
||||
* assume core is experimental (i.e. all 'fit for consumption'
|
||||
* cores must have a valid/complete core info file) */
|
||||
entry->display_name = strdup(filename_str);
|
||||
entry->is_experimental = true;
|
||||
}
|
||||
|
||||
/* description */
|
||||
if (!string_is_empty(core_info->description))
|
||||
entry->description = strdup(core_info->description);
|
||||
else
|
||||
entry->description = strdup("");
|
||||
|
||||
/* licenses_list */
|
||||
if (!string_is_empty(core_info->licenses))
|
||||
entry->licenses_list = string_split(core_info->licenses, "|");
|
||||
|
||||
/* Clean up */
|
||||
core_info_free_core_updater_info(core_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If info file is missing, use core filename and
|
||||
* assume core is experimental (i.e. all 'fit for consumption'
|
||||
* cores must have a valid/complete core info file) */
|
||||
entry->display_name = strdup(filename_str);
|
||||
entry->is_experimental = true;
|
||||
entry->description = strdup("");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -576,10 +649,15 @@ static bool core_updater_list_push_entry(
|
||||
list_entry->remote_core_path = entry->remote_core_path;
|
||||
list_entry->local_core_path = entry->local_core_path;
|
||||
list_entry->local_info_path = entry->local_info_path;
|
||||
|
||||
/* Assign core info */
|
||||
list_entry->display_name = entry->display_name;
|
||||
list_entry->description = entry->description;
|
||||
list_entry->licenses_list = entry->licenses_list;
|
||||
list_entry->is_experimental = entry->is_experimental;
|
||||
|
||||
/* Copy crc */
|
||||
list_entry->crc = entry->crc;
|
||||
list_entry->crc = entry->crc;
|
||||
|
||||
/* Copy date */
|
||||
memcpy(&list_entry->date, &entry->date, sizeof(core_updater_list_date_t));
|
||||
@ -644,6 +722,12 @@ static void core_updater_list_add_entry(
|
||||
filename_str))
|
||||
goto error;
|
||||
|
||||
if (!core_updater_list_set_core_info(
|
||||
&entry,
|
||||
entry.local_info_path,
|
||||
filename_str))
|
||||
goto error;
|
||||
|
||||
/* Add entry to list */
|
||||
if (!core_updater_list_push_entry(core_list, &entry))
|
||||
goto error;
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <retro_common_api.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include <lists/string_list.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
@ -52,6 +54,9 @@ typedef struct
|
||||
char *local_core_path;
|
||||
char *local_info_path;
|
||||
char *display_name;
|
||||
char *description;
|
||||
struct string_list *licenses_list;
|
||||
bool is_experimental;
|
||||
uint32_t crc;
|
||||
core_updater_list_date_t date;
|
||||
} core_updater_list_entry_t;
|
||||
|
@ -144,7 +144,7 @@ void libretro_dummy_retro_get_system_av_info(
|
||||
refresh_rate = 60.0;
|
||||
|
||||
info->timing.fps = refresh_rate;
|
||||
info->timing.sample_rate = 30000.0;
|
||||
info->timing.sample_rate = 48000.0;
|
||||
|
||||
info->geometry.base_width = frame_buf_width;
|
||||
info->geometry.base_height = frame_buf_height;
|
||||
|
@ -126,12 +126,6 @@ else ifneq (,$(findstring win,$(platform)))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BIGENDIAN),1)
|
||||
CPUOPTS += -DHAVE_BIGENDIAN=1 -DMSB_FIRST
|
||||
else
|
||||
CPUOPTS += -DHAVE_BIGENDIAN=0
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SSA), 1)
|
||||
LIBS += $(shell pkg-config libass --libs)
|
||||
DEFINES += -DHAVE_SSA
|
||||
|
@ -692,38 +692,42 @@ void CORE_PREFIX(retro_run)(void)
|
||||
frames[0] = tmp;
|
||||
}
|
||||
|
||||
while (!decode_thread_dead && min_pts > frames[1].pts)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
|
||||
if (!decode_thread_dead)
|
||||
video_buffer_wait_for_finished_slot(video_buffer);
|
||||
|
||||
if (!decode_thread_dead)
|
||||
{
|
||||
uint32_t *data = video_frame_temp_buffer;
|
||||
|
||||
video_decoder_context_t *ctx = NULL;
|
||||
video_buffer_get_finished_slot(video_buffer, &ctx);
|
||||
pts = ctx->pts;
|
||||
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
|
||||
if (use_gl)
|
||||
if (use_gl)
|
||||
{
|
||||
float mix_factor;
|
||||
|
||||
while (!decode_thread_dead && min_pts > frames[1].pts)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
|
||||
if (!decode_thread_dead)
|
||||
video_buffer_wait_for_finished_slot(video_buffer);
|
||||
|
||||
if (!decode_thread_dead)
|
||||
{
|
||||
unsigned y;
|
||||
const uint8_t *src;
|
||||
int stride, width;
|
||||
uint32_t *data = video_frame_temp_buffer;
|
||||
|
||||
video_decoder_context_t *ctx = NULL;
|
||||
video_buffer_get_finished_slot(video_buffer, &ctx);
|
||||
pts = ctx->pts;
|
||||
|
||||
#ifndef HAVE_OPENGLES
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, frames[1].pbo);
|
||||
#ifdef __MACH__
|
||||
data = (uint32_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
data = (uint32_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
#else
|
||||
data = (uint32_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER,
|
||||
data = (uint32_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER,
|
||||
0, media.width * media.height * sizeof(uint32_t), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const uint8_t *src = ctx->target->data[0];
|
||||
int stride = ctx->target->linesize[0];
|
||||
int width = media.width * sizeof(uint32_t);
|
||||
for (unsigned y = 0; y < media.height; y++, src += stride, data += width/4)
|
||||
src = ctx->target->data[0];
|
||||
stride = ctx->target->linesize[0];
|
||||
width = media.width * sizeof(uint32_t);
|
||||
for (y = 0; y < media.height; y++, src += stride, data += width/4)
|
||||
memcpy(data, src, width);
|
||||
|
||||
#ifndef HAVE_OPENGLES
|
||||
@ -741,28 +745,13 @@ void CORE_PREFIX(retro_run)(void)
|
||||
#ifndef HAVE_OPENGLES
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
#endif
|
||||
video_buffer_open_slot(video_buffer, ctx);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const uint8_t *src = ctx->target->data[0];
|
||||
int stride = ctx->target->linesize[0];
|
||||
size_t width = media.width * sizeof(uint32_t);
|
||||
for (unsigned y = 0; y < media.height; y++, src += stride, data += width/4)
|
||||
memcpy(data, src, width);
|
||||
|
||||
dupe = false;
|
||||
}
|
||||
video_buffer_open_slot(video_buffer, ctx);
|
||||
frames[1].pts = av_q2d(fctx->streams[video_stream_index]->time_base) * pts;
|
||||
}
|
||||
|
||||
frames[1].pts = av_q2d(fctx->streams[video_stream_index]->time_base) * pts;
|
||||
}
|
||||
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
|
||||
if (use_gl)
|
||||
{
|
||||
float mix_factor = (min_pts - frames[0].pts) / (frames[1].pts - frames[0].pts);
|
||||
mix_factor = (min_pts - frames[0].pts) / (frames[1].pts - frames[0].pts);
|
||||
|
||||
if (!temporal_interpolation)
|
||||
mix_factor = 1.0f;
|
||||
@ -804,6 +793,36 @@ void CORE_PREFIX(retro_run)(void)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
while (!decode_thread_dead && min_pts > frames[1].pts)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
|
||||
if (!decode_thread_dead)
|
||||
video_buffer_wait_for_finished_slot(video_buffer);
|
||||
|
||||
if (!decode_thread_dead)
|
||||
{
|
||||
unsigned y;
|
||||
const uint8_t *src;
|
||||
int stride, width;
|
||||
uint32_t *data = video_frame_temp_buffer;
|
||||
video_decoder_context_t *ctx = NULL;
|
||||
|
||||
video_buffer_get_finished_slot(video_buffer, &ctx);
|
||||
pts = ctx->pts;
|
||||
src = ctx->target->data[0];
|
||||
stride = ctx->target->linesize[0];
|
||||
width = media.width * sizeof(uint32_t);
|
||||
for (y = 0; y < media.height; y++, src += stride, data += width/4)
|
||||
memcpy(data, src, width);
|
||||
|
||||
dupe = false;
|
||||
video_buffer_open_slot(video_buffer, ctx);
|
||||
}
|
||||
|
||||
frames[1].pts = av_q2d(fctx->streams[video_stream_index]->time_base) * pts;
|
||||
}
|
||||
|
||||
CORE_PREFIX(video_cb)(dupe ? NULL : video_frame_temp_buffer,
|
||||
media.width, media.height, media.width * sizeof(uint32_t));
|
||||
}
|
||||
|
@ -37,25 +37,32 @@ void ctr_linear_free_pages(u32 pages);
|
||||
|
||||
void ctr_free_pages(u32 pages)
|
||||
{
|
||||
u32 linear_free_pages;
|
||||
u32 stack_free, stack_usage, stack_free_pages;
|
||||
|
||||
if(!pages)
|
||||
return;
|
||||
|
||||
u32 linear_free_pages = ctr_get_linear_free() >> 12;
|
||||
linear_free_pages = ctr_get_linear_free() >> 12;
|
||||
|
||||
if((ctr_get_linear_unused() >> 12) > pages + 0x100)
|
||||
if ((ctr_get_linear_unused() >> 12) > pages + 0x100)
|
||||
return ctr_linear_free_pages(pages);
|
||||
|
||||
#if 0
|
||||
if(linear_free_pages > pages + 0x400)
|
||||
if (linear_free_pages > pages + 0x400)
|
||||
return ctr_linear_free_pages(pages);
|
||||
#endif
|
||||
|
||||
u32 stack_free = ctr_get_stack_free();
|
||||
u32 stack_usage = __stacksize__ > stack_free? __stacksize__ - stack_free: 0;
|
||||
stack_free = ctr_get_stack_free();
|
||||
stack_usage = __stacksize__ > stack_free
|
||||
? __stacksize__ - stack_free
|
||||
: 0;
|
||||
|
||||
stack_free = stack_free > __stack_size_extra ? __stack_size_extra : stack_free;
|
||||
stack_free = stack_free > __stack_size_extra
|
||||
? __stack_size_extra
|
||||
: stack_free;
|
||||
|
||||
u32 stack_free_pages = stack_free >> 12;
|
||||
stack_free_pages = stack_free >> 12;
|
||||
|
||||
if(linear_free_pages + (stack_free_pages - (stack_usage >> 12)) > pages)
|
||||
{
|
||||
@ -83,7 +90,8 @@ void ctr_free_pages(u32 pages)
|
||||
__stacksize__ -= stack_free_pages << 12;
|
||||
#if 0
|
||||
printf("s:0x%08X-->0x%08X(-0x%08X) \n", stack_free,
|
||||
stack_free - (stack_free_pages << 12), stack_free_pages << 12);
|
||||
stack_free - (stack_free_pages << 12),
|
||||
stack_free_pages << 12);
|
||||
DEBUG_HOLD();
|
||||
#endif
|
||||
}
|
||||
@ -111,11 +119,12 @@ void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
|
||||
{
|
||||
static u32 sbrk_top = 0;
|
||||
u32 tmp;
|
||||
int diff;
|
||||
|
||||
if (!sbrk_top)
|
||||
sbrk_top = __heapBase;
|
||||
|
||||
int diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
|
||||
diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
|
||||
- (__heapBase + __heap_size);
|
||||
|
||||
if (diff > 0)
|
||||
|
265
ctr/ctr_svchax.c
265
ctr/ctr_svchax.c
@ -15,13 +15,53 @@
|
||||
#define SVC_ACL_MASK(svc_id) (0x1 << ((svc_id) & 0x1F))
|
||||
#define THREAD_PAGE_ACL_OFFSET 0xF38
|
||||
|
||||
u32 __ctr_svchax = 0;
|
||||
u32 __ctr_svchax = 0;
|
||||
u32 __ctr_svchax_srv = 0;
|
||||
|
||||
extern void* __service_ptr;
|
||||
|
||||
typedef u32(*backdoor_fn)(u32 arg0, u32 arg1);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Handle started_event;
|
||||
Handle lock;
|
||||
volatile u32 target_kaddr;
|
||||
volatile u32 target_val;
|
||||
} mch2_thread_args_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32* stack_top;
|
||||
Handle handle;
|
||||
bool keep;
|
||||
mch2_thread_args_t args;
|
||||
} mch2_thread_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 old_cpu_time_limit;
|
||||
bool isNew3DS;
|
||||
u32 kernel_fcram_mapping_offset;
|
||||
|
||||
Handle arbiter;
|
||||
volatile u32 alloc_address;
|
||||
volatile u32 alloc_size;
|
||||
u8* flush_buffer;
|
||||
|
||||
Handle dummy_threads_lock;
|
||||
Handle target_threads_lock;
|
||||
Handle main_thread_lock;
|
||||
u32* thread_page_va;
|
||||
u32 thread_page_kva;
|
||||
|
||||
u32 threads_limit;
|
||||
Handle alloc_thread;
|
||||
Handle poll_thread;
|
||||
mch2_thread_t threads[MCH2_THREAD_COUNT_MAX];
|
||||
} mch2_vars_t;
|
||||
|
||||
|
||||
__attribute((naked))
|
||||
static u32 svc_7b(backdoor_fn entry_fn, ...) /* can pass up to two arguments to entry_fn(...) */
|
||||
{
|
||||
@ -46,7 +86,7 @@ static u32 svc_7b(backdoor_fn entry_fn, ...) /* can pass up to two arguments to
|
||||
|
||||
static void k_enable_all_svcs(u32 isNew3DS)
|
||||
{
|
||||
u32* thread_ACL = *(*(u32***)CURRENT_KTHREAD + 0x22) - 0x6;
|
||||
u32* thread_ACL = *(*(u32***)CURRENT_KTHREAD + 0x22) - 0x6;
|
||||
u32* process_ACL = *(u32**)CURRENT_KPROCESS + (isNew3DS ? 0x24 : 0x22);
|
||||
|
||||
memset(thread_ACL, 0xFF, 0x10);
|
||||
@ -88,45 +128,6 @@ static u32 get_thread_page(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Handle started_event;
|
||||
Handle lock;
|
||||
volatile u32 target_kaddr;
|
||||
volatile u32 target_val;
|
||||
} mch2_thread_args_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32* stack_top;
|
||||
Handle handle;
|
||||
bool keep;
|
||||
mch2_thread_args_t args;
|
||||
} mch2_thread_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 old_cpu_time_limit;
|
||||
bool isNew3DS;
|
||||
u32 kernel_fcram_mapping_offset;
|
||||
|
||||
Handle arbiter;
|
||||
volatile u32 alloc_address;
|
||||
volatile u32 alloc_size;
|
||||
u8* flush_buffer;
|
||||
|
||||
Handle dummy_threads_lock;
|
||||
Handle target_threads_lock;
|
||||
Handle main_thread_lock;
|
||||
u32* thread_page_va;
|
||||
u32 thread_page_kva;
|
||||
|
||||
u32 threads_limit;
|
||||
Handle alloc_thread;
|
||||
Handle poll_thread;
|
||||
mch2_thread_t threads[MCH2_THREAD_COUNT_MAX];
|
||||
} mch2_vars_t;
|
||||
|
||||
static void alloc_thread_entry(mch2_vars_t* mch2)
|
||||
{
|
||||
u32 tmp;
|
||||
@ -162,7 +163,7 @@ static u32 get_first_free_basemem_page(bool isNew3DS)
|
||||
{
|
||||
s64 v1;
|
||||
int memused_base_linear; /* guessed */
|
||||
int memused_base = osGetMemRegionUsed(MEMREGION_BASE);
|
||||
int memused_base = osGetMemRegionUsed(MEMREGION_BASE);
|
||||
|
||||
svcGetSystemInfo(&v1, 2, 0);
|
||||
memused_base_linear = 0x6C000 + v1 +
|
||||
@ -197,13 +198,25 @@ static void do_memchunkhax2(void)
|
||||
{
|
||||
static u8 flush_buffer[0x8000];
|
||||
static u8 thread_stacks[MCH2_THREAD_STACKS_SIZE];
|
||||
|
||||
extern u32 __heapBase;
|
||||
extern u32 __heap_size;
|
||||
int i;
|
||||
u32 tmp;
|
||||
mch2_vars_t mch2 = {0};
|
||||
u32 linear_buffer;
|
||||
u32 linear_address;
|
||||
u32 dst_memchunk;
|
||||
u32 mem_free;
|
||||
u32 fragmented_size;
|
||||
u32* mapped_page;
|
||||
volatile u32 *thread_ACL;
|
||||
u32 alloc_address_kaddr;
|
||||
u32 fragmented_address = 0;
|
||||
u32 linear_size = 0xF000;
|
||||
u32 skip_pages = 2;
|
||||
mch2_vars_t mch2 = {0};
|
||||
|
||||
mch2.flush_buffer = flush_buffer;
|
||||
mch2.threads_limit = get_threads_limit();
|
||||
mch2.flush_buffer = flush_buffer;
|
||||
mch2.threads_limit = get_threads_limit();
|
||||
mch2.kernel_fcram_mapping_offset = (osGetKernelVersion() > SYSTEM_VERSION(2, 40, 0)) ? 0xC0000000 : 0xD0000000;
|
||||
|
||||
for (i = 0; i < MCH2_THREAD_COUNT_MAX; i++)
|
||||
@ -215,8 +228,10 @@ static void do_memchunkhax2(void)
|
||||
|
||||
for (i = 0; i < mch2.threads_limit; i++)
|
||||
{
|
||||
svcCreateThread(&mch2.threads[i].handle, (ThreadFunc)check_tls_thread_entry, (u32)&mch2.threads[i].keep,
|
||||
mch2.threads[i].stack_top, 0x18, 0);
|
||||
svcCreateThread(&mch2.threads[i].handle,
|
||||
(ThreadFunc)check_tls_thread_entry,
|
||||
(u32)&mch2.threads[i].keep,
|
||||
mch2.threads[i].stack_top, 0x18, 0);
|
||||
svcWaitSynchronization(mch2.threads[i].handle, U64_MAX);
|
||||
}
|
||||
|
||||
@ -229,61 +244,70 @@ static void do_memchunkhax2(void)
|
||||
|
||||
for (i = 0; i < mch2.threads_limit; i++)
|
||||
if (!mch2.threads[i].keep)
|
||||
svcCreateThread(&mch2.threads[i].handle, (ThreadFunc)dummy_thread_entry, mch2.dummy_threads_lock,
|
||||
mch2.threads[i].stack_top, 0x3F - i, 0);
|
||||
svcCreateThread(&mch2.threads[i].handle,
|
||||
(ThreadFunc)dummy_thread_entry,
|
||||
mch2.dummy_threads_lock,
|
||||
mch2.threads[i].stack_top, 0x3F - i, 0);
|
||||
|
||||
svcSignalEvent(mch2.dummy_threads_lock);
|
||||
|
||||
for (i = mch2.threads_limit - 1; i >= 0; i--)
|
||||
{
|
||||
if (!mch2.threads[i].keep)
|
||||
{
|
||||
svcWaitSynchronization(mch2.threads[i].handle, U64_MAX);
|
||||
svcCloseHandle(mch2.threads[i].handle);
|
||||
mch2.threads[i].handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
svcCloseHandle(mch2.dummy_threads_lock);
|
||||
|
||||
u32 fragmented_address = 0;
|
||||
mch2.arbiter = __sync_get_arbiter();
|
||||
|
||||
mch2.arbiter = __sync_get_arbiter();
|
||||
svcControlMemory(&linear_buffer, 0, 0, 0x1000,
|
||||
MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
u32 linear_buffer;
|
||||
svcControlMemory(&linear_buffer, 0, 0, 0x1000, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
mch2.alloc_size = ((((linear_size - (skip_pages << 12))
|
||||
+ 0x1000) >> 13) << 12);
|
||||
|
||||
u32 linear_size = 0xF000;
|
||||
u32 skip_pages = 2;
|
||||
mch2.alloc_size = ((((linear_size - (skip_pages << 12)) + 0x1000) >> 13) << 12);
|
||||
u32 mem_free = osGetMemRegionFree(MEMREGION_APPLICATION);
|
||||
mem_free = osGetMemRegionFree(MEMREGION_APPLICATION);
|
||||
fragmented_size = mem_free - linear_size;
|
||||
|
||||
u32 fragmented_size = mem_free - linear_size;
|
||||
extern u32 __heapBase;
|
||||
extern u32 __heap_size;
|
||||
fragmented_address = __heapBase + __heap_size;
|
||||
u32 linear_address;
|
||||
mch2.alloc_address = fragmented_address + fragmented_size;
|
||||
fragmented_address = __heapBase + __heap_size;
|
||||
mch2.alloc_address = fragmented_address + fragmented_size;
|
||||
|
||||
svcControlMemory(&linear_address, 0x0, 0x0, linear_size, MEMOP_ALLOC_LINEAR,
|
||||
MEMPERM_READ | MEMPERM_WRITE);
|
||||
svcControlMemory(&linear_address,
|
||||
0x0, 0x0, linear_size, MEMOP_ALLOC_LINEAR,
|
||||
MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
if (fragmented_size)
|
||||
svcControlMemory(&tmp, (u32)fragmented_address, 0x0, fragmented_size, MEMOP_ALLOC,
|
||||
MEMPERM_READ | MEMPERM_WRITE);
|
||||
svcControlMemory(&tmp,
|
||||
(u32)fragmented_address, 0x0, fragmented_size, MEMOP_ALLOC,
|
||||
MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
if (skip_pages)
|
||||
svcControlMemory(&tmp, (u32)linear_address, 0x0, (skip_pages << 12), MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
svcControlMemory(&tmp,
|
||||
(u32)linear_address, 0x0, (skip_pages << 12), MEMOP_FREE,
|
||||
MEMPERM_DONTCARE);
|
||||
|
||||
for (i = skip_pages; i < (linear_size >> 12) ; i += 2)
|
||||
svcControlMemory(&tmp, (u32)linear_address + (i << 12), 0x0, 0x1000, MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
svcControlMemory(&tmp,
|
||||
(u32)linear_address + (i << 12), 0x0, 0x1000,
|
||||
MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
|
||||
u32 alloc_address_kaddr = osConvertVirtToPhys((void*)linear_address) + mch2.kernel_fcram_mapping_offset;
|
||||
alloc_address_kaddr = osConvertVirtToPhys(
|
||||
(void*)linear_address) + mch2.kernel_fcram_mapping_offset;
|
||||
|
||||
mch2.thread_page_kva = get_first_free_basemem_page(mch2.isNew3DS) - 0x10000; /* skip down 16 pages */
|
||||
mch2.thread_page_kva = get_first_free_basemem_page(mch2.isNew3DS)
|
||||
- 0x10000; /* skip down 16 pages */
|
||||
((u32*)linear_buffer)[0] = 1;
|
||||
((u32*)linear_buffer)[1] = mch2.thread_page_kva;
|
||||
((u32*)linear_buffer)[2] = alloc_address_kaddr + (((mch2.alloc_size >> 12) - 3) << 13) + (skip_pages << 12);
|
||||
|
||||
u32 dst_memchunk = linear_address + (((mch2.alloc_size >> 12) - 2) << 13) + (skip_pages << 12);
|
||||
dst_memchunk = linear_address
|
||||
+ (((mch2.alloc_size >> 12) - 2) << 13)
|
||||
+ (skip_pages << 12);
|
||||
|
||||
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||
|
||||
@ -291,18 +315,21 @@ static void do_memchunkhax2(void)
|
||||
GSPGPU_FlushDataCache((void*)linear_buffer, 16);
|
||||
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||
|
||||
/* can't clear gspEvents[GSPGPU_EVENT_PPF]), directly so execute a dummy copy
|
||||
* and use gspWaitForEvent to clear it. */
|
||||
/* can't clear gspEvents[GSPGPU_EVENT_PPF]),
|
||||
* directly so execute a dummy copy
|
||||
* and use gspWaitForEvent to clear it. */
|
||||
|
||||
/* LightEvent_Clear(&gspEvents[GSPGPU_EVENT_PPF]); */
|
||||
/* LightEvent_Clear(&gspEvents[GSPGPU_EVENT_PPF]); */
|
||||
GX_TextureCopy((void*)linear_buffer, 0, (void*)dst_memchunk, 0, 16, 8);
|
||||
gspWaitForEvent(GSPGPU_EVENT_PPF, false);
|
||||
|
||||
svcCreateThread(&mch2.alloc_thread, (ThreadFunc)alloc_thread_entry, (u32)&mch2,
|
||||
mch2.threads[MCH2_THREAD_COUNT_MAX - 1].stack_top, 0x3F, 1);
|
||||
svcCreateThread(&mch2.alloc_thread,
|
||||
(ThreadFunc)alloc_thread_entry, (u32)&mch2,
|
||||
mch2.threads[MCH2_THREAD_COUNT_MAX - 1].stack_top, 0x3F, 1);
|
||||
|
||||
while ((u32) svcArbitrateAddress(mch2.arbiter, mch2.alloc_address, ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0,
|
||||
0) == 0xD9001814);
|
||||
while ((u32) svcArbitrateAddress(mch2.arbiter, mch2.alloc_address,
|
||||
ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0,
|
||||
0) == 0xD9001814);
|
||||
|
||||
GX_TextureCopy((void*)linear_buffer, 0, (void*)dst_memchunk, 0, 16, 8);
|
||||
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||
@ -311,9 +338,9 @@ static void do_memchunkhax2(void)
|
||||
svcWaitSynchronization(mch2.alloc_thread, U64_MAX);
|
||||
svcCloseHandle(mch2.alloc_thread);
|
||||
|
||||
u32* mapped_page = (u32*)(mch2.alloc_address + mch2.alloc_size - 0x1000);
|
||||
|
||||
volatile u32* thread_ACL = &mapped_page[THREAD_PAGE_ACL_OFFSET >> 2];
|
||||
mapped_page = (u32*)
|
||||
(mch2.alloc_address + mch2.alloc_size - 0x1000);
|
||||
thread_ACL = &mapped_page[THREAD_PAGE_ACL_OFFSET >> 2];
|
||||
|
||||
svcCreateEvent(&mch2.main_thread_lock, 0);
|
||||
svcCreateEvent(&mch2.target_threads_lock, 1);
|
||||
@ -325,16 +352,18 @@ static void do_memchunkhax2(void)
|
||||
continue;
|
||||
|
||||
mch2.threads[i].args.started_event = mch2.main_thread_lock;
|
||||
mch2.threads[i].args.lock = mch2.target_threads_lock;
|
||||
mch2.threads[i].args.target_kaddr = 0;
|
||||
mch2.threads[i].args.lock = mch2.target_threads_lock;
|
||||
mch2.threads[i].args.target_kaddr = 0;
|
||||
|
||||
thread_ACL[0] = 0;
|
||||
thread_ACL[0] = 0;
|
||||
GSPGPU_FlushDataCache((void*)thread_ACL, 16);
|
||||
GSPGPU_InvalidateDataCache((void*)thread_ACL, 16);
|
||||
|
||||
svcClearEvent(mch2.main_thread_lock);
|
||||
svcCreateThread(&mch2.threads[i].handle, (ThreadFunc)target_thread_entry, (u32)&mch2.threads[i].args,
|
||||
mch2.threads[i].stack_top, 0x18, 0);
|
||||
svcCreateThread(&mch2.threads[i].handle,
|
||||
(ThreadFunc)target_thread_entry,
|
||||
(u32)&mch2.threads[i].args,
|
||||
mch2.threads[i].stack_top, 0x18, 0);
|
||||
svcWaitSynchronization(mch2.main_thread_lock, U64_MAX);
|
||||
|
||||
if (thread_ACL[0])
|
||||
@ -342,8 +371,10 @@ static void do_memchunkhax2(void)
|
||||
thread_ACL[SVC_ACL_OFFSET(0x7B) >> 2] = SVC_ACL_MASK(0x7B);
|
||||
GSPGPU_FlushDataCache((void*)thread_ACL, 16);
|
||||
GSPGPU_InvalidateDataCache((void*)thread_ACL, 16);
|
||||
mch2.threads[i].args.target_kaddr = get_thread_page() + THREAD_PAGE_ACL_OFFSET + SVC_ACL_OFFSET(0x7B);
|
||||
mch2.threads[i].args.target_val = SVC_ACL_MASK(0x7B);
|
||||
mch2.threads[i].args.target_kaddr = get_thread_page()
|
||||
+ THREAD_PAGE_ACL_OFFSET
|
||||
+ SVC_ACL_OFFSET(0x7B);
|
||||
mch2.threads[i].args.target_val = SVC_ACL_MASK(0x7B);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -365,14 +396,18 @@ static void do_memchunkhax2(void)
|
||||
svcCloseHandle(mch2.target_threads_lock);
|
||||
svcCloseHandle(mch2.main_thread_lock);
|
||||
|
||||
svcControlMemory(&tmp, mch2.alloc_address, 0, mch2.alloc_size, MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
svcControlMemory(&tmp, mch2.alloc_address, 0, mch2.alloc_size,
|
||||
MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
write_kaddr(alloc_address_kaddr + linear_size - 0x3000 + 0x4, alloc_address_kaddr + linear_size - 0x1000);
|
||||
svcControlMemory(&tmp, (u32)fragmented_address, 0x0, fragmented_size, MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
svcControlMemory(&tmp, (u32)fragmented_address, 0x0, fragmented_size,
|
||||
MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
|
||||
for (i = 1 + skip_pages; i < (linear_size >> 12) ; i += 2)
|
||||
svcControlMemory(&tmp, (u32)linear_address + (i << 12), 0x0, 0x1000, MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
svcControlMemory(&tmp, (u32)linear_address + (i << 12), 0x0, 0x1000,
|
||||
MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
|
||||
svcControlMemory(&tmp, linear_buffer, 0, 0x1000, MEMOP_FREE, MEMPERM_DONTCARE);
|
||||
svcControlMemory(&tmp, linear_buffer, 0, 0x1000, MEMOP_FREE,
|
||||
MEMPERM_DONTCARE);
|
||||
|
||||
APT_SetAppCpuTimeLimit(mch2.old_cpu_time_limit);
|
||||
}
|
||||
@ -418,7 +453,8 @@ static void memchunkhax1_write_pair(u32 val1, u32 val2)
|
||||
u32* next_ptr1;
|
||||
u32* prev_ptr6;
|
||||
|
||||
svcControlMemory(&linear_buffer, 0, 0, 0x10000, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
svcControlMemory(&linear_buffer, 0, 0, 0x10000,
|
||||
MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
flush_buffer = (u8*)(linear_buffer + 0x8000);
|
||||
|
||||
@ -426,23 +462,24 @@ static void memchunkhax1_write_pair(u32 val1, u32 val2)
|
||||
svcControlMemory(&tmp, linear_buffer + 0x3000, 0, 0x2000, MEMOP_FREE, 0);
|
||||
svcControlMemory(&tmp, linear_buffer + 0x6000, 0, 0x1000, MEMOP_FREE, 0);
|
||||
|
||||
next_ptr1 = (u32*)(linear_buffer + 0x0004);
|
||||
next_ptr1 = (u32*)(linear_buffer + 0x0004);
|
||||
gspwn(linear_buffer + 0x0000, linear_buffer + 0x1000, 16, flush_buffer);
|
||||
|
||||
next_ptr3 = (u32*)(linear_buffer + 0x2004);
|
||||
prev_ptr3 = (u32*)(linear_buffer + 0x2008);
|
||||
next_ptr3 = (u32*)(linear_buffer + 0x2004);
|
||||
prev_ptr3 = (u32*)(linear_buffer + 0x2008);
|
||||
gspwn(linear_buffer + 0x2000, linear_buffer + 0x3000, 16, flush_buffer);
|
||||
|
||||
prev_ptr6 = (u32*)(linear_buffer + 0x5008);
|
||||
prev_ptr6 = (u32*)(linear_buffer + 0x5008);
|
||||
gspwn(linear_buffer + 0x5000, linear_buffer + 0x6000, 16, flush_buffer);
|
||||
|
||||
*next_ptr1 = *next_ptr3;
|
||||
*prev_ptr6 = *prev_ptr3;
|
||||
*next_ptr1 = *next_ptr3;
|
||||
*prev_ptr6 = *prev_ptr3;
|
||||
|
||||
*prev_ptr3 = val1 - 4;
|
||||
*next_ptr3 = val2;
|
||||
*prev_ptr3 = val1 - 4;
|
||||
*next_ptr3 = val2;
|
||||
gspwn(linear_buffer + 0x3000, linear_buffer + 0x2000, 16, flush_buffer);
|
||||
svcControlMemory(&tmp, 0, 0, 0x2000, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
svcControlMemory(&tmp, 0, 0, 0x2000,
|
||||
MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
gspwn(linear_buffer + 0x1000, linear_buffer + 0x0000, 16, flush_buffer);
|
||||
gspwn(linear_buffer + 0x6000, linear_buffer + 0x5000, 16, flush_buffer);
|
||||
@ -450,7 +487,6 @@ static void memchunkhax1_write_pair(u32 val1, u32 val2)
|
||||
svcControlMemory(&tmp, linear_buffer + 0x0000, 0, 0x1000, MEMOP_FREE, 0);
|
||||
svcControlMemory(&tmp, linear_buffer + 0x2000, 0, 0x4000, MEMOP_FREE, 0);
|
||||
svcControlMemory(&tmp, linear_buffer + 0x7000, 0, 0x9000, MEMOP_FREE, 0);
|
||||
|
||||
}
|
||||
|
||||
static void do_memchunkhax1(void)
|
||||
@ -458,7 +494,9 @@ static void do_memchunkhax1(void)
|
||||
u32 saved_vram_value = *(u32*)0x1F000008;
|
||||
|
||||
/* 0x1F000000 contains the enable bit for svc 0x7B */
|
||||
memchunkhax1_write_pair(get_thread_page() + THREAD_PAGE_ACL_OFFSET + SVC_ACL_OFFSET(0x7B), 0x1F000000);
|
||||
memchunkhax1_write_pair(get_thread_page()
|
||||
+ THREAD_PAGE_ACL_OFFSET
|
||||
+ SVC_ACL_OFFSET(0x7B), 0x1F000000);
|
||||
|
||||
write_kaddr(0x1F000008, saved_vram_value);
|
||||
}
|
||||
@ -480,9 +518,11 @@ Result get_luma_version(u32 *major, u32 *minor)
|
||||
Result svchax_init(bool patch_srv)
|
||||
{
|
||||
bool isNew3DS;
|
||||
u32 kver;
|
||||
|
||||
APT_CheckNew3DS(&isNew3DS);
|
||||
|
||||
u32 kver = osGetKernelVersion();
|
||||
kver = osGetKernelVersion();
|
||||
|
||||
if (!__ctr_svchax)
|
||||
{
|
||||
@ -491,9 +531,11 @@ Result svchax_init(bool patch_srv)
|
||||
u32 luma_major, luma_minor;
|
||||
|
||||
if (kver > SYSTEM_VERSION(2, 50, 11) &&
|
||||
(R_FAILED(get_luma_version(&luma_major, &luma_minor) || luma_major < 8)))
|
||||
(R_FAILED(get_luma_version(&luma_major, &luma_minor)
|
||||
|| luma_major < 8)))
|
||||
return -1;
|
||||
else if (kver > SYSTEM_VERSION(2, 46, 0) && kver <= SYSTEM_VERSION(2, 50, 11))
|
||||
else if (kver > SYSTEM_VERSION(2, 46, 0)
|
||||
&& kver <= SYSTEM_VERSION(2, 50, 11))
|
||||
do_memchunkhax2();
|
||||
else if (kver <= SYSTEM_VERSION(2, 46, 0))
|
||||
do_memchunkhax1();
|
||||
@ -506,8 +548,9 @@ Result svchax_init(bool patch_srv)
|
||||
|
||||
if (patch_srv && !__ctr_svchax_srv)
|
||||
{
|
||||
u32 PID_kaddr = read_kaddr(CURRENT_KPROCESS) + (isNew3DS ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC);
|
||||
u32 old_PID = read_kaddr(PID_kaddr);
|
||||
u32 PID_kaddr = read_kaddr(CURRENT_KPROCESS)
|
||||
+ (isNew3DS ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC);
|
||||
u32 old_PID = read_kaddr(PID_kaddr);
|
||||
write_kaddr(PID_kaddr, 0);
|
||||
srvExit();
|
||||
srvInit();
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#define CTR_APPMEMALLOC_PTR ((u32*)0x1FF80040)
|
||||
|
||||
/* Global variables */
|
||||
u32 __stacksize__ = 0x00400000;
|
||||
u32 __linear_heap_size = 0x01000000;
|
||||
|
||||
@ -22,22 +23,24 @@ u32 __stack_size_extra;
|
||||
|
||||
extern u32 __linear_heap_size_hbl;
|
||||
extern u32 __heap_size_hbl;
|
||||
extern void* __service_ptr;
|
||||
|
||||
extern void (*__system_retAddr)(void);
|
||||
|
||||
/* Forward declarations */
|
||||
void envDestroyHandles(void);
|
||||
void __appExit();
|
||||
void __appExit(void);
|
||||
void __libc_fini_array(void);
|
||||
|
||||
void __appInit();
|
||||
void __appInit(void);
|
||||
void __libc_init_array(void);
|
||||
void __system_initSyscalls(void);
|
||||
void __system_initArgv();
|
||||
void __system_initArgv(void);
|
||||
|
||||
void __ctru_exit(int rc);
|
||||
int __libctru_gtod(struct _reent* ptr, struct timeval* tp, struct timezone* tz);
|
||||
int __libctru_gtod(struct _reent* ptr,
|
||||
struct timeval* tp, struct timezone* tz);
|
||||
void (*__system_retAddr)(void);
|
||||
extern void* __service_ptr;
|
||||
|
||||
Result __sync_init(void) __attribute__((weak));
|
||||
|
||||
@ -140,37 +143,41 @@ extern const char* __system_arglist;
|
||||
char __argv_hmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53,
|
||||
0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
|
||||
|
||||
Result APT_ReceiveDeliverArg_(void* param, size_t param_size, void* hmac, size_t hmac_size, u64* source_pid, bool* received)
|
||||
Result APT_ReceiveDeliverArg_(void* param, size_t param_size,
|
||||
void* hmac, size_t hmac_size, u64* source_pid, bool* received)
|
||||
{
|
||||
u32 cmdbuf[16];
|
||||
cmdbuf[0]=IPC_MakeHeader(0x35,2,0);
|
||||
cmdbuf[1]=param_size;
|
||||
cmdbuf[2]=hmac_size;
|
||||
|
||||
u32 saved_threadstorage[4];
|
||||
u32* staticbufs = getThreadStaticBuffers();
|
||||
saved_threadstorage[0]=staticbufs[0];
|
||||
saved_threadstorage[1]=staticbufs[1];
|
||||
saved_threadstorage[2]=staticbufs[2];
|
||||
saved_threadstorage[3]=staticbufs[3];
|
||||
staticbufs[0]=IPC_Desc_StaticBuffer(param_size, 0);
|
||||
staticbufs[1]=(u32)param;
|
||||
staticbufs[2]=IPC_Desc_StaticBuffer(hmac_size, 2);
|
||||
staticbufs[3]=(u32)hmac;
|
||||
u32 *staticbufs;
|
||||
Result ret;
|
||||
|
||||
Result ret = aptSendCommand(cmdbuf);
|
||||
staticbufs[0]=saved_threadstorage[0];
|
||||
staticbufs[1]=saved_threadstorage[1];
|
||||
staticbufs[2]=saved_threadstorage[2];
|
||||
staticbufs[3]=saved_threadstorage[3];
|
||||
cmdbuf[0] = IPC_MakeHeader(0x35,2,0);
|
||||
cmdbuf[1] = param_size;
|
||||
cmdbuf[2] = hmac_size;
|
||||
|
||||
staticbufs = getThreadStaticBuffers();
|
||||
saved_threadstorage[0] = staticbufs[0];
|
||||
saved_threadstorage[1] = staticbufs[1];
|
||||
saved_threadstorage[2] = staticbufs[2];
|
||||
saved_threadstorage[3] = staticbufs[3];
|
||||
staticbufs[0] = IPC_Desc_StaticBuffer(param_size, 0);
|
||||
staticbufs[1] = (u32)param;
|
||||
staticbufs[2] = IPC_Desc_StaticBuffer(hmac_size, 2);
|
||||
staticbufs[3] = (u32)hmac;
|
||||
|
||||
ret = aptSendCommand(cmdbuf);
|
||||
staticbufs[0] = saved_threadstorage[0];
|
||||
staticbufs[1] = saved_threadstorage[1];
|
||||
staticbufs[2] = saved_threadstorage[2];
|
||||
staticbufs[3] = saved_threadstorage[3];
|
||||
|
||||
if(R_FAILED(ret))
|
||||
return ret;
|
||||
|
||||
if(source_pid)
|
||||
*source_pid = ((u64*)cmdbuf)[1];
|
||||
*source_pid = ((u64*)cmdbuf)[1];
|
||||
if(received)
|
||||
*received = ((bool*)cmdbuf)[16];
|
||||
*received = ((bool*)cmdbuf)[16];
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
@ -202,13 +209,15 @@ void __system_initArgv(void)
|
||||
|
||||
if (__system_argc)
|
||||
{
|
||||
__system_argv = (char**) malloc((__system_argc + 1) * sizeof(char**));
|
||||
__system_argv[0] = arg_struct->args;
|
||||
__system_argv = (char**)malloc(
|
||||
(__system_argc + 1) * sizeof(char**));
|
||||
__system_argv[0] = arg_struct->args;
|
||||
for (i = 1; i < __system_argc; i++)
|
||||
__system_argv[i] = __system_argv[i - 1] + strlen(__system_argv[i - 1]) + 1;
|
||||
|
||||
i = __system_argc - 1;
|
||||
i = __system_argc - 1;
|
||||
__system_argc = 1;
|
||||
|
||||
while (i)
|
||||
{
|
||||
if(__system_argv[i] && isalnum(__system_argv[i][0])
|
||||
@ -223,8 +232,8 @@ void __system_initArgv(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
__system_argc = 1;
|
||||
__system_argv = (char**) malloc(sizeof(char**) * 2);
|
||||
__system_argc = 1;
|
||||
__system_argv = (char**) malloc(sizeof(char**) * 2);
|
||||
__system_argv[0] = "sdmc:/retroarch/retroarch";
|
||||
}
|
||||
__system_argv[__system_argc] = NULL;
|
||||
@ -269,8 +278,6 @@ void dump_result_value(Result val)
|
||||
printf("level : %u\n", res.level);
|
||||
}
|
||||
|
||||
bool select_pressed = false;
|
||||
|
||||
void wait_for_input(void)
|
||||
{
|
||||
printf("\n\nPress Start.\n\n");
|
||||
@ -290,10 +297,6 @@ void wait_for_input(void)
|
||||
if (kDown & KEY_SELECT)
|
||||
exit(0);
|
||||
|
||||
#if 0
|
||||
select_pressed = true;
|
||||
#endif
|
||||
|
||||
svcSleepThread(1000000);
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,12 @@ static void (*launch_3dsx)(const char* path,
|
||||
static int exec_3dsx_actual(const char* path,
|
||||
const char** args, bool appendPath)
|
||||
{
|
||||
bool inited;
|
||||
bool fileExists;
|
||||
struct stat sBuff;
|
||||
argData_s newProgramArgs;
|
||||
unsigned int argChars = 0;
|
||||
unsigned int argNum = 0;
|
||||
bool fileExists;
|
||||
bool inited;
|
||||
unsigned int argNum = 0;
|
||||
|
||||
if (!path || path[0] == '\0')
|
||||
{
|
||||
@ -51,7 +51,8 @@ static int exec_3dsx_actual(const char* path,
|
||||
newProgramArgs.dst += strlen(path) + 1;
|
||||
newProgramArgs.buf[0]++;
|
||||
}
|
||||
while(args[argNum] != NULL)
|
||||
|
||||
while(args[argNum])
|
||||
{
|
||||
strcpy(newProgramArgs.dst, args[argNum]);
|
||||
newProgramArgs.dst += strlen(args[argNum]) + 1;
|
||||
@ -59,18 +60,18 @@ static int exec_3dsx_actual(const char* path,
|
||||
argNum++;
|
||||
}
|
||||
|
||||
inited = loader_Rosalina.init();
|
||||
launch_3dsx = loader_Rosalina.launchFile;
|
||||
inited = loader_Rosalina.init();
|
||||
launch_3dsx = loader_Rosalina.launchFile;
|
||||
|
||||
if (!inited)
|
||||
{
|
||||
inited = loader_Ninjhax2.init();
|
||||
inited = loader_Ninjhax2.init();
|
||||
launch_3dsx = loader_Ninjhax2.launchFile;
|
||||
}
|
||||
|
||||
if (!inited)
|
||||
{
|
||||
inited = loader_Ninjhax1.init();
|
||||
inited = loader_Ninjhax1.init();
|
||||
launch_3dsx = loader_Ninjhax1.launchFile;
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,10 @@
|
||||
|
||||
#define FILE_CHUNK_SIZE 4096
|
||||
|
||||
typedef struct{
|
||||
u32 argc;
|
||||
char args[0x300 - 0x4];
|
||||
typedef struct
|
||||
{
|
||||
u32 argc;
|
||||
char args[0x300 - 0x4];
|
||||
}ciaParam;
|
||||
|
||||
char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
|
||||
@ -28,11 +29,10 @@ static int isCiaInstalled(u64 titleId, u16 version)
|
||||
u32 titlesToRetrieve;
|
||||
u32 titlesRetrieved;
|
||||
u64* titleIds;
|
||||
bool titleExists = false;
|
||||
u32 titlesToCheck;
|
||||
AM_TitleEntry titleInfo;
|
||||
Result failed;
|
||||
|
||||
failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
|
||||
bool titleExists = false;
|
||||
Result failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
|
||||
if (R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
@ -44,7 +44,7 @@ static int isCiaInstalled(u64 titleId, u16 version)
|
||||
if (R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++)
|
||||
for(titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++)
|
||||
{
|
||||
if (titleIds[titlesToCheck] == titleId)
|
||||
{
|
||||
@ -57,7 +57,8 @@ static int isCiaInstalled(u64 titleId, u16 version)
|
||||
|
||||
if (titleExists)
|
||||
{
|
||||
failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo);
|
||||
failed = AM_GetTitleInfo(MEDIATYPE_SD,
|
||||
1 /*titleCount*/, &titleId, &titleInfo);
|
||||
if (R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
@ -70,15 +71,13 @@ static int isCiaInstalled(u64 titleId, u16 version)
|
||||
|
||||
static int installCia(Handle ciaFile)
|
||||
{
|
||||
Result failed;
|
||||
Handle outputHandle;
|
||||
u64 fileSize;
|
||||
u64 fileOffset = 0;
|
||||
u32 bytesRead;
|
||||
u32 bytesWritten;
|
||||
u8 transferBuffer[FILE_CHUNK_SIZE];
|
||||
|
||||
failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
|
||||
u64 fileOffset = 0;
|
||||
Result failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
|
||||
if (R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
@ -89,14 +88,19 @@ static int installCia(Handle ciaFile)
|
||||
while(fileOffset < fileSize)
|
||||
{
|
||||
u64 bytesRemaining = fileSize - fileOffset;
|
||||
failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE);
|
||||
failed = FSFILE_Read(ciaFile, &bytesRead,
|
||||
fileOffset, transferBuffer,
|
||||
bytesRemaining < FILE_CHUNK_SIZE
|
||||
? bytesRemaining
|
||||
: FILE_CHUNK_SIZE);
|
||||
if (R_FAILED(failed))
|
||||
{
|
||||
AM_CancelCIAInstall(outputHandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0);
|
||||
failed = FSFILE_Write(outputHandle, &bytesWritten,
|
||||
fileOffset, transferBuffer, bytesRead, 0);
|
||||
if (R_FAILED(failed))
|
||||
{
|
||||
AM_CancelCIAInstall(outputHandle);
|
||||
@ -146,6 +150,7 @@ int exec_cia(const char* path, const char** args)
|
||||
}
|
||||
|
||||
inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
|
||||
|
||||
if (inited)
|
||||
{
|
||||
AM_TitleEntry ciaInfo;
|
||||
@ -155,12 +160,15 @@ int exec_cia(const char* path, const char** args)
|
||||
ciaParam param;
|
||||
int argsLength;
|
||||
/* open CIA file */
|
||||
Result res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
|
||||
Result res = FSUSER_OpenArchive(&ciaArchive,
|
||||
ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
|
||||
|
||||
if (R_FAILED(res))
|
||||
errorAndQuit("Cant open SD FS archive.");
|
||||
|
||||
res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
|
||||
res = FSUSER_OpenFile(&ciaFile,
|
||||
ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/),
|
||||
FS_OPEN_READ, 0);
|
||||
if (R_FAILED(res))
|
||||
errorAndQuit("Cant open CIA file.");
|
||||
|
||||
@ -185,10 +193,11 @@ int exec_cia(const char* path, const char** args)
|
||||
FSFILE_Close(ciaFile);
|
||||
FSUSER_CloseArchive(ciaArchive);
|
||||
|
||||
param.argc = 0;
|
||||
argsLength = 0;
|
||||
char* argLocation = param.args;
|
||||
while(args[param.argc] != NULL)
|
||||
param.argc = 0;
|
||||
argsLength = 0;
|
||||
char *argLocation = param.args;
|
||||
|
||||
while(args[param.argc])
|
||||
{
|
||||
strcpy(argLocation, args[param.argc]);
|
||||
argLocation += strlen(args[param.argc]) + 1;
|
||||
@ -200,7 +209,8 @@ int exec_cia(const char* path, const char** args)
|
||||
if (R_FAILED(res))
|
||||
errorAndQuit("CIA cant run, cant prepare.");
|
||||
|
||||
res = APT_DoApplicationJump(¶m, sizeof(param.argc) + argsLength, argvHmac);
|
||||
res = APT_DoApplicationJump(¶m, sizeof(param.argc)
|
||||
+ argsLength, argvHmac);
|
||||
if (R_FAILED(res))
|
||||
errorAndQuit("CIA cant run, cant jump.");
|
||||
|
||||
|
@ -3,20 +3,24 @@
|
||||
Handle launchOpenFile(const char* path)
|
||||
{
|
||||
Handle file;
|
||||
Result res;
|
||||
ssize_t units;
|
||||
static uint16_t __utf16path[PATH_MAX+1];
|
||||
|
||||
if (strncmp(path, "sdmc:/", 6) == 0)
|
||||
path += 5;
|
||||
else if (*path != '/')
|
||||
return 0;
|
||||
|
||||
/* Convert the executable path to UTF-16 */
|
||||
static uint16_t __utf16path[PATH_MAX+1];
|
||||
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX);
|
||||
units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX);
|
||||
if (units < 0 || units >= PATH_MAX) return 0;
|
||||
__utf16path[units] = 0;
|
||||
|
||||
/* Open the file directly */
|
||||
FS_Path apath = { PATH_EMPTY, 1, (u8*)"" };
|
||||
FS_Path fpath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
|
||||
Result res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, apath, fpath, FS_OPEN_READ, 0);
|
||||
res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC,
|
||||
apath, fpath, FS_OPEN_READ, 0);
|
||||
return R_SUCCEEDED(res) ? file : 0;
|
||||
}
|
||||
|
@ -9,28 +9,32 @@ static bool init(void)
|
||||
|
||||
static Result HBLDR_SetTarget(const char* path)
|
||||
{
|
||||
Result rc;
|
||||
u32 pathLen = strlen(path) + 1;
|
||||
u32* cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(2, 0, 2); /* 0x20002 */
|
||||
cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0);
|
||||
cmdbuf[2] = (u32)path;
|
||||
cmdbuf[0] = IPC_MakeHeader(2, 0, 2); /* 0x20002 */
|
||||
cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0);
|
||||
cmdbuf[2] = (u32)path;
|
||||
|
||||
Result rc = svcSendSyncRequest(hbldrHandle);
|
||||
if (R_SUCCEEDED(rc)) rc = cmdbuf[1];
|
||||
rc = svcSendSyncRequest(hbldrHandle);
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = cmdbuf[1];
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result HBLDR_SetArgv(const void* buffer, u32 size)
|
||||
{
|
||||
Result rc;
|
||||
u32* cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(3, 0, 2); /* 0x30002 */
|
||||
cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1);
|
||||
cmdbuf[2] = (u32)buffer;
|
||||
cmdbuf[0] = IPC_MakeHeader(3, 0, 2); /* 0x30002 */
|
||||
cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1);
|
||||
cmdbuf[2] = (u32)buffer;
|
||||
|
||||
Result rc = svcSendSyncRequest(hbldrHandle);
|
||||
if (R_SUCCEEDED(rc)) rc = cmdbuf[1];
|
||||
rc = svcSendSyncRequest(hbldrHandle);
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = cmdbuf[1];
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -39,7 +43,8 @@ static void deinit(void)
|
||||
svcCloseHandle(hbldrHandle);
|
||||
}
|
||||
|
||||
static void launchFile(const char* path, argData_s* args, executableMetadata_s* em)
|
||||
static void launchFile(const char* path,
|
||||
argData_s* args, executableMetadata_s* em)
|
||||
{
|
||||
if (strncmp(path, "sdmc:/",6) == 0)
|
||||
path += 5;
|
||||
|
173
ctr/gpu_old.c
173
ctr/gpu_old.c
@ -25,14 +25,17 @@ void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize)
|
||||
GPUCMD_SetBuffer(gpuBuf, gpuBufSize, 0);
|
||||
}
|
||||
|
||||
void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numreg)
|
||||
void GPU_SetFloatUniform(GPU_SHADER_TYPE type,
|
||||
u32 startreg, u32* data, u32 numreg)
|
||||
{
|
||||
int regOffset;
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
int regOffset = (type == GPU_GEOMETRY_SHADER) ? (-0x30) : (0x0);
|
||||
regOffset = (type == GPU_GEOMETRY_SHADER) ? (-0x30) : (0x0);
|
||||
|
||||
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+regOffset, 0x80000000|startreg);
|
||||
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+regOffset,
|
||||
0x80000000 | startreg);
|
||||
GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+regOffset, data, numreg*4);
|
||||
}
|
||||
|
||||
@ -40,43 +43,46 @@ void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numr
|
||||
void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer,
|
||||
u32 x, u32 y, u32 w, u32 h)
|
||||
{
|
||||
u32 f116e;
|
||||
u32 param[0x4];
|
||||
float fw=(float)w;
|
||||
float fh=(float)h;
|
||||
float fw = (float)w;
|
||||
float fh = (float)h;
|
||||
|
||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 0x00000001);
|
||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 0x00000001);
|
||||
|
||||
u32 f116e=0x01000000|(((h-1)&0xFFF)<<12)|(w&0xFFF);
|
||||
f116e = 0x01000000 | (((h-1) & 0xFFF) << 12) | (w & 0xFFF);
|
||||
|
||||
param[0x0]=((u32)depthBuffer)>>3;
|
||||
param[0x1]=((u32)colorBuffer)>>3;
|
||||
param[0x2]=f116e;
|
||||
param[0x0] = ((u32)depthBuffer) >> 3;
|
||||
param[0x1] = ((u32)colorBuffer) >> 3;
|
||||
param[0x2] = f116e;
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 0x00000003);
|
||||
|
||||
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, f116e);
|
||||
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 0x00000003); /* depth buffer format */
|
||||
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0x00000002); /* color buffer format */
|
||||
/* depth buffer format */
|
||||
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 0x00000003);
|
||||
/* color buffer format */
|
||||
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0x00000002);
|
||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); /* ? */
|
||||
|
||||
param[0x0]=f32tof24(fw/2);
|
||||
param[0x1]=f32tof31(2.0f / fw) << 1;
|
||||
param[0x2]=f32tof24(fh/2);
|
||||
param[0x3]=f32tof31(2.0f / fh) << 1;
|
||||
param[0x0] = f32tof24(fw/2);
|
||||
param[0x1] = f32tof31(2.0f / fw) << 1;
|
||||
param[0x2] = f32tof24(fh/2);
|
||||
param[0x3] = f32tof31(2.0f / fh) << 1;
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_VIEWPORT_WIDTH, param, 0x00000004);
|
||||
|
||||
GPUCMD_AddWrite(GPUREG_VIEWPORT_XY, (y<<16)|(x&0xFFFF));
|
||||
GPUCMD_AddWrite(GPUREG_VIEWPORT_XY, (y << 16)|(x & 0xFFFF));
|
||||
|
||||
param[0x0]=0x00000000;
|
||||
param[0x1]=0x00000000;
|
||||
param[0x2]=((h-1)<<16)|((w-1)&0xFFFF);
|
||||
param[0x0] = 0x00000000;
|
||||
param[0x1] = 0x00000000;
|
||||
param[0x2] = ((h-1) << 16)|((w-1) & 0xFFFF);
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, param, 0x00000003);
|
||||
|
||||
/* enable depth buffer */
|
||||
param[0x0]=0x0000000F;
|
||||
param[0x1]=0x0000000F;
|
||||
param[0x2]=0x00000002;
|
||||
param[0x3]=0x00000002;
|
||||
param[0x0] = 0x0000000F;
|
||||
param[0x1] = 0x0000000F;
|
||||
param[0x2] = 0x00000002;
|
||||
param[0x3] = 0x00000002;
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_COLORBUFFER_READ, param, 0x00000004);
|
||||
}
|
||||
|
||||
@ -85,8 +91,8 @@ void GPU_SetScissorTest(GPU_SCISSORMODE mode, u32 left, u32 bottom, u32 right, u
|
||||
u32 param[3];
|
||||
|
||||
param[0x0] = mode;
|
||||
param[0x1] = (bottom<<16)|(left&0xFFFF);
|
||||
param[0x2] = ((top-1)<<16)|((right-1)&0xFFFF);
|
||||
param[0x1] = (bottom << 16) | (left & 0xFFFF);
|
||||
param[0x2] = ((top-1) << 16) | ((right-1) & 0xFFFF);
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, param, 0x00000003);
|
||||
}
|
||||
|
||||
@ -99,12 +105,14 @@ void GPU_DepthMap(float zScale, float zOffset)
|
||||
|
||||
void GPU_SetAlphaTest(bool enable, GPU_TESTFUNC function, u8 ref)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_FRAGOP_ALPHA_TEST, (enable&1)|((function&7)<<4)|(ref<<8));
|
||||
GPUCMD_AddWrite(GPUREG_FRAGOP_ALPHA_TEST,
|
||||
(enable&1)|((function&7) << 4)|(ref << 8));
|
||||
}
|
||||
|
||||
void GPU_SetStencilTest(bool enable, GPU_TESTFUNC function, u8 ref, u8 input_mask, u8 write_mask)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_STENCIL_TEST, (enable&1)|((function&7)<<4)|(write_mask<<8)|(ref<<16)|(input_mask<<24));
|
||||
GPUCMD_AddWrite(GPUREG_STENCIL_TEST,
|
||||
(enable&1)|((function&7) << 4)|(write_mask << 8)|(ref << 16)|(input_mask << 24));
|
||||
}
|
||||
|
||||
void GPU_SetStencilOp(GPU_STENCILOP sfail, GPU_STENCILOP dfail, GPU_STENCILOP pass)
|
||||
@ -114,14 +122,14 @@ void GPU_SetStencilOp(GPU_STENCILOP sfail, GPU_STENCILOP dfail, GPU_STENCILOP pa
|
||||
|
||||
void GPU_SetDepthTestAndWriteMask(bool enable, GPU_TESTFUNC function, GPU_WRITEMASK writemask)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_DEPTH_COLOR_MASK, (enable&1)|((function&7)<<4)|(writemask<<8));
|
||||
GPUCMD_AddWrite(GPUREG_DEPTH_COLOR_MASK, (enable&1)|((function&7) << 4)|(writemask << 8));
|
||||
}
|
||||
|
||||
void GPU_SetAlphaBlending(GPU_BLENDEQUATION colorEquation, GPU_BLENDEQUATION alphaEquation,
|
||||
GPU_BLENDFACTOR colorSrc, GPU_BLENDFACTOR colorDst,
|
||||
GPU_BLENDFACTOR alphaSrc, GPU_BLENDFACTOR alphaDst)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_BLEND_FUNC, colorEquation | (alphaEquation<<8) | (colorSrc<<16) | (colorDst<<20) | (alphaSrc<<24) | (alphaDst<<28));
|
||||
GPUCMD_AddWrite(GPUREG_BLEND_FUNC, colorEquation | (alphaEquation << 8) | (colorSrc << 16) | (colorDst << 20) | (alphaSrc << 24) | (alphaDst << 28));
|
||||
GPUCMD_AddMaskedWrite(GPUREG_COLOR_OPERATION, 0x2, 0x00000100);
|
||||
}
|
||||
|
||||
@ -138,7 +146,7 @@ void GPU_SetBlendingColor(u8 r, u8 g, u8 b, u8 a)
|
||||
|
||||
void GPU_SetTextureEnable(GPU_TEXUNIT units)
|
||||
{
|
||||
GPUCMD_AddMaskedWrite(GPUREG_SH_OUTATTR_CLOCK, 0x2, units<<8); /* enables texcoord outputs */
|
||||
GPUCMD_AddMaskedWrite(GPUREG_SH_OUTATTR_CLOCK, 0x2, units << 8); /* enables texcoord outputs */
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, 0x00011000|units); /* enables texture units */
|
||||
}
|
||||
|
||||
@ -148,22 +156,22 @@ void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 para
|
||||
{
|
||||
case GPU_TEXUNIT0:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_TYPE, colorType);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_ADDR1, ((u32)data)>>3);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_DIM, (width<<16)|height);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_ADDR1, ((u32)data) >> 3);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_DIM, (width << 16)|height);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_PARAM, param);
|
||||
break;
|
||||
|
||||
case GPU_TEXUNIT1:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_TYPE, colorType);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_ADDR, ((u32)data)>>3);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_DIM, (width<<16)|height);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_ADDR, ((u32)data) >> 3);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_DIM, (width << 16)|height);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_PARAM, param);
|
||||
break;
|
||||
|
||||
case GPU_TEXUNIT2:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_TYPE, colorType);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_ADDR, ((u32)data)>>3);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_DIM, (width<<16)|height);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_ADDR, ((u32)data) >> 3);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_DIM, (width << 16)|height);
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_PARAM, param);
|
||||
break;
|
||||
}
|
||||
@ -172,49 +180,60 @@ void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 para
|
||||
void GPU_SetTextureBorderColor(GPU_TEXUNIT unit,u32 borderColor)
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case GPU_TEXUNIT0:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_BORDER_COLOR, borderColor);
|
||||
break;
|
||||
{
|
||||
case GPU_TEXUNIT0:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_BORDER_COLOR, borderColor);
|
||||
break;
|
||||
|
||||
case GPU_TEXUNIT1:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_BORDER_COLOR, borderColor);
|
||||
break;
|
||||
case GPU_TEXUNIT1:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT1_BORDER_COLOR, borderColor);
|
||||
break;
|
||||
|
||||
case GPU_TEXUNIT2:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_BORDER_COLOR, borderColor);
|
||||
break;
|
||||
}
|
||||
case GPU_TEXUNIT2:
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT2_BORDER_COLOR, borderColor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const u8 GPU_FORMATSIZE[4]={1,1,2,4};
|
||||
|
||||
void GPU_SetAttributeBuffers(u8 totalAttributes, u32* baseAddress, u64 attributeFormats, u16 attributeMask, u64 attributePermutation, u8 numBuffers, u32 bufferOffsets[], u64 bufferPermutations[], u8 bufferNumAttributes[])
|
||||
void GPU_SetAttributeBuffers(
|
||||
u8 totalAttributes,
|
||||
u32* baseAddress,
|
||||
u64 attributeFormats,
|
||||
u16 attributeMask,
|
||||
u64 attributePermutation,
|
||||
u8 numBuffers,
|
||||
u32 bufferOffsets[],
|
||||
u64 bufferPermutations[],
|
||||
u8 bufferNumAttributes[])
|
||||
{
|
||||
int i, j;
|
||||
u32 param[0x28];
|
||||
u8 sizeTable[0xC];
|
||||
|
||||
memset(param, 0x00, 0x28*4);
|
||||
|
||||
param[0x0]=((u32)baseAddress)>>3;
|
||||
param[0x1]=attributeFormats&0xFFFFFFFF;
|
||||
param[0x2]=((totalAttributes-1)<<28)|((attributeMask&0xFFF)<<16)|((attributeFormats>>32)&0xFFFF);
|
||||
param[0x0] = ((u32)baseAddress) >> 3;
|
||||
param[0x1] = attributeFormats & 0xFFFFFFFF;
|
||||
param[0x2] = ((totalAttributes-1) << 28) | ((attributeMask & 0xFFF) << 16) | ((attributeFormats >> 32) & 0xFFFF);
|
||||
|
||||
int i, j;
|
||||
u8 sizeTable[0xC];
|
||||
for(i=0;i<totalAttributes;i++)
|
||||
for(i = 0; i < totalAttributes; i++)
|
||||
{
|
||||
u8 v=attributeFormats&0xF;
|
||||
sizeTable[i]=GPU_FORMATSIZE[v&3]*((v>>2)+1);
|
||||
attributeFormats>>=4;
|
||||
u8 v = attributeFormats & 0xF;
|
||||
sizeTable[i] = GPU_FORMATSIZE[v & 3]*((v>>2)+1);
|
||||
attributeFormats >>= 4;
|
||||
}
|
||||
|
||||
for(i=0;i<numBuffers;i++)
|
||||
{
|
||||
u16 stride=0;
|
||||
param[3*(i+1)+0]=bufferOffsets[i];
|
||||
param[3*(i+1)+1]=bufferPermutations[i]&0xFFFFFFFF;
|
||||
for(j=0;j<bufferNumAttributes[i];j++)stride+=sizeTable[(bufferPermutations[i]>>(4*j))&0xF];
|
||||
param[3*(i+1)+2]=(bufferNumAttributes[i]<<28)|((stride&0xFFF)<<16)|((bufferPermutations[i]>>32)&0xFFFF);
|
||||
u16 stride = 0;
|
||||
param[3*(i+1)+0] = bufferOffsets[i];
|
||||
param[3*(i+1)+1] = bufferPermutations[i] & 0xFFFFFFFF;
|
||||
for(j = 0; j < bufferNumAttributes[i]; j++)
|
||||
stride += sizeTable[(bufferPermutations[i]>>(4*j)) & 0xF];
|
||||
|
||||
param[3*(i+1)+2] = (bufferNumAttributes[i] << 28) | ((stride & 0xFFF)<< 16) | ((bufferPermutations[i] >> 32) & 0xFFFF);
|
||||
}
|
||||
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_ATTRIBBUFFERS_LOC, param, 0x00000027);
|
||||
@ -222,17 +241,17 @@ void GPU_SetAttributeBuffers(u8 totalAttributes, u32* baseAddress, u64 attribute
|
||||
GPUCMD_AddMaskedWrite(GPUREG_VSH_INPUTBUFFER_CONFIG, 0xB, 0xA0000000|(totalAttributes-1));
|
||||
GPUCMD_AddWrite(GPUREG_VSH_NUM_ATTR, (totalAttributes-1));
|
||||
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, ((u32[]){attributePermutation&0xFFFFFFFF, (attributePermutation>>32)&0xFFFF}), 2);
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, ((u32[]){attributePermutation & 0xFFFFFFFF, (attributePermutation >> 32) & 0xFFFF}), 2);
|
||||
}
|
||||
|
||||
void GPU_SetAttributeBuffersAddress(u32* baseAddress)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_ATTRIBBUFFERS_LOC, ((u32)baseAddress)>>3);
|
||||
GPUCMD_AddWrite(GPUREG_ATTRIBBUFFERS_LOC, ((u32)baseAddress) >> 3);
|
||||
}
|
||||
|
||||
void GPU_SetFaceCulling(GPU_CULLMODE mode)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_FACECULLING_CONFIG, mode&0x3);
|
||||
GPUCMD_AddWrite(GPUREG_FACECULLING_CONFIG, mode & 0x3);
|
||||
}
|
||||
|
||||
void GPU_SetCombinerBufferWrite(u8 rgb_config, u8 alpha_config)
|
||||
@ -244,15 +263,16 @@ const u8 GPU_TEVID[]={0xC0,0xC8,0xD0,0xD8,0xF0,0xF8};
|
||||
|
||||
void GPU_SetTexEnv(u8 id, u16 rgbSources, u16 alphaSources, u16 rgbOperands, u16 alphaOperands, GPU_COMBINEFUNC rgbCombine, GPU_COMBINEFUNC alphaCombine, u32 constantColor)
|
||||
{
|
||||
if(id>6)return;
|
||||
u32 param[0x5];
|
||||
if(id > 6)
|
||||
return;
|
||||
memset(param, 0x00, 5*4);
|
||||
|
||||
param[0x0]=(alphaSources<<16)|(rgbSources);
|
||||
param[0x1]=(alphaOperands<<12)|(rgbOperands);
|
||||
param[0x2]=(alphaCombine<<16)|(rgbCombine);
|
||||
param[0x3]=constantColor;
|
||||
param[0x4]=0x00000000; /* ? */
|
||||
param[0x0] = (alphaSources << 16) | (rgbSources);
|
||||
param[0x1] = (alphaOperands << 12) | (rgbOperands);
|
||||
param[0x2] = (alphaCombine << 16) | (rgbCombine);
|
||||
param[0x3] = constantColor;
|
||||
param[0x4] = 0x00000000; /* ? */
|
||||
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_0000|GPU_TEVID[id], param, 0x00000005);
|
||||
}
|
||||
@ -262,7 +282,8 @@ void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count)
|
||||
/* set primitive type */
|
||||
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
|
||||
/* index buffer address register should be cleared (except bit 31) before drawing */
|
||||
/* index buffer address register should be cleared
|
||||
* (except bit 31) before drawing */
|
||||
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000);
|
||||
/* pass number of vertices */
|
||||
GPUCMD_AddWrite(GPUREG_NUMVERTICES, count);
|
||||
@ -298,10 +319,11 @@ void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n)
|
||||
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000001);
|
||||
GPUCMD_AddWrite(GPUREG_VTX_FUNC, 0x00000001);
|
||||
|
||||
/* CHECKME: does this one also require GPUREG_FRAMEBUFFER_FLUSH at the end? */
|
||||
/* CHECKME: does this one also require
|
||||
* GPUREG_FRAMEBUFFER_FLUSH at the end? */
|
||||
}
|
||||
|
||||
void GPU_FinishDrawing()
|
||||
void GPU_FinishDrawing(void)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 0x00000001);
|
||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 0x00000001);
|
||||
@ -317,7 +339,8 @@ void GPU_Finalize(void)
|
||||
GPUCMD_Split(NULL, NULL);
|
||||
#else
|
||||
GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678);
|
||||
/* not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now */
|
||||
/* not the cleanest way of guaranteeing 0x10-byte size
|
||||
* but whatever good enough for now */
|
||||
GPUCMD_AddWrite(GPUREG_FINALIZE,0x12345678);
|
||||
#endif
|
||||
}
|
||||
|
@ -217,30 +217,39 @@ static int database_cursor_iterate(libretrodb_cursor_t *cur,
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->franchise = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "bbfc_rating"))
|
||||
else if (string_ends_with(str, "_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->bbfc_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "esrb_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->esrb_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "elspa_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->elspa_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "cero_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->cero_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "pegi_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->pegi_rating = strdup(val_string);
|
||||
if (string_is_equal(str, "bbfc_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->bbfc_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "esrb_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->esrb_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "elspa_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->elspa_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "cero_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->cero_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "pegi_rating"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->pegi_rating = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "edge_rating"))
|
||||
db_info->edge_magazine_rating = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "famitsu_rating"))
|
||||
db_info->famitsu_magazine_rating = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "tgdb_rating"))
|
||||
db_info->tgdb_rating = (unsigned)val->val.uint_;
|
||||
}
|
||||
else if (string_is_equal(str, "enhancement_hw"))
|
||||
{
|
||||
@ -252,14 +261,8 @@ static int database_cursor_iterate(libretrodb_cursor_t *cur,
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->edge_magazine_review = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "edge_rating"))
|
||||
db_info->edge_magazine_rating = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "edge_issue"))
|
||||
db_info->edge_magazine_issue = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "famitsu_rating"))
|
||||
db_info->famitsu_magazine_rating = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "tgdb_rating"))
|
||||
db_info->tgdb_rating = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "users"))
|
||||
db_info->max_users = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "releasemonth"))
|
||||
|
@ -17,8 +17,6 @@
|
||||
#ifndef _PS3_DEFINES_H
|
||||
#define _PS3_DEFINES_H
|
||||
|
||||
#include <sdk_version.h>
|
||||
|
||||
/*============================================================
|
||||
AUDIO PROTOTYPES
|
||||
============================================================ */
|
||||
@ -71,6 +69,7 @@ extern int audioAddData(uint32_t portNum, float *data, uint32_t frames, float vo
|
||||
#define sys_semaphore_t sys_sem_t
|
||||
|
||||
#else
|
||||
#include <sdk_version.h>
|
||||
#include <cell/audio.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/synchronization.h>
|
||||
@ -330,6 +329,11 @@ extern int audioAddData(uint32_t portNum, float *data, uint32_t frames, float vo
|
||||
#define sys_ppu_thread_join sysThreadJoin
|
||||
#define sys_ppu_thread_exit sysThreadExit
|
||||
|
||||
#define sys_process_exit sysProcessExit
|
||||
#define sys_game_process_exitspawn sysProcessExitSpawn2
|
||||
|
||||
#define SYS_PROCESS_PRIMARY_STACK_SIZE_1M SYS_PROCESS_SPAWN_STACK_SIZE_1M
|
||||
|
||||
#define SYS_PPU_THREAD_CREATE_JOINABLE 0 /* FIXME - not sure if this is correct */
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#include <sys/ppu_thread.h>
|
||||
@ -572,6 +576,7 @@ extern int audioAddData(uint32_t portNum, float *data, uint32_t frames, float vo
|
||||
#define socketclose close
|
||||
|
||||
#define sys_net_initialize_network netInitialize
|
||||
#define sys_net_finalize_network netFinalizeNetwork
|
||||
#else
|
||||
#include <netex/net.h>
|
||||
#include <np.h>
|
||||
|
1
deps/7zip/CpuArch.h
vendored
1
deps/7zip/CpuArch.h
vendored
@ -4,6 +4,7 @@
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
||||
#include <retro_endianness.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
11
deps/discord-rpc/include/discord_register.h
vendored
11
deps/discord-rpc/include/discord_register.h
vendored
@ -1,14 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#define DISCORD_EXPORT
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && !defined(CXX_BUILD)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command);
|
||||
DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId);
|
||||
int get_process_id(void);
|
||||
void Discord_Register(const char* applicationId, const char* command);
|
||||
void Discord_RegisterSteamGame(const char* applicationId, const char* steamId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && !defined(CXX_BUILD)
|
||||
}
|
||||
#endif
|
||||
|
28
deps/discord-rpc/include/discord_rpc.h
vendored
28
deps/discord-rpc/include/discord_rpc.h
vendored
@ -1,12 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
# define DISCORD_EXPORT
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -52,28 +46,28 @@ typedef struct DiscordEventHandlers
|
||||
#define DISCORD_REPLY_YES 1
|
||||
#define DISCORD_REPLY_IGNORE 2
|
||||
|
||||
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId);
|
||||
DISCORD_EXPORT void Discord_Shutdown(void);
|
||||
void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId);
|
||||
void Discord_Shutdown(void);
|
||||
|
||||
/* checks for incoming messages, dispatches callbacks */
|
||||
DISCORD_EXPORT void Discord_RunCallbacks(void);
|
||||
void Discord_RunCallbacks(void);
|
||||
|
||||
/* If you disable the lib starting its own I/O thread,
|
||||
* you'll need to call this from your own */
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
DISCORD_EXPORT void Discord_UpdateConnection(void);
|
||||
void Discord_UpdateConnection(void);
|
||||
#endif
|
||||
|
||||
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||
DISCORD_EXPORT void Discord_ClearPresence(void);
|
||||
void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||
void Discord_ClearPresence(void);
|
||||
|
||||
DISCORD_EXPORT void Discord_Respond(const char* userid,
|
||||
void Discord_Respond(const char* userid,
|
||||
/* DISCORD_REPLY_ */ int reply);
|
||||
|
||||
DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
|
||||
void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
55
deps/discord-rpc/src/backoff.h
vendored
55
deps/discord-rpc/src/backoff.h
vendored
@ -5,36 +5,37 @@
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
struct Backoff {
|
||||
int64_t minAmount;
|
||||
int64_t maxAmount;
|
||||
int64_t current;
|
||||
int fails;
|
||||
std::mt19937_64 randGenerator;
|
||||
std::uniform_real_distribution<> randDistribution;
|
||||
struct Backoff
|
||||
{
|
||||
int64_t minAmount;
|
||||
int64_t maxAmount;
|
||||
int64_t current;
|
||||
int fails;
|
||||
std::mt19937_64 randGenerator;
|
||||
std::uniform_real_distribution<> randDistribution;
|
||||
|
||||
double rand01() { return randDistribution(randGenerator); }
|
||||
double rand01() { return randDistribution(randGenerator); }
|
||||
|
||||
Backoff(int64_t min, int64_t max)
|
||||
Backoff(int64_t min, int64_t max)
|
||||
: minAmount(min)
|
||||
, maxAmount(max)
|
||||
, current(min)
|
||||
, fails(0)
|
||||
, randGenerator((uint64_t)time(0))
|
||||
{
|
||||
}
|
||||
, maxAmount(max)
|
||||
, current(min)
|
||||
, fails(0)
|
||||
, randGenerator((uint64_t)time(0))
|
||||
{
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
fails = 0;
|
||||
current = minAmount;
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
fails = 0;
|
||||
current = minAmount;
|
||||
}
|
||||
|
||||
int64_t nextDelay()
|
||||
{
|
||||
++fails;
|
||||
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
|
||||
current = std::min(current + delay, maxAmount);
|
||||
return current;
|
||||
}
|
||||
int64_t nextDelay()
|
||||
{
|
||||
++fails;
|
||||
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
|
||||
current = std::min(current + delay, maxAmount);
|
||||
return current;
|
||||
}
|
||||
};
|
||||
|
20
deps/discord-rpc/src/connection.h
vendored
20
deps/discord-rpc/src/connection.h
vendored
@ -5,15 +5,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* not really connectiony, but need per-platform */
|
||||
int GetProcessId();
|
||||
|
||||
struct BaseConnection {
|
||||
static BaseConnection* Create();
|
||||
static void Destroy(BaseConnection*&);
|
||||
bool isOpen{false};
|
||||
bool Open();
|
||||
bool Close();
|
||||
bool Write(const void* data, size_t length);
|
||||
bool Read(void* data, size_t length);
|
||||
struct BaseConnection
|
||||
{
|
||||
static BaseConnection* Create();
|
||||
static void Destroy(BaseConnection*&);
|
||||
bool isOpen{false};
|
||||
bool Open();
|
||||
bool Close();
|
||||
bool Write(const void* data, size_t length);
|
||||
bool Read(void* data, size_t length);
|
||||
};
|
||||
|
5
deps/discord-rpc/src/connection_unix.cpp
vendored
5
deps/discord-rpc/src/connection_unix.cpp
vendored
@ -9,11 +9,6 @@
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int GetProcessId()
|
||||
{
|
||||
return ::getpid();
|
||||
}
|
||||
|
||||
struct BaseConnectionUnix : public BaseConnection {
|
||||
int sock{-1};
|
||||
};
|
||||
|
5
deps/discord-rpc/src/connection_win.cpp
vendored
5
deps/discord-rpc/src/connection_win.cpp
vendored
@ -6,11 +6,6 @@
|
||||
#define NOIME
|
||||
#include <windows.h>
|
||||
|
||||
int GetProcessId()
|
||||
{
|
||||
return (int)::GetCurrentProcessId();
|
||||
}
|
||||
|
||||
struct BaseConnectionWin : public BaseConnection
|
||||
{
|
||||
HANDLE pipe{INVALID_HANDLE_VALUE};
|
||||
|
18
deps/discord-rpc/src/discord_register_linux.c
vendored
18
deps/discord-rpc/src/discord_register_linux.c
vendored
@ -1,21 +1,29 @@
|
||||
#include "discord_rpc.h"
|
||||
#include "discord_register.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <file/file_path.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#include <discord_rpc.h>
|
||||
|
||||
int get_process_id(void)
|
||||
{
|
||||
return getpid();
|
||||
}
|
||||
|
||||
/* we want to register games so we can run them from
|
||||
* Discord client as discord-<appid>:// */
|
||||
void Discord_Register(const char* applicationId, const char* command)
|
||||
void Discord_Register(const char *applicationId, const char *command)
|
||||
{
|
||||
FILE* fp;
|
||||
int fileLen;
|
||||
@ -82,9 +90,7 @@ void Discord_Register(const char* applicationId, const char* command)
|
||||
fprintf(stderr, "Failed to register mime handler\n");
|
||||
}
|
||||
|
||||
void Discord_RegisterSteamGame(
|
||||
const char* applicationId,
|
||||
const char* steamId)
|
||||
void Discord_RegisterSteamGame(const char *applicationId, const char *steamId)
|
||||
{
|
||||
char command[256];
|
||||
snprintf(command, sizeof(command), "xdg-open steam://rungameid/%s", steamId);
|
||||
|
79
deps/discord-rpc/src/discord_register_osx.m
vendored
79
deps/discord-rpc/src/discord_register_osx.m
vendored
@ -3,7 +3,10 @@
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#include "../include/discord_register.h"
|
||||
int get_process_id(void)
|
||||
{
|
||||
return getpid();
|
||||
}
|
||||
|
||||
static void RegisterCommand(const char* applicationId, const char* command)
|
||||
{
|
||||
@ -31,54 +34,52 @@ static void RegisterCommand(const char* applicationId, const char* command)
|
||||
|
||||
static void RegisterURL(const char* applicationId)
|
||||
{
|
||||
char url[256];
|
||||
snprintf(url, sizeof(url), "discord-%s", applicationId);
|
||||
CFStringRef cfURL = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8);
|
||||
NSString* myBundleId = [[NSBundle mainBundle] bundleIdentifier];
|
||||
char url[256];
|
||||
snprintf(url, sizeof(url), "discord-%s", applicationId);
|
||||
CFStringRef cfURL = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8);
|
||||
NSString* myBundleId = [[NSBundle mainBundle] bundleIdentifier];
|
||||
|
||||
if (!myBundleId)
|
||||
{
|
||||
fprintf(stderr, "No bundle id found\n");
|
||||
return;
|
||||
}
|
||||
if (!myBundleId)
|
||||
{
|
||||
fprintf(stderr, "No bundle id found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL* myURL = [[NSBundle mainBundle] bundleURL];
|
||||
if (!myURL)
|
||||
{
|
||||
fprintf(stderr, "No bundle url found\n");
|
||||
return;
|
||||
}
|
||||
NSURL* myURL = [[NSBundle mainBundle] bundleURL];
|
||||
if (!myURL)
|
||||
{
|
||||
fprintf(stderr, "No bundle url found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
OSStatus status = LSSetDefaultHandlerForURLScheme(cfURL, (__bridge CFStringRef)myBundleId);
|
||||
if (status != noErr)
|
||||
{
|
||||
fprintf(stderr, "Error in LSSetDefaultHandlerForURLScheme: %d\n", (int)status);
|
||||
return;
|
||||
}
|
||||
OSStatus status = LSSetDefaultHandlerForURLScheme(cfURL, (__bridge CFStringRef)myBundleId);
|
||||
if (status != noErr)
|
||||
{
|
||||
fprintf(stderr, "Error in LSSetDefaultHandlerForURLScheme: %d\n", (int)status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = LSRegisterURL((__bridge CFURLRef)myURL, true);
|
||||
if (status != noErr)
|
||||
{
|
||||
fprintf(stderr, "Error in LSRegisterURL: %d\n", (int)status);
|
||||
}
|
||||
status = LSRegisterURL((__bridge CFURLRef)myURL, true);
|
||||
if (status != noErr)
|
||||
fprintf(stderr, "Error in LSRegisterURL: %d\n", (int)status);
|
||||
}
|
||||
|
||||
void Discord_Register(const char* applicationId, const char* command)
|
||||
{
|
||||
if (command)
|
||||
RegisterCommand(applicationId, command);
|
||||
else
|
||||
{
|
||||
/* RAII Lite */
|
||||
@autoreleasepool {
|
||||
RegisterURL(applicationId);
|
||||
}
|
||||
}
|
||||
if (command)
|
||||
RegisterCommand(applicationId, command);
|
||||
else
|
||||
{
|
||||
/* RAII Lite */
|
||||
@autoreleasepool {
|
||||
RegisterURL(applicationId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Discord_RegisterSteamGame(const char* applicationId, const char* steamId)
|
||||
{
|
||||
char command[256];
|
||||
snprintf(command, sizeof(command), "steam://rungameid/%s", steamId);
|
||||
Discord_Register(applicationId, command);
|
||||
char command[256];
|
||||
snprintf(command, sizeof(command), "steam://rungameid/%s", steamId);
|
||||
Discord_Register(applicationId, command);
|
||||
}
|
||||
|
155
deps/discord-rpc/src/discord_register_win.c
vendored
155
deps/discord-rpc/src/discord_register_win.c
vendored
@ -1,5 +1,4 @@
|
||||
#include "discord_rpc.h"
|
||||
#include "discord_register.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
@ -10,6 +9,11 @@
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int get_process_id(void)
|
||||
{
|
||||
return (int)GetCurrentProcessId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updated fixes for MinGW and WinXP
|
||||
* This block is written the way it does not involve changing the rest of the code
|
||||
@ -53,99 +57,99 @@ static LSTATUS regset(HKEY hkey,
|
||||
const void* data,
|
||||
DWORD len)
|
||||
{
|
||||
HKEY htkey = hkey, hsubkey = NULL;
|
||||
LSTATUS ret;
|
||||
if (subkey && subkey[0])
|
||||
{
|
||||
if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) !=
|
||||
LSTATUS ret;
|
||||
HKEY htkey = hkey, hsubkey = NULL;
|
||||
if (subkey && subkey[0])
|
||||
{
|
||||
if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) !=
|
||||
ERROR_SUCCESS)
|
||||
return ret;
|
||||
htkey = hsubkey;
|
||||
}
|
||||
ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len);
|
||||
if (hsubkey && hsubkey != hkey)
|
||||
RegCloseKey(hsubkey);
|
||||
return ret;
|
||||
return ret;
|
||||
htkey = hsubkey;
|
||||
}
|
||||
ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len);
|
||||
if (hsubkey && hsubkey != hkey)
|
||||
RegCloseKey(hsubkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void Discord_RegisterW(
|
||||
const wchar_t* applicationId, const wchar_t* command)
|
||||
{
|
||||
/* https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
|
||||
* we want to register games so we can run them as discord-<appid>://
|
||||
* Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. */
|
||||
/* https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
|
||||
* we want to register games so we can run them as discord-<appid>://
|
||||
* Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. */
|
||||
|
||||
DWORD len;
|
||||
LSTATUS result;
|
||||
wchar_t urlProtocol = 0;
|
||||
wchar_t keyName[256];
|
||||
wchar_t protocolName[64];
|
||||
wchar_t protocolDescription[128];
|
||||
wchar_t exeFilePath[MAX_PATH];
|
||||
DWORD exeLen = GetModuleFileNameW(NULL, exeFilePath, MAX_PATH);
|
||||
wchar_t openCommand[1024];
|
||||
DWORD len;
|
||||
LSTATUS result;
|
||||
wchar_t urlProtocol = 0;
|
||||
wchar_t keyName[256];
|
||||
wchar_t protocolName[64];
|
||||
wchar_t protocolDescription[128];
|
||||
wchar_t exeFilePath[MAX_PATH];
|
||||
DWORD exeLen = GetModuleFileNameW(NULL, exeFilePath, MAX_PATH);
|
||||
wchar_t openCommand[1024];
|
||||
|
||||
if (command && command[0])
|
||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%S", command);
|
||||
else
|
||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%S", exeFilePath);
|
||||
if (command && command[0])
|
||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%S", command);
|
||||
else
|
||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%S", exeFilePath);
|
||||
|
||||
StringCbPrintfW(protocolName, sizeof(protocolName),
|
||||
L"discord-%S", applicationId);
|
||||
StringCbPrintfW(
|
||||
protocolDescription, sizeof(protocolDescription),
|
||||
L"URL:Run game %S protocol", applicationId);
|
||||
StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%S", protocolName);
|
||||
HKEY key;
|
||||
LSTATUS status =
|
||||
StringCbPrintfW(protocolName, sizeof(protocolName),
|
||||
L"discord-%S", applicationId);
|
||||
StringCbPrintfW(
|
||||
protocolDescription, sizeof(protocolDescription),
|
||||
L"URL:Run game %S protocol", applicationId);
|
||||
StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%S", protocolName);
|
||||
HKEY key;
|
||||
LSTATUS status =
|
||||
RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Error creating key\n");
|
||||
return;
|
||||
}
|
||||
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||
result =
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Error creating key\n");
|
||||
return;
|
||||
}
|
||||
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||
result =
|
||||
RegSetKeyValueW(key, NULL, NULL, REG_SZ, protocolDescription, len * sizeof(wchar_t));
|
||||
if (FAILED(result)) {
|
||||
fprintf(stderr, "Error writing description\n");
|
||||
}
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing description\n");
|
||||
|
||||
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||
result = RegSetKeyValueW(key, NULL, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t));
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing description\n");
|
||||
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||
result = RegSetKeyValueW(key, NULL, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t));
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing description\n");
|
||||
|
||||
result = RegSetKeyValueW(
|
||||
key, L"DefaultIcon", NULL, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t));
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing icon\n");
|
||||
result = RegSetKeyValueW(
|
||||
key, L"DefaultIcon", NULL, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t));
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing icon\n");
|
||||
|
||||
len = (DWORD)lstrlenW(openCommand) + 1;
|
||||
result = RegSetKeyValueW(
|
||||
key, L"shell\\open\\command", NULL, REG_SZ, openCommand, len * sizeof(wchar_t));
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing command\n");
|
||||
RegCloseKey(key);
|
||||
len = (DWORD)lstrlenW(openCommand) + 1;
|
||||
result = RegSetKeyValueW(
|
||||
key, L"shell\\open\\command", NULL, REG_SZ, openCommand, len * sizeof(wchar_t));
|
||||
if (FAILED(result))
|
||||
fprintf(stderr, "Error writing command\n");
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
void Discord_Register(const char* applicationId, const char* command)
|
||||
{
|
||||
wchar_t openCommand[1024];
|
||||
const wchar_t* wcommand = NULL;
|
||||
wchar_t appId[32];
|
||||
wchar_t appId[32];
|
||||
wchar_t openCommand[1024];
|
||||
const wchar_t* wcommand = NULL;
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||
if (command && command[0])
|
||||
{
|
||||
const int commandBufferLen =
|
||||
sizeof(openCommand) / sizeof(*openCommand);
|
||||
MultiByteToWideChar(CP_UTF8, 0, command, -1,
|
||||
openCommand, commandBufferLen);
|
||||
wcommand = openCommand;
|
||||
}
|
||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||
|
||||
Discord_RegisterW(appId, wcommand);
|
||||
if (command && command[0])
|
||||
{
|
||||
const int commandBufferLen =
|
||||
sizeof(openCommand) / sizeof(*openCommand);
|
||||
MultiByteToWideChar(CP_UTF8, 0, command, -1,
|
||||
openCommand, commandBufferLen);
|
||||
wcommand = openCommand;
|
||||
}
|
||||
|
||||
Discord_RegisterW(appId, wcommand);
|
||||
}
|
||||
|
||||
void Discord_RegisterSteamGame(
|
||||
@ -172,7 +176,8 @@ void Discord_RegisterSteamGame(
|
||||
status = RegQueryValueExW(key,
|
||||
L"SteamExe", NULL, NULL, (BYTE*)steamPath, &pathBytes);
|
||||
RegCloseKey(key);
|
||||
if (status != ERROR_SUCCESS || pathBytes < 1) {
|
||||
if (status != ERROR_SUCCESS || pathBytes < 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading SteamExe key\n");
|
||||
return;
|
||||
}
|
||||
|
169
deps/discord-rpc/src/discord_rpc.cpp
vendored
169
deps/discord-rpc/src/discord_rpc.cpp
vendored
@ -1,7 +1,7 @@
|
||||
#include "discord_rpc.h"
|
||||
#include "discord_register.h"
|
||||
|
||||
#include "backoff.h"
|
||||
#include "discord_register.h"
|
||||
#include "msg_queue.h"
|
||||
#include "rpc_connection.h"
|
||||
#include "serialization.h"
|
||||
@ -15,14 +15,10 @@
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
constexpr size_t MaxMessageSize{16 * 1024};
|
||||
constexpr size_t MessageQueueSize{8};
|
||||
constexpr size_t JoinQueueSize{8};
|
||||
|
||||
struct QueuedMessage
|
||||
{
|
||||
size_t length;
|
||||
char buffer[MaxMessageSize];
|
||||
char buffer[16384];
|
||||
|
||||
void Copy(const QueuedMessage& other)
|
||||
{
|
||||
@ -50,25 +46,32 @@ struct User
|
||||
* from future changes in these sizes */
|
||||
};
|
||||
|
||||
static int Pid{0};
|
||||
static int Nonce{1};
|
||||
static int LastErrorCode{0};
|
||||
static int LastDisconnectErrorCode{0};
|
||||
|
||||
static char JoinGameSecret[256];
|
||||
static char SpectateGameSecret[256];
|
||||
static char LastErrorMessage[256];
|
||||
static char LastDisconnectErrorMessage[256];
|
||||
|
||||
static RpcConnection* Connection{nullptr};
|
||||
|
||||
static DiscordEventHandlers QueuedHandlers{};
|
||||
static DiscordEventHandlers Handlers{};
|
||||
|
||||
static std::atomic_bool WasJustConnected{false};
|
||||
static std::atomic_bool WasJustDisconnected{false};
|
||||
static std::atomic_bool GotErrorMessage{false};
|
||||
static std::atomic_bool WasJoinGame{false};
|
||||
static std::atomic_bool WasSpectateGame{false};
|
||||
static char JoinGameSecret[256];
|
||||
static char SpectateGameSecret[256];
|
||||
static int LastErrorCode{0};
|
||||
static char LastErrorMessage[256];
|
||||
static int LastDisconnectErrorCode{0};
|
||||
static char LastDisconnectErrorMessage[256];
|
||||
|
||||
static std::mutex PresenceMutex;
|
||||
static std::mutex HandlerMutex;
|
||||
static QueuedMessage QueuedPresence{};
|
||||
static MsgQueue<QueuedMessage, MessageQueueSize> SendQueue;
|
||||
static MsgQueue<User, JoinQueueSize> JoinAskQueue;
|
||||
static MsgQueue<QueuedMessage, 8> SendQueue;
|
||||
static MsgQueue<User, 8> JoinAskQueue;
|
||||
static User connectedUser;
|
||||
|
||||
/* We want to auto connect, and retry on failure,
|
||||
@ -76,64 +79,64 @@ static User connectedUser;
|
||||
* backoff from 0.5 seconds to 1 minute */
|
||||
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
||||
static auto NextConnect = std::chrono::system_clock::now();
|
||||
static int Pid{0};
|
||||
static int Nonce{1};
|
||||
|
||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||
static void Discord_UpdateConnection(void);
|
||||
class IoThreadHolder {
|
||||
private:
|
||||
std::atomic_bool keepRunning{true};
|
||||
std::mutex waitForIOMutex;
|
||||
std::condition_variable waitForIOActivity;
|
||||
std::thread ioThread;
|
||||
class IoThreadHolder
|
||||
{
|
||||
private:
|
||||
std::atomic_bool keepRunning{true};
|
||||
std::mutex waitForIOMutex;
|
||||
std::condition_variable waitForIOActivity;
|
||||
std::thread ioThread;
|
||||
|
||||
public:
|
||||
void Start()
|
||||
{
|
||||
keepRunning.store(true);
|
||||
ioThread = std::thread([&]() {
|
||||
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||
Discord_UpdateConnection();
|
||||
while (keepRunning.load()) {
|
||||
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||
waitForIOActivity.wait_for(lock, maxWait);
|
||||
Discord_UpdateConnection();
|
||||
}
|
||||
});
|
||||
}
|
||||
public:
|
||||
void Start()
|
||||
{
|
||||
keepRunning.store(true);
|
||||
ioThread = std::thread([&]() {
|
||||
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||
Discord_UpdateConnection();
|
||||
while (keepRunning.load()) {
|
||||
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||
waitForIOActivity.wait_for(lock, maxWait);
|
||||
Discord_UpdateConnection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Notify() { waitForIOActivity.notify_all(); }
|
||||
void Notify() { waitForIOActivity.notify_all(); }
|
||||
|
||||
void Stop()
|
||||
{
|
||||
keepRunning.exchange(false);
|
||||
Notify();
|
||||
if (ioThread.joinable())
|
||||
void Stop()
|
||||
{
|
||||
keepRunning.exchange(false);
|
||||
Notify();
|
||||
if (ioThread.joinable())
|
||||
ioThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
~IoThreadHolder() { Stop(); }
|
||||
~IoThreadHolder() { Stop(); }
|
||||
};
|
||||
#else
|
||||
class IoThreadHolder {
|
||||
public:
|
||||
void Start() {}
|
||||
void Stop() {}
|
||||
void Notify() {}
|
||||
class IoThreadHolder
|
||||
{
|
||||
public:
|
||||
void Start() {}
|
||||
void Stop() {}
|
||||
void Notify() {}
|
||||
};
|
||||
#endif /* DISCORD_DISABLE_IO_THREAD */
|
||||
|
||||
static IoThreadHolder* IoThread{nullptr};
|
||||
|
||||
static void UpdateReconnectTime()
|
||||
static void UpdateReconnectTime(void)
|
||||
{
|
||||
NextConnect = std::chrono::system_clock::now() +
|
||||
std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
|
||||
}
|
||||
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
extern "C" DISCORD_EXPORT void Discord_UpdateConnection(void)
|
||||
extern "C" void Discord_UpdateConnection(void)
|
||||
#else
|
||||
static void Discord_UpdateConnection(void)
|
||||
#endif
|
||||
@ -160,18 +163,18 @@ static void Discord_UpdateConnection(void)
|
||||
if (!Connection->Read(message))
|
||||
break;
|
||||
|
||||
const char* evtName = GetStrMember(&message, "evt");
|
||||
const char* nonce = GetStrMember(&message, "nonce");
|
||||
const char *evtName = GetStrMember(&message, "evt");
|
||||
const char *nonce = GetStrMember(&message, "nonce");
|
||||
|
||||
if (nonce)
|
||||
{
|
||||
/* in responses only --
|
||||
* should use to match up response when needed. */
|
||||
|
||||
if (evtName && strcmp(evtName, "ERROR") == 0)
|
||||
if (evtName && !strcmp(evtName, "ERROR"))
|
||||
{
|
||||
auto data = GetObjMember(&message, "data");
|
||||
LastErrorCode = GetIntMember(data, "code");
|
||||
JsonValue *data = GetObjMember(&message, "data");
|
||||
LastErrorCode = GetIntMember(data, "code");
|
||||
StringCopy(LastErrorMessage, GetStrMember(data, "message", ""));
|
||||
GotErrorMessage.store(true);
|
||||
}
|
||||
@ -182,39 +185,40 @@ static void Discord_UpdateConnection(void)
|
||||
if (!evtName)
|
||||
continue;
|
||||
|
||||
auto data = GetObjMember(&message, "data");
|
||||
JsonValue *data = GetObjMember(&message, "data");
|
||||
|
||||
if (strcmp(evtName, "ACTIVITY_JOIN") == 0)
|
||||
if (!strcmp(evtName, "ACTIVITY_JOIN"))
|
||||
{
|
||||
auto secret = GetStrMember(data, "secret");
|
||||
const char *secret = GetStrMember(data, "secret");
|
||||
if (secret)
|
||||
{
|
||||
StringCopy(JoinGameSecret, secret);
|
||||
WasJoinGame.store(true);
|
||||
}
|
||||
}
|
||||
else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0)
|
||||
else if (!strcmp(evtName, "ACTIVITY_SPECTATE"))
|
||||
{
|
||||
auto secret = GetStrMember(data, "secret");
|
||||
const char *secret = GetStrMember(data, "secret");
|
||||
if (secret)
|
||||
{
|
||||
StringCopy(SpectateGameSecret, secret);
|
||||
WasSpectateGame.store(true);
|
||||
}
|
||||
}
|
||||
else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0)
|
||||
else if (!strcmp(evtName, "ACTIVITY_JOIN_REQUEST"))
|
||||
{
|
||||
auto user = GetObjMember(data, "user");
|
||||
auto userId = GetStrMember(user, "id");
|
||||
auto username = GetStrMember(user, "username");
|
||||
auto avatar = GetStrMember(user, "avatar");
|
||||
auto joinReq = JoinAskQueue.GetNextAddMessage();
|
||||
JsonValue *user = GetObjMember(data, "user");
|
||||
const char *userId = GetStrMember(user, "id");
|
||||
const char *username = GetStrMember(user, "username");
|
||||
const char *avatar = GetStrMember(user, "avatar");
|
||||
auto joinReq = JoinAskQueue.GetNextAddMessage();
|
||||
|
||||
if (userId && username && joinReq)
|
||||
{
|
||||
StringCopy(joinReq->userId, userId);
|
||||
StringCopy(joinReq->username, username);
|
||||
auto discriminator = GetStrMember(user, "discriminator");
|
||||
const char *discriminator = GetStrMember(user,
|
||||
"discriminator");
|
||||
if (discriminator)
|
||||
StringCopy(joinReq->discriminator, discriminator);
|
||||
if (avatar)
|
||||
@ -283,7 +287,7 @@ static bool DeregisterForEvent(const char* evtName)
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Initialize(
|
||||
extern "C" void Discord_Initialize(
|
||||
const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
@ -301,7 +305,7 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(
|
||||
Discord_Register(applicationId, nullptr);
|
||||
}
|
||||
|
||||
Pid = GetProcessId();
|
||||
Pid = get_process_id();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
@ -321,16 +325,16 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(
|
||||
Connection->onConnect = [](JsonDocument& readyMessage)
|
||||
{
|
||||
Discord_UpdateHandlers(&QueuedHandlers);
|
||||
auto data = GetObjMember(&readyMessage, "data");
|
||||
auto user = GetObjMember(data, "user");
|
||||
auto userId = GetStrMember(user, "id");
|
||||
auto username = GetStrMember(user, "username");
|
||||
auto avatar = GetStrMember(user, "avatar");
|
||||
JsonValue *data = GetObjMember(&readyMessage, "data");
|
||||
JsonValue *user = GetObjMember(data, "user");
|
||||
const char *userId = GetStrMember(user, "id");
|
||||
const char *username = GetStrMember(user, "username");
|
||||
const char *avatar = GetStrMember(user, "avatar");
|
||||
if (userId && username)
|
||||
{
|
||||
StringCopy(connectedUser.userId, userId);
|
||||
StringCopy(connectedUser.username, username);
|
||||
auto discriminator = GetStrMember(user, "discriminator");
|
||||
const char *discriminator = GetStrMember(user, "discriminator");
|
||||
if (discriminator)
|
||||
StringCopy(connectedUser.discriminator, discriminator);
|
||||
if (avatar)
|
||||
@ -356,7 +360,7 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(
|
||||
IoThread->Start();
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
|
||||
extern "C" void Discord_Shutdown(void)
|
||||
{
|
||||
if (!Connection)
|
||||
return;
|
||||
@ -373,8 +377,7 @@ extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
|
||||
RpcConnection::Destroy(Connection);
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void
|
||||
Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||
extern "C" void Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
@ -385,12 +388,12 @@ Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||
IoThread->Notify();
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_ClearPresence(void)
|
||||
extern "C" void Discord_ClearPresence(void)
|
||||
{
|
||||
Discord_UpdatePresence(nullptr);
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
|
||||
extern "C" void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
|
||||
{
|
||||
/* if we are not connected, let's not batch up stale messages for later */
|
||||
if (!Connection || !Connection->IsOpen())
|
||||
@ -406,7 +409,7 @@ extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_RE
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
|
||||
extern "C" void Discord_RunCallbacks(void)
|
||||
{
|
||||
/* Note on some weirdness: internally we might connect, get other signals, disconnect any number
|
||||
* of times inbetween calls here. Externally, we want the sequence to seem sane, so any other
|
||||
@ -498,7 +501,7 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
|
||||
DeregisterForEvent(event)
|
||||
#endif
|
||||
|
||||
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
|
||||
extern "C" void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
|
||||
{
|
||||
if (newHandlers)
|
||||
{
|
||||
|
9
deps/discord-rpc/src/rpc_connection.cpp
vendored
9
deps/discord-rpc/src/rpc_connection.cpp
vendored
@ -3,7 +3,8 @@
|
||||
|
||||
#include <atomic>
|
||||
|
||||
static const int RpcVersion = 1;
|
||||
#define RPC_VERSION 1
|
||||
|
||||
static RpcConnection Instance;
|
||||
|
||||
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId)
|
||||
@ -36,8 +37,8 @@ void RpcConnection::Open()
|
||||
JsonDocument message;
|
||||
if (Read(message))
|
||||
{
|
||||
auto cmd = GetStrMember(&message, "cmd");
|
||||
auto evt = GetStrMember(&message, "evt");
|
||||
const char *cmd = GetStrMember(&message, "cmd");
|
||||
const char *evt = GetStrMember(&message, "evt");
|
||||
if (cmd && evt
|
||||
&& !strcmp(cmd, "DISPATCH")
|
||||
&& !strcmp(evt, "READY"))
|
||||
@ -52,7 +53,7 @@ void RpcConnection::Open()
|
||||
{
|
||||
sendFrame.opcode = Opcode::Handshake;
|
||||
sendFrame.length = (uint32_t)JsonWriteHandshakeObj(
|
||||
sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId);
|
||||
sendFrame.message, sizeof(sendFrame.message), RPC_VERSION, appId);
|
||||
|
||||
if (connection->Write(&sendFrame,
|
||||
sizeof(MessageFrameHeader) + sendFrame.length))
|
||||
|
4
deps/discord-rpc/src/rpc_connection.h
vendored
4
deps/discord-rpc/src/rpc_connection.h
vendored
@ -5,7 +5,7 @@
|
||||
|
||||
/* I took this from the buffer size libuv uses for named pipes;
|
||||
* I suspect ours would usually be much smaller. */
|
||||
constexpr size_t MaxRpcFrameSize = 64 * 1024;
|
||||
#define MAX_RPC_FRAMESIZE 65536
|
||||
|
||||
struct RpcConnection
|
||||
{
|
||||
@ -33,7 +33,7 @@ struct RpcConnection
|
||||
|
||||
struct MessageFrame : public MessageFrameHeader
|
||||
{
|
||||
char message[MaxRpcFrameSize - sizeof(MessageFrameHeader)];
|
||||
char message[MAX_RPC_FRAMESIZE - sizeof(MessageFrameHeader)];
|
||||
};
|
||||
|
||||
enum class State : uint32_t
|
||||
|
5
deps/libfat/directory.c
vendored
5
deps/libfat/directory.c
vendored
@ -1162,19 +1162,14 @@ void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct st
|
||||
0,
|
||||
u8array_to_u16 (entry->entryData, DIR_ENTRY_aDate)
|
||||
);
|
||||
st->st_spare1 = 0;
|
||||
st->st_mtime = _FAT_filetime_to_time_t (
|
||||
u8array_to_u16 (entry->entryData, DIR_ENTRY_mTime),
|
||||
u8array_to_u16 (entry->entryData, DIR_ENTRY_mDate)
|
||||
);
|
||||
st->st_spare2 = 0;
|
||||
st->st_ctime = _FAT_filetime_to_time_t (
|
||||
u8array_to_u16 (entry->entryData, DIR_ENTRY_cTime),
|
||||
u8array_to_u16 (entry->entryData, DIR_ENTRY_cDate)
|
||||
);
|
||||
st->st_spare3 = 0;
|
||||
st->st_blksize = partition->bytesPerSector; /* Prefered file I/O block size */
|
||||
st->st_blocks = (st->st_size + partition->bytesPerSector - 1) / partition->bytesPerSector; /* File size in blocks */
|
||||
st->st_spare4[0] = 0;
|
||||
st->st_spare4[1] = 0;
|
||||
}
|
||||
|
8
deps/libgo2/include/go2/display.h
vendored
8
deps/libgo2/include/go2/display.h
vendored
@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef struct go2_display go2_display_t;
|
||||
@ -78,18 +79,19 @@ void* go2_surface_map(go2_surface_t* surface);
|
||||
void go2_surface_unmap(go2_surface_t* surface);
|
||||
void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidth, int srcHeight,
|
||||
go2_surface_t* dstSurface, int dstX, int dstY, int dstWidth, int dstHeight,
|
||||
go2_rotation_t rotation);
|
||||
go2_rotation_t rotation, int scale_mode);
|
||||
int go2_surface_save_as_png(go2_surface_t* surface, const char* filename);
|
||||
|
||||
|
||||
go2_frame_buffer_t* go2_frame_buffer_create(go2_surface_t* surface);
|
||||
void go2_frame_buffer_destroy(go2_frame_buffer_t* frame_buffer);
|
||||
go2_surface_t* go2_frame_buffer_surface_get(go2_frame_buffer_t* frame_buffer);
|
||||
go2_display_t* go2_presenter_display_get(go2_presenter_t* presenter);
|
||||
|
||||
|
||||
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color);
|
||||
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color, bool managed);
|
||||
void go2_presenter_destroy(go2_presenter_t* presenter);
|
||||
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation);
|
||||
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation, int scale_mode);
|
||||
|
||||
|
||||
go2_context_t* go2_context_create(go2_display_t* display, int width, int height, const go2_context_attributes_t* attributes);
|
||||
|
167
deps/libgo2/src/display.c
vendored
167
deps/libgo2/src/display.c
vendored
@ -71,7 +71,6 @@ typedef struct go2_surface
|
||||
int stride;
|
||||
uint32_t format;
|
||||
int prime_fd;
|
||||
bool is_mapped;
|
||||
uint8_t* map;
|
||||
} go2_surface_t;
|
||||
|
||||
@ -93,6 +92,7 @@ typedef struct go2_presenter
|
||||
sem_t freeSem;
|
||||
sem_t usedSem;
|
||||
volatile bool terminating;
|
||||
bool managed;
|
||||
} go2_presenter_t;
|
||||
|
||||
|
||||
@ -100,7 +100,6 @@ go2_display_t* go2_display_create()
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
go2_display_t* result = malloc(sizeof(*result));
|
||||
if (!result)
|
||||
{
|
||||
@ -121,7 +120,7 @@ go2_display_t* go2_display_create()
|
||||
|
||||
|
||||
drmModeRes* resources = drmModeGetResources(result->fd);
|
||||
if (!resources)
|
||||
if (!resources)
|
||||
{
|
||||
printf("drmModeGetResources failed: %s\n", strerror(errno));
|
||||
goto err_01;
|
||||
@ -164,7 +163,7 @@ go2_display_t* go2_display_create()
|
||||
mode = NULL;
|
||||
}
|
||||
|
||||
if (!mode)
|
||||
if (!mode)
|
||||
{
|
||||
printf("DRM_MODE_TYPE_PREFERRED not found.\n");
|
||||
goto err_03;
|
||||
@ -184,7 +183,7 @@ go2_display_t* go2_display_create()
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
drmModeFreeEncoder(encoder);
|
||||
encoder = NULL;
|
||||
}
|
||||
@ -195,13 +194,13 @@ go2_display_t* go2_display_create()
|
||||
printf("could not find encoder!\n");
|
||||
goto err_03;
|
||||
}
|
||||
|
||||
|
||||
result->crtc_id = encoder->crtc_id;
|
||||
|
||||
drmModeFreeEncoder(encoder);
|
||||
drmModeFreeConnector(connector);
|
||||
drmModeFreeResources(resources);
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
|
||||
@ -243,7 +242,7 @@ void go2_display_present(go2_display_t* display, go2_frame_buffer_t* frame_buffe
|
||||
int ret = drmModeSetCrtc(display->fd, display->crtc_id, frame_buffer->fb_id, 0, 0, &display->connector_id, 1, &display->mode);
|
||||
if (ret)
|
||||
{
|
||||
printf("drmModeSetCrtc failed.\n");
|
||||
printf("drmModeSetCrtc failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +284,7 @@ uint32_t go2_display_backlight_get(go2_display_t* display)
|
||||
value = atoi(buffer);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
float percent = value / (float)max * 100.0f;
|
||||
@ -298,7 +297,7 @@ void go2_display_backlight_set(go2_display_t* display, uint32_t value)
|
||||
int max = 255;
|
||||
char buffer[BACKLIGHT_BUFFER_SIZE + 1];
|
||||
|
||||
|
||||
|
||||
if (value > 100) value = 100;
|
||||
|
||||
fd = open(BACKLIGHT_BRIGHTNESS_MAX_NAME, O_RDONLY);
|
||||
@ -331,13 +330,13 @@ void go2_display_backlight_set(go2_display_t* display, uint32_t value)
|
||||
printf("go2_display_backlight_set write failed.\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("go2_display_backlight_set open failed.\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -371,7 +370,7 @@ int go2_drm_format_get_bpp(uint32_t format)
|
||||
case DRM_FORMAT_BGR565:
|
||||
result = 16;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case DRM_FORMAT_RGB888:
|
||||
case DRM_FORMAT_BGR888:
|
||||
@ -443,6 +442,7 @@ go2_surface_t* go2_surface_create(go2_display_t* display, int width, int height,
|
||||
result->height = height;
|
||||
result->stride = args.pitch;
|
||||
result->format = format;
|
||||
result->map = NULL;
|
||||
|
||||
return result;
|
||||
|
||||
@ -459,7 +459,7 @@ void go2_surface_destroy(go2_surface_t* surface)
|
||||
int io = drmIoctl(surface->display->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args);
|
||||
if (io < 0)
|
||||
{
|
||||
printf("DRM_IOCTL_MODE_DESTROY_DUMB failed.\n");
|
||||
printf("DRM_IOCTL_MODE_DESTROY_DUMB failed.\n");
|
||||
}
|
||||
|
||||
free(surface);
|
||||
@ -511,10 +511,9 @@ out:
|
||||
|
||||
void* go2_surface_map(go2_surface_t* surface)
|
||||
{
|
||||
if (surface->is_mapped)
|
||||
if (surface->map)
|
||||
return surface->map;
|
||||
|
||||
|
||||
int prime_fd = go2_surface_prime_fd(surface);
|
||||
surface->map = mmap(NULL, surface->size, PROT_READ | PROT_WRITE, MAP_SHARED, prime_fd, 0);
|
||||
if (surface->map == MAP_FAILED)
|
||||
@ -523,17 +522,14 @@ void* go2_surface_map(go2_surface_t* surface)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface->is_mapped = true;
|
||||
return surface->map;
|
||||
}
|
||||
|
||||
void go2_surface_unmap(go2_surface_t* surface)
|
||||
{
|
||||
if (surface->is_mapped)
|
||||
if (surface->map)
|
||||
{
|
||||
munmap(surface->map, surface->size);
|
||||
|
||||
surface->is_mapped = false;
|
||||
surface->map = NULL;
|
||||
}
|
||||
}
|
||||
@ -545,29 +541,29 @@ static uint32_t go2_rkformat_get(uint32_t drm_fourcc)
|
||||
{
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
return RK_FORMAT_RGBA_8888;
|
||||
|
||||
|
||||
case DRM_FORMAT_RGBX8888:
|
||||
return RK_FORMAT_RGBX_8888;
|
||||
|
||||
|
||||
case DRM_FORMAT_RGB888:
|
||||
return RK_FORMAT_RGB_888;
|
||||
|
||||
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
return RK_FORMAT_BGRA_8888;
|
||||
|
||||
|
||||
case DRM_FORMAT_RGB565:
|
||||
return RK_FORMAT_RGB_565;
|
||||
|
||||
case DRM_FORMAT_RGBA5551:
|
||||
return RK_FORMAT_RGBA_5551;
|
||||
|
||||
|
||||
case DRM_FORMAT_RGBA4444:
|
||||
return RK_FORMAT_RGBA_4444;
|
||||
|
||||
case DRM_FORMAT_BGR888:
|
||||
return RK_FORMAT_BGR_888;
|
||||
|
||||
|
||||
default:
|
||||
printf("RKFORMAT not supported. ");
|
||||
printf("drm_fourcc=%c%c%c%c\n", drm_fourcc & 0xff, drm_fourcc >> 8 & 0xff, drm_fourcc >> 16 & 0xff, drm_fourcc >> 24);
|
||||
@ -577,7 +573,7 @@ static uint32_t go2_rkformat_get(uint32_t drm_fourcc)
|
||||
|
||||
void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidth, int srcHeight,
|
||||
go2_surface_t* dstSurface, int dstX, int dstY, int dstWidth, int dstHeight,
|
||||
go2_rotation_t rotation)
|
||||
go2_rotation_t rotation, int scale_mode)
|
||||
{
|
||||
rga_info_t dst = { 0 };
|
||||
dst.fd = go2_surface_prime_fd(dstSurface);
|
||||
@ -634,13 +630,12 @@ void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidt
|
||||
B_SPLINE = 0x3,
|
||||
}; /*bicubic coefficient*/
|
||||
#endif
|
||||
src.scale_mode = 2;
|
||||
|
||||
src.scale_mode = scale_mode;
|
||||
|
||||
int ret = c_RkRgaBlit(&src, &dst, NULL);
|
||||
if (ret)
|
||||
{
|
||||
printf("c_RkRgaBlit failed.\n");
|
||||
printf("c_RkRgaBlit failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -652,14 +647,14 @@ int go2_surface_save_as_png(go2_surface_t* surface, const char* filename)
|
||||
|
||||
|
||||
png_byte color_type = 0;
|
||||
png_byte bit_depth = 0;
|
||||
png_byte bit_depth = 0;
|
||||
switch (surface->format)
|
||||
{
|
||||
{
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
color_type = PNG_COLOR_TYPE_RGBA;
|
||||
bit_depth = 8;
|
||||
break;
|
||||
|
||||
|
||||
case DRM_FORMAT_RGB888:
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
bit_depth = 8;
|
||||
@ -733,7 +728,7 @@ int go2_surface_save_as_png(go2_surface_t* surface, const char* filename)
|
||||
|
||||
/* write bytes */
|
||||
png_bytep src = (png_bytep)go2_surface_map(surface);
|
||||
row_pointers = malloc(sizeof(png_bytep) * surface->height);
|
||||
row_pointers = malloc(sizeof(png_bytep) * surface->height);
|
||||
for (int y = 0; y < surface->height; ++y)
|
||||
{
|
||||
row_pointers[y] = src + (surface->stride * y);
|
||||
@ -891,14 +886,19 @@ static void* go2_presenter_renderloop(void* arg)
|
||||
sem_post(&presenter->freeSem);
|
||||
}
|
||||
|
||||
prevFrameBuffer = dstFrameBuffer;
|
||||
prevFrameBuffer = dstFrameBuffer;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color)
|
||||
go2_display_t* go2_presenter_display_get(go2_presenter_t* presenter)
|
||||
{
|
||||
return presenter->display;
|
||||
}
|
||||
|
||||
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color, bool managed)
|
||||
{
|
||||
go2_presenter_t* result = malloc(sizeof(*result));
|
||||
if (!result)
|
||||
@ -913,67 +913,74 @@ go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, u
|
||||
result->display = display;
|
||||
result->format = format;
|
||||
result->background_color = background_color;
|
||||
result->freeFrameBuffers = go2_queue_create(BUFFER_COUNT);
|
||||
result->usedFrameBuffers = go2_queue_create(BUFFER_COUNT);
|
||||
result->managed = managed;
|
||||
if (managed) {
|
||||
result->freeFrameBuffers = go2_queue_create(BUFFER_COUNT);
|
||||
result->usedFrameBuffers = go2_queue_create(BUFFER_COUNT);
|
||||
|
||||
int width = go2_display_width_get(display);
|
||||
int height = go2_display_height_get(display);
|
||||
int width = go2_display_width_get(display);
|
||||
int height = go2_display_height_get(display);
|
||||
|
||||
for (int i = 0; i < BUFFER_COUNT; ++i)
|
||||
{
|
||||
go2_surface_t* surface = go2_surface_create(display, width, height, format);
|
||||
go2_frame_buffer_t* frameBuffer = go2_frame_buffer_create(surface);
|
||||
for (int i = 0; i < BUFFER_COUNT; ++i)
|
||||
{
|
||||
go2_surface_t* surface = go2_surface_create(display, width, height, format);
|
||||
go2_frame_buffer_t* frameBuffer = go2_frame_buffer_create(surface);
|
||||
|
||||
go2_queue_push(result->freeFrameBuffers, frameBuffer);
|
||||
go2_queue_push(result->freeFrameBuffers, frameBuffer);
|
||||
}
|
||||
|
||||
sem_init(&result->usedSem, 0, 0);
|
||||
sem_init(&result->freeSem, 0, BUFFER_COUNT);
|
||||
|
||||
pthread_mutex_init(&result->queueMutex, NULL);
|
||||
|
||||
pthread_create(&result->renderThread, NULL, go2_presenter_renderloop, result);
|
||||
}
|
||||
else {
|
||||
result->freeFrameBuffers = go2_queue_create(0);
|
||||
result->usedFrameBuffers = go2_queue_create(0);
|
||||
}
|
||||
|
||||
|
||||
sem_init(&result->usedSem, 0, 0);
|
||||
sem_init(&result->freeSem, 0, BUFFER_COUNT);
|
||||
|
||||
pthread_mutex_init(&result->queueMutex, NULL);
|
||||
|
||||
pthread_create(&result->renderThread, NULL, go2_presenter_renderloop, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void go2_presenter_destroy(go2_presenter_t* presenter)
|
||||
{
|
||||
presenter->terminating = true;
|
||||
sem_post(&presenter->usedSem);
|
||||
if (presenter->managed) {
|
||||
presenter->terminating = true;
|
||||
sem_post(&presenter->usedSem);
|
||||
|
||||
pthread_join(presenter->renderThread, NULL);
|
||||
pthread_mutex_destroy(&presenter->queueMutex);
|
||||
pthread_join(presenter->renderThread, NULL);
|
||||
pthread_mutex_destroy(&presenter->queueMutex);
|
||||
|
||||
sem_destroy(&presenter->freeSem);
|
||||
sem_destroy(&presenter->usedSem);
|
||||
sem_destroy(&presenter->freeSem);
|
||||
sem_destroy(&presenter->usedSem);
|
||||
|
||||
|
||||
while(go2_queue_count_get(presenter->usedFrameBuffers) > 0)
|
||||
{
|
||||
go2_frame_buffer_t* frameBuffer = go2_queue_pop(presenter->usedFrameBuffers);
|
||||
|
||||
go2_surface_t* surface = frameBuffer->surface;
|
||||
|
||||
go2_frame_buffer_destroy(frameBuffer);
|
||||
go2_surface_destroy(surface);
|
||||
}
|
||||
while(go2_queue_count_get(presenter->usedFrameBuffers) > 0)
|
||||
{
|
||||
go2_frame_buffer_t* frameBuffer = go2_queue_pop(presenter->usedFrameBuffers);
|
||||
|
||||
while(go2_queue_count_get(presenter->freeFrameBuffers) > 0)
|
||||
{
|
||||
go2_frame_buffer_t* frameBuffer = go2_queue_pop(presenter->freeFrameBuffers);
|
||||
|
||||
go2_surface_t* surface = frameBuffer->surface;
|
||||
go2_surface_t* surface = frameBuffer->surface;
|
||||
|
||||
go2_frame_buffer_destroy(frameBuffer);
|
||||
go2_surface_destroy(surface);
|
||||
go2_frame_buffer_destroy(frameBuffer);
|
||||
go2_surface_destroy(surface);
|
||||
}
|
||||
|
||||
while(go2_queue_count_get(presenter->freeFrameBuffers) > 0)
|
||||
{
|
||||
go2_frame_buffer_t* frameBuffer = go2_queue_pop(presenter->freeFrameBuffers);
|
||||
|
||||
go2_surface_t* surface = frameBuffer->surface;
|
||||
|
||||
go2_frame_buffer_destroy(frameBuffer);
|
||||
go2_surface_destroy(surface);
|
||||
}
|
||||
}
|
||||
|
||||
free(presenter);
|
||||
}
|
||||
|
||||
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation)
|
||||
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation, int scale_mode)
|
||||
{
|
||||
sem_wait(&presenter->freeSem);
|
||||
|
||||
@ -1012,7 +1019,7 @@ void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int
|
||||
}
|
||||
|
||||
|
||||
go2_surface_blit(surface, srcX, srcY, srcWidth, srcHeight, dstSurface, dstX, dstY, dstWidth, dstHeight, rotation);
|
||||
go2_surface_blit(surface, srcX, srcY, srcWidth, srcHeight, dstSurface, dstX, dstY, dstWidth, dstHeight, rotation, scale_mode);
|
||||
|
||||
|
||||
pthread_mutex_lock(&presenter->queueMutex);
|
||||
@ -1022,8 +1029,6 @@ void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int
|
||||
sem_post(&presenter->usedSem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define BUFFER_MAX (3)
|
||||
|
||||
typedef struct buffer_surface_pair
|
||||
@ -1034,7 +1039,7 @@ typedef struct buffer_surface_pair
|
||||
|
||||
typedef struct go2_context
|
||||
{
|
||||
go2_display_t* display;
|
||||
go2_display_t* display;
|
||||
int width;
|
||||
int height;
|
||||
go2_context_attributes_t attributes;
|
||||
|
10
deps/libgo2/src/display.h
vendored
10
deps/libgo2/src/display.h
vendored
@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef struct go2_display go2_display_t;
|
||||
@ -78,7 +79,7 @@ void* go2_surface_map(go2_surface_t* surface);
|
||||
void go2_surface_unmap(go2_surface_t* surface);
|
||||
void go2_surface_blit(go2_surface_t* srcSurface, int srcX, int srcY, int srcWidth, int srcHeight,
|
||||
go2_surface_t* dstSurface, int dstX, int dstY, int dstWidth, int dstHeight,
|
||||
go2_rotation_t rotation);
|
||||
go2_rotation_t rotation, int scale_mode);
|
||||
int go2_surface_save_as_png(go2_surface_t* surface, const char* filename);
|
||||
|
||||
|
||||
@ -87,9 +88,10 @@ void go2_frame_buffer_destroy(go2_frame_buffer_t* frame_buffer);
|
||||
go2_surface_t* go2_frame_buffer_surface_get(go2_frame_buffer_t* frame_buffer);
|
||||
|
||||
|
||||
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color);
|
||||
go2_presenter_t* go2_presenter_create(go2_display_t* display, uint32_t format, uint32_t background_color, bool managed);
|
||||
void go2_presenter_destroy(go2_presenter_t* presenter);
|
||||
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation);
|
||||
void go2_presenter_post(go2_presenter_t* presenter, go2_surface_t* surface, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, go2_rotation_t rotation, int scale_mode);
|
||||
go2_display_t* go2_presenter_display_get(go2_presenter_t* presenter);
|
||||
|
||||
|
||||
go2_context_t* go2_context_create(go2_display_t* display, int width, int height, const go2_context_attributes_t* attributes);
|
||||
@ -100,6 +102,8 @@ void go2_context_swap_buffers(go2_context_t* context);
|
||||
go2_surface_t* go2_context_surface_lock(go2_context_t* context);
|
||||
void go2_context_surface_unlock(go2_context_t* context, go2_surface_t* surface);
|
||||
|
||||
go2_frame_buffer_t* go2_frame_buffer_create(go2_surface_t* surface);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
225
deps/math-neon/README
vendored
225
deps/math-neon/README
vendored
@ -36,134 +36,133 @@ Email: lachlan.ts@gmail.com
|
||||
|
||||
PSVITA performances test results:
|
||||
|
||||
RUNFAST: Enabled
|
||||
RUNFAST: Disabled
|
||||
------------------------------------------------------------------------------------------------------
|
||||
MATRIX FUNCTION TESTS
|
||||
------------------------------------------------------------------------------------------------------
|
||||
matmul2_c =
|
||||
|-7.16, 9.42|
|
||||
|17.86, -10.70|
|
||||
|-14.56, 5.96|
|
||||
|-15.35, 10.50|
|
||||
matmul2_neon =
|
||||
|-7.16, 9.42|
|
||||
|17.86, -10.70|
|
||||
matmul2: c=183985 neon=87480 rate=2.10
|
||||
matvec2_c = |-7.16, 17.86|
|
||||
matvec2_neon = |-7.16, 17.86|
|
||||
matvec2: c=98178 neon=66040 rate=1.49
|
||||
|-14.56, 5.96|
|
||||
|-15.35, 10.50|
|
||||
matmul2: c=174924 neon=64490 rate=2.71
|
||||
matvec2_c = |-14.56, -15.35|
|
||||
matvec2_neon = |-14.56, -15.35|
|
||||
matvec2: c=88957 neon=58337 rate=1.52
|
||||
matmul3_c =
|
||||
|11.14, -0.78, -3.98|
|
||||
|16.56, 17.96, 23.58|
|
||||
|8.73, -0.18, 1.57|
|
||||
|-21.39, -4.68, -1.74|
|
||||
|-8.66, -8.97, 1.83|
|
||||
|15.88, 0.30, -2.23|
|
||||
matmul3_neon =
|
||||
|11.14, -0.78, -3.98|
|
||||
|16.56, 17.96, 23.58|
|
||||
|8.73, -0.18, 1.57|
|
||||
matmul3: c=551838 neon=340292 rate=1.62
|
||||
matvec3_c = |11.14, 16.56, 8.73|
|
||||
matvec3_neon = |11.14, 16.56, 8.73|
|
||||
matvec3: c=98178 neon=66040 rate=1.49
|
||||
|-21.39, -4.68, -1.74|
|
||||
|-8.66, -8.97, 1.83|
|
||||
|15.88, 0.30, -2.23|
|
||||
matmul3: c=552486 neon=297268 rate=1.86
|
||||
matvec3_c = |-21.39, -8.66, 15.88|
|
||||
matvec3_neon = |-21.39, -8.66, 15.88|
|
||||
matvec3: c=184104 neon=128780 rate=1.43
|
||||
matmul4_c =
|
||||
|17.91, -23.96, 1.86, 16.53|
|
||||
|4.10, -18.16, 4.17, 29.06|
|
||||
|6.92, -1.60, 3.12, 27.81|
|
||||
|-15.13, -7.46, -17.91, 22.49|
|
||||
|-13.65, -1.80, -12.92, 6.56|
|
||||
|-10.21, 9.47, 2.73, 14.79|
|
||||
|0.97, 11.69, -0.64, -12.87|
|
||||
|20.06, 6.77, 35.61, -0.02|
|
||||
matmul4_neon =
|
||||
|17.91, -23.96, 1.86, 16.53|
|
||||
|4.10, -18.16, 4.17, 29.06|
|
||||
|6.92, -1.60, 3.12, 27.81|
|
||||
|-15.13, -7.46, -17.91, 22.49|
|
||||
matmul4: c=1316131 neon=315444 rate=4.17
|
||||
matvec4_c = |17.91, 4.10, 6.92, -15.126419|
|
||||
matvec4_neon = |17.91, 4.10, 6.92, -15.126419|
|
||||
matvec4: c=98178 neon=66040 rate=1.49
|
||||
|-13.65, -1.80, -12.92, 6.56|
|
||||
|-10.21, 9.47, 2.73, 14.79|
|
||||
|0.97, 11.69, -0.64, -12.87|
|
||||
|20.06, 6.77, 35.61, -0.02|
|
||||
matmul4: c=1315568 neon=254227 rate=5.17
|
||||
matvec4_c = |-13.65, -10.21, 0.97, 20.058556|
|
||||
matvec4_neon = |-13.65, -10.21, 0.97, 20.058556|
|
||||
matvec4: c=331712 neon=147196 rate=2.25
|
||||
|
||||
dot2_c = 5.804099
|
||||
dot2_neon = 5.804099
|
||||
dot2: c=291526 neon=307025 rate=0.95
|
||||
normalize2_c = [0.97, 0.24]
|
||||
normalize2_neon = [0.97, 0.24]
|
||||
normalize2: c=1058588 neon=965696 rate=1.10
|
||||
dot2_c = -10.903330
|
||||
dot2_neon = -10.903330
|
||||
dot2: c=230295 neon=168799 rate=1.36
|
||||
normalize2_c = [-0.74, 0.67]
|
||||
normalize2_neon = [-0.74, 0.67]
|
||||
normalize2: c=950716 neon=965780 rate=0.98
|
||||
|
||||
dot3_c = -0.817487
|
||||
dot3_neon = -0.817487
|
||||
dot3: c=322094 neon=444834 rate=0.72
|
||||
normalize3_c = [0.50, 0.12, -0.86]
|
||||
normalize3_neon = [0.50, 0.12, -0.86]
|
||||
normalize3: c=1257201 neon=1134375 rate=1.11
|
||||
cross3_c = [-13.16, -17.29, -10.19]
|
||||
cross3_neon = [-13.16, -17.29, -10.19]
|
||||
cross3: c=705298 neon=766477 rate=0.92
|
||||
dot3_c = -4.226746
|
||||
dot3_neon = -4.226746
|
||||
dot3: c=306957 neon=337316 rate=0.91
|
||||
normalize3_c = [-0.69, 0.62, -0.38]
|
||||
normalize3_neon = [-0.69, 0.62, -0.38]
|
||||
normalize3: c=1180950 neon=1134557 rate=1.04
|
||||
cross3_c = [-9.67, -19.39, -14.24]
|
||||
cross3_neon = [-9.67, -19.39, -14.24]
|
||||
cross3: c=659558 neon=766896 rate=0.86
|
||||
|
||||
dot4_c = -7.880241
|
||||
dot4_neon = -7.880241
|
||||
dot4: c=414431 neon=506460 rate=0.82
|
||||
normalize4_c = [0.45, 0.11, -0.77, -0.44]
|
||||
normalize4_neon = [0.45, 0.11, -0.77, -0.44]
|
||||
normalize4: c=1410727 neon=1102802 rate=1.28
|
||||
dot4_c = 2.782796
|
||||
dot4_neon = 2.782796
|
||||
dot4: c=414233 neon=276068 rate=1.50
|
||||
normalize4_c = [-0.59, 0.53, -0.32, -0.52]
|
||||
normalize4_neon = [-0.59, 0.53, -0.32, -0.52]
|
||||
normalize4: c=1364294 neon=1103327 rate=1.24
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
CMATH FUNCTION TESTS
|
||||
------------------------------------------------------------------------------------------------------
|
||||
Function Range Number ABS Max Error REL Max Error RMS Error Time Rate
|
||||
------------------------------------------------------------------------------------------------------
|
||||
sinf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 647042739 x1.00
|
||||
sinf_c [-3.14, 3.14] 500000 7.75e-07 1.00e+02% 4.09e-07 646276691 x1.00
|
||||
sinf_neon [-3.14, 3.14] 500000 1.00e+00 1.00e+02% 7.07e-01 645546381 x1.00
|
||||
cosf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 644742077 x1.00
|
||||
cosf_c [-3.14, 3.14] 500000 7.75e-07 6.74e-01% 4.15e-07 643957358 x1.00
|
||||
cosf_neon [-3.14, 3.14] 500000 1.00e+00 1.00e+02% 7.06e-01 643211256 x1.00
|
||||
tanf [-0.79, 0.79] 500000 0.00e+00 0.00e+00% 0.00e+00 642444112 x1.00
|
||||
tanf_c [-0.79, 0.79] 500000 2.98e-06 7.94e-04% 1.31e-06 641628507 x1.00
|
||||
tanf_neon [-0.79, 0.79] 500000 1.00e+00 1.00e+02% nan 640740514 x1.00
|
||||
asinf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 639560380 x1.00
|
||||
asinf_c [-1.00, 1.00] 500000 5.54e-05 1.06e-02% nan 638453383 x1.00
|
||||
asinf_neon [-1.00, 1.00] 500000 1.57e+00 1.00e+02% 6.84e-01 637349653 x1.00
|
||||
acosf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 636078992 x1.00
|
||||
acosf_c [-1.00, 1.00] 500000 5.56e-05 6.46e-03% nan 634934201 x1.00
|
||||
acosf_neon [-1.00, 1.00] 500000 1.57e+00 1.02e+05% 6.84e-01 633793585 x1.00
|
||||
atanf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 632835241 x1.00
|
||||
atanf_c [-1.00, 1.00] 500000 1.67e-04 2.12e-02% 7.40e-05 632142823 x1.00
|
||||
atanf_neon [-1.00, 1.00] 500000 7.85e-01 0.00e+00% nan 631387330 x1.00
|
||||
sinhf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 630142014 x1.00
|
||||
sinhf_c [-3.14, 3.14] 500000 1.91e-06 1.52e-01% 1.85e-07 628992714 x1.00
|
||||
sinhf_neon [-3.14, 3.14] 500000 1.15e+01 1.00e+02% 4.55e+00 627998454 x1.00
|
||||
coshf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 626869866 x1.00
|
||||
coshf_c [-3.14, 3.14] 500000 9.54e-07 2.38e-05% 1.64e-07 625829657 x1.00
|
||||
coshf_neon [-3.14, 3.14] 500000 1.06e+01 9.14e+01% 3.92e+00 624873969 x1.00
|
||||
tanhf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 623689093 x1.00
|
||||
tanhf_c [-3.14, 3.14] 500000 1.20e-05 2.48e-01% 5.48e-06 622547097 x1.00
|
||||
tanhf_neon [-3.14, 3.14] 500000 9.96e-01 1.00e+02% 8.26e-01 621506812 x1.00
|
||||
expf [0.00, 10.00] 500000 0.00e+00 0.00e+00% 0.00e+00 620497304 x1.00
|
||||
expf_c [0.00, 10.00] 500000 9.77e-03 6.15e-05% 1.64e-03 619569554 x1.00
|
||||
expf_neon [0.00, 10.00] 500000 2.20e+04 1.00e+02% 4.92e+03 618761400 x1.00
|
||||
logf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 617882765 x1.00
|
||||
logf_c [1.00, 1000.00] 500000 6.20e-06 1.62e-02% 9.83e-07 617087810 x1.00
|
||||
logf_neon [1.00, 1000.00] 500000 9.49e+01 inf% 9.39e+01 616388420 x1.00
|
||||
log10f [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 615405364 x1.00
|
||||
log10f_c [1.00, 1000.00] 500000 2.86e-06 6.68e-03% 4.79e-07 614442585 x1.00
|
||||
log10f_neon [1.00, 1000.00] 500000 4.12e+01 inf% 4.07e+01 613671782 x1.00
|
||||
floorf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 611113689 x1.00
|
||||
floorf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 608159325 x1.00
|
||||
floorf_neon [1.00, 1000.00] 5000000 2.00e+00 2.00e+02% 1.42e-02 604769008 x1.01
|
||||
ceilf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 601342443 x1.00
|
||||
ceilf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 598387998 x1.00
|
||||
ceilf_neon [1.00, 1000.00] 5000000 2.00e+00 1.00e+02% 1.02e+00 594959710 x1.01
|
||||
fabsf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 592068236 x1.00
|
||||
fabsf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 589808748 x1.00
|
||||
fabsf_neon [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 587712180 x1.01
|
||||
sqrtf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 586496654 x1.00
|
||||
sqrtf_c [1.00, 1000.00] 500000 2.33e-04 1.06e-03% 8.69e-05 585470866 x1.00
|
||||
sqrtf_neon [1.00, 1000.00] 500000 0.00e+00 0.00e+00% nan 584594551 x1.00
|
||||
invsqrtf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 583492213 x1.00
|
||||
invsqrtf_c [1.00, 1000.00] 500000 4.35e-06 4.78e-04% 2.00e-07 582448164 x1.00
|
||||
invsqrtf_neon [1.00, 1000.00] 500000 0.00e+00 0.00e+00% nan 581642365 x1.00
|
||||
atan2f [0.10, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 83594269 x1.00
|
||||
atan2f_c [0.10, 10.00] 10000 1.73e-04 2.23e-02% 0.00e+00 85383651 x0.98
|
||||
atan2f_neon [0.10, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 87387055 x0.96
|
||||
powf [1.00, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 93430489 x1.00
|
||||
powf_c [1.00, 10.00] 10000 1.08e+05 4.37e-03% 0.00e+00 96726976 x0.97
|
||||
powf_neon [1.00, 10.00] 10000 9.97e+09 1.00e+02% 0.00e+00 100185753 x0.93
|
||||
fmodf [1.00, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 101653673 x1.00
|
||||
fmodf_c [1.00, 10.00] 10000 9.90e+00 8.06e-02% 0.00e+00 103177551 x0.99
|
||||
fmodf_neon [1.00, 10.00] 10000 9.99e+00 1.00e+02% 0.00e+00 104771240 x0.97
|
||||
|
||||
sinf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 1394459996 x1.00
|
||||
sinf_c [-3.14, 3.14] 500000 7.75e-07 1.00e+02% 4.09e-07 1395128226 x1.00
|
||||
sinf_neon [-3.14, 3.14] 500000 8.34e-07 1.00e+02% 4.09e-07 1395853554 x1.00
|
||||
cosf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 1396644271 x1.00
|
||||
cosf_c [-3.14, 3.14] 500000 7.75e-07 6.74e-01% 4.15e-07 1397360321 x1.00
|
||||
cosf_neon [-3.14, 3.14] 500000 8.34e-07 6.74e-01% 4.16e-07 1398126872 x1.00
|
||||
tanf [-0.79, 0.79] 500000 0.00e+00 0.00e+00% 0.00e+00 1398889596 x1.00
|
||||
tanf_c [-0.79, 0.79] 500000 2.98e-06 7.94e-04% 1.31e-06 1399704712 x1.00
|
||||
tanf_neon [-0.79, 0.79] 500000 1.91e-06 3.62e-04% 6.66e-07 1400612899 x1.00
|
||||
asinf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1401838993 x1.00
|
||||
asinf_c [-1.00, 1.00] 500000 5.54e-05 1.06e-02% nan 1402745512 x1.00
|
||||
asinf_neon [-1.00, 1.00] 500000 4.66e-05 8.90e-03% nan 1403967661 x1.00
|
||||
acosf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1405317842 x1.00
|
||||
acosf_c [-1.00, 1.00] 500000 5.56e-05 6.46e-03% nan 1406294753 x1.00
|
||||
acosf_neon [-1.00, 1.00] 500000 4.67e-05 6.35e-03% nan 1407598039 x1.00
|
||||
atanf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1408314869 x1.00
|
||||
atanf_c [-1.00, 1.00] 500000 1.67e-04 2.12e-02% 7.40e-05 1408872421 x1.00
|
||||
atanf_neon [-1.00, 1.00] 500000 1.67e-04 2.12e-02% 7.40e-05 1409736652 x1.00
|
||||
sinhf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 1411101066 x1.00
|
||||
sinhf_c [-3.14, 3.14] 500000 1.91e-06 1.52e-01% 1.85e-07 1412173492 x1.00
|
||||
sinhf_neon [-3.14, 3.14] 500000 1.91e-06 1.52e-01% 1.90e-07 1413205410 x1.00
|
||||
coshf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 1414417802 x1.00
|
||||
coshf_c [-3.14, 3.14] 500000 9.54e-07 2.38e-05% 1.64e-07 1415426083 x1.00
|
||||
coshf_neon [-3.14, 3.14] 500000 1.91e-06 2.22e-05% 1.68e-07 1416412636 x1.00
|
||||
tanhf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 1417684273 x1.00
|
||||
tanhf_c [-3.14, 3.14] 500000 1.20e-05 2.48e-01% 5.48e-06 1418659628 x1.00
|
||||
tanhf_neon [-3.14, 3.14] 500000 2.38e-07 2.47e-01% 5.40e-08 1419650721 x1.00
|
||||
expf [0.00, 10.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1420706074 x1.00
|
||||
expf_c [0.00, 10.00] 500000 9.77e-03 6.15e-05% 1.64e-03 1421444150 x1.00
|
||||
expf_neon [0.00, 10.00] 500000 9.77e-03 6.58e-05% 1.64e-03 1422203499 x1.00
|
||||
logf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1423106698 x1.00
|
||||
logf_c [1.00, 1000.00] 500000 6.20e-06 1.62e-02% 9.83e-07 1423735174 x1.00
|
||||
logf_neon [1.00, 1000.00] 500000 7.63e-06 1.03e-02% 1.07e-06 1424434406 x1.00
|
||||
log10f [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1425516892 x1.00
|
||||
log10f_c [1.00, 1000.00] 500000 2.86e-06 6.68e-03% 4.79e-07 1426200368 x1.00
|
||||
log10f_neon [1.00, 1000.00] 500000 3.34e-06 6.68e-03% 4.84e-07 1426966844 x1.00
|
||||
floorf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1429081993 x1.00
|
||||
floorf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1430839273 x1.00
|
||||
floorf_neon [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1433474766 x1.00
|
||||
ceilf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1435602956 x1.00
|
||||
ceilf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1437403711 x1.00
|
||||
ceilf_neon [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1440044970 x1.00
|
||||
fabsf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1441265630 x1.00
|
||||
fabsf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1442491716 x1.00
|
||||
fabsf_neon [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 1443680744 x1.00
|
||||
sqrtf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1444844144 x1.00
|
||||
sqrtf_c [1.00, 1000.00] 500000 2.33e-04 1.06e-03% 8.69e-05 1445710342 x1.00
|
||||
sqrtf_neon [1.00, 1000.00] 500000 7.63e-06 2.91e-05% 1.60e-06 1446544637 x1.00
|
||||
invsqrtf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 1446995307 x1.00
|
||||
invsqrtf_c [1.00, 1000.00] 500000 4.35e-06 4.78e-04% 2.00e-07 1447471977 x1.00
|
||||
invsqrtf_neon [1.00, 1000.00] 500000 1.19e-07 2.12e-05% 4.81e-09 1447987675 x1.00
|
||||
atan2f [0.10, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 1449713108 x1.00
|
||||
atan2f_c [0.10, 10.00] 10000 1.73e-04 2.23e-02% 0.00e+00 1451276575 x1.00
|
||||
atan2f_neon [0.10, 10.00] 10000 1.67e-04 2.12e-02% 0.00e+00 1453093260 x1.00
|
||||
powf [1.00, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 1458606663 x1.00
|
||||
powf_c [1.00, 10.00] 10000 1.08e+05 4.37e-03% 0.00e+00 1461584933 x1.00
|
||||
powf_neon [1.00, 10.00] 10000 1.36e+05 5.88e-03% 0.00e+00 1464702743 x1.00
|
||||
fmodf [1.00, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 1466022029 x1.00
|
||||
fmodf_c [1.00, 10.00] 10000 9.90e+00 8.06e-02% 0.00e+00 1467403015 x1.00
|
||||
fmodf_neon [1.00, 10.00] 10000 9.97e+00 8.06e-02% 0.00e+00 1468767755 x1.00
|
||||
|
689
deps/math-neon/math_debug.c
vendored
Normal file
689
deps/math-neon/math_debug.c
vendored
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
Math-NEON: Neon Optimised Math Library based on cmath
|
||||
Contact: lachlan.ts@gmail.com
|
||||
Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <math_neon.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#ifdef WIN32
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#define randf() (rand() / (RAND_MAX + 1.0f))
|
||||
|
||||
void LOG(const char *format, ...) {
|
||||
__gnuc_va_list arg;
|
||||
va_start(arg, format);
|
||||
char msg[512];
|
||||
vsprintf(msg, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
FILE *log = fopen("ux0:/data/mathneon.log", "a+");
|
||||
if (log != NULL) {
|
||||
fwrite(msg, 1, strlen(msg), log);
|
||||
fclose(log);
|
||||
}
|
||||
}
|
||||
|
||||
struct test1_s {
|
||||
const char* name;
|
||||
float (*func)(float); //the function
|
||||
float (*bench)(float); //the function to benchmark against.
|
||||
float rng0, rng1;
|
||||
int num;
|
||||
float emaxabs;
|
||||
float xmaxabs;
|
||||
float emaxrel;
|
||||
float xmaxrel;
|
||||
float erms;
|
||||
int time; //time to execute num functions;
|
||||
};
|
||||
|
||||
struct test2_s {
|
||||
const char* name;
|
||||
float (*func)(float, float); //the function
|
||||
float (*bench)(float, float); //the function to benchmark against.
|
||||
float rng0, rng1;
|
||||
int num;
|
||||
float emaxabs;
|
||||
float xmaxabs;
|
||||
float emaxrel;
|
||||
float xmaxrel;
|
||||
float erms;
|
||||
int time; //time to execute num functions;
|
||||
};
|
||||
|
||||
|
||||
float invsqrtf(float x){
|
||||
return (1.0f / sqrtf(x));
|
||||
}
|
||||
|
||||
typedef struct test1_s test1_t;
|
||||
typedef struct test2_s test2_t;
|
||||
|
||||
test1_t test1[51] =
|
||||
{
|
||||
{"sinf ", sinf, sinf, -M_PI, M_PI, 500000},
|
||||
{"sinf_c ", sinf_c, sinf, -M_PI, M_PI, 500000},
|
||||
{"sinf_neon ", sinf_neon, sinf, -M_PI, M_PI, 500000},
|
||||
|
||||
{"cosf ", cosf, cosf, -M_PI, M_PI, 500000},
|
||||
{"cosf_c ", cosf_c, cosf, -M_PI, M_PI, 500000},
|
||||
{"cosf_neon ", cosf_neon, cosf, -M_PI, M_PI, 500000},
|
||||
|
||||
{"tanf ", tanf, tanf, -M_PI_4, M_PI_4, 500000, 0, 0, 0},
|
||||
{"tanf_c ", tanf_c, tanf, -M_PI_4, M_PI_4, 500000, 0, 0, 0},
|
||||
{"tanf_neon ", tanf_neon, tanf, -M_PI_4, M_PI_4, 500000, 0, 0, 0},
|
||||
|
||||
{"asinf ", asinf, asinf, -1, 1, 500000, 0, 0, 0},
|
||||
{"asinf_c ", asinf_c, asinf, -1, 1, 500000, 0, 0, 0},
|
||||
{"asinf_neon ", asinf_neon, asinf, -1, 1, 500000, 0, 0, 0},
|
||||
|
||||
{"acosf ", acosf, acosf, -1, 1, 500000, 0, 0, 0},
|
||||
{"acosf_c ", acosf_c, acosf, -1, 1, 500000, 0, 0, 0},
|
||||
{"acosf_neon ", acosf_neon, acosf, -1, 1, 500000, 0, 0, 0},
|
||||
|
||||
{"atanf ", atanf, atanf, -1, 1, 500000, 0, 0, 0},
|
||||
{"atanf_c ", atanf_c, atanf, -1, 1, 500000, 0, 0, 0},
|
||||
{"atanf_neon ", atanf_neon, atanf, -1, 1, 500000, 0, 0, 0},
|
||||
|
||||
{"sinhf ", sinhf, sinhf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
{"sinhf_c ", sinhf_c, sinhf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
{"sinhf_neon ", sinhf_neon, sinhf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
|
||||
{"coshf ", coshf, coshf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
{"coshf_c ", coshf_c, coshf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
{"coshf_neon ", coshf_neon, coshf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
|
||||
{"tanhf ", tanhf, tanhf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
{"tanhf_c ", tanhf_c, tanhf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
{"tanhf_neon ", tanhf_neon, tanhf, -M_PI, M_PI, 500000, 0, 0, 0},
|
||||
|
||||
{"expf ", expf, expf, 0, 10, 500000, 0, 0, 0},
|
||||
{"expf_c ", expf_c, expf, 0, 10, 500000, 0, 0, 0},
|
||||
{"expf_neon ", expf_neon, expf, 0, 10, 500000, 0, 0, 0},
|
||||
|
||||
{"logf ", logf, logf, 1, 1000, 500000, 0, 0, 0},
|
||||
{"logf_c ", logf_c, logf, 1, 1000, 500000, 0, 0, 0},
|
||||
{"logf_neon ", logf_neon, logf, 1, 1000, 500000, 0, 0, 0},
|
||||
|
||||
{"log10f ", log10f, log10f, 1, 1000, 500000, 0, 0, 0},
|
||||
{"log10f_c ", log10f_c, log10f, 1, 1000, 500000, 0, 0, 0},
|
||||
{"log10f_neon ", log10f_neon,log10f, 1, 1000, 500000, 0, 0, 0},
|
||||
|
||||
{"floorf ", floorf, floorf, 1, 1000, 5000000, 0, 0, 0},
|
||||
{"floorf_c ", floorf_c, floorf, 1, 1000, 5000000, 0, 0, 0},
|
||||
{"floorf_neon", floorf_neon,floorf, 1, 1000, 5000000, 0, 0, 0},
|
||||
|
||||
{"ceilf ", ceilf, ceilf, 1, 1000, 5000000, 0, 0, 0},
|
||||
{"ceilf_c ", ceilf_c, ceilf, 1, 1000, 5000000, 0, 0, 0},
|
||||
{"ceilf_neon", ceilf_neon, ceilf, 1, 1000, 5000000, 0, 0, 0},
|
||||
|
||||
{"fabsf ", fabsf, fabsf, 1, 1000, 5000000, 0, 0, 0},
|
||||
{"fabsf_c ", fabsf_c, fabsf, 1, 1000, 5000000, 0, 0, 0},
|
||||
{"fabsf_neon", fabsf_neon, fabsf, 1, 1000, 5000000, 0, 0, 0},
|
||||
|
||||
{"sqrtf ", sqrtf, sqrtf, 1, 1000, 500000, 0, 0, 0},
|
||||
{"sqrtf_c ", sqrtf_c, sqrtf, 1, 1000, 500000, 0, 0, 0},
|
||||
{"sqrtf_neon ", sqrtf_neon, sqrtf, 1, 1000, 500000, 0, 0, 0},
|
||||
|
||||
{"invsqrtf ", invsqrtf, invsqrtf, 1, 1000, 500000, 0, 0, 0},
|
||||
{"invsqrtf_c ", invsqrtf_c, invsqrtf, 1, 1000, 500000, 0, 0, 0},
|
||||
{"invsqrtf_neon ", invsqrtf_neon, invsqrtf, 1, 1000, 500000, 0, 0, 0},
|
||||
};
|
||||
|
||||
test2_t test2[9] =
|
||||
{
|
||||
{"atan2f ", atan2f, atan2f, 0.1, 10, 10000, 0, 0, 0},
|
||||
{"atan2f_c ", atan2f_c, atan2f, 0.1, 10, 10000, 0, 0, 0},
|
||||
{"atan2f_neon ", atan2f_neon,atan2f, 0.1, 10, 10000, 0, 0, 0},
|
||||
|
||||
{"powf ", powf, powf, 1, 10, 10000, 0, 0, 0},
|
||||
{"powf_c ", powf_c, powf, 1, 10, 10000, 0, 0, 0},
|
||||
{"powf_neon ", powf_neon, powf, 1, 10, 10000, 0, 0, 0},
|
||||
|
||||
{"fmodf ", fmodf, fmodf, 1, 10, 10000, 0, 0, 0},
|
||||
{"fmodf_c ", fmodf_c, fmodf, 1, 10, 10000, 0, 0, 0},
|
||||
{"fmodf_neon ", fmodf_neon, fmodf, 1, 10, 10000, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
test_mathfunc1(test1_t *tst)
|
||||
{
|
||||
|
||||
float x;
|
||||
float dx = (tst->rng1 - tst->rng0) / ((float)tst->num);
|
||||
#ifndef WIN32
|
||||
struct rusage ru;
|
||||
#endif
|
||||
|
||||
tst->emaxabs = tst->xmaxabs = 0;
|
||||
tst->emaxrel = tst->xmaxrel = 0;
|
||||
tst->erms = 0;
|
||||
for(x = tst->rng0; x < tst->rng1 ; x += dx){
|
||||
float r = (tst->func)((float)x);
|
||||
float rr = (tst->bench)((float)x);
|
||||
float dr = fabs(r - rr);
|
||||
float drr = dr * (100.0f / rr);
|
||||
tst->erms += dr*dr;
|
||||
if (dr > tst->emaxabs){
|
||||
tst->emaxabs = dr;
|
||||
tst->xmaxabs = x;
|
||||
}
|
||||
if (drr > tst->emaxrel){
|
||||
tst->emaxrel = drr;
|
||||
tst->xmaxrel = x;
|
||||
}
|
||||
}
|
||||
tst->erms = sqrt(tst->erms / ((float) tst->num));
|
||||
|
||||
#ifdef WIN32
|
||||
tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000);
|
||||
#else
|
||||
tst->time = sceKernelGetSystemTimeWide();
|
||||
#endif
|
||||
|
||||
for(x = tst->rng0; x < tst->rng1 ; x += dx){
|
||||
(tst->func)((float)x);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000) - tst->time;
|
||||
#else
|
||||
tst->time = sceKernelGetSystemTimeWide();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_mathfunc2(test2_t *tst)
|
||||
{
|
||||
float x, y;
|
||||
float rng = tst->rng1 - tst->rng0;
|
||||
float d = (rng * rng) / ((float) tst->num);
|
||||
#ifndef WIN32
|
||||
struct rusage ru;
|
||||
#endif
|
||||
|
||||
tst->emaxabs = tst->xmaxabs = 0;
|
||||
tst->emaxrel = tst->xmaxrel = 0;
|
||||
for(y = (tst->rng0); y < (tst->rng1) ; y += d){
|
||||
for(x = (tst->rng0); x < (tst->rng1); x += d){
|
||||
float r = (tst->func)((float)x, y);
|
||||
float rr = (tst->bench)((float)x, y);
|
||||
float dr = fabs(r - rr);
|
||||
float drr = dr * (100.0f / rr);
|
||||
if (dr > tst->emaxabs){
|
||||
tst->emaxabs = dr;
|
||||
tst->xmaxabs = x;
|
||||
}
|
||||
if (drr > tst->emaxrel && fabsf(rr) > 0.0001){
|
||||
tst->emaxrel = drr;
|
||||
tst->xmaxrel = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000) ;
|
||||
#else
|
||||
tst->time = sceKernelGetSystemTimeWide();
|
||||
#endif
|
||||
|
||||
for(y = tst->rng0; y < tst->rng1 ; y += d){
|
||||
for(x = tst->rng0; x < tst->rng1 ; x += d){
|
||||
(tst->func)((float)x, (float)y);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000) - tst->time;
|
||||
#else
|
||||
tst->time = sceKernelGetSystemTimeWide();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void test_vectorfunc()
|
||||
{
|
||||
float v0[4], v1[4], d[4];
|
||||
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
v0[i] = 10*randf() - 5;
|
||||
v1[i] = 10*randf() - 5;
|
||||
d[i] = 10*randf() - 5;
|
||||
}
|
||||
|
||||
int testnum = 5000000;
|
||||
struct rusage ru;
|
||||
int v2t[3], v3t[3], v4t[3];
|
||||
float r;
|
||||
|
||||
LOG("\n");
|
||||
|
||||
//dot 2
|
||||
v2t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
r = dot2_c(v0, v1);
|
||||
};
|
||||
v2t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
r = dot2_neon(v0, v1);
|
||||
};
|
||||
v2t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
r = dot2_c(v0, v1);
|
||||
LOG("dot2_c = %f\n", r);
|
||||
r = dot2_neon(v0, v1);
|
||||
LOG("dot2_neon = %f\n", r);
|
||||
|
||||
LOG("dot2: c=%i \t neon=%i \t rate=%.2f \n", v2t[1] - v2t[0], v2t[2] - v2t[1],
|
||||
(float)(v2t[1] - v2t[0]) / (float)(v2t[2] - v2t[1]));
|
||||
|
||||
//normalize 2
|
||||
v2t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
normalize2_c(v0, d);
|
||||
};
|
||||
v2t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
normalize2_neon(v0, d);
|
||||
};
|
||||
v2t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
|
||||
normalize2_c(v0, d);
|
||||
LOG("normalize2_c = [%.2f, %.2f]\n", d[0], d[1]);
|
||||
normalize2_neon(v0, d);
|
||||
LOG("normalize2_neon = [%.2f, %.2f]\n", d[0], d[1]);
|
||||
|
||||
LOG("normalize2: c=%i \t neon=%i \t rate=%.2f \n", v2t[1] - v2t[0], v2t[2] - v2t[1],
|
||||
(float)(v2t[1] - v2t[0]) / (float)(v2t[2] - v2t[1]));
|
||||
LOG("\n");
|
||||
|
||||
|
||||
//dot 3
|
||||
v3t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
r = dot3_c(v0, v1);
|
||||
};
|
||||
v3t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
r = dot3_neon(v0, v1);
|
||||
};
|
||||
v3t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
r = dot3_c(v0, v1);
|
||||
LOG("dot3_c = %f\n", r);
|
||||
r = dot3_neon(v0, v1);
|
||||
LOG("dot3_neon = %f\n", r);
|
||||
|
||||
LOG("dot3: c=%i \t neon=%i \t rate=%.2f \n", v3t[1] - v3t[0], v3t[2] - v3t[1],
|
||||
(float)(v3t[1] - v3t[0]) / (float)(v3t[2] - v3t[1]));
|
||||
|
||||
//normalize 3
|
||||
v3t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
normalize3_c(v0, d);
|
||||
};
|
||||
v3t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
normalize3_neon(v0, d);
|
||||
};
|
||||
v3t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
|
||||
normalize3_c(v0, d);
|
||||
LOG("normalize3_c = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]);
|
||||
normalize3_neon(v0, d);
|
||||
LOG("normalize3_neon = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]);
|
||||
|
||||
LOG("normalize3: c=%i \t neon=%i \t rate=%.2f \n", v3t[1] - v3t[0], v3t[2] - v3t[1],
|
||||
(float)(v3t[1] - v3t[0]) / (float)(v3t[2] - v3t[1]));
|
||||
|
||||
//cross 3
|
||||
v3t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
cross3_c(v0, v1, d);
|
||||
};
|
||||
v3t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
cross3_neon(v0, v1, d);
|
||||
};
|
||||
v3t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
|
||||
cross3_c(v0, v1, d);
|
||||
LOG("cross3_c = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]);
|
||||
cross3_neon(v0, v1, d);
|
||||
LOG("cross3_neon = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]);
|
||||
|
||||
LOG("cross3: c=%i \t neon=%i \t rate=%.2f \n", v3t[1] - v3t[0], v3t[2] - v3t[1],
|
||||
(float)(v3t[1] - v3t[0]) / (float)(v3t[2] - v3t[1]));
|
||||
LOG("\n");
|
||||
|
||||
|
||||
//dot 4
|
||||
v4t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
r = dot4_c(v0, v1);
|
||||
};
|
||||
v4t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
r = dot4_neon(v0, v1);
|
||||
};
|
||||
v4t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
r = dot4_c(v0, v1);
|
||||
LOG("dot4_c = %f\n", r);
|
||||
r = dot4_neon(v0, v1);
|
||||
LOG("dot4_neon = %f\n", r);
|
||||
|
||||
LOG("dot4: c=%i \t neon=%i \t rate=%.2f \n", v4t[1] - v4t[0], v4t[2] - v4t[1],
|
||||
(float)(v4t[1] - v4t[0]) / (float)(v4t[2] - v4t[1]));
|
||||
|
||||
//normalize 4
|
||||
v4t[0] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
normalize4_c(v0, d);
|
||||
};
|
||||
v4t[1] = sceKernelGetSystemTimeWide();
|
||||
for(int i=0;i < testnum; i++)
|
||||
{
|
||||
normalize4_neon(v0, d);
|
||||
};
|
||||
v4t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
|
||||
normalize4_c(v0, d);
|
||||
LOG("normalize4_c = [%.2f, %.2f, %.2f, %.2f]\n", d[0], d[1], d[2], d[3]);
|
||||
normalize4_neon(v0, d);
|
||||
LOG("normalize4_neon = [%.2f, %.2f, %.2f, %.2f]\n", d[0], d[1], d[2], d[3]);
|
||||
|
||||
LOG("normalize4: c=%i \t neon=%i \t rate=%.2f \n", v4t[1] - v4t[0], v4t[2] - v4t[1],
|
||||
(float)(v4t[1] - v4t[0]) / (float)(v4t[2] - v4t[1]));
|
||||
LOG("\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void test_matrixfunc()
|
||||
{
|
||||
float m0[16], m1[16], m2[16];
|
||||
int m2t[3], m3t[3], m4t[3];
|
||||
|
||||
int i;
|
||||
int testnum = 1000000;
|
||||
struct rusage ru;
|
||||
|
||||
for(int i=0;i<16;i++)
|
||||
{
|
||||
m0[i] = 10.0f * randf() - 5.0f;
|
||||
m1[i] = 10.0f * randf() - 5.0f;
|
||||
m2[i] = 10.0f * randf() - 5.0f;
|
||||
}
|
||||
|
||||
|
||||
//matmul2
|
||||
m2t[0] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matmul2_c(m0, m1, m2);
|
||||
}
|
||||
m2t[1] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matmul2_neon(m0, m1, m2);
|
||||
}
|
||||
m2t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
matmul2_c(m0, m1, m2);
|
||||
LOG("matmul2_c = \n");
|
||||
LOG("\t\t\t|%.2f, %.2f|\n", m2[0], m2[2]);
|
||||
LOG("\t\t\t|%.2f, %.2f|\n", m2[1], m2[3]);
|
||||
|
||||
matmul2_neon(m0, m1, m2);
|
||||
LOG("matmul2_neon = \n");
|
||||
LOG("\t\t\t|%.2f, %.2f|\n", m2[0], m2[2]);
|
||||
LOG("\t\t\t|%.2f, %.2f|\n", m2[1], m2[3]);
|
||||
|
||||
LOG("matmul2: c=%i \t neon=%i \t rate=%.2f \n", m2t[1] - m2t[0], m2t[2] - m2t[1],
|
||||
(float)(m2t[1] - m2t[0]) / (float)(m2t[2] - m2t[1]));
|
||||
|
||||
|
||||
//matvec2
|
||||
m2t[0] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matvec2_c(m0, m1, m2);
|
||||
}
|
||||
m2t[1] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matvec2_neon(m0, m1, m2);
|
||||
}
|
||||
m2t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
memset(m2, 0, 4*sizeof(float));
|
||||
matvec2_c(m0, m1, m2);
|
||||
LOG("matvec2_c = |%.2f, %.2f|\n", m2[0], m2[1]);
|
||||
|
||||
memset(m2, 0, 4*sizeof(float));
|
||||
matvec2_neon(m0, m1, m2);
|
||||
LOG("matvec2_neon = |%.2f, %.2f|\n", m2[0], m2[1]);
|
||||
|
||||
LOG("matvec2: c=%i \t neon=%i \t rate=%.2f \n", m2t[1] - m2t[0], m2t[2] - m2t[1],
|
||||
(float)(m2t[1] - m2t[0]) / (float)(m2t[2] - m2t[1]));
|
||||
|
||||
//MAT3
|
||||
m3t[0] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matmul3_c(m0, m1, m2);
|
||||
}
|
||||
m3t[1] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matmul3_neon(m0, m1, m2);
|
||||
}
|
||||
m3t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
memset(m2, 0, 9*sizeof(float));
|
||||
matmul3_c(m0, m1, m2);
|
||||
LOG("matmul3_c =\n");
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f|\n", m2[0], m2[3], m2[6]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f|\n", m2[1], m2[4], m2[7]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f|\n", m2[2], m2[5], m2[8]);
|
||||
|
||||
memset(m2, 0, 9*sizeof(float));
|
||||
matmul3_neon(m0, m1, m2);
|
||||
LOG("matmul3_neon =\n");
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f|\n", m2[0], m2[3], m2[6]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f|\n", m2[1], m2[4], m2[7]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f|\n", m2[2], m2[5], m2[8]);
|
||||
|
||||
LOG("matmul3: c=%i \t neon=%i \t rate=%.2f \n", m3t[1] - m3t[0], m3t[2] - m3t[1],
|
||||
(float)(m3t[1] - m3t[0]) / (float)(m3t[2] - m3t[1]));
|
||||
|
||||
//matvec3
|
||||
m3t[0] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matvec3_c(m0, m1, m2);
|
||||
}
|
||||
m3t[1] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matvec3_neon(m0, m1, m2);
|
||||
}
|
||||
m3t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
memset(m2, 0, 4*sizeof(float));
|
||||
matvec3_c(m0, m1, m2);
|
||||
LOG("matvec3_c = |%.2f, %.2f, %.2f|\n", m2[0], m2[1], m2[2]);
|
||||
|
||||
memset(m2, 0, 4*sizeof(float));
|
||||
matvec3_neon(m0, m1, m2);
|
||||
LOG("matvec3_neon = |%.2f, %.2f, %.2f|\n", m2[0], m2[1], m2[2]);
|
||||
|
||||
LOG("matvec3: c=%i \t neon=%i \t rate=%.2f \n", m3t[1] - m3t[0], m3t[2] - m3t[1],
|
||||
(float)(m3t[1] - m3t[0]) / (float)(m3t[2] - m3t[1]));
|
||||
|
||||
//MAT4
|
||||
m4t[0] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matmul4_c(m0, m1, m2);
|
||||
}
|
||||
m4t[1] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matmul4_neon(m0, m1, m2);
|
||||
}
|
||||
m4t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
memset(m2, 0, 16*sizeof(float));
|
||||
matmul4_c(m0, m1, m2);
|
||||
LOG("matmul4_c =\n");
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[0], m2[4], m2[8], m2[12]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[1], m2[5], m2[9], m2[13]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[2], m2[6], m2[10], m2[14]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[3], m2[7], m2[11], m2[15]);
|
||||
|
||||
memset(m2, 0, 16*sizeof(float));
|
||||
matmul4_neon(m0, m1, m2);
|
||||
LOG("matmul4_neon =\n");
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[0], m2[4], m2[8], m2[12]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[1], m2[5], m2[9], m2[13]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[2], m2[6], m2[10], m2[14]);
|
||||
LOG("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[3], m2[7], m2[11], m2[15]);
|
||||
|
||||
LOG("matmul4: c=%i \t neon=%i \t rate=%.2f \n", m4t[1] - m4t[0], m4t[2] - m4t[1],
|
||||
(float)(m4t[1] - m4t[0]) / (float)(m4t[2] - m4t[1]));
|
||||
|
||||
//matvec4
|
||||
m4t[0] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matvec4_c(m0, m1, m2);
|
||||
}
|
||||
m4t[1] = sceKernelGetSystemTimeWide();
|
||||
for(i = 0; i < testnum; i++){
|
||||
matvec4_neon(m0, m1, m2);
|
||||
}
|
||||
m4t[2] = sceKernelGetSystemTimeWide();
|
||||
|
||||
memset(m2, 0, 4*sizeof(float));
|
||||
matvec4_c(m0, m1, m2);
|
||||
LOG("matvec4_c = |%.2f, %.2f, %.2f, %f|\n", m2[0], m2[1], m2[2], m2[3]);
|
||||
|
||||
memset(m2, 0, 4*sizeof(float));
|
||||
matvec4_neon(m0, m1, m2);
|
||||
LOG("matvec4_neon = |%.2f, %.2f, %.2f, %f|\n", m2[0], m2[1], m2[2], m2[3]);
|
||||
|
||||
LOG("matvec4: c=%i \t neon=%i \t rate=%.2f \n", m4t[1] - m4t[0], m4t[2] - m4t[1],
|
||||
(float)(m4t[1] - m4t[0]) / (float)(m4t[2] - m4t[1]));
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
int i, ii;
|
||||
#if 1
|
||||
LOG("RUNFAST: Disabled \n");
|
||||
#else
|
||||
LOG("RUNFAST: Enabled \n");
|
||||
enable_runfast();
|
||||
#endif
|
||||
srand(time(NULL));
|
||||
|
||||
#if 1
|
||||
//test single argument functions:
|
||||
LOG("------------------------------------------------------------------------------------------------------\n");
|
||||
LOG("MATRIX FUNCTION TESTS \n");
|
||||
LOG("------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
test_matrixfunc();
|
||||
test_vectorfunc();
|
||||
|
||||
LOG("------------------------------------------------------------------------------------------------------\n");
|
||||
LOG("CMATH FUNCTION TESTS \n");
|
||||
LOG("------------------------------------------------------------------------------------------------------\n");
|
||||
LOG("Function\tRange\t\tNumber\tABS Max Error\tREL Max Error\tRMS Error\tTime\tRate\n");
|
||||
LOG("------------------------------------------------------------------------------------------------------\n");
|
||||
for(i = 0; i < 51; i++){
|
||||
test_mathfunc1(&test1[i]);
|
||||
|
||||
ii = i - (i % 3);
|
||||
LOG("%s\t", test1[i].name);
|
||||
LOG("[%.2f, %.2f]\t", test1[i].rng0, test1[i].rng1);
|
||||
LOG("%i\t", test1[i].num);
|
||||
LOG("%.2e\t", test1[i].emaxabs);
|
||||
LOG("%.2e%%\t", test1[i].emaxrel);
|
||||
LOG("%.2e\t", test1[i].erms);
|
||||
LOG("%i\t", test1[i].time);
|
||||
LOG("x%.2f\t", (float)test1[ii].time / test1[i].time);
|
||||
LOG("\n");
|
||||
}
|
||||
for(i = 0; i < 9; i++){
|
||||
test_mathfunc2(&test2[i]);
|
||||
|
||||
ii = i - (i % 3);
|
||||
|
||||
LOG("%s\t", test2[i].name);
|
||||
LOG("[%.2f, %.2f]\t", test2[i].rng0, test2[i].rng1);
|
||||
LOG("%i\t", test2[i].num);
|
||||
LOG("%.2e\t", test2[i].emaxabs);
|
||||
LOG("%.2e%%\t", test2[i].emaxrel);
|
||||
LOG("%.2e\t", test2[i].erms);
|
||||
LOG("%i\t", test2[i].time);
|
||||
LOG("x%.2f\t", (float)test2[ii].time / test2[i].time);
|
||||
LOG("\n");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
float x = 0;
|
||||
for(x = -M_PI_2; x < M_PI_2; x+= 0.01)
|
||||
{
|
||||
LOG("x=%.2f\t in=%.2f\t c=%.2f\t neon=%.2f \n", x, sinhf(x), sinhf_c(x), sinhf_neon(x));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
6
deps/math-neon/source/math_neon.h
vendored
6
deps/math-neon/source/math_neon.h
vendored
@ -33,7 +33,7 @@ THE SOFTWARE.
|
||||
//Default Floating Point value ABI: 0=softfp, 1=hardfp. Only effects *_neon routines.
|
||||
//You can access the hardfp versions directly via the *_hard suffix.
|
||||
//You can access the softfp versions directly via the *_soft suffix.
|
||||
#define __MATH_FPABI 0
|
||||
#define __MATH_FPABI 1
|
||||
|
||||
#endif
|
||||
|
||||
@ -84,6 +84,10 @@ THE SOFTWARE.
|
||||
#define modf_neon modf_neon_hfp
|
||||
#define sqrtf_neon sqrtf_neon_hfp
|
||||
#define invsqrtf_neon invsqrtf_neon_hfp
|
||||
|
||||
#define dot2_neon dot2_neon_hfp
|
||||
#define dot3_neon dot3_neon_hfp
|
||||
#define dot4_neon dot4_neon_hfp
|
||||
#else
|
||||
#define sinf_neon sinf_neon_sfp
|
||||
#define cosf_neon cosf_neon_sfp
|
||||
|
49
deps/rcheevos/CHANGELOG.md
vendored
49
deps/rcheevos/CHANGELOG.md
vendored
@ -1,3 +1,52 @@
|
||||
# v9.0.0
|
||||
|
||||
* new size: RC_MEMSIZE_BITCOUNT
|
||||
* new flag: RC_CONDITION_OR_NEXT
|
||||
* new flag: RC_CONDITION_TRIGGER
|
||||
* new flag: RC_CONDITION_MEASURED_IF
|
||||
* new operators: RC_OPERATOR_MULT / RC_OPERATOR_DIV
|
||||
* is_bcd removed from memref - now part of RC_MEMSIZE
|
||||
* add rc_runtime_t and associated functions
|
||||
* add rc_hash_ functions
|
||||
* add rc_error_str function
|
||||
* add game_hash parameter to rc_url_award_cheevo
|
||||
* remove hash parameter from rc_url_submit_lboard
|
||||
* add rc_url_ping function
|
||||
* add rc_console_ functions
|
||||
|
||||
# v8.1.0
|
||||
|
||||
* new flag: RC_CONDITION_MEASURED
|
||||
* new flag: RC_CONDITION_ADD_ADDRESS
|
||||
* add rc_evaluate_trigger - extended version of rc_test_trigger with more granular return codes
|
||||
* make rc_evaluate_value return a signed int (was unsigned int)
|
||||
* new formats: RC_FORMAT_MINUTES and RC_FORMAT_SECONDS_AS_MINUTES
|
||||
* removed " Points" text from RC_FORMAT_SCORE format
|
||||
* removed RC_FORMAT_OTHER format. "OTHER" format now parses to RC_FORMAT_SCORE
|
||||
* bugfix: AddHits will now honor AndNext on previous condition
|
||||
|
||||
# v8.0.1
|
||||
|
||||
* bugfix: prevent null reference exception if rich presence contains condition without display string
|
||||
* bugfix: 24-bit read from memory should only read 24-bits
|
||||
|
||||
# v8.0.0
|
||||
|
||||
* support for prior operand type
|
||||
* support for AndNext condition flag
|
||||
* support for rich presence
|
||||
* bugfix: update delta/prior memory values while group is paused
|
||||
* bugfix: allow floating point number without leading 0
|
||||
* bugfix: support empty alt groups
|
||||
|
||||
# v7.1.1
|
||||
|
||||
* Address signed/unsigned mismatch warnings
|
||||
|
||||
# v7.1.0
|
||||
|
||||
* Added the RC_DISABLE_LUA macro to compile rcheevos without Lua support
|
||||
|
||||
# v7.0.2
|
||||
|
||||
* Make sure the code is C89-compliant
|
||||
|
287
deps/rcheevos/README.md
vendored
287
deps/rcheevos/README.md
vendored
@ -59,10 +59,16 @@ enum {
|
||||
RC_INVALID_VALUE_FLAG = -20,
|
||||
RC_MISSING_VALUE_MEASURED = -21,
|
||||
RC_MULTIPLE_MEASURED = -22,
|
||||
RC_INVALID_MEASURED_TARGET = -23
|
||||
RC_INVALID_MEASURED_TARGET = -23,
|
||||
RC_INVALID_COMPARISON = -24
|
||||
};
|
||||
```
|
||||
|
||||
To convert the return code into something human-readable, pass it to:
|
||||
```c
|
||||
const char* rc_error_str(int ret);
|
||||
```
|
||||
|
||||
### Console identifiers
|
||||
|
||||
This enumeration uniquely identifies each of the supported platforms in RetroAchievements.
|
||||
@ -92,14 +98,38 @@ enum {
|
||||
RC_CONSOLE_PLAYSTATION_2 = 21,
|
||||
RC_CONSOLE_XBOX = 22,
|
||||
RC_CONSOLE_SKYNET = 23,
|
||||
RC_CONSOLE_XBOX_ONE = 24,
|
||||
RC_CONSOLE_POKEMON_MINI = 24,
|
||||
RC_CONSOLE_ATARI_2600 = 25,
|
||||
RC_CONSOLE_MS_DOS = 26,
|
||||
RC_CONSOLE_ARCADE = 27,
|
||||
RC_CONSOLE_VIRTUAL_BOY = 28,
|
||||
RC_CONSOLE_MSX = 29,
|
||||
RC_CONSOLE_COMMODORE_64 = 30,
|
||||
RC_CONSOLE_ZX81 = 31
|
||||
RC_CONSOLE_ZX81 = 31,
|
||||
RC_CONSOLE_ORIC = 32,
|
||||
RC_CONSOLE_SG1000 = 33,
|
||||
RC_CONSOLE_VIC20 = 34,
|
||||
RC_CONSOLE_AMIGA = 35,
|
||||
RC_CONSOLE_AMIGA_ST = 36,
|
||||
RC_CONSOLE_AMSTRAD_PC = 37,
|
||||
RC_CONSOLE_APPLE_II = 38,
|
||||
RC_CONSOLE_SATURN = 39,
|
||||
RC_CONSOLE_DREAMCAST = 40,
|
||||
RC_CONSOLE_PSP = 41,
|
||||
RC_CONSOLE_CDI = 42,
|
||||
RC_CONSOLE_3DO = 43,
|
||||
RC_CONSOLE_COLECOVISION = 44,
|
||||
RC_CONSOLE_INTELLIVISION = 45,
|
||||
RC_CONSOLE_VECTREX = 46,
|
||||
RC_CONSOLE_PC8800 = 47,
|
||||
RC_CONSOLE_PC9800 = 48,
|
||||
RC_CONSOLE_PCFX = 49,
|
||||
RC_CONSOLE_ATARI_5200 = 50,
|
||||
RC_CONSOLE_ATARI_7800 = 51,
|
||||
RC_CONSOLE_X68K = 52,
|
||||
RC_CONSOLE_WONDERSWAN = 53,
|
||||
RC_CONSOLE_CASSETTEVISION = 54,
|
||||
RC_CONSOLE_SUPER_CASSETTEVISION = 55
|
||||
};
|
||||
```
|
||||
|
||||
@ -115,27 +145,23 @@ An operand is the leaf node of RetroAchievements expressions, and can hold one o
|
||||
typedef struct {
|
||||
union {
|
||||
/* A value read from memory. */
|
||||
struct {
|
||||
/* The memory address or constant value of this variable. */
|
||||
unsigned value;
|
||||
/* The previous memory contents if RC_OPERAND_DELTA. */
|
||||
unsigned previous;
|
||||
rc_memref_value_t* memref;
|
||||
|
||||
/* The size of the variable. */
|
||||
char size;
|
||||
/* True if the value is in BCD. */
|
||||
char is_bcd;
|
||||
/* The type of the variable. */
|
||||
};
|
||||
/* An integer value. */
|
||||
unsigned num;
|
||||
|
||||
/* A floating point value. */
|
||||
double fp_value;
|
||||
double dbl;
|
||||
|
||||
/* A reference to the Lua function that provides the value. */
|
||||
int function_ref;
|
||||
int luafunc;
|
||||
};
|
||||
|
||||
/* specifies which member of the value union is being used */
|
||||
char type;
|
||||
|
||||
/* the actual RC_MEMSIZE of the operand - memref.size may differ */
|
||||
char size;
|
||||
}
|
||||
rc_operand_t;
|
||||
```
|
||||
@ -144,20 +170,21 @@ The `size` field, when applicable, holds one of these values:
|
||||
|
||||
```c
|
||||
enum {
|
||||
RC_OPERAND_BIT_0,
|
||||
RC_OPERAND_BIT_1,
|
||||
RC_OPERAND_BIT_2,
|
||||
RC_OPERAND_BIT_3,
|
||||
RC_OPERAND_BIT_4,
|
||||
RC_OPERAND_BIT_5,
|
||||
RC_OPERAND_BIT_6,
|
||||
RC_OPERAND_BIT_7,
|
||||
RC_OPERAND_LOW,
|
||||
RC_OPERAND_HIGH,
|
||||
RC_OPERAND_8_BITS,
|
||||
RC_OPERAND_16_BITS,
|
||||
RC_OPERAND_24_BITS,
|
||||
RC_OPERAND_32_BITS,
|
||||
RC_MEMSIZE_8_BITS,
|
||||
RC_MEMSIZE_16_BITS,
|
||||
RC_MEMSIZE_24_BITS,
|
||||
RC_MEMSIZE_32_BITS,
|
||||
RC_MEMSIZE_LOW,
|
||||
RC_MEMSIZE_HIGH,
|
||||
RC_MEMSIZE_BIT_0,
|
||||
RC_MEMSIZE_BIT_1,
|
||||
RC_MEMSIZE_BIT_2,
|
||||
RC_MEMSIZE_BIT_3,
|
||||
RC_MEMSIZE_BIT_4,
|
||||
RC_MEMSIZE_BIT_5,
|
||||
RC_MEMSIZE_BIT_6,
|
||||
RC_MEMSIZE_BIT_7,
|
||||
RC_MEMSIZE_BITCOUNT
|
||||
};
|
||||
```
|
||||
|
||||
@ -165,15 +192,18 @@ The `type` field is always valid, and holds one of these values:
|
||||
|
||||
```c
|
||||
enum {
|
||||
RC_OPERAND_ADDRESS, /* Compare to the value of a live address in RAM. */
|
||||
RC_OPERAND_DELTA, /* The value last known at this address. */
|
||||
RC_OPERAND_CONST, /* A 32-bit unsigned integer. */
|
||||
RC_OPERAND_FP, /* A floating point value. */
|
||||
RC_OPERAND_LUA /* A Lua function that provides the value. */
|
||||
RC_OPERAND_ADDRESS, /* The value of a live address in RAM. */
|
||||
RC_OPERAND_DELTA, /* The value last known at this address. */
|
||||
RC_OPERAND_CONST, /* A 32-bit unsigned integer. */
|
||||
RC_OPERAND_FP, /* A floating point value. */
|
||||
RC_OPERAND_LUA, /* A Lua function that provides the value. */
|
||||
RC_OPERAND_PRIOR, /* The last differing value at this address. */
|
||||
RC_OPERAND_BCD, /* The BCD-decoded value of a live address in RAM */
|
||||
RC_OPERAND_INVERTED /* The twos-complement value of a live address in RAM */
|
||||
};
|
||||
```
|
||||
|
||||
`RC_OPERAND_ADDRESS`, `RC_OPERAND_DELTA` and `RC_OPERAND_CONST` mean that the anonymous structure in the union is active. `RC_OPERAND_FP` means that `fp_value` is active. `RC_OPERAND_LUA` means `function_ref` is active.
|
||||
`RC_OPERAND_ADDRESS`, `RC_OPERAND_DELTA`, `RC_OPERAND_PRIOR`, `RC_OPERAND_BCD`, and `RC_OPERAND_INVERTED` mean that `memref` is active. `RC_OPERAND_CONST` means that `num` is active. `RC_OPERAND_FP` means that `dbl` is active. `RC_OPERAND_LUA` means `luafunc` is active.
|
||||
|
||||
|
||||
### `rc_condition_t`
|
||||
@ -184,9 +214,6 @@ A condition compares its two operands according to the defined operator. It also
|
||||
typedef struct rc_condition_t rc_condition_t;
|
||||
|
||||
struct rc_condition_t {
|
||||
/* The next condition in the chain. */
|
||||
rc_condition_t* next;
|
||||
|
||||
/* The condition's operands. */
|
||||
rc_operand_t operand1;
|
||||
rc_operand_t operand2;
|
||||
@ -196,6 +223,9 @@ struct rc_condition_t {
|
||||
/* Number of hits so far. */
|
||||
unsigned current_hits;
|
||||
|
||||
/* The next condition in the chain. */
|
||||
rc_condition_t* next;
|
||||
|
||||
/* The type of the condition. */
|
||||
char type;
|
||||
/* The comparison operator to use. */
|
||||
@ -219,7 +249,9 @@ enum {
|
||||
RC_CONDITION_ADD_HITS,
|
||||
RC_CONDITION_AND_NEXT,
|
||||
RC_CONDITION_MEASURED,
|
||||
RC_CONDITION_ADD_ADDRESS
|
||||
RC_CONDITION_ADD_ADDRESS,
|
||||
RC_CONDITION_TRIGGER,
|
||||
RC_CONDITION_MEASURED_IF
|
||||
};
|
||||
```
|
||||
|
||||
@ -227,13 +259,16 @@ enum {
|
||||
|
||||
```c
|
||||
enum {
|
||||
RC_CONDITION_EQ,
|
||||
RC_CONDITION_LT,
|
||||
RC_CONDITION_LE,
|
||||
RC_CONDITION_GT,
|
||||
RC_CONDITION_GE,
|
||||
RC_CONDITION_NE,
|
||||
RC_CONDITION_NONE
|
||||
RC_OPERATOR_EQ,
|
||||
RC_OPERATOR_LT,
|
||||
RC_OPERATOR_LE,
|
||||
RC_OPERATOR_GT,
|
||||
RC_OPERATOR_GE,
|
||||
RC_OPERATOR_NE,
|
||||
RC_OPERATOR_NONE,
|
||||
RC_OPERATOR_MULT,
|
||||
RC_OPERATOR_DIV,
|
||||
RC_OPERATOR_AND
|
||||
};
|
||||
```
|
||||
|
||||
@ -267,6 +302,9 @@ typedef struct {
|
||||
|
||||
/* The list of sub condition sets in this test. */
|
||||
rc_condset_t* alternative;
|
||||
|
||||
/* The memory references required by the trigger. */
|
||||
rc_memref_value_t* memrefs;
|
||||
}
|
||||
rc_trigger_t;
|
||||
```
|
||||
@ -313,7 +351,8 @@ enum {
|
||||
RC_TRIGGER_STATE_ACTIVE, /* achievement is active and may trigger */
|
||||
RC_TRIGGER_STATE_PAUSED, /* achievement is currently paused and will not trigger */
|
||||
RC_TRIGGER_STATE_RESET, /* achievement hit counts were reset */
|
||||
RC_TRIGGER_STATE_TRIGGERED /* achievement has triggered */
|
||||
RC_TRIGGER_STATE_TRIGGERED, /* achievement has triggered */
|
||||
RC_TRIGGER_STATE_PRIMED /* all non-Trigger conditions are true */
|
||||
};
|
||||
```
|
||||
|
||||
@ -323,52 +362,12 @@ Finally, `rc_reset_trigger` can be used to reset the internal state of a trigger
|
||||
void rc_reset_trigger(rc_trigger_t* self);
|
||||
```
|
||||
|
||||
### `rc_term_t`
|
||||
|
||||
A term is the leaf node of expressions used to compute values from operands. A term is evaluated by multiplying its two operands. `invert` is used to invert the bits of the second operand of the term, when the unary operator `~` is used.
|
||||
|
||||
```c
|
||||
typedef struct rc_term_t rc_term_t;
|
||||
|
||||
struct rc_term_t {
|
||||
/* The next term in this chain. */
|
||||
rc_term_t* next;
|
||||
|
||||
/* The first operand. */
|
||||
rc_operand_t operand1;
|
||||
/* The second operand. */
|
||||
rc_operand_t operand2;
|
||||
|
||||
/* A value that is applied to the second variable to invert its bits. */
|
||||
unsigned invert;
|
||||
};
|
||||
```
|
||||
|
||||
### `rc_expression_t`
|
||||
|
||||
An expression is a collection of terms. All terms in the collection are added together to give the value of the expression.
|
||||
|
||||
```c
|
||||
typedef struct rc_expression_t rc_expression_t;
|
||||
|
||||
struct rc_expression_t {
|
||||
/* The next expression in this chain. */
|
||||
rc_expression_t* next;
|
||||
|
||||
/* The list of terms in this expression. */
|
||||
rc_term_t* terms;
|
||||
};
|
||||
```
|
||||
|
||||
### `rc_value_t`
|
||||
|
||||
A value is a collection of expressions. It's used to give the value for a leaderboard, and it evaluates to value of the expression with the greatest value in the collection.
|
||||
A value is a collection of conditions that result in a single RC_CONDITION_MEASURED expression. It's used to calculate the value for a leaderboard and for lookups in rich presence.
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
/* The list of expression to evaluate. */
|
||||
rc_expression_t* expressions;
|
||||
|
||||
/* The list of conditions to evaluate. */
|
||||
rc_condset_t* conditions;
|
||||
|
||||
@ -413,9 +412,9 @@ typedef struct {
|
||||
rc_trigger_t cancel;
|
||||
rc_value_t value;
|
||||
rc_value_t* progress;
|
||||
rc_memref_value_t* memrefs;
|
||||
|
||||
char started;
|
||||
char submitted;
|
||||
char state;
|
||||
}
|
||||
rc_lboard_t;
|
||||
```
|
||||
@ -437,11 +436,12 @@ The function returns an action that must be performed by the caller, and `value`
|
||||
|
||||
```c
|
||||
enum {
|
||||
RC_LBOARD_INACTIVE,
|
||||
RC_LBOARD_ACTIVE,
|
||||
RC_LBOARD_STARTED,
|
||||
RC_LBOARD_CANCELED,
|
||||
RC_LBOARD_TRIGGERED
|
||||
RC_LBOARD_STATE_INACTIVE, /* leaderboard is not being processed */
|
||||
RC_LBOARD_STATE_WAITING, /* leaderboard cannot activate until the start condition has been false for at least one frame */
|
||||
RC_LBOARD_STATE_ACTIVE, /* leaderboard is active and may start */
|
||||
RC_LBOARD_STATE_STARTED, /* leaderboard attempt in progress */
|
||||
RC_LBOARD_STATE_CANCELED, /* leaderboard attempt canceled */
|
||||
RC_LBOARD_STATE_TRIGGERED /* leaderboard attempt complete, value should be submitted */
|
||||
};
|
||||
```
|
||||
|
||||
@ -458,6 +458,101 @@ The caller must keep track of these values and do the necessary actions:
|
||||
void rc_reset_lboard(rc_lboard_t* lboard);
|
||||
```
|
||||
|
||||
### `rc_runtime_t`
|
||||
|
||||
The runtime encapsulates a set of achievements and leaderboards and manages processing them for each frame. When important things occur, events are raised for the caller via a callback.
|
||||
|
||||
```c
|
||||
typedef struct rc_runtime_t {
|
||||
rc_runtime_trigger_t* triggers;
|
||||
unsigned trigger_count;
|
||||
unsigned trigger_capacity;
|
||||
|
||||
rc_runtime_lboard_t* lboards;
|
||||
unsigned lboard_count;
|
||||
unsigned lboard_capacity;
|
||||
|
||||
rc_runtime_richpresence_t* richpresence;
|
||||
char* richpresence_display_buffer;
|
||||
char richpresence_update_timer;
|
||||
|
||||
rc_memref_value_t* memrefs;
|
||||
rc_memref_value_t** next_memref;
|
||||
}
|
||||
rc_runtime_t;
|
||||
```
|
||||
|
||||
The runtime must first be initialized.
|
||||
```c
|
||||
void rc_runtime_init(rc_runtime_t* runtime);
|
||||
```
|
||||
|
||||
Then individual achievements, leaderboards, and even rich presence can be loaded into the runtime. These functions return RC_OK, or one of the negative value error codes listed above.
|
||||
```c
|
||||
int rc_runtime_activate_achievement(rc_runtime_t* runtime, unsigned id, const char* memaddr, lua_State* L, int funcs_idx);
|
||||
int rc_runtime_activate_lboard(rc_runtime_t* runtime, unsigned id, const char* memaddr, lua_State* L, int funcs_idx);
|
||||
int rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx);
|
||||
```
|
||||
|
||||
The runtime should be called once per frame to evaluate the state of the active achievements/leaderboards:
|
||||
```c
|
||||
void rc_runtime_do_frame(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_peek_t peek, void* ud, lua_State* L);
|
||||
```
|
||||
|
||||
The `event_handler` is a callback function that is called for each event that occurs when processing the frame.
|
||||
```c
|
||||
typedef struct rc_runtime_event_t {
|
||||
unsigned id;
|
||||
int value;
|
||||
char type;
|
||||
}
|
||||
rc_runtime_event_t;
|
||||
|
||||
typedef void (*rc_runtime_event_handler_t)(const rc_runtime_event_t* runtime_event);
|
||||
```
|
||||
|
||||
The `event.type` field will be one of the following:
|
||||
* RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED (id=achievement id)
|
||||
An achievement starts in the RC_TRIGGER_STATE_WAITING state and cannot trigger until it has been false for at least one frame. This event indicates the achievement is no longer waiting and may trigger on a future frame.
|
||||
* RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED (id=achievement id)
|
||||
One or more conditions in the achievement have disabled the achievement.
|
||||
* RC_RUNTIME_EVENT_ACHIEVEMENT_RESET (id=achievement id)
|
||||
One or more conditions in the achievement have reset any progress captured in the achievement.
|
||||
* RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED (id=achievement id)
|
||||
All conditions for the achievement have been met and the user should be informed.
|
||||
NOTE: If `rc_runtime_reset` is called without deactivating the achievement, it may trigger again.
|
||||
* RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED (id=achievement id)
|
||||
All non-trigger conditions for the achievement have been met. This typically indicates the achievement is a challenge achievement and the challenge is active.
|
||||
* RC_RUNTIME_EVENT_LBOARD_STARTED (id=leaderboard id, value=leaderboard value)
|
||||
The leaderboard's start condition has been met and the user should be informed that a leaderboard attempt has started.
|
||||
* RC_RUNTIME_EVENT_LBOARD_CANCELED (id=leaderboard id, value=leaderboard value)
|
||||
The leaderboard's cancel condition has been met and the user should be informed that a leaderboard attempt has failed.
|
||||
* RC_RUNTIME_EVENT_LBOARD_UPDATED (id=leaderboard id, value=leaderboard value)
|
||||
The leaderboard value has changed.
|
||||
* RC_RUNTIME_EVENT_LBOARD_TRIGGERED (id=leaderboard id, value=leaderboard value)
|
||||
The leaderboard's submit condition has been met and the user should be informed that a leaderboard attempt was successful. The value should be submitted.
|
||||
|
||||
When an achievement triggers, it should be deactivated so it won't trigger again:
|
||||
```c
|
||||
void rc_runtime_deactivate_achievement(rc_runtime_t* runtime, unsigned id);
|
||||
```
|
||||
Additionally, the unlock should be submitted to the server.
|
||||
|
||||
When a leaderboard triggers, it should not be deactivated in case the player wants to try again for a better score. The value should be submitted to the server.
|
||||
|
||||
`rc_runtime_do_frame` also periodically updates the rich presense string (every 60 frames). To get the current value, call
|
||||
```c
|
||||
const char* rc_runtime_get_richpresence(const rc_runtime_t* runtime);
|
||||
```
|
||||
|
||||
When the game is reset, the runtime should also be reset:
|
||||
```c
|
||||
void rc_runtime_reset(rc_runtime_t* runtime);
|
||||
```
|
||||
|
||||
This ensures any active achievements/leaderboards are set back to their initial states and prevents unexpected triggers when the memory changes in atypical way.
|
||||
|
||||
|
||||
### Value Formatting
|
||||
|
||||
**rcheevos** includes helper functions to parse formatting strings from RetroAchievements, and format values according to them.
|
||||
|
266
deps/rcheevos/include/rcheevos.h
vendored
266
deps/rcheevos/include/rcheevos.h
vendored
@ -35,46 +35,12 @@ enum {
|
||||
RC_INVALID_VALUE_FLAG = -20,
|
||||
RC_MISSING_VALUE_MEASURED = -21,
|
||||
RC_MULTIPLE_MEASURED = -22,
|
||||
RC_INVALID_MEASURED_TARGET = -23
|
||||
RC_INVALID_MEASURED_TARGET = -23,
|
||||
RC_INVALID_COMPARISON = -24,
|
||||
RC_INVALID_STATE = -25
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
| Console identifiers |
|
||||
\*****************************************************************************/
|
||||
|
||||
enum {
|
||||
RC_CONSOLE_MEGA_DRIVE = 1,
|
||||
RC_CONSOLE_NINTENDO_64 = 2,
|
||||
RC_CONSOLE_SUPER_NINTENDO = 3,
|
||||
RC_CONSOLE_GAMEBOY = 4,
|
||||
RC_CONSOLE_GAMEBOY_ADVANCE = 5,
|
||||
RC_CONSOLE_GAMEBOY_COLOR = 6,
|
||||
RC_CONSOLE_NINTENDO = 7,
|
||||
RC_CONSOLE_PC_ENGINE = 8,
|
||||
RC_CONSOLE_SEGA_CD = 9,
|
||||
RC_CONSOLE_SEGA_32X = 10,
|
||||
RC_CONSOLE_MASTER_SYSTEM = 11,
|
||||
RC_CONSOLE_PLAYSTATION = 12,
|
||||
RC_CONSOLE_ATARI_LYNX = 13,
|
||||
RC_CONSOLE_NEOGEO_POCKET = 14,
|
||||
RC_CONSOLE_GAME_GEAR = 15,
|
||||
RC_CONSOLE_GAMECUBE = 16,
|
||||
RC_CONSOLE_ATARI_JAGUAR = 17,
|
||||
RC_CONSOLE_NINTENDO_DS = 18,
|
||||
RC_CONSOLE_WII = 19,
|
||||
RC_CONSOLE_WII_U = 20,
|
||||
RC_CONSOLE_PLAYSTATION_2 = 21,
|
||||
RC_CONSOLE_XBOX = 22,
|
||||
RC_CONSOLE_SKYNET = 23,
|
||||
RC_CONSOLE_XBOX_ONE = 24,
|
||||
RC_CONSOLE_ATARI_2600 = 25,
|
||||
RC_CONSOLE_MS_DOS = 26,
|
||||
RC_CONSOLE_ARCADE = 27,
|
||||
RC_CONSOLE_VIRTUAL_BOY = 28,
|
||||
RC_CONSOLE_MSX = 29,
|
||||
RC_CONSOLE_COMMODORE_64 = 30,
|
||||
RC_CONSOLE_ZX81 = 31
|
||||
};
|
||||
const char* rc_error_str(int ret);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Callbacks |
|
||||
@ -93,6 +59,12 @@ typedef unsigned (*rc_peek_t)(unsigned address, unsigned num_bytes, void* ud);
|
||||
|
||||
/* Sizes. */
|
||||
enum {
|
||||
RC_MEMSIZE_8_BITS,
|
||||
RC_MEMSIZE_16_BITS,
|
||||
RC_MEMSIZE_24_BITS,
|
||||
RC_MEMSIZE_32_BITS,
|
||||
RC_MEMSIZE_LOW,
|
||||
RC_MEMSIZE_HIGH,
|
||||
RC_MEMSIZE_BIT_0,
|
||||
RC_MEMSIZE_BIT_1,
|
||||
RC_MEMSIZE_BIT_2,
|
||||
@ -101,12 +73,7 @@ enum {
|
||||
RC_MEMSIZE_BIT_5,
|
||||
RC_MEMSIZE_BIT_6,
|
||||
RC_MEMSIZE_BIT_7,
|
||||
RC_MEMSIZE_LOW,
|
||||
RC_MEMSIZE_HIGH,
|
||||
RC_MEMSIZE_8_BITS,
|
||||
RC_MEMSIZE_16_BITS,
|
||||
RC_MEMSIZE_24_BITS,
|
||||
RC_MEMSIZE_32_BITS
|
||||
RC_MEMSIZE_BITCOUNT
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -114,8 +81,6 @@ typedef struct {
|
||||
unsigned address;
|
||||
/* The size of the variable. */
|
||||
char size;
|
||||
/* True if the value is in BCD. */
|
||||
char is_bcd;
|
||||
/* True if the reference will be used in indirection */
|
||||
char is_indirect;
|
||||
} rc_memref_t;
|
||||
@ -143,12 +108,14 @@ struct rc_memref_value_t {
|
||||
|
||||
/* types */
|
||||
enum {
|
||||
RC_OPERAND_ADDRESS, /* Compare to the value of a live address in RAM. */
|
||||
RC_OPERAND_DELTA, /* The value last known at this address. */
|
||||
RC_OPERAND_CONST, /* A 32-bit unsigned integer. */
|
||||
RC_OPERAND_FP, /* A floating point value. */
|
||||
RC_OPERAND_LUA, /* A Lua function that provides the value. */
|
||||
RC_OPERAND_PRIOR /* The last differing value at this address. */
|
||||
RC_OPERAND_ADDRESS, /* The value of a live address in RAM. */
|
||||
RC_OPERAND_DELTA, /* The value last known at this address. */
|
||||
RC_OPERAND_CONST, /* A 32-bit unsigned integer. */
|
||||
RC_OPERAND_FP, /* A floating point value. */
|
||||
RC_OPERAND_LUA, /* A Lua function that provides the value. */
|
||||
RC_OPERAND_PRIOR, /* The last differing value at this address. */
|
||||
RC_OPERAND_BCD, /* The BCD-decoded value of a live address in RAM */
|
||||
RC_OPERAND_INVERTED /* The twos-complement value of a live address in RAM */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -166,7 +133,11 @@ typedef struct {
|
||||
int luafunc;
|
||||
} value;
|
||||
|
||||
/* specifies which member of the value union is being used */
|
||||
char type;
|
||||
|
||||
/* the actual RC_MEMSIZE of the operand - memref.size may differ */
|
||||
char size;
|
||||
}
|
||||
rc_operand_t;
|
||||
|
||||
@ -184,18 +155,24 @@ enum {
|
||||
RC_CONDITION_ADD_HITS,
|
||||
RC_CONDITION_AND_NEXT,
|
||||
RC_CONDITION_MEASURED,
|
||||
RC_CONDITION_ADD_ADDRESS
|
||||
RC_CONDITION_ADD_ADDRESS,
|
||||
RC_CONDITION_OR_NEXT,
|
||||
RC_CONDITION_TRIGGER,
|
||||
RC_CONDITION_MEASURED_IF
|
||||
};
|
||||
|
||||
/* operators */
|
||||
enum {
|
||||
RC_CONDITION_EQ,
|
||||
RC_CONDITION_LT,
|
||||
RC_CONDITION_LE,
|
||||
RC_CONDITION_GT,
|
||||
RC_CONDITION_GE,
|
||||
RC_CONDITION_NE,
|
||||
RC_CONDITION_NONE
|
||||
RC_OPERATOR_EQ,
|
||||
RC_OPERATOR_LT,
|
||||
RC_OPERATOR_LE,
|
||||
RC_OPERATOR_GT,
|
||||
RC_OPERATOR_GE,
|
||||
RC_OPERATOR_NE,
|
||||
RC_OPERATOR_NONE,
|
||||
RC_OPERATOR_MULT,
|
||||
RC_OPERATOR_DIV,
|
||||
RC_OPERATOR_AND
|
||||
};
|
||||
|
||||
typedef struct rc_condition_t rc_condition_t;
|
||||
@ -256,7 +233,8 @@ enum {
|
||||
RC_TRIGGER_STATE_ACTIVE, /* achievement is active and may trigger */
|
||||
RC_TRIGGER_STATE_PAUSED, /* achievement is currently paused and will not trigger */
|
||||
RC_TRIGGER_STATE_RESET, /* achievement hit counts were reset */
|
||||
RC_TRIGGER_STATE_TRIGGERED /* achievement has triggered */
|
||||
RC_TRIGGER_STATE_TRIGGERED, /* achievement has triggered */
|
||||
RC_TRIGGER_STATE_PRIMED /* all non-Trigger conditions are true */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -290,38 +268,10 @@ int rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State*
|
||||
void rc_reset_trigger(rc_trigger_t* self);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Expressions and values |
|
||||
| Values |
|
||||
\*****************************************************************************/
|
||||
|
||||
typedef struct rc_term_t rc_term_t;
|
||||
|
||||
struct rc_term_t {
|
||||
/* The next term in this chain. */
|
||||
rc_term_t* next;
|
||||
|
||||
/* The first operand. */
|
||||
rc_operand_t operand1;
|
||||
/* The second operand. */
|
||||
rc_operand_t operand2;
|
||||
|
||||
/* A value that is applied to the second variable to invert its bits. */
|
||||
unsigned invert;
|
||||
};
|
||||
|
||||
typedef struct rc_expression_t rc_expression_t;
|
||||
|
||||
struct rc_expression_t {
|
||||
/* The next expression in this chain. */
|
||||
rc_expression_t* next;
|
||||
|
||||
/* The list of terms in this expression. */
|
||||
rc_term_t* terms;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* The list of expression to evaluate. */
|
||||
rc_expression_t* expressions;
|
||||
|
||||
/* The list of conditions to evaluate. */
|
||||
rc_condset_t* conditions;
|
||||
|
||||
@ -340,11 +290,12 @@ int rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L)
|
||||
|
||||
/* Return values for rc_evaluate_lboard. */
|
||||
enum {
|
||||
RC_LBOARD_INACTIVE,
|
||||
RC_LBOARD_ACTIVE,
|
||||
RC_LBOARD_STARTED,
|
||||
RC_LBOARD_CANCELED,
|
||||
RC_LBOARD_TRIGGERED
|
||||
RC_LBOARD_STATE_INACTIVE, /* leaderboard is not being processed */
|
||||
RC_LBOARD_STATE_WAITING, /* leaderboard cannot activate until the start condition has been false for at least one frame */
|
||||
RC_LBOARD_STATE_ACTIVE, /* leaderboard is active and may start */
|
||||
RC_LBOARD_STATE_STARTED, /* leaderboard attempt in progress */
|
||||
RC_LBOARD_STATE_CANCELED, /* leaderboard attempt canceled */
|
||||
RC_LBOARD_STATE_TRIGGERED /* leaderboard attempt complete, value should be submitted */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -355,8 +306,7 @@ typedef struct {
|
||||
rc_value_t* progress;
|
||||
rc_memref_value_t* memrefs;
|
||||
|
||||
char started;
|
||||
char submitted;
|
||||
char state;
|
||||
}
|
||||
rc_lboard_t;
|
||||
|
||||
@ -433,6 +383,128 @@ int rc_richpresence_size(const char* script);
|
||||
rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx);
|
||||
int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, unsigned buffersize, rc_peek_t peek, void* peek_ud, lua_State* L);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Runtime |
|
||||
\*****************************************************************************/
|
||||
|
||||
typedef struct rc_runtime_trigger_t {
|
||||
unsigned id;
|
||||
rc_trigger_t* trigger;
|
||||
void* buffer;
|
||||
unsigned char md5[16];
|
||||
char owns_memrefs;
|
||||
}
|
||||
rc_runtime_trigger_t;
|
||||
|
||||
typedef struct rc_runtime_lboard_t {
|
||||
unsigned id;
|
||||
int value;
|
||||
rc_lboard_t* lboard;
|
||||
void* buffer;
|
||||
unsigned char md5[16];
|
||||
char owns_memrefs;
|
||||
}
|
||||
rc_runtime_lboard_t;
|
||||
|
||||
typedef struct rc_runtime_richpresence_t {
|
||||
rc_richpresence_t* richpresence;
|
||||
void* buffer;
|
||||
struct rc_runtime_richpresence_t* previous;
|
||||
char owns_memrefs;
|
||||
}
|
||||
rc_runtime_richpresence_t;
|
||||
|
||||
typedef struct rc_runtime_t {
|
||||
rc_runtime_trigger_t* triggers;
|
||||
unsigned trigger_count;
|
||||
unsigned trigger_capacity;
|
||||
|
||||
rc_runtime_lboard_t* lboards;
|
||||
unsigned lboard_count;
|
||||
unsigned lboard_capacity;
|
||||
|
||||
rc_runtime_richpresence_t* richpresence;
|
||||
char* richpresence_display_buffer;
|
||||
char richpresence_update_timer;
|
||||
|
||||
rc_memref_value_t* memrefs;
|
||||
rc_memref_value_t** next_memref;
|
||||
}
|
||||
rc_runtime_t;
|
||||
|
||||
void rc_runtime_init(rc_runtime_t* runtime);
|
||||
void rc_runtime_destroy(rc_runtime_t* runtime);
|
||||
|
||||
int rc_runtime_activate_achievement(rc_runtime_t* runtime, unsigned id, const char* memaddr, lua_State* L, int funcs_idx);
|
||||
void rc_runtime_deactivate_achievement(rc_runtime_t* runtime, unsigned id);
|
||||
rc_trigger_t* rc_runtime_get_achievement(const rc_runtime_t* runtime, unsigned id);
|
||||
|
||||
int rc_runtime_activate_lboard(rc_runtime_t* runtime, unsigned id, const char* memaddr, lua_State* L, int funcs_idx);
|
||||
void rc_runtime_deactivate_lboard(rc_runtime_t* runtime, unsigned id);
|
||||
rc_lboard_t* rc_runtime_get_lboard(const rc_runtime_t* runtime, unsigned id);
|
||||
|
||||
int rc_runtime_activate_richpresence(rc_runtime_t* runtime, const char* script, lua_State* L, int funcs_idx);
|
||||
const char* rc_runtime_get_richpresence(const rc_runtime_t* runtime);
|
||||
|
||||
enum {
|
||||
RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED, /* from WAITING, PAUSED, or PRIMED to ACTIVE */
|
||||
RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED,
|
||||
RC_RUNTIME_EVENT_ACHIEVEMENT_RESET,
|
||||
RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED,
|
||||
RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED,
|
||||
RC_RUNTIME_EVENT_LBOARD_STARTED,
|
||||
RC_RUNTIME_EVENT_LBOARD_CANCELED,
|
||||
RC_RUNTIME_EVENT_LBOARD_UPDATED,
|
||||
RC_RUNTIME_EVENT_LBOARD_TRIGGERED
|
||||
};
|
||||
|
||||
typedef struct rc_runtime_event_t {
|
||||
unsigned id;
|
||||
int value;
|
||||
char type;
|
||||
}
|
||||
rc_runtime_event_t;
|
||||
|
||||
typedef void (*rc_runtime_event_handler_t)(const rc_runtime_event_t* runtime_event);
|
||||
|
||||
void rc_runtime_do_frame(rc_runtime_t* runtime, rc_runtime_event_handler_t event_handler, rc_peek_t peek, void* ud, lua_State* L);
|
||||
void rc_runtime_reset(rc_runtime_t* runtime);
|
||||
|
||||
int rc_runtime_progress_size(const rc_runtime_t* runtime, lua_State* L);
|
||||
int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, lua_State* L);
|
||||
int rc_runtime_deserialize_progress(rc_runtime_t* runtime, const unsigned char* serialized, lua_State* L);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Memory mapping |
|
||||
\*****************************************************************************/
|
||||
|
||||
enum {
|
||||
RC_MEMORY_TYPE_SYSTEM_RAM, /* normal system memory */
|
||||
RC_MEMORY_TYPE_SAVE_RAM, /* memory that persists between sessions */
|
||||
RC_MEMORY_TYPE_VIDEO_RAM, /* memory reserved for graphical processing */
|
||||
RC_MEMORY_TYPE_READONLY, /* memory that maps to read only data */
|
||||
RC_MEMORY_TYPE_HARDWARE_CONTROLLER, /* memory for interacting with system components */
|
||||
RC_MEMORY_TYPE_VIRTUAL_RAM, /* secondary address space that maps to real memory in system RAM */
|
||||
RC_MEMORY_TYPE_UNUSED /* these addresses don't really exist */
|
||||
};
|
||||
|
||||
typedef struct rc_memory_region_t {
|
||||
unsigned start_address; /* first address of block as queried by RetroAchievements */
|
||||
unsigned end_address; /* last address of block as queried by RetroAchievements */
|
||||
unsigned real_address; /* real address for first address of block */
|
||||
char type; /* RC_MEMORY_TYPE_ for block */
|
||||
const char* description; /* short description of block */
|
||||
}
|
||||
rc_memory_region_t;
|
||||
|
||||
typedef struct rc_memory_regions_t {
|
||||
const rc_memory_region_t* region;
|
||||
unsigned num_regions;
|
||||
}
|
||||
rc_memory_regions_t;
|
||||
|
||||
const rc_memory_regions_t* rc_console_memory_regions(int console_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
79
deps/rcheevos/include/rconsoles.h
vendored
Normal file
79
deps/rcheevos/include/rconsoles.h
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef RCONSOLES_H
|
||||
#define RCONSOLES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************\
|
||||
| Console identifiers |
|
||||
\*****************************************************************************/
|
||||
|
||||
enum {
|
||||
RC_CONSOLE_MEGA_DRIVE = 1,
|
||||
RC_CONSOLE_NINTENDO_64 = 2,
|
||||
RC_CONSOLE_SUPER_NINTENDO = 3,
|
||||
RC_CONSOLE_GAMEBOY = 4,
|
||||
RC_CONSOLE_GAMEBOY_ADVANCE = 5,
|
||||
RC_CONSOLE_GAMEBOY_COLOR = 6,
|
||||
RC_CONSOLE_NINTENDO = 7,
|
||||
RC_CONSOLE_PC_ENGINE = 8,
|
||||
RC_CONSOLE_SEGA_CD = 9,
|
||||
RC_CONSOLE_SEGA_32X = 10,
|
||||
RC_CONSOLE_MASTER_SYSTEM = 11,
|
||||
RC_CONSOLE_PLAYSTATION = 12,
|
||||
RC_CONSOLE_ATARI_LYNX = 13,
|
||||
RC_CONSOLE_NEOGEO_POCKET = 14,
|
||||
RC_CONSOLE_GAME_GEAR = 15,
|
||||
RC_CONSOLE_GAMECUBE = 16,
|
||||
RC_CONSOLE_ATARI_JAGUAR = 17,
|
||||
RC_CONSOLE_NINTENDO_DS = 18,
|
||||
RC_CONSOLE_WII = 19,
|
||||
RC_CONSOLE_WII_U = 20,
|
||||
RC_CONSOLE_PLAYSTATION_2 = 21,
|
||||
RC_CONSOLE_XBOX = 22,
|
||||
/* 23 used to be EVENTS */
|
||||
RC_CONSOLE_POKEMON_MINI = 24,
|
||||
RC_CONSOLE_ATARI_2600 = 25,
|
||||
RC_CONSOLE_MS_DOS = 26,
|
||||
RC_CONSOLE_ARCADE = 27,
|
||||
RC_CONSOLE_VIRTUAL_BOY = 28,
|
||||
RC_CONSOLE_MSX = 29,
|
||||
RC_CONSOLE_COMMODORE_64 = 30,
|
||||
RC_CONSOLE_ZX81 = 31,
|
||||
RC_CONSOLE_ORIC = 32,
|
||||
RC_CONSOLE_SG1000 = 33,
|
||||
RC_CONSOLE_VIC20 = 34,
|
||||
RC_CONSOLE_AMIGA = 35,
|
||||
RC_CONSOLE_AMIGA_ST = 36,
|
||||
RC_CONSOLE_AMSTRAD_PC = 37,
|
||||
RC_CONSOLE_APPLE_II = 38,
|
||||
RC_CONSOLE_SATURN = 39,
|
||||
RC_CONSOLE_DREAMCAST = 40,
|
||||
RC_CONSOLE_PSP = 41,
|
||||
RC_CONSOLE_CDI = 42,
|
||||
RC_CONSOLE_3DO = 43,
|
||||
RC_CONSOLE_COLECOVISION = 44,
|
||||
RC_CONSOLE_INTELLIVISION = 45,
|
||||
RC_CONSOLE_VECTREX = 46,
|
||||
RC_CONSOLE_PC8800 = 47,
|
||||
RC_CONSOLE_PC9800 = 48,
|
||||
RC_CONSOLE_PCFX = 49,
|
||||
RC_CONSOLE_ATARI_5200 = 50,
|
||||
RC_CONSOLE_ATARI_7800 = 51,
|
||||
RC_CONSOLE_X68K = 52,
|
||||
RC_CONSOLE_WONDERSWAN = 53,
|
||||
RC_CONSOLE_CASSETTEVISION = 54,
|
||||
RC_CONSOLE_SUPER_CASSETTEVISION = 55,
|
||||
|
||||
RC_CONSOLE_HUBS = 100,
|
||||
RC_CONSOLE_EVENTS = 101
|
||||
};
|
||||
|
||||
const char* rc_console_name(int console_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RCONSOLES_H */
|
124
deps/rcheevos/include/rhash.h
vendored
Normal file
124
deps/rcheevos/include/rhash.h
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
#ifndef RHASH_H
|
||||
#define RHASH_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rconsoles.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
/* generates a hash from a block of memory.
|
||||
* returns non-zero on success, or zero on failure.
|
||||
*/
|
||||
int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/* generates a hash from a file.
|
||||
* returns non-zero on success, or zero on failure.
|
||||
*/
|
||||
int rc_hash_generate_from_file(char hash[33], int console_id, const char* path);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
/* data for rc_hash_iterate
|
||||
*/
|
||||
struct rc_hash_iterator
|
||||
{
|
||||
uint8_t* buffer;
|
||||
size_t buffer_size;
|
||||
uint8_t consoles[12];
|
||||
int index;
|
||||
const char* path;
|
||||
};
|
||||
|
||||
/* initializes a rc_hash_iterator
|
||||
* - path must be provided
|
||||
* - if buffer and buffer_size are provided, path may be a filename (i.e. for something extracted from a zip file)
|
||||
*/
|
||||
void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char* path, uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/* releases resources associated to a rc_hash_iterator
|
||||
*/
|
||||
void rc_hash_destroy_iterator(struct rc_hash_iterator* iterator);
|
||||
|
||||
/* generates the next hash for the data in the rc_hash_iterator.
|
||||
* returns non-zero if a hash was generated, or zero if no more hashes can be generated for the data.
|
||||
*/
|
||||
int rc_hash_iterate(char hash[33], struct rc_hash_iterator* iterator);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
/* specifies a function to call when an error occurs to display the error message */
|
||||
typedef void (*rc_hash_message_callback)(const char*);
|
||||
void rc_hash_init_error_message_callback(rc_hash_message_callback callback);
|
||||
|
||||
/* specifies a function to call for verbose logging */
|
||||
void rc_hash_init_verbose_message_callback(rc_hash_message_callback callback);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
/* opens a file */
|
||||
typedef void* (*rc_hash_filereader_open_file_handler)(const char* path_utf8);
|
||||
|
||||
/* moves the file pointer - standard fseek parameters */
|
||||
typedef void (*rc_hash_filereader_seek_handler)(void* file_handle, size_t offset, int origin);
|
||||
|
||||
/* locates the file pointer */
|
||||
typedef size_t (*rc_hash_filereader_tell_handler)(void* file_handle);
|
||||
|
||||
/* reads the specified number of bytes from the file starting at the read pointer.
|
||||
* returns the number of bytes actually read.
|
||||
*/
|
||||
typedef size_t (*rc_hash_filereader_read_handler)(void* file_handle, void* buffer, size_t requested_bytes);
|
||||
|
||||
/* closes the file */
|
||||
typedef void (*rc_hash_filereader_close_file_handler)(void* file_handle);
|
||||
|
||||
struct rc_hash_filereader
|
||||
{
|
||||
rc_hash_filereader_open_file_handler open;
|
||||
rc_hash_filereader_seek_handler seek;
|
||||
rc_hash_filereader_tell_handler tell;
|
||||
rc_hash_filereader_read_handler read;
|
||||
rc_hash_filereader_close_file_handler close;
|
||||
};
|
||||
|
||||
void rc_hash_init_custom_filereader(struct rc_hash_filereader* reader);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
/* opens a track from the specified file. track 0 indicates the first data track should be opened.
|
||||
* returns a handle to be passed to the other functions, or NULL if the track could not be opened.
|
||||
*/
|
||||
typedef void* (*rc_hash_cdreader_open_track_handler)(const char* path, uint32_t track);
|
||||
|
||||
/* attempts to read the specified number of bytes from the file starting at the read pointer.
|
||||
* returns the number of bytes actually read.
|
||||
*/
|
||||
typedef size_t (*rc_hash_cdreader_read_sector_handler)(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes);
|
||||
|
||||
/* closes the track handle */
|
||||
typedef void (*rc_hash_cdreader_close_track_handler)(void* track_handle);
|
||||
|
||||
struct rc_hash_cdreader
|
||||
{
|
||||
rc_hash_cdreader_open_track_handler open_track;
|
||||
rc_hash_cdreader_read_sector_handler read_sector;
|
||||
rc_hash_cdreader_close_track_handler close_track;
|
||||
};
|
||||
|
||||
void rc_hash_init_default_cdreader();
|
||||
void rc_hash_init_custom_cdreader(struct rc_hash_cdreader* reader);
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RHASH_H */
|
9
deps/rcheevos/include/rurl.h
vendored
9
deps/rcheevos/include/rurl.h
vendored
@ -7,11 +7,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned cheevo_id, int hardcore);
|
||||
int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned cheevo_id, int hardcore, const char* game_hash);
|
||||
|
||||
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value, const char* game_hash);
|
||||
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value);
|
||||
|
||||
int rc_url_get_gameid(char* buffer, size_t size, unsigned char hash[16]);
|
||||
int rc_url_get_gameid(char* buffer, size_t size, const char* hash);
|
||||
|
||||
int rc_url_get_patch(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid);
|
||||
|
||||
@ -25,6 +25,9 @@ int rc_url_get_unlock_list(char* buffer, size_t size, const char* user_name, con
|
||||
|
||||
int rc_url_post_playing(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid);
|
||||
|
||||
int rc_url_ping(char* url_buffer, size_t url_buffer_size, char* post_buffer, size_t post_buffer_size,
|
||||
const char* user_name, const char* login_token, unsigned gameid, const char* rich_presence);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
34
deps/rcheevos/src/rcheevos/alloc.c
vendored
34
deps/rcheevos/src/rcheevos/alloc.c
vendored
@ -52,3 +52,37 @@ void rc_destroy_parse_state(rc_parse_state_t* parse)
|
||||
if (parse->scratch.memref != parse->scratch.memref_buffer)
|
||||
free(parse->scratch.memref);
|
||||
}
|
||||
|
||||
const char* rc_error_str(int ret)
|
||||
{
|
||||
switch (ret) {
|
||||
case RC_OK: return "OK";
|
||||
case RC_INVALID_LUA_OPERAND: return "Invalid Lua operand";
|
||||
case RC_INVALID_MEMORY_OPERAND: return "Invalid memory operand";
|
||||
case RC_INVALID_CONST_OPERAND: return "Invalid constant operand";
|
||||
case RC_INVALID_FP_OPERAND: return "Invalid floating-point operand";
|
||||
case RC_INVALID_CONDITION_TYPE: return "Invalid condition type";
|
||||
case RC_INVALID_OPERATOR: return "Invalid operator";
|
||||
case RC_INVALID_REQUIRED_HITS: return "Invalid required hits";
|
||||
case RC_DUPLICATED_START: return "Duplicated start condition";
|
||||
case RC_DUPLICATED_CANCEL: return "Duplicated cancel condition";
|
||||
case RC_DUPLICATED_SUBMIT: return "Duplicated submit condition";
|
||||
case RC_DUPLICATED_VALUE: return "Duplicated value expression";
|
||||
case RC_DUPLICATED_PROGRESS: return "Duplicated progress expression";
|
||||
case RC_MISSING_START: return "Missing start condition";
|
||||
case RC_MISSING_CANCEL: return "Missing cancel condition";
|
||||
case RC_MISSING_SUBMIT: return "Missing submit condition";
|
||||
case RC_MISSING_VALUE: return "Missing value expression";
|
||||
case RC_INVALID_LBOARD_FIELD: return "Invalid field in leaderboard";
|
||||
case RC_MISSING_DISPLAY_STRING: return "Missing display string";
|
||||
case RC_OUT_OF_MEMORY: return "Out of memory";
|
||||
case RC_INVALID_VALUE_FLAG: return "Invalid flag in value expression";
|
||||
case RC_MISSING_VALUE_MEASURED: return "Missing measured flag in value expression";
|
||||
case RC_MULTIPLE_MEASURED: return "Multiple measured targets";
|
||||
case RC_INVALID_MEASURED_TARGET: return "Invalid measured target";
|
||||
case RC_INVALID_COMPARISON: return "Invalid comparison";
|
||||
case RC_INVALID_STATE: return "Invalid state";
|
||||
|
||||
default: return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
44
deps/rcheevos/src/rcheevos/compat.c
vendored
Normal file
44
deps/rcheevos/src/rcheevos/compat.c
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
#include "compat.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int rc_strncasecmp(const char* left, const char* right, size_t length)
|
||||
{
|
||||
while (length)
|
||||
{
|
||||
if (*left != *right)
|
||||
{
|
||||
const int diff = tolower(*left) - tolower(*right);
|
||||
if (diff != 0)
|
||||
return diff;
|
||||
}
|
||||
|
||||
++left;
|
||||
++right;
|
||||
--length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* rc_strdup(const char* str)
|
||||
{
|
||||
const size_t length = strlen(str);
|
||||
char* buffer = (char*)malloc(length + 1);
|
||||
memcpy(buffer, str, length + 1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int rc_snprintf(char* buffer, size_t size, const char* format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
/* assume buffer is large enough and ignore size */
|
||||
result = vsprintf(buffer, format, args);
|
||||
va_end(args);
|
||||
|
||||
return result;
|
||||
}
|
55
deps/rcheevos/src/rcheevos/compat.h
vendored
Normal file
55
deps/rcheevos/src/rcheevos/compat.h
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef RC_COMPAT_H
|
||||
#define RC_COMPAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MINGW) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
|
||||
/* MinGW redefinitions */
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
/* Visual Studio redefinitions */
|
||||
|
||||
#ifndef strcasecmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
#ifndef strncasecmp
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
#ifndef strdup
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
#elif __STDC_VERSION__ < 199901L
|
||||
|
||||
/* C89 redefinitions */
|
||||
|
||||
#ifndef snprintf
|
||||
extern int rc_snprintf(char* buffer, size_t size, const char* format, ...);
|
||||
#define snprintf rc_snprintf
|
||||
#endif
|
||||
|
||||
#ifndef strncasecmp
|
||||
extern int rc_strncasecmp(const char* left, const char* right, size_t length);
|
||||
#define strncasecmp rc_strncasecmp
|
||||
#endif
|
||||
|
||||
#ifndef strdup
|
||||
extern char* rc_strdup(const char* str);
|
||||
#define strdup rc_strdup
|
||||
#endif
|
||||
|
||||
#endif /* __STDC_VERSION__ < 199901L */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RC_COMPAT_H */
|
122
deps/rcheevos/src/rcheevos/condition.c
vendored
122
deps/rcheevos/src/rcheevos/condition.c
vendored
@ -6,6 +6,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
rc_condition_t* self;
|
||||
const char* aux;
|
||||
int ret2;
|
||||
int can_modify = 0;
|
||||
|
||||
aux = *memaddr;
|
||||
self = RC_ALLOC(rc_condition_t, parse);
|
||||
@ -15,12 +16,15 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
switch (*aux) {
|
||||
case 'p': case 'P': self->type = RC_CONDITION_PAUSE_IF; break;
|
||||
case 'r': case 'R': self->type = RC_CONDITION_RESET_IF; break;
|
||||
case 'a': case 'A': self->type = RC_CONDITION_ADD_SOURCE; break;
|
||||
case 'b': case 'B': self->type = RC_CONDITION_SUB_SOURCE; break;
|
||||
case 'a': case 'A': self->type = RC_CONDITION_ADD_SOURCE; can_modify = 1; break;
|
||||
case 'b': case 'B': self->type = RC_CONDITION_SUB_SOURCE; can_modify = 1; break;
|
||||
case 'c': case 'C': self->type = RC_CONDITION_ADD_HITS; break;
|
||||
case 'n': case 'N': self->type = RC_CONDITION_AND_NEXT; break;
|
||||
case 'o': case 'O': self->type = RC_CONDITION_OR_NEXT; break;
|
||||
case 'm': case 'M': self->type = RC_CONDITION_MEASURED; break;
|
||||
case 'i': case 'I': self->type = RC_CONDITION_ADD_ADDRESS; break;
|
||||
case 'q': case 'Q': self->type = RC_CONDITION_MEASURED_IF; break;
|
||||
case 'i': case 'I': self->type = RC_CONDITION_ADD_ADDRESS; can_modify = 1; break;
|
||||
case 't': case 'T': self->type = RC_CONDITION_TRIGGER; break;
|
||||
default: parse->offset = RC_INVALID_CONDITION_TYPE; return 0;
|
||||
}
|
||||
|
||||
@ -37,9 +41,14 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->operand1.type == RC_OPERAND_FP) {
|
||||
parse->offset = can_modify ? RC_INVALID_FP_OPERAND : RC_INVALID_COMPARISON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (*aux++) {
|
||||
case '=':
|
||||
self->oper = RC_CONDITION_EQ;
|
||||
self->oper = RC_OPERATOR_EQ;
|
||||
aux += *aux == '=';
|
||||
break;
|
||||
|
||||
@ -51,33 +60,45 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->oper = RC_CONDITION_NE;
|
||||
self->oper = RC_OPERATOR_NE;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
self->oper = RC_CONDITION_LT;
|
||||
self->oper = RC_OPERATOR_LT;
|
||||
|
||||
if (*aux == '=') {
|
||||
self->oper = RC_CONDITION_LE;
|
||||
self->oper = RC_OPERATOR_LE;
|
||||
aux++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '>':
|
||||
self->oper = RC_CONDITION_GT;
|
||||
self->oper = RC_OPERATOR_GT;
|
||||
|
||||
if (*aux == '=') {
|
||||
self->oper = RC_CONDITION_GE;
|
||||
self->oper = RC_OPERATOR_GE;
|
||||
aux++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '*':
|
||||
self->oper = RC_OPERATOR_MULT;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
self->oper = RC_OPERATOR_DIV;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
self->oper = RC_OPERATOR_AND;
|
||||
break;
|
||||
|
||||
case '_':
|
||||
case ')':
|
||||
case '\0':
|
||||
self->oper = RC_CONDITION_NONE;
|
||||
self->oper = RC_OPERATOR_NONE;
|
||||
self->operand2.type = RC_OPERAND_CONST;
|
||||
self->operand2.value.num = 1;
|
||||
self->required_hits = 0;
|
||||
@ -85,6 +106,36 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
return self;
|
||||
}
|
||||
|
||||
switch (self->oper) {
|
||||
case RC_OPERATOR_MULT:
|
||||
case RC_OPERATOR_DIV:
|
||||
case RC_OPERATOR_AND:
|
||||
/* modifying operators are only valid on modifying statements */
|
||||
if (!can_modify) {
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* comparison operators are not valid on modifying statements */
|
||||
if (can_modify) {
|
||||
switch (self->type) {
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
/* prevent parse errors on legacy achievements where a condition was present before changing the type */
|
||||
self->oper = RC_OPERATOR_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ret2 = rc_parse_operand(&self->operand2, &aux, 1, is_indirect, parse);
|
||||
|
||||
if (ret2 < 0) {
|
||||
@ -92,6 +143,17 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->oper == RC_OPERATOR_NONE) {
|
||||
/* if operator is none, explicitly clear out the right side */
|
||||
self->operand2.type = RC_INVALID_CONST_OPERAND;
|
||||
self->operand2.value.num = 0;
|
||||
}
|
||||
|
||||
if (!can_modify && self->operand2.type == RC_OPERAND_FP) {
|
||||
parse->offset = RC_INVALID_COMPARISON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*aux == '(') {
|
||||
char* end;
|
||||
self->required_hits = (unsigned)strtoul(++aux, &end, 10);
|
||||
@ -127,13 +189,39 @@ int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state) {
|
||||
unsigned value2 = rc_evaluate_operand(&self->operand2, eval_state);
|
||||
|
||||
switch (self->oper) {
|
||||
case RC_CONDITION_EQ: return value1 == value2;
|
||||
case RC_CONDITION_NE: return value1 != value2;
|
||||
case RC_CONDITION_LT: return value1 < value2;
|
||||
case RC_CONDITION_LE: return value1 <= value2;
|
||||
case RC_CONDITION_GT: return value1 > value2;
|
||||
case RC_CONDITION_GE: return value1 >= value2;
|
||||
case RC_CONDITION_NONE: return 1;
|
||||
case RC_OPERATOR_EQ: return value1 == value2;
|
||||
case RC_OPERATOR_NE: return value1 != value2;
|
||||
case RC_OPERATOR_LT: return value1 < value2;
|
||||
case RC_OPERATOR_LE: return value1 <= value2;
|
||||
case RC_OPERATOR_GT: return value1 > value2;
|
||||
case RC_OPERATOR_GE: return value1 >= value2;
|
||||
case RC_OPERATOR_NONE: return 1;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int rc_evaluate_condition_value(rc_condition_t* self, rc_eval_state_t* eval_state) {
|
||||
unsigned value = rc_evaluate_operand(&self->operand1, eval_state);
|
||||
|
||||
switch (self->oper) {
|
||||
case RC_OPERATOR_MULT:
|
||||
if (self->operand2.type == RC_OPERAND_FP)
|
||||
value = (int)((double)value * self->operand2.value.dbl);
|
||||
else
|
||||
value *= rc_evaluate_operand(&self->operand2, eval_state);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_DIV:
|
||||
if (self->operand2.type == RC_OPERAND_FP)
|
||||
value = (int)((double)value / self->operand2.value.dbl);
|
||||
else
|
||||
value /= rc_evaluate_operand(&self->operand2, eval_state);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_AND:
|
||||
value &= rc_evaluate_operand(&self->operand2, eval_state);
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
183
deps/rcheevos/src/rcheevos/condset.c
vendored
183
deps/rcheevos/src/rcheevos/condset.c
vendored
@ -9,15 +9,16 @@ static void rc_update_condition_pause(rc_condition_t* condition, int* in_pause)
|
||||
case RC_CONDITION_PAUSE_IF:
|
||||
*in_pause = condition->pause = 1;
|
||||
break;
|
||||
|
||||
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
case RC_CONDITION_OR_NEXT:
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
condition->pause = *in_pause;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
*in_pause = condition->pause = 0;
|
||||
break;
|
||||
@ -48,14 +49,15 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*next)->oper == RC_CONDITION_NONE) {
|
||||
if ((*next)->oper == RC_OPERATOR_NONE) {
|
||||
switch ((*next)->type) {
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
break;
|
||||
case RC_CONDITION_OR_NEXT:
|
||||
break;
|
||||
|
||||
default:
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
@ -110,10 +112,14 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
|
||||
static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc_eval_state_t* eval_state) {
|
||||
rc_condition_t* condition;
|
||||
int set_valid, cond_valid, prev_cond;
|
||||
int set_valid, cond_valid, and_next, or_next;
|
||||
unsigned measured_value = 0;
|
||||
int can_measure = 1, measured_from_hits = 0;
|
||||
|
||||
eval_state->primed = 1;
|
||||
set_valid = 1;
|
||||
prev_cond = 1;
|
||||
and_next = 1;
|
||||
or_next = 0;
|
||||
eval_state->add_value = eval_state->add_hits = eval_state->add_address = 0;
|
||||
|
||||
for (condition = self->conditions; condition != 0; condition = condition->next) {
|
||||
@ -121,93 +127,107 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc
|
||||
continue;
|
||||
}
|
||||
|
||||
/* STEP 1: process modifier conditions */
|
||||
switch (condition->type) {
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
eval_state->add_value += rc_evaluate_operand(&condition->operand1, eval_state);
|
||||
eval_state->add_value += rc_evaluate_condition_value(condition, eval_state);
|
||||
eval_state->add_address = 0;
|
||||
continue;
|
||||
|
||||
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
eval_state->add_value -= rc_evaluate_operand(&condition->operand1, eval_state);
|
||||
eval_state->add_address = 0;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
/* always evaluate the condition to ensure everything is updated correctly */
|
||||
cond_valid = rc_test_condition(condition, eval_state);
|
||||
|
||||
/* merge AndNext value and reset it for the next condition */
|
||||
cond_valid &= prev_cond;
|
||||
prev_cond = 1;
|
||||
|
||||
/* if the condition is true, tally it */
|
||||
if (cond_valid) {
|
||||
if (condition->required_hits == 0 || condition->current_hits < condition->required_hits) {
|
||||
condition->current_hits++;
|
||||
}
|
||||
|
||||
condition->is_true = (condition->required_hits == 0 || condition->current_hits >= condition->required_hits);
|
||||
}
|
||||
else {
|
||||
condition->is_true = 0;
|
||||
}
|
||||
|
||||
eval_state->add_value = 0;
|
||||
eval_state->add_address = 0;
|
||||
eval_state->add_hits += condition->current_hits;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
prev_cond &= rc_test_condition(condition, eval_state);
|
||||
eval_state->add_value = 0;
|
||||
eval_state->add_value -= rc_evaluate_condition_value(condition, eval_state);
|
||||
eval_state->add_address = 0;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
eval_state->add_address = rc_evaluate_operand(&condition->operand1, eval_state);
|
||||
eval_state->add_address = rc_evaluate_condition_value(condition, eval_state);
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_MEASURED:
|
||||
if (condition->required_hits == 0) {
|
||||
/* Measured condition without a hit target measures the value of the left operand */
|
||||
measured_value = rc_evaluate_condition_value(condition, eval_state) + eval_state->add_value;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* always evaluate the condition to ensure everything is updated correctly */
|
||||
cond_valid = rc_test_condition(condition, eval_state);
|
||||
/* STEP 2: evaluate the current condition */
|
||||
condition->is_true = rc_test_condition(condition, eval_state);
|
||||
eval_state->add_value = 0;
|
||||
eval_state->add_address = 0;
|
||||
|
||||
/* merge AndNext value and reset it for the next condition */
|
||||
cond_valid &= prev_cond;
|
||||
prev_cond = 1;
|
||||
/* apply logic flags and reset them for the next condition */
|
||||
cond_valid = condition->is_true;
|
||||
cond_valid &= and_next;
|
||||
cond_valid |= or_next;
|
||||
and_next = 1;
|
||||
or_next = 0;
|
||||
|
||||
/* if the condition has a target hit count that has already been met, it's automatically true, even if not currently true. */
|
||||
if (condition->required_hits != 0 && (condition->current_hits + eval_state->add_hits) >= condition->required_hits) {
|
||||
cond_valid = 1;
|
||||
}
|
||||
else if (cond_valid) {
|
||||
condition->current_hits++;
|
||||
/* true conditions should update hit count */
|
||||
if (cond_valid) {
|
||||
eval_state->has_hits = 1;
|
||||
|
||||
if (condition->required_hits == 0) {
|
||||
/* not a hit-based requirement: ignore any additional logic! */
|
||||
/* no target hit count, just keep tallying */
|
||||
++condition->current_hits;
|
||||
}
|
||||
else if ((condition->current_hits + eval_state->add_hits) < condition->required_hits) {
|
||||
/* HitCount target has not yet been met, condition is not yet valid */
|
||||
cond_valid = 0;
|
||||
else if (condition->current_hits < condition->required_hits) {
|
||||
/* target hit count hasn't been met, tally and revalidate - only true if hit count becomes met */
|
||||
++condition->current_hits;
|
||||
cond_valid = (condition->current_hits == condition->required_hits);
|
||||
}
|
||||
else {
|
||||
/* target hit count has been met, do nothing */
|
||||
}
|
||||
}
|
||||
condition->is_true = cond_valid;
|
||||
eval_state->has_hits |= (condition->current_hits || eval_state->add_hits);
|
||||
else if (condition->current_hits > 0) {
|
||||
/* target has been true in the past, if the hit target is met, consider it true now */
|
||||
eval_state->has_hits = 1;
|
||||
cond_valid = (condition->current_hits == condition->required_hits);
|
||||
}
|
||||
|
||||
/* capture measured state */
|
||||
if (condition->type == RC_CONDITION_MEASURED) {
|
||||
unsigned int measured_value;
|
||||
if (condition->required_hits > 0)
|
||||
/* STEP 3: handle logic flags */
|
||||
switch (condition->type) {
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
eval_state->add_hits += condition->current_hits;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
and_next = cond_valid;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_OR_NEXT:
|
||||
or_next = cond_valid;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (eval_state->add_hits) {
|
||||
if (condition->required_hits != 0) {
|
||||
/* if the condition has a target hit count, we have to recalculate cond_valid including the AddHits counter */
|
||||
measured_from_hits = 1;
|
||||
measured_value = condition->current_hits + eval_state->add_hits;
|
||||
else
|
||||
measured_value = rc_evaluate_operand(&condition->operand1, eval_state) + eval_state->add_value;
|
||||
cond_valid = (measured_value >= condition->required_hits);
|
||||
}
|
||||
else {
|
||||
/* no target hit count. we can't tell if the add_hits value is from this frame or not, so ignore it.
|
||||
complex condition will only be true if the current condition is true */
|
||||
}
|
||||
|
||||
if (measured_value > eval_state->measured_value)
|
||||
eval_state->measured_value = measured_value;
|
||||
eval_state->add_hits = 0;
|
||||
}
|
||||
else if (condition->required_hits != 0) {
|
||||
/* if there's a hit target, capture the current hits for recording Measured value later */
|
||||
measured_from_hits = 1;
|
||||
measured_value = condition->current_hits;
|
||||
}
|
||||
|
||||
/* reset AddHits and AddSource/SubSource values */
|
||||
eval_state->add_value = eval_state->add_hits = eval_state->add_address = 0;
|
||||
|
||||
/* STEP 4: handle special flags */
|
||||
switch (condition->type) {
|
||||
case RC_CONDITION_PAUSE_IF:
|
||||
/* as soon as we find a PauseIf that evaluates to true, stop processing the rest of the group */
|
||||
@ -227,20 +247,38 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc
|
||||
/* PauseIf has a HitCount that hasn't been met, ignore it for now. */
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_RESET_IF:
|
||||
if (cond_valid) {
|
||||
eval_state->was_reset = 1; /* let caller know to reset all hit counts */
|
||||
set_valid = 0; /* cannot be valid if we've hit a reset condition */
|
||||
}
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_MEASURED_IF:
|
||||
if (!cond_valid)
|
||||
can_measure = 0;
|
||||
break;
|
||||
|
||||
case RC_CONDITION_TRIGGER:
|
||||
/* update truthiness of set, but do not update truthiness of primed state */
|
||||
set_valid &= cond_valid;
|
||||
continue;
|
||||
|
||||
default:
|
||||
set_valid &= cond_valid;
|
||||
break;
|
||||
}
|
||||
|
||||
/* STEP 5: update overall truthiness of set and primed state */
|
||||
eval_state->primed &= cond_valid;
|
||||
set_valid &= cond_valid;
|
||||
}
|
||||
|
||||
/* if not suppressed, update the measured value */
|
||||
if (measured_value > eval_state->measured_value && can_measure) {
|
||||
eval_state->measured_value = measured_value;
|
||||
eval_state->measured_from_hits = measured_from_hits;
|
||||
}
|
||||
|
||||
return set_valid;
|
||||
@ -255,6 +293,7 @@ int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state) {
|
||||
if (self->has_pause) {
|
||||
if ((self->is_paused = rc_test_condset_internal(self, 1, eval_state))) {
|
||||
/* one or more Pause conditions exists, if any of them are true, stop processing this group */
|
||||
eval_state->primed = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
590
deps/rcheevos/src/rcheevos/consoleinfo.c
vendored
Normal file
590
deps/rcheevos/src/rcheevos/consoleinfo.c
vendored
Normal file
@ -0,0 +1,590 @@
|
||||
#include "rcheevos.h"
|
||||
#include "rconsoles.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
const char* rc_console_name(int console_id)
|
||||
{
|
||||
switch (console_id)
|
||||
{
|
||||
case RC_CONSOLE_3DO:
|
||||
return "3DO";
|
||||
|
||||
case RC_CONSOLE_AMIGA:
|
||||
return "Amiga";
|
||||
|
||||
case RC_CONSOLE_AMIGA_ST:
|
||||
return "Amiga ST";
|
||||
|
||||
case RC_CONSOLE_AMSTRAD_PC:
|
||||
return "Amstrad CPC";
|
||||
|
||||
case RC_CONSOLE_APPLE_II:
|
||||
return "Apple II";
|
||||
|
||||
case RC_CONSOLE_ARCADE:
|
||||
return "Arcade";
|
||||
|
||||
case RC_CONSOLE_ATARI_2600:
|
||||
return "Atari 2600";
|
||||
|
||||
case RC_CONSOLE_ATARI_5200:
|
||||
return "Atari 5200";
|
||||
|
||||
case RC_CONSOLE_ATARI_7800:
|
||||
return "Atari 7800";
|
||||
|
||||
case RC_CONSOLE_ATARI_JAGUAR:
|
||||
return "Atari Jaguar";
|
||||
|
||||
case RC_CONSOLE_ATARI_LYNX:
|
||||
return "Atari Lynx";
|
||||
|
||||
case RC_CONSOLE_CASSETTEVISION:
|
||||
return "CassetteVision";
|
||||
|
||||
case RC_CONSOLE_CDI:
|
||||
return "CD-I";
|
||||
|
||||
case RC_CONSOLE_COLECOVISION:
|
||||
return "ColecoVision";
|
||||
|
||||
case RC_CONSOLE_COMMODORE_64:
|
||||
return "Commodore 64";
|
||||
|
||||
case RC_CONSOLE_DREAMCAST:
|
||||
return "Dreamcast";
|
||||
|
||||
case RC_CONSOLE_EVENTS:
|
||||
return "Events";
|
||||
|
||||
case RC_CONSOLE_GAMEBOY:
|
||||
return "GameBoy";
|
||||
|
||||
case RC_CONSOLE_GAMEBOY_ADVANCE:
|
||||
return "GameBoy Advance";
|
||||
|
||||
case RC_CONSOLE_GAMEBOY_COLOR:
|
||||
return "GameBoy Color";
|
||||
|
||||
case RC_CONSOLE_GAMECUBE:
|
||||
return "GameCube";
|
||||
|
||||
case RC_CONSOLE_GAME_GEAR:
|
||||
return "Game Gear";
|
||||
|
||||
case RC_CONSOLE_HUBS:
|
||||
return "Hubs";
|
||||
|
||||
case RC_CONSOLE_INTELLIVISION:
|
||||
return "Intellivision";
|
||||
|
||||
case RC_CONSOLE_MASTER_SYSTEM:
|
||||
return "Master System";
|
||||
|
||||
case RC_CONSOLE_MEGA_DRIVE:
|
||||
return "Sega Genesis";
|
||||
|
||||
case RC_CONSOLE_MS_DOS:
|
||||
return "MS-DOS";
|
||||
|
||||
case RC_CONSOLE_MSX:
|
||||
return "MSX";
|
||||
|
||||
case RC_CONSOLE_NINTENDO:
|
||||
return "Nintendo Entertainment System";
|
||||
|
||||
case RC_CONSOLE_NINTENDO_64:
|
||||
return "Nintendo 64";
|
||||
|
||||
case RC_CONSOLE_NINTENDO_DS:
|
||||
return "Nintendo DS";
|
||||
|
||||
case RC_CONSOLE_NEOGEO_POCKET:
|
||||
return "Neo Geo Pocket";
|
||||
|
||||
case RC_CONSOLE_ORIC:
|
||||
return "Oric";
|
||||
|
||||
case RC_CONSOLE_PC8800:
|
||||
return "PC-8000/8800";
|
||||
|
||||
case RC_CONSOLE_PC9800:
|
||||
return "PC-9800";
|
||||
|
||||
case RC_CONSOLE_PCFX:
|
||||
return "PCFX";
|
||||
|
||||
case RC_CONSOLE_PC_ENGINE:
|
||||
return "PCEngine";
|
||||
|
||||
case RC_CONSOLE_PLAYSTATION:
|
||||
return "PlayStation";
|
||||
|
||||
case RC_CONSOLE_PLAYSTATION_2:
|
||||
return "PlayStation 2";
|
||||
|
||||
case RC_CONSOLE_PSP:
|
||||
return "PlayStation Portable";
|
||||
|
||||
case RC_CONSOLE_POKEMON_MINI:
|
||||
return "Pokemon Mini";
|
||||
|
||||
case RC_CONSOLE_SEGA_32X:
|
||||
return "Sega 32X";
|
||||
|
||||
case RC_CONSOLE_SEGA_CD:
|
||||
return "Sega CD";
|
||||
|
||||
case RC_CONSOLE_SATURN:
|
||||
return "Sega Saturn";
|
||||
|
||||
case RC_CONSOLE_SG1000:
|
||||
return "SG-1000";
|
||||
|
||||
case RC_CONSOLE_SUPER_NINTENDO:
|
||||
return "Super Nintendo Entertainment System";
|
||||
|
||||
case RC_CONSOLE_SUPER_CASSETTEVISION:
|
||||
return "Super CassetteVision";
|
||||
|
||||
case RC_CONSOLE_WONDERSWAN:
|
||||
return "WonderSwan";
|
||||
|
||||
case RC_CONSOLE_VECTREX:
|
||||
return "Vectrex";
|
||||
|
||||
case RC_CONSOLE_VIC20:
|
||||
return "VIC-20";
|
||||
|
||||
case RC_CONSOLE_VIRTUAL_BOY:
|
||||
return "Virtual Boy";
|
||||
|
||||
case RC_CONSOLE_WII:
|
||||
return "Wii";
|
||||
|
||||
case RC_CONSOLE_WII_U:
|
||||
return "Wii-U";
|
||||
|
||||
case RC_CONSOLE_X68K:
|
||||
return "X68K";
|
||||
|
||||
case RC_CONSOLE_XBOX:
|
||||
return "XBOX";
|
||||
|
||||
case RC_CONSOLE_ZX81:
|
||||
return "ZX-81";
|
||||
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 3DO ===== */
|
||||
/* http://www.arcaderestoration.com/memorymap/48/3DO+Bios.aspx */
|
||||
/* NOTE: the Opera core attempts to expose the NVRAM as RETRO_SAVE_RAM, but the 3DO documentation
|
||||
* says that applications should only access NVRAM through API calls as it's shared across mulitple
|
||||
* games. This suggests that even if the core does expose it, it may change depending on which other
|
||||
* games the user has played - so ignore it.
|
||||
*/
|
||||
static const rc_memory_region_t _rc_memory_regions_3do[] = {
|
||||
{ 0x000000U, 0x1FFFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" },
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_3do = { _rc_memory_regions_3do, 1 };
|
||||
|
||||
/* ===== Apple II ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_appleii[] = {
|
||||
{ 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" },
|
||||
{ 0x010000U, 0x01FFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Auxillary RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_appleii = { _rc_memory_regions_appleii, 2 };
|
||||
|
||||
/* ===== Atari 2600 ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_atari2600[] = {
|
||||
{ 0x000000U, 0x00007FU, 0x000080U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_atari2600 = { _rc_memory_regions_atari2600, 1 };
|
||||
|
||||
/* ===== Atari 7800 ===== */
|
||||
/* http://www.atarihq.com/danb/files/78map.txt */
|
||||
/* http://pdf.textfiles.com/technical/7800_devkit.pdf */
|
||||
static const rc_memory_region_t _rc_memory_regions_atari7800[] = {
|
||||
{ 0x000000U, 0x0017FFU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware Interface" },
|
||||
{ 0x001800U, 0x0027FFU, 0x001800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x002800U, 0x002FFFU, 0x002800U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored RAM" },
|
||||
{ 0x003000U, 0x0037FFU, 0x003000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored RAM" },
|
||||
{ 0x003800U, 0x003FFFU, 0x003800U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored RAM" },
|
||||
{ 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" },
|
||||
{ 0x008000U, 0x00FFFFU, 0x008000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_atari7800 = { _rc_memory_regions_atari7800, 7 };
|
||||
|
||||
/* ===== Atari Jaguar ===== */
|
||||
/* https://www.mulle-kybernetik.com/jagdox/memorymap.html */
|
||||
static const rc_memory_region_t _rc_memory_regions_atari_jaguar[] = {
|
||||
{ 0x000000U, 0x1FFFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_atari_jaguar = { _rc_memory_regions_atari_jaguar, 1 };
|
||||
|
||||
/* ===== Atari Lynx ===== */
|
||||
/* http://www.retroisle.com/atari/lynx/Technical/Programming/lynxprgdumm.php */
|
||||
static const rc_memory_region_t _rc_memory_regions_atari_lynx[] = {
|
||||
{ 0x000000U, 0x0000FFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Zero Page" },
|
||||
{ 0x000100U, 0x0001FFU, 0x000100U, RC_MEMORY_TYPE_SYSTEM_RAM, "Stack" },
|
||||
{ 0x000200U, 0x00FBFFU, 0x000200U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x00FC00U, 0x00FCFFU, 0x00FC00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "SUZY hardware access" },
|
||||
{ 0x00FD00U, 0x00FDFFU, 0x00FD00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "MIKEY hardware access" },
|
||||
{ 0x00FE00U, 0x00FFF7U, 0x00FE00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Boot ROM" },
|
||||
{ 0x00FFF8U, 0x00FFFFU, 0x00FFF8U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware vectors" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_atari_lynx = { _rc_memory_regions_atari_lynx, 7 };
|
||||
|
||||
/* ===== ColecoVision ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_colecovision[] = {
|
||||
{ 0x000000U, 0x0003FFU, 0x006000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_colecovision = { _rc_memory_regions_colecovision, 1 };
|
||||
|
||||
/* ===== GameBoy / GameBoy Color ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_gameboy[] = {
|
||||
{ 0x000000U, 0x0000FFU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt vector" },
|
||||
{ 0x000100U, 0x00014FU, 0x000100U, RC_MEMORY_TYPE_READONLY, "Cartridge header" },
|
||||
{ 0x000150U, 0x003FFFU, 0x000150U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM (fixed)" }, /* bank 0 */
|
||||
{ 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM (paged)" }, /* bank 1-XX (switchable) */
|
||||
{ 0x008000U, 0x0097FFU, 0x008000U, RC_MEMORY_TYPE_VIDEO_RAM, "Tile RAM" },
|
||||
{ 0x009800U, 0x009BFFU, 0x009800U, RC_MEMORY_TYPE_VIDEO_RAM, "BG1 map data" },
|
||||
{ 0x009C00U, 0x009FFFU, 0x009C00U, RC_MEMORY_TYPE_VIDEO_RAM, "BG2 map data" },
|
||||
{ 0x00A000U, 0x00BFFFU, 0x00A000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM"},
|
||||
{ 0x00C000U, 0x00CFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (fixed)" },
|
||||
{ 0x00D000U, 0x00DFFFU, 0x00D000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (bank 1)" },
|
||||
{ 0x00E000U, 0x00FDFFU, 0x00C000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Echo RAM" },
|
||||
{ 0x00FE00U, 0x00FE9FU, 0x00FE00U, RC_MEMORY_TYPE_VIDEO_RAM, "Sprite RAM"},
|
||||
{ 0x00FEA0U, 0x00FEFFU, 0x00FEA0U, RC_MEMORY_TYPE_READONLY, "Unusable"},
|
||||
{ 0x00FF00U, 0x00FF7FU, 0x00FF00U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Hardware I/O"},
|
||||
{ 0x00FF80U, 0x00FFFEU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "Quick RAM"},
|
||||
{ 0x00FFFFU, 0x00FFFFU, 0x00FFFFU, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt enable"},
|
||||
|
||||
/* GameBoy Color provides six extra banks of memory that can be paged out through the $DXXX
|
||||
* memory space, but the timing of that does not correspond with blanks, which is when achievements
|
||||
* are processed. As such, it is desirable to always have access to these extra banks. We do this
|
||||
* by expecting the extra banks to be addressable at addresses not supported by the native system. */
|
||||
{ 0x010000U, 0x015FFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM (banks 2-7, GBC only)" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_gameboy = { _rc_memory_regions_gameboy, 16 };
|
||||
static const rc_memory_regions_t rc_memory_regions_gameboy_color = { _rc_memory_regions_gameboy, 17 };
|
||||
|
||||
/* ===== GameBoy Advance ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_gameboy_advance[] = {
|
||||
{ 0x000000U, 0x007FFFU, 0x03000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" },
|
||||
{ 0x008000U, 0x047FFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_gameboy_advance = { _rc_memory_regions_gameboy_advance, 2 };
|
||||
|
||||
/* ===== Game Gear ===== */
|
||||
/* http://www.smspower.org/Development/MemoryMap */
|
||||
static const rc_memory_region_t _rc_memory_regions_game_gear[] = {
|
||||
{ 0x000000U, 0x001FFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_game_gear = { _rc_memory_regions_game_gear, 1 };
|
||||
|
||||
/* ===== Intellivision ===== */
|
||||
/* http://wiki.intellivision.us/index.php%3Ftitle%3DMemory_Map */
|
||||
static const rc_memory_region_t _rc_memory_regions_intellivision[] = {
|
||||
{ 0x000000U, 0x00007FU, 0x000000U, RC_MEMORY_TYPE_VIDEO_RAM, "STIC Registers" },
|
||||
{ 0x000080U, 0x0000FFU, 0x000080U, RC_MEMORY_TYPE_UNUSED, "" },
|
||||
{ 0x000100U, 0x00035FU, 0x000100U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x000360U, 0x0003FFU, 0x000360U, RC_MEMORY_TYPE_UNUSED, "" },
|
||||
{ 0x000400U, 0x000FFFU, 0x000400U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
|
||||
{ 0x001000U, 0x001FFFU, 0x001000U, RC_MEMORY_TYPE_UNUSED, "" },
|
||||
{ 0x002000U, 0x002FFFU, 0x002000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
|
||||
{ 0x003000U, 0x003FFFU, 0x003000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" },
|
||||
{ 0x004000U, 0x00FFFFU, 0x004000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_intellivision = { _rc_memory_regions_intellivision, 9 };
|
||||
|
||||
/* ===== Master System ===== */
|
||||
/* http://www.smspower.org/Development/MemoryMap */
|
||||
static const rc_memory_region_t _rc_memory_regions_master_system[] = {
|
||||
{ 0x000000U, 0x001FFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_master_system = { _rc_memory_regions_master_system, 1 };
|
||||
|
||||
/* ===== MegaDrive (Genesis) ===== */
|
||||
/* http://www.smspower.org/Development/MemoryMap */
|
||||
static const rc_memory_region_t _rc_memory_regions_megadrive[] = {
|
||||
{ 0x000000U, 0x00FFFFU, 0xFF0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x010000U, 0x01FFFFU, 0x000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_megadrive = { _rc_memory_regions_megadrive, 2 };
|
||||
|
||||
/* ===== MSX ===== */
|
||||
/* https://www.msx.org/wiki/The_Memory */
|
||||
/* MSX only has 64KB of addressable RAM, of which 32KB is reserved for the system/BIOS.
|
||||
* However, the system has up to 512KB of RAM, which is paged into the addressable RAM
|
||||
* We expect the raw RAM to be exposed, rather than force the devs to worry about the
|
||||
* paging system. The entire RAM is expected to appear starting at $10000, which is not
|
||||
* addressable by the system itself.
|
||||
*/
|
||||
static const rc_memory_region_t _rc_memory_regions_msx[] = {
|
||||
{ 0x000000U, 0x07FFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_msx = { _rc_memory_regions_msx, 1 };
|
||||
|
||||
/* ===== Neo Geo Pocket ===== */
|
||||
/* http://neopocott.emuunlim.com/docs/tech-11.txt */
|
||||
static const rc_memory_region_t _rc_memory_regions_neo_geo_pocket[] = {
|
||||
/* MednafenNGP exposes 16KB, but the doc suggests there's 24-32KB */
|
||||
{ 0x000000U, 0x003FFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_neo_geo_pocket = { _rc_memory_regions_neo_geo_pocket, 1 };
|
||||
|
||||
/* ===== Nintendo Entertainment System ===== */
|
||||
/* https://wiki.nesdev.com/w/index.php/CPU_memory_map */
|
||||
static const rc_memory_region_t _rc_memory_regions_nes[] = {
|
||||
{ 0x0000U, 0x07FFU, 0x0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x0800U, 0x0FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */
|
||||
{ 0x1000U, 0x17FFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */
|
||||
{ 0x1800U, 0x1FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */
|
||||
{ 0x2000U, 0x2007U, 0x2000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "PPU Register" },
|
||||
{ 0x2008U, 0x3FFFU, 0x2008U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored PPU Register" }, /* repeats every 8 bytes */
|
||||
{ 0x4000U, 0x4017U, 0x4000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O register" },
|
||||
{ 0x4018U, 0x401FU, 0x4018U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O test register" },
|
||||
{ 0x4020U, 0x5FFFU, 0x4020U, RC_MEMORY_TYPE_READONLY, "Cartridge data"}, /* varies by mapper */
|
||||
{ 0x6000U, 0x7FFFU, 0x6000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM"},
|
||||
{ 0x8000U, 0xFFFFU, 0x8000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM"},
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_nes = { _rc_memory_regions_nes, 11 };
|
||||
|
||||
/* ===== Nintendo 64 ===== */
|
||||
/* https://raw.githubusercontent.com/mikeryan/n64dev/master/docs/n64ops/n64ops%23h.txt */
|
||||
static const rc_memory_region_t _rc_memory_regions_n64[] = {
|
||||
{ 0x000000U, 0x1FFFFFU, 0x00000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RDRAM 1 */
|
||||
{ 0x200000U, 0x3FFFFFU, 0x00020000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RDRAM 2 */
|
||||
{ 0x400000U, 0x7FFFFFU, 0x80000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" } /* expansion pak - cannot find any details for real address */
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_n64 = { _rc_memory_regions_n64, 3 };
|
||||
|
||||
/* ===== Nintendo DS ===== */
|
||||
/* https://www.akkit.org/info/gbatek.htm#dsmemorymaps */
|
||||
static const rc_memory_region_t _rc_memory_regions_nintendo_ds[] = {
|
||||
{ 0x000000U, 0x3FFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_nintendo_ds = { _rc_memory_regions_nintendo_ds, 1 };
|
||||
|
||||
/* ===== Oric ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_oric[] = {
|
||||
/* actual size depends on machine type - up to 64KB */
|
||||
{ 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_oric = { _rc_memory_regions_oric, 1 };
|
||||
|
||||
/* ===== PC-8800 ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_pc8800[] = {
|
||||
{ 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Main RAM" },
|
||||
{ 0x010000U, 0x010FFFU, 0x010000U, RC_MEMORY_TYPE_VIDEO_RAM, "Text VRAM" } /* technically VRAM, but often used as system RAM */
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_pc8800 = { _rc_memory_regions_pc8800, 2 };
|
||||
|
||||
/* ===== PC Engine ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_pcengine[] = {
|
||||
{ 0x000000U, 0x001FFFU, 0x1F0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x002000U, 0x011FFFU, 0x100000U, RC_MEMORY_TYPE_SYSTEM_RAM, "CD RAM" },
|
||||
{ 0x012000U, 0x041FFFU, 0x0D0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Super System Card RAM" },
|
||||
{ 0x042000U, 0x0427FFU, 0x1EE000U, RC_MEMORY_TYPE_SAVE_RAM, "CD Battery-backed RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_pcengine = { _rc_memory_regions_pcengine, 4 };
|
||||
|
||||
/* ===== PlayStation ===== */
|
||||
/* http://www.raphnet.net/electronique/psx_adaptor/Playstation.txt */
|
||||
static const rc_memory_region_t _rc_memory_regions_playstation[] = {
|
||||
{ 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" },
|
||||
{ 0x010000U, 0x1FFFFFU, 0x010000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_playstation = { _rc_memory_regions_playstation, 2 };
|
||||
|
||||
/* ===== Pokemon Mini ===== */
|
||||
/* https://www.pokemon-mini.net/documentation/memory-map/ */
|
||||
static const rc_memory_region_t _rc_memory_regions_pokemini[] = {
|
||||
{ 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "BIOS RAM" },
|
||||
{ 0x001000U, 0x001FFFU, 0x001000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_pokemini = { _rc_memory_regions_pokemini, 2 };
|
||||
|
||||
/* ===== Sega CD ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_segacd[] = {
|
||||
{ 0x000000U, 0x00FFFFU, 0x00FF0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "68000 RAM" },
|
||||
{ 0x010000U, 0x08FFFFU, 0x80020000U, RC_MEMORY_TYPE_SAVE_RAM, "CD PRG RAM" } /* normally banked into $020000-$03FFFF */
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_segacd = { _rc_memory_regions_segacd, 2 };
|
||||
|
||||
/* ===== Sega Saturn ===== */
|
||||
/* https://segaretro.org/Sega_Saturn_hardware_notes_(2004-04-27) */
|
||||
static const rc_memory_region_t _rc_memory_regions_saturn[] = {
|
||||
{ 0x000000U, 0x0FFFFFU, 0x00200000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Work RAM Low" },
|
||||
{ 0x100000U, 0x1FFFFFU, 0x06000000U, RC_MEMORY_TYPE_SAVE_RAM, "Work RAM High" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_saturn = { _rc_memory_regions_saturn, 2 };
|
||||
|
||||
/* ===== SG-1000 ===== */
|
||||
/* http://www.smspower.org/Development/MemoryMap */
|
||||
static const rc_memory_region_t _rc_memory_regions_sg1000[] = {
|
||||
{ 0x000000U, 0x0003FFU, 0xC000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
/* TODO: should cartridge memory be exposed ($0000-$BFFF)? it's usually just ROM data, but may contain on-cartridge RAM
|
||||
* This not is also concerning: http://www.smspower.org/Development/MemoryMap
|
||||
* Cartridges may disable the system RAM and thus take over the full 64KB address space. */
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_sg1000 = { _rc_memory_regions_sg1000, 1 };
|
||||
|
||||
/* ===== Super Cassette Vision ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_scv[] = {
|
||||
{ 0x000000U, 0x000FFFU, 0x000000U, RC_MEMORY_TYPE_READONLY, "System ROM" },
|
||||
{ 0x001000U, 0x001FFFU, 0x001000U, RC_MEMORY_TYPE_UNUSED, "" },
|
||||
{ 0x002000U, 0x003FFFU, 0x002000U, RC_MEMORY_TYPE_VIDEO_RAM, "Video RAM" },
|
||||
{ 0x004000U, 0x007FFFU, 0x004000U, RC_MEMORY_TYPE_UNUSED, "" },
|
||||
{ 0x008000U, 0x00DFFFU, 0x008000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM" },
|
||||
{ 0x00E000U, 0x00FF7FU, 0x00E000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" },
|
||||
{ 0x00FF80U, 0x00FFFFU, 0x00FF80U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_scv = { _rc_memory_regions_scv, 7 };
|
||||
|
||||
/* ===== Super Nintendo ===== */
|
||||
/* https://segaretro.org/Sega_Saturn_hardware_notes_(2004-04-27) */
|
||||
static const rc_memory_region_t _rc_memory_regions_snes[] = {
|
||||
{ 0x000000U, 0x01FFFFU, 0x7E0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x020000U, 0x03FFFFU, 0xFE0000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_snes = { _rc_memory_regions_snes, 2 };
|
||||
|
||||
/* ===== WonderSwan ===== */
|
||||
/* http://daifukkat.su/docs/wsman/#ovr_memmap */
|
||||
static const rc_memory_region_t _rc_memory_regions_wonderswan[] = {
|
||||
/* RAM ends at 0x3FFF for WonderSwan, WonderSwan color uses all 64KB */
|
||||
{ 0x000000U, 0x00FFFFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x010000U, 0x01FFFFU, 0x000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_wonderswan = { _rc_memory_regions_wonderswan, 2 };
|
||||
|
||||
/* ===== Vectrex ===== */
|
||||
/* https://roadsidethoughts.com/vectrex/vectrex-memory-map.htm */
|
||||
static const rc_memory_region_t _rc_memory_regions_vectrex[] = {
|
||||
{ 0x000000U, 0x0003FFU, 0x00C800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_vectrex = { _rc_memory_regions_vectrex, 1 };
|
||||
|
||||
/* ===== Virtual Boy ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_virtualboy[] = {
|
||||
{ 0x000000U, 0x00FFFFU, 0x05000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x010000U, 0x01FFFFU, 0x06000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_virtualboy = { _rc_memory_regions_virtualboy, 2 };
|
||||
|
||||
/* ===== default ===== */
|
||||
static const rc_memory_regions_t rc_memory_regions_none = { 0, 0 };
|
||||
|
||||
const rc_memory_regions_t* rc_console_memory_regions(int console_id)
|
||||
{
|
||||
switch (console_id)
|
||||
{
|
||||
case RC_CONSOLE_3DO:
|
||||
return &rc_memory_regions_3do;
|
||||
|
||||
case RC_CONSOLE_APPLE_II:
|
||||
return &rc_memory_regions_appleii;
|
||||
|
||||
case RC_CONSOLE_ATARI_2600:
|
||||
return &rc_memory_regions_atari2600;
|
||||
|
||||
case RC_CONSOLE_ATARI_7800:
|
||||
return &rc_memory_regions_atari7800;
|
||||
|
||||
case RC_CONSOLE_ATARI_JAGUAR:
|
||||
return &rc_memory_regions_atari_jaguar;
|
||||
|
||||
case RC_CONSOLE_ATARI_LYNX:
|
||||
return &rc_memory_regions_atari_lynx;
|
||||
|
||||
case RC_CONSOLE_COLECOVISION:
|
||||
return &rc_memory_regions_colecovision;
|
||||
|
||||
case RC_CONSOLE_GAMEBOY:
|
||||
return &rc_memory_regions_gameboy;
|
||||
|
||||
case RC_CONSOLE_GAMEBOY_COLOR:
|
||||
return &rc_memory_regions_gameboy_color;
|
||||
|
||||
case RC_CONSOLE_GAMEBOY_ADVANCE:
|
||||
return &rc_memory_regions_gameboy_advance;
|
||||
|
||||
case RC_CONSOLE_GAME_GEAR:
|
||||
return &rc_memory_regions_game_gear;
|
||||
|
||||
case RC_CONSOLE_INTELLIVISION:
|
||||
return &rc_memory_regions_intellivision;
|
||||
|
||||
case RC_CONSOLE_MASTER_SYSTEM:
|
||||
return &rc_memory_regions_master_system;
|
||||
|
||||
case RC_CONSOLE_MEGA_DRIVE:
|
||||
case RC_CONSOLE_SEGA_32X:
|
||||
/* NOTE: 32x adds an extra 512KB of memory (256KB RAM + 256KB VRAM) to the
|
||||
* Genesis, but we currently don't support it. */
|
||||
return &rc_memory_regions_megadrive;
|
||||
|
||||
case RC_CONSOLE_MSX:
|
||||
return &rc_memory_regions_msx;
|
||||
|
||||
case RC_CONSOLE_NEOGEO_POCKET:
|
||||
return &rc_memory_regions_neo_geo_pocket;
|
||||
|
||||
case RC_CONSOLE_NINTENDO:
|
||||
return &rc_memory_regions_nes;
|
||||
|
||||
case RC_CONSOLE_NINTENDO_64:
|
||||
return &rc_memory_regions_n64;
|
||||
|
||||
case RC_CONSOLE_NINTENDO_DS:
|
||||
return &rc_memory_regions_nintendo_ds;
|
||||
|
||||
case RC_CONSOLE_ORIC:
|
||||
return &rc_memory_regions_oric;
|
||||
|
||||
case RC_CONSOLE_PC8800:
|
||||
return &rc_memory_regions_pc8800;
|
||||
|
||||
case RC_CONSOLE_PC_ENGINE:
|
||||
return &rc_memory_regions_pcengine;
|
||||
|
||||
case RC_CONSOLE_PLAYSTATION:
|
||||
return &rc_memory_regions_playstation;
|
||||
|
||||
case RC_CONSOLE_POKEMON_MINI:
|
||||
return &rc_memory_regions_pokemini;
|
||||
|
||||
case RC_CONSOLE_SATURN:
|
||||
return &rc_memory_regions_saturn;
|
||||
|
||||
case RC_CONSOLE_SEGA_CD:
|
||||
return &rc_memory_regions_segacd;
|
||||
|
||||
case RC_CONSOLE_SG1000:
|
||||
return &rc_memory_regions_sg1000;
|
||||
|
||||
case RC_CONSOLE_SUPER_CASSETTEVISION:
|
||||
return &rc_memory_regions_scv;
|
||||
|
||||
case RC_CONSOLE_SUPER_NINTENDO:
|
||||
return &rc_memory_regions_snes;
|
||||
|
||||
case RC_CONSOLE_WONDERSWAN:
|
||||
return &rc_memory_regions_wonderswan;
|
||||
|
||||
case RC_CONSOLE_VECTREX:
|
||||
return &rc_memory_regions_vectrex;
|
||||
|
||||
case RC_CONSOLE_VIRTUAL_BOY:
|
||||
return &rc_memory_regions_virtualboy;
|
||||
|
||||
default:
|
||||
return &rc_memory_regions_none;
|
||||
}
|
||||
}
|
41
deps/rcheevos/src/rcheevos/expression.c
vendored
41
deps/rcheevos/src/rcheevos/expression.c
vendored
@ -1,41 +0,0 @@
|
||||
#include "internal.h"
|
||||
|
||||
rc_expression_t* rc_parse_expression(const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_expression_t* self;
|
||||
rc_term_t** next;
|
||||
|
||||
self = RC_ALLOC(rc_expression_t, parse);
|
||||
next = &self->terms;
|
||||
|
||||
for (;;) {
|
||||
*next = rc_parse_term(memaddr, 0, parse);
|
||||
|
||||
if (parse->offset < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
next = &(*next)->next;
|
||||
|
||||
if (**memaddr != '_') {
|
||||
break;
|
||||
}
|
||||
|
||||
(*memaddr)++;
|
||||
}
|
||||
|
||||
*next = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
int rc_evaluate_expression(rc_expression_t* self, rc_eval_state_t* eval_state) {
|
||||
rc_term_t* term;
|
||||
int value;
|
||||
|
||||
value = 0;
|
||||
|
||||
for (term = self->terms; term != 0; term = term->next) {
|
||||
value += rc_evaluate_term(term, eval_state);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
8
deps/rcheevos/src/rcheevos/format.c
vendored
8
deps/rcheevos/src/rcheevos/format.c
vendored
@ -1,5 +1,7 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -11,7 +13,7 @@ int rc_parse_format(const char* format_str) {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'T':
|
||||
if (!strcmp(format_str, "IME")) {
|
||||
return RC_FORMAT_FRAMES;
|
||||
@ -21,7 +23,7 @@ int rc_parse_format(const char* format_str) {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'S':
|
||||
if (!strcmp(format_str, "ECS")) {
|
||||
return RC_FORMAT_SECONDS;
|
||||
@ -34,7 +36,7 @@ int rc_parse_format(const char* format_str) {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'M':
|
||||
if (!strcmp(format_str, "ILLISECS")) {
|
||||
return RC_FORMAT_CENTISECS;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user