Compare commits

...
Author SHA1 Message Date
twinaphex d11ffdbb6b Bump version 2021-09-19 05:19:36 +02:00
Autechre b71d34068b Update CHANGES.md 2021-09-19 05:12:15 +02:00
gblues ae617c0ee6 Update some Wii U development metadata (#13013)
== DETAILS
- add a `WiiU` IntelliSense configuration for vscode
- rewrite the `net_listen.sh` script in python because the
  shell script approach just isn't portable enough and doesn't handle
  things like multiple network adapters gracefully at all.
2021-09-19 01:22:59 +02:00
twinaphex b3d724b7a3 Move code out of retroarch.c 2021-09-18 22:05:03 +02:00
twinaphex eb895f9947 move more code out of retroarch.c 2021-09-18 21:14:15 +02:00
twinaphex 1c546cb7fd move more code out of retroarch.c 2021-09-18 21:03:16 +02:00
twinaphex db3f0a8468 Move code out of retroarch.c - move it into
network/netplay/netplay_frontend.c
2021-09-18 06:15:02 +02:00
twinaphex 7c74e035b0 Small cleanups 2021-09-18 06:15:02 +02:00
Víctor "IlDucci 226f5fb456 Fetch translations from Crowdin 17-Sep-2021 (#13007) 2021-09-17 20:23:02 +02:00
tunip3andTunip3 895676430f make dir stuff more like the normal win32 stuff (#13006)
Co-authored-by: Tunip3 <[email protected]>
2021-09-17 17:41:56 +02:00
jdgleaver 0a5bb29c43 (libnx) Enable video filters (#13004) 2021-09-17 14:27:37 +02:00
jdgleaver bae6f8e097 (vfs_implementation.c) Place 'memmap.h' include behind '#if defined(HAVE_MMAP)' guard (#13003) 2021-09-17 14:25:44 +02:00
Autechre 62a66ff0e5 Prevent crash pointed out by LIJI - primary_joypad can be NULL (#13002) 2021-09-17 05:20:09 +02:00
Michael Burgardt d8db234df0 Concatinate some previously truncated strings for easier translation (#12120) 2021-09-16 19:00:14 +02:00
twinaphex 251bfdb302 Buildfix for prior PR 2021-09-16 01:15:36 +02:00
Tony 5aafe9eb0c Add distinct mouse zero index label for drivers that do not support multimouse (#13000) 2021-09-16 01:08:03 +02:00
Mats 6a59dad08c Add compile option to make unix use cwd as env (#12989)
Setting UNIX_CWD_ENV to 1 when compiling with the unix platform will make
the base path for the env the cwd. This is to be able to match the behavior on
Windows.
2021-09-15 21:48:11 +02:00
tunip3andTunip3 249e24fbe7 fix issues where provided paths could sometimes contain a double slash, this would cause issues as path formatting was disabled (#12999)
Co-authored-by: Tunip3 <[email protected]>
2021-09-15 21:44:58 +02:00
MrHuu 70376abe1b (3DS) Add unique ID's (#12996)
add gearboy
add gearcoleco
add gearsystem
2021-09-15 20:21:12 +02:00
jdgleaver 5b13047623 Add 'Picoscale_256x-320x240' video filter (#12997) 2021-09-15 20:20:56 +02:00
gblues 78858a9474 Fix analog inputs on HID devices (#12991)
== DETAILS

File this one under "I'm not sure how this ever worked."

I mean, it did (in 1.8.8). I'm not sure what changed, but ultimately what I did was
a bunch of comparative testing against 1.8.8:

- I confirmed the packet data was still being read successfully
- I confirmed that the axis value being passed into pad->get_axis() had
  not changed
- I confirmed the work done in `gamepad_read_axis_data()` was working the same
  between 1.8.8 and master

With the only difference between 1.8.8 and current being the return value from
`gamepad_read_axis_data()`, I just rewrote the method to work properly, and
also fixed up the default axis mapping.

I tested this with a sixaxis controller and GCA, configuring the analog-to-digital
control override to use the right stick.
2021-09-15 03:30:05 +02:00
MajorPainTheCactus 0e9f246b30 Fixed d3d9 mvp matrix issue (#12984) 2021-09-15 01:17:56 +02:00
jdgleaver 516dcb34d9 (Audio Mixer) Pad sample buffers to prevent potential heap-buffer-overflows when resampling (fixes crash when using 30 kHz menu audio files) (#12987) 2021-09-15 01:17:45 +02:00
twinaphex 868a4bf3fc Fix some warnings; set gfx_white_texture to 0 in deinit function at the
end
2021-09-13 20:52:57 +02:00
twinaphex 90775e7306 Silence warnings/errors 2021-09-13 20:30:22 +02:00
twinaphex 5e4ce74000 Get rid of duplicate code in gfx_widgets -
gfx_display_get_widget_dpi_scale made redundant
2021-09-13 20:21:36 +02:00
twinaphex 490233f3c5 wite_texture is now a static global variable inside gfx_display.c
- no longer referenced outside
2021-09-13 19:55:53 +02:00
twinaphex fe14274b96 Get rid of referencing of gfx_display_white_texture outside 2021-09-13 19:20:43 +02:00
twinaphex fc4d4c53cd Cleanup some references to gfx_display_white_texture and
don't assume NULL == 0 for uintptr_t
2021-09-13 19:07:09 +02:00
twinaphex 3c69a941da Move code over to input_driver.c 2021-09-13 18:33:53 +02:00
twinaphex 2b08ebb677 Cleanups 2021-09-13 18:09:44 +02:00
jdgleaver 12f787547c Add workaround to fix keyboard input when using x11+udev (#12981) 2021-09-13 18:02:40 +02:00
MajorPainTheCactusandtwinaphex 3c6bdfd0d8 Fixed numerous issues with HDR (#12979)
* Fix for warning and fix for incorrect comment

* Fixed contrast to be more correct - now scales from 0-10 linearly and behaves more the way you'd expect it to - changed name to ditch legacy settings users may have
Added ability to skip inverse tonemapper to the shader via the constant buffer using 'inverse_tonemap' - set to 0.0f to skip
Fixed potential bug when swapping between hdr and sdr and the bit depth not being set correctly
Fixed dx11's blend, rasterizer and topology states not being set to the sames when using hdr and leaving the menu - caused issues with PCSX2's Shadow of the Colossus
Added numerous helper functions to help create the correct values to colour the UI - normally the white UI elements should be rendered at paper white not max brightness for various reasons

* Fix stylistic issues - * Don't use camelcase for variables and function names * Use '(void)' for function declarations instead of () in C code * Declare variables at the top of a function or code block * Make sure functions that return a value always have a default return path that is not encapsulated by an else block * Use more unique names for retro_math functions which are less likely to overlap with other libraries' function symbols

Co-authored-by: twinaphex <[email protected]>
2021-09-13 16:54:50 +02:00
Autechre e24440d4a9 Merge pull request #12976 from grant2258/mouse_index
this function is called more than once dont use static
2021-09-13 11:44:28 +02:00
Autechre ed6f33b173 Merge pull request #12978 from 3rd-fork/master
Fix issues when opening file with extra long path name
2021-09-13 00:00:03 +02:00
grant2258 88b15c1b1d this function is called more than once dont use static 2021-09-12 20:58:49 +01:00
Tunip3 2991e82575 fix issue where it would fail to get a handle for a file as the path was too long 2021-09-12 20:26:09 +01:00
twinaphex ad4b51b903 Move cde from retroarch.c to input_driver.c 2021-09-12 19:27:12 +02:00
twinaphex b5138b6122 Move input_config_get_bind_string to input_driver.c 2021-09-12 17:41:00 +02:00
twinaphex ad39b1d115 Simplify osk_update_last_codepoint() 2021-09-12 17:36:22 +02:00
twinaphex 3d303a63df (Ozone) Reduce rotate_z calls 2021-09-12 17:14:03 +02:00
twinaphex c3cd3b34b0 (XMB) Reduce amount of times we call blend_begin/blend_end and
rotate_z
2021-09-12 17:06:59 +02:00
twinaphex 26b9439dbc C89_BUILD buildfix 2021-09-12 16:50:46 +02:00
Autechre cfcd0a7a0d Merge pull request #12795 from sonninnos/video-rate-switch
Automatic PAL/NTSC refresh rate switch where available
2021-09-12 16:15:04 +02:00
twinaphex 1b8d68c6e4 Another buildfix 2021-09-11 18:36:12 +02:00
twinaphex c4cbcb2ff4 Add ifdef around this 2021-09-11 18:22:07 +02:00
twinaphex 2490f6e215 Move code from retroarch.c to video_shader_parse.c 2021-09-11 18:15:35 +02:00
twinaphex f09be107c6 Cleanup some extra ifdefs 2021-09-11 17:56:44 +02:00
Autechre 589c72d9a8 Merge pull request #12966 from IlDucci/doublebeforefix
Fixing a typo at MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_VALIDATE_ENTRIES
2021-09-11 12:57:25 +02:00
IlDucci 08f75ab195 Fixing a typo at MENU_ENUM_SUBLABEL_MANUAL_CONTENT_SCAN_VALIDATE_ENTRIES 2021-09-10 17:11:55 +02:00
Autechre dcf77c4d1e Merge pull request #12821 from markwkidd/config_h
standardize include paths for config.h
2021-09-10 16:59:15 +02:00
Autechre 27bd9868d7 Merge pull request #12963 from jdgleaver/playlist-refresh
(Playlist Manager) Add 'Refresh Playlist' option
2021-09-09 18:44:42 +02:00
Autechre f34c8865ee Merge pull request #12815 from markwkidd/vscode-fix
[VS Code IDE] set .h file association and add vscode configuration to gitignore
2021-09-09 18:44:09 +02:00
Autechre 84174598a4 Merge pull request #12858 from sonninnos/authors-script
Update AUTHORS.h and script
2021-09-09 18:35:26 +02:00
twinaphex c75bb549e5 Move another function over to menu_driver.c 2021-09-09 17:26:59 +02:00
twinaphex 4830150d22 Move function out of retroarch.c and into menu_driver.c 2021-09-09 17:21:48 +02:00
jdgleaver 6da778b934 (Playlist Manager) Add 'Refresh Playlist' option 2021-09-09 16:18:26 +01:00
twinaphex 8564b4f8e3 Fix compilation problem when HAVE_BSV_MOVIE is not defined 2021-09-09 16:58:52 +02:00
twinaphex 6a310ecfed Move more code to command.c 2021-09-09 16:55:14 +02:00
twinaphex 14cd338b97 Move code from retroarch.c to command.c 2021-09-09 16:31:35 +02:00
twinaphex 9b8145f05d Cleanups 2021-09-09 16:06:57 +02:00
twinaphex a11b1c3b72 (retroarch.c) Cleanups 2021-09-09 16:01:33 +02:00
twinaphex 772282eeec Move menu shader code over to menu_driver.c 2021-09-09 15:33:17 +02:00
twinaphex 28389d30e8 Move some code from retroarch.c over to menu_driver.c 2021-09-09 15:22:12 +02:00
twinaphex 6c79cebc6e Move input_overlay_auto_rotate_ out of retroarch.c and into
input_driver.c
2021-09-09 14:24:42 +02:00
twinaphex 81e7dab159 Move code out of retroarch.c and into input_driver.c 2021-09-09 14:11:46 +02:00
Autechre 49cce025c7 Merge pull request #12952 from DisasterMo/rumble
Rebase 'Add generic rumble gain to input settings' by davidgfnet
2021-09-09 13:52:00 +02:00
Autechre ace9267c7b Merge pull request #12960 from Jamiras/cheevos_cfg_overrides
(cheevos) don't write achievement credentials to overrides
2021-09-09 09:32:56 +02:00
Michael Burgardt 303d17e2e6 Rebase 'Add generic rumble gain to input settings' by davidgfnet 2021-09-08 19:52:32 +02:00
Jamiras f0a3ee6003 don't write achievement credentials to overrides 2021-09-08 11:34:19 -06:00
Jamiras 8a31b732dd disable slowmotion when enabling hardcore mode (#12958) 2021-09-08 18:57:19 +02:00
Tony 51b365b5e3 New regular widget message appearance (#12851) 2021-09-08 18:14:41 +02:00
bulzipke 8018be5c9b Fix ram states to file when core deinit (#12956)
* Fix ram states to file when core deinit

* Fix unterminated state_path
Call CMD_EVENT_RAM_STATE_TO_FILE when CMD_EVENT_UNLOAD_CORE too
2021-09-08 18:01:07 +02:00
twinaphex c9e587a5a7 Move more input code over to input_driver.c from retroarch.c 2021-09-07 14:55:37 +02:00
twinaphex ccbbf45760 retroarch.c - cleanups 2021-09-07 13:55:42 +02:00
twinaphex 276b4fd72c Move more code over from retroarch.c to input_driver.c 2021-09-07 13:08:31 +02:00
twinaphex 67defbcf26 Transfer code over from retroarch.c to input_driver.c 2021-09-07 12:42:03 +02:00
twinaphex 5b1872f6be retroarch.c - some cleanups - retroarch_set_frame_limit - return
value - other cleanups
2021-09-07 12:29:44 +02:00
twinaphex 10782f9abc Cleanups - move code over to menu_driver.c 2021-09-07 11:55:12 +02:00
twinaphex 3a78b46862 Move code to input_driver.c 2021-09-07 10:17:06 +02:00
twinaphex 138afafbb3 generic_menu_entry_action - cleanup 2021-09-07 08:35:27 +02:00
twinaphex 71067d8873 Preinitialize varaibles in video_driver_translate_coord_viewport 2021-09-07 08:11:32 +02:00
twinaphex a0856c9847 Move another function to menu_driver.c 2021-09-07 07:14:27 +02:00
twinaphex 722166cb15 Move functions from retroarch.c to input_driver.c 2021-09-07 07:11:42 +02:00
twinaphex 7c665702a8 Move input_driver_toggle_button_combo to input_driver.c 2021-09-07 06:50:18 +02:00
jdgleaver 1151504fa9 (OpenDingux Beta) Disable OpenAL + minor compilation flag optimisation (#12948) 2021-09-06 16:11:44 +02:00
tunip3andTunip3 5ae7bc2ce2 use findfirst file and manually get all items in a dir to reduce errors and increase access (#12947)
Co-authored-by: Tunip3 <[email protected]>
2021-09-06 14:27:49 +02:00
MrHuu 07600392df (3DS) Add bottom screen idle state (#12942) 2021-09-06 01:16:16 +02:00
MajorPainTheCactus 0ac542f1db Fix for warning and fix for incorrect comment (#12944) 2021-09-06 01:16:01 +02:00
Autechre 36888612eb Reduce gfx_display_rotate_z calls in menu drivers (#12937)
* (Ozone) Take out gfx_display_rotate_z out of ozone_draw_icon -
lots of matrix rotates and multiplies were happening when
just calling it once would suffice

* (MaterialUI) Reduce calls to gfx_display_rotate_z

* (XMB) Cleanup
2021-09-05 03:46:52 +02:00
twinaphex f597138827 Cleanups 2021-09-04 21:40:37 +02:00
twinaphex 623e09dc47 Fix wording 2021-09-04 21:38:33 +02:00
twinaphex b05a0d5aed * Enable HDR for WinRT/UWP (only works on PC UWP for now, won't work on Xbox yet swapchain
issues with both D3D11/12)
* Add sublabel for Expand Gamut
*
2021-09-04 21:36:48 +02:00
MajorPainTheCactusandAutechre 536d18778b Fixed up HDR for UWP/WinRT builds (#12936)
Fixed D3D11 validation warnings
Fixed up technically incorrect labels

Co-authored-by: Autechre <[email protected]>
2021-09-04 21:13:24 +02:00
twinaphex 28d1788e1e (HDR) Add sublabels 2021-09-04 19:59:16 +02:00
Víctor "IlDucci 017f9f8939 Fetch translations from Crowdin 04-Sep-2021 (#12934) 2021-09-04 17:43:20 +02:00
Víctor "IlDucci 916ebb98e7 Fixing a couple of minor typos related to the HDR PR. (#12935) 2021-09-04 17:43:11 +02:00
twinaphex 85c0607696 Add to CHANGES.md 2021-09-04 10:32:43 +02:00
twinaphex 43838dc4ea Bump version 2021-09-04 10:30:46 +02:00
twinaphex f905012376 Simplify float_to_s16/s16_to_float functions for ARM NEON ASM codepath 2021-09-04 00:39:49 +02:00
twinaphex 6d1c0e96a3 Simplify sinc NEON code 2021-09-04 00:35:45 +02:00
Autechre 9a5f4602cc Add intrinsic NEON versions for float_to_s16/s16_to_float (#12933)
* Add intrinsic NEON versions for float_to_s16/s16_to_float courtesy
of davidgfnet

* Define -DDONT_WANT_ARM_OPTIMIZATIONS for resampler sinc - this should
default to intrinsic versions

* Default to ARM NEON intrinsic codepath and make the ASM codepaths
optional by defining HAVE_ARM_NEON_ASM_OPTIMIZATIONS

* (Pkg/apple/Android) Take out ASM files being compiled in
2021-09-04 00:25:21 +02:00
twinaphex 19f4504943 Prevent collision with quasi88 in statically linked cores 2021-09-03 21:29:38 +02:00
bulzipke 8adc24ecbc (3DS) Add bottom screen menu (#12470)
* (3DS) Add bottom screen menu
 -> User can save/load state on botom screen with thumbnail.
 -> Call a save_state_to_file() when RAM state has data to write a disk.
 -> If the bottom screen needs updating, swap the bottom framebuffers.

Add: SAVE/LODE STATE TO RAM
 -> This is useful for devices with slow I/O
 -> 3DS bottom save state use CMD_EVENT_SAVE_STATE_TO_RAM
 -> 3DS bottom load state use CMD_EVENT_LOAD_STATE when RAM state has no data
 -> 3DS bottom load state use CMD_EVENT_LOAD_STATE_FROM_RAM when RAM sate has data

* Rewrite path_get_state to retroarch_get_current_savestate_path

* Fix unterminated state_path
2021-09-03 18:14:03 +02:00
Autechre 51dcad6cb3 Merge pull request #12932 from jdgleaver/cheat-search
Add enhanced search functionality to the 'Cheats' menu
2021-09-03 17:03:58 +02:00
Autechre 204834f88e Merge pull request #12927 from 3rd-fork/master
code clean up and simplification of uwp vfs driver
2021-09-03 17:03:34 +02:00
Autechre e39784189e Merge pull request #12772 from DisasterMo/core_option_translation
New example_translation core options sample
2021-09-03 16:59:42 +02:00
Autechre 87b40b7c57 Merge pull request #12930 from bslenul/master
Update menu toggle combo list in retroarch.cfg
2021-09-03 16:49:13 +02:00
Autechre 588c1305c8 Merge pull request #12931 from jdgleaver/runahead-cheats
Fix cheats when using second instance runahead
2021-09-03 16:48:30 +02:00
jdgleaver 508b0c2ee2 Add enhanced search functionality to the 'Cheats' menu 2021-09-03 14:58:33 +01:00
jdgleaver 743aea1810 Fix cheats when using second instance runahead 2021-09-03 11:27:12 +01:00
bslenul 76f114a9fe Update menu toggle combo list 2021-09-03 12:10:05 +02:00
twinaphex 274638b89e (D3D11) Look at D3D11 feature level - if we are 11.0 or above,
we use Shader Model 5.0 instead of the default SM 4.0 - this fixes
FSR on D3D11 which requires SM5.0
2021-09-03 07:51:44 +02:00
twinaphex b900555494 (D3D11) Add logging after device creation so we can see which
feature level it used
2021-09-03 07:15:53 +02:00
twinaphex a0e4d64c3b menu_bind_state struct definitions need to be moved over to menu_input.h 2021-09-03 06:48:06 +02:00
twinaphex 93dbd746db (Android) Buildfix 2021-09-03 06:31:40 +02:00
Autechre 7b9cbc08d7 Add HDR support for D3D12 (rebased PR from MajorPainTheCactus) (#12917)
* Add HDR support

* Attempt to fix Mingw build and Metal builds

* (D3D12) Fix relative header includes

* Add missing hdr_sm5.hlsl.h

* (d3d12_common.c) Some C89 build fixes

* Fix MSVC build

* - Attempt to fix build on mingw/msys unix with dirty hack
- Fix shader compilation of hdr_sm5.hlsl.h on MSVC/Visual Studio -
the define was seen as an error and was causing the first pipeline
to error out
- Make sure we manually set handle of backBuffer to NULL

* Moving the release of the texture above the freeing of desc.srv_heap
and desc.rtv_heap solves the hard crashes on teardown/setup in RA -
it was crashing hard in d3d12_release_texture before

* Add HAVE_D3D12_HDR ifdef - needs to be disabled for WinRT for now
because of several things that are Windows desktop-specific right now
(GetWindowRect)

* Add dirty GUID hack - should work for both mingw/msys on Windows/Linux
as well as MSVC/Visual Studio (hopefully)

* Change HAVE_D3D12_HDR to HAVE_DXGI_HDR

* Move away from camelcase named variables

* Fix RARCH_ERR logs - they need a newline at the end

* d3d12_check_display_hdr_support - make it return a bool on return
and set d3d12->hdr.support and d3d12->hdr.enable outside of the
function

* (DXGI) Remove D3D12 dependencies from dxgi_check_display_hdr_support and
move it to dxgi_common.c instead

* (DXGI) move d3d12_swapchain_color_space over to dxgi_common.c and
rename it dxgi_swapchain_color_space

* (DXGI) move d3d12_set_hdr_metadata to dxgi_common.c and
rename it dxgi_set_hdr_metadata

* (DXGI) dxgi_check_display_hdr_support - better error handling?

* Fix typo

* Remove video_force_resolution

* (D3D12) Address TODO/FIXME

* (D3D12) Backport
https://github.com/libretro/RetroArch/pull/12916/commits/c1b6c0bff2aa33cde035b43cb31ac7e78ff2a07a
- Fixed resource transition for present when HDR is off
Fixed cel shader displaying all black as blending was enabled when the hdr shader was being applied - turned off blending during this shader

* Move d3d12_hdr_uniform_t to dxgi_common.h and
rename it dxgi_hdr_uniform_t

* (D3D11) Add HDR support

* Add TODO/FIXME notes

* Cache hdr_enable in video_frame_info_t

* Update comment
2021-09-03 06:15:25 +02:00
Tunip3 9228a6f8ab disable cpu model check on xbox as it doesn't work and can even crash the app for some users 2021-09-02 18:21:16 +01:00
Michael Burgardt f6f7d145d2 Add core options translation scripts 2021-09-02 19:07:28 +02:00
twinaphex 868865c388 Include "config.h" before including msg_hash.h - we were
getting a crash at startup of the Qt desktop interface because
we didn't do this
2021-09-02 01:12:24 +02:00
Autechre ad01f5d5b6 Merge pull request #12923 from jdgleaver/mixer-reinit
Ensure than menu sounds are re-enabled when calling CMD_EVENT_AUDIO_REINIT
2021-09-01 19:10:53 +02:00
jdgleaver 48d9df6bb7 Ensure than menu sounds are re-enabled when calling CMD_EVENT_AUDIO_REINIT 2021-09-01 17:59:46 +01:00
Autechre 11b88c748e Merge pull request #12921 from jdgleaver/menu-sounds-fix
Fix menu sounds (audio mixing) when using the 'sinc' resampler with quality lower than 'normal'
2021-09-01 17:57:34 +02:00
jdgleaver 547f04b894 Fix menu sounds (audio mixing) when using the 'sinc' resampler with quality lower than 'normal' 2021-09-01 15:55:58 +01:00
sonninnos 19602d394f Update AUTHORS.h and script 2021-08-31 22:42:31 +03:00
twinaphex 9ea6f15c1d (Ozone) Forgot to add ozone.c file 2021-08-31 18:43:58 +02:00
twinaphex d0d495edc3 Combine all ozone files into one - discussed internally first -
allows us to modify the scope of the global variables from public
to static - also allows for easier refactors amongst
XMB/materialui/Ozone/RGUI later
2021-08-31 18:42:43 +02:00
twinaphex a785bd8d80 Remove HAVE_STRIPES - unfinished and unusable menu driver right
now
2021-08-31 17:50:24 +02:00
Autechre 256713e888 Merge pull request #12914 from libretro/move-code-over-to-menu-driver
Move lots of menu code over to menu/menu_driver.c
2021-08-31 14:20:42 +02:00
twinaphex fb35460c6d Move more code over 2021-08-31 01:47:57 +02:00
twinaphex 5677799faf Move more code over 2021-08-31 01:27:36 +02:00
twinaphex fc4081cd8f Fix some builds 2021-08-31 00:55:46 +02:00
twinaphex 0db409d5b5 Move lots of menu code over to menu/menu_driver.c - moved at least
44Kb of code over
2021-08-31 00:43:04 +02:00
twinaphex 70ebc85b6c Buildfix for targets with no HAVE_OVERLAY defined 2021-08-30 22:58:53 +02:00
twinaphex dbf3e278dd menu_driver_toggle - cleanups 2021-08-30 22:31:30 +02:00
twinaphex 03c54a9854 Cleanup menu_event and nested functions so that we remove p_rarch
dependencies
2021-08-30 21:59:35 +02:00
twinaphex 8460618666 menu_input_get_mouse_hw_state - horiz mouse wheel up/down were inverted 2021-08-30 21:17:08 +02:00
twinaphex c6f2e52d62 Simplify menu_driver_toggle 2021-08-30 21:11:43 +02:00
twinaphex 7e61c7ab32 Optimize menu_input_get_mouse_hw_state 2021-08-30 20:55:27 +02:00
twinaphex b68ace9e3d Simplify several menu poll functions 2021-08-30 20:46:07 +02:00
twinaphex 37aa13bb47 (X11) get_video_mode - make sure parameter does not hide global
variable of the same name
2021-08-30 18:39:02 +02:00
twinaphex e384c2b099 Fix some warnings in retroarch.c - local variables hiding parameter
of the same name, local variable being unused on one platform because
it's only used within an ifdef, etc.
2021-08-30 18:27:55 +02:00
twinaphex 1bafa70837 Simplify config_load_file - get rid of end label 2021-08-30 17:52:50 +02:00
Autechre 2406894329 Merge pull request #12913 from libretro/move-code-over-to-configuration
Move code in retroarch.c over to configuration file
2021-08-30 17:45:50 +02:00
twinaphex 220dfe4dbf Move code in retroarch.c over to configuration file 2021-08-30 16:52:05 +02:00
twinaphex bfc7e824fe Rmeove some obsolete comments 2021-08-30 16:13:47 +02:00
twinaphex 2f14d2e4e2 Move some command functions over from retroarch.c to command.c - the
other ones have some dependencies on static locals in retroarch.c so
can't be easily transferred over for now
2021-08-30 16:08:50 +02:00
Autechre cd126f0236 Merge pull request #12911 from Jamiras/rcheevos102
(cheevos) upgrade to rcheevos 10.2
2021-08-30 05:19:04 +02:00
twinaphex d2283a5237 Use better already existing race guard 'audio_suspended' instead
of 'video_driver_is_switching_mode'
2021-08-30 05:08:09 +02:00
twinaphex d429ecf304 Safer way of avoiding the race condition in
audio_driver_sample/audio_driver_sample_batch - we can check
is_display_mode_switching to see if we're doing a fs/windowed toggle
(full teardown/setup), no audio should be processed at this point in
time
2021-08-30 04:52:28 +02:00
twinaphex d45945cda2 When audio driver write callback function fails, don't
turn audio off completely - look if audio_driver_output_samples_conv_buf
is non-NULL first before we attempt to write audio
2021-08-30 02:13:19 +02:00
twinaphex 943e14051c Increased safety for non-batched audio sample callback - fixes audio_driver_sample crashing in PCSX2 when toggling fullscreen 2021-08-30 01:54:49 +02:00
Autechre 4b6a82a3b0 Merge pull request #12908 from libretro/input-robustness-for-threaded-cores
Input robustness for threaded cores
2021-08-29 23:00:48 +02:00
twinaphex bf2e7b93f0 (Vulkan) Fix Vulkan validation layer - fix thanks to flyinghead -
see comments
2021-08-29 20:39:22 +02:00
twinaphex 24721e6a1d C89 buildfix for MSVC 2021-08-29 20:37:09 +02:00
twinaphex 0a1affba7a Simplify menu_input_get_mouse_hw_state/menu_input_read_mouse_hw 2021-08-29 19:05:38 +02:00
twinaphex a9f1dd3647 input_driver_poll; remove shadowed variable
menu_input_read_mouse_hw - cleanup + go through local pointer
variable for primary_joypad
2021-08-29 18:41:58 +02:00
twinaphex 540d192ecb Buildfix for Apple + make sure primary_joypad/secondary_joypad goes through local pointers; cut down on HAVE_MFI ifdefs in retroarch.c 2021-08-29 18:34:52 +02:00
twinaphex f1f3998d28 Prevent joypad objects being destroyed before their pointers are being
NULLed. Another thread could access a "half destroyed" object before
2021-08-29 18:06:08 +02:00
twinaphex 46fb61bede input_state_wrap - do not attempt to access joypad or sec_joypad
pointers if non-NULL
2021-08-29 16:57:41 +02:00
twinaphex cf7b30481b Get rid of gfx_widgets_draw_icon_blend - was just a duplicate of
gfx_widgets_draw_icon with blend_begin and blend_end wrapped around it
2021-08-29 15:21:40 +02:00
Brian Weiss 30db7d8cd3 upgrade to rcheevos 10.2 2021-08-28 13:58:33 -06:00
Autechre 2474fe3c2e Updating CODING-GUIDELINES - typo fix 2021-08-28 17:24:32 +02:00
twinaphex 5b3e5f5daa Update CODING-GUIDELINES 2021-08-28 17:22:24 +02:00
Autechre 861cb2953a Merge pull request #12902 from 4th-fork/master
set background colour for splash screen to black
2021-08-28 15:12:23 +02:00
Tunip3 6dfe20e247 set background colour for splash screen to black rather than the default light gray 2021-08-28 13:47:57 +01:00
Tunip3 bb0fe6c2d1 fix extraction issues 2021-08-26 23:18:42 +01:00
Tunip3 45a16fab1b clean up retro_vfs_file_open_impl 2021-08-25 23:12:29 +01:00
Tunip3 8396bd599d strip out unneeded uwp specific file io functions 2021-08-25 15:54:09 +01:00
sonninnos b8188baeaf Automatic refresh rate switch where available 2021-08-21 01:15:41 +03:00
Mark W. Kidd 2b3dfeb10c standardize include path for config.h 2021-08-18 18:54:40 -04:00
Mark W. Kidd d87ae5b5d7 set vscode .h association and gitignore its configuration 2021-08-17 20:30:50 -04:00
319 changed files with 35052 additions and 29162 deletions

No files matched your search

+3
View File
@@ -225,3 +225,6 @@ param.sfo
*.vpk
/.vs
/deps/SPIRV-Cross/out/build/x64-Debug
# Visual Studio Code
./vscode/
+166 -148
View File
@@ -1,155 +1,173 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceRoot}/libretro-common/include"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceRoot}/libretro-common/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include",
"${workspaceRoot}/libretro-common/include"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include",
"${workspaceRoot}/libretro-common/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}"
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}",
"${workspaceFolder}/libretro-common/include"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++17"
},
{
"name": "msys2-mingw32",
"includePath": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
"defines": [
"_DEBUG",
"UNICODE"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "msys2-mingw64",
"includePath": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared",
"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/winrt",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++17",
"configurationProvider": "ms-vscode.makefile-tools"
},
{
"name": "msys2-mingw32",
"includePath": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Switch",
"includePath": [
"/opt/devkitpro/devkitA64/aarch64-none-elf/include",
"/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include",
"/opt/devkitpro/libnx/include",
"/opt/devkitpro/portlibs/switch/include",
"/opt/devkitpro/portlibs/switch/include/freetype2",
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"__aarch64__",
"__SWITCH__",
"HAVE_LIBNX"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw32/include",
"C:/msys64/mingw32/i686-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "msys2-mingw64",
"includePath": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/msys64/mingw64/include",
"C:/msys64/mingw64/x86_64-w64-mingw32/include",
"${workspaceRoot}/libretro-common/include",
"${workspaceRoot}/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Switch",
"includePath": [
"/opt/devkitpro/devkitA64/aarch64-none-elf/include",
"/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include",
"/opt/devkitpro/libnx/include",
"/opt/devkitpro/portlibs/switch/include",
"/opt/devkitpro/portlibs/switch/include/freetype2",
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"__aarch64__",
"__SWITCH__",
"HAVE_LIBNX"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "gcc-x64"
},
{
"name": "WiiU",
"includePath": [
"/opt/devkitpro/devkitPPC/powerpc-eabi/include",
"/opt/devkitpro/devkitPPC/lib/gcc/powerpc-eabi/6.3.0/include",
"/opt/devkitpro/portlibs/ppc/include",
"${workspaceFolder}/**"
],
"defines": [
"WIIU"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "/opt/devkitpro/devkitPPC/bin/powerpc-eabi-gcc",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}
+2 -31
View File
@@ -11,20 +11,15 @@
"editor.insertSpaces": true,
"editor.formatOnSave": false,
"files.associations": {
"frontend_driver.h": "c",
"*.h": "c",
"*.in": "c",
"*.rh": "c",
"array": "c",
"file_stream.h": "c",
"driver.h": "c",
"iosfwd": "c",
"xlocbuf": "c",
"xmemory0": "c",
"ios": "c",
"list": "c",
"input_driver.h": "c",
"menu_driver.h": "c",
"file_path.h": "c",
"unordered_map": "c",
"unordered_set": "c",
"sstream": "cpp",
@@ -33,39 +28,15 @@
"initializer_list": "c",
"string_view": "c",
"utility": "c",
"menu_input.h": "c",
"tasks_internal.h": "c",
"ozone.h": "c",
"ozone_theme.h": "c",
"ozone_texture.h": "c",
"string_list.h": "c",
"core_info.h": "c",
"thread": "c",
"xlocale": "c",
"gfx_widgets.h": "c",
"message_queue.h": "c",
"task_queue.h": "c",
"fifo_queue.h": "c",
"file_list.h": "c",
"strl.h": "c",
"configuration.h": "c",
"ozone_display.h": "c",
"verbosity.h": "c",
"retroarch.h": "c",
"gfx_animation.h": "c",
"netplay.h": "c",
"scaler.h": "c",
"deque": "c",
"vector": "c",
"xhash": "c",
"xiosbase": "c",
"xstring": "c",
"xtree": "c",
"xutility": "c",
"menu_input_dialog.h": "c",
"ozone_sidebar.h": "c",
"menu_thumbnail_path.h": "c",
"badges.h": "c"
"xutility": "c"
},
"C_Cpp.dimInactiveRegions": false,
}
+175 -40
View File
@@ -3,18 +3,26 @@ RetroArch and the libretro team would like to
acknowledge the following contributors:
1ch (L0sted)
Aaahh Ahh (Aaahh)
51eating (dnjstlr555)
6lackmag3
A Schain (aschain)
Aaron Oneal (aarononeal)
Adam Londero (alondero)
Adam Mechtley (amechtley)
AdrianoML
Adrien Moulin (elyosh)
Aethyrion
ajefr
AKuHAK
Alberto Alonso Ruibal (albertoruibal)
Alberto Simon (asimonf)
Alcaro
Aleksey Samoilov (Sunderland93)
Alessandro Mangone (Vektor) (zevektor)
Alessio Tosto (Rinnegatamante)
Alex Eckhart (alex34567)
Alex Folland (AlexFolland)
Alex Kornitzer (alexkornitzer)
Alexander Spady (alkaseltzerspadt)
Alexandre Garcia (Alexandre-Garcia)
Alfredo Monclus (alfrix)
@@ -23,98 +31,151 @@ alphanu1
altiereslima
Alwin Garside (Yogarine)
Amiga1200Gamer (amigagamer)
amtz
Andre Leiradella (leiradel)
Andrés (fr500)
Andy Nguyen (TheOfficialFloW)
Anthony J. Bentley (bentley)
Antonio Jose Ramos Marquez (psxdev)
AridRayne
ArnaudFaucher
arstn
Arto Vainiolehto (arakerlu)
asavah
Ash (QuarkTheAwesome)
Ashura (CoalaJoe)
Autechre64
Autechre (twinaphex)
Avton1
ayssia
barbudreadmon
Barry Rowe (BarryJRowe)
Bartłomiej Burdukiewicz (dev-0x7C6)
bearoso
benklop
benutzer193
Bernhard Schelling (schellingb)
blackgur
bmaupin
Bobby Smith (bslenul)
Boris Timofeev (btimofeev)
bparker06
Brandon Johnson (Denu8thell)
Brad (SpiralBrad)
Braden Farmer (farmerbb)
Brandon Johnson (BinaryFissionGames)
Breno Dantas Mendonça (brenodantas10)
Brian Hoem (ZornTaov)
Brian Koropoff (bkoropoff)
Brian S. Stephan (bsstephan)
BringerethOfLight
Brunnis
bsmith (DogParty)
bubuleur
bulzipke
C.W. Betts (MaddTheSane)
Casey Borders (CaseyB)
CatGreen90
ceb33
celerizer
Charlène (julianaito)
CheezeCake
Chris Merrett (chrisfu)
Christian Murphy (grimpunch)
christianhaitian
Christoffer Tibell (Brottweiler)
chu (9chu)
Chuck Smith (chucksmith)
CidVonHighwind
clienthax
cold-brewed
CompCom
ComradeEcho
confusedguy9
Conn O'Griofa (psyke83)
Connor McLaughlin (stenzek)
Conrad Kreyling (konistehrad)
CozmoP
Cpasjuste
cpsw
Cray Elliott (MP2E)
Crestwave
CrewMdk
Cristi Mitrana (cmitu)
Cristian Sandu (crazyquark)
ctult
crystalct
CTCaer
cucholix
cudencuden
cxd4
Cyan (44100hertz)
Daehan Kim (iAmGhost)
dalter
Dan Weiss (Dwedit)
danieljg
Daniil Zhilin (LaserMoai)
dankcushions
Darren Thompson (DiscoStarslayer)
Dave (freakdave)
Dave Leaver (danzel)
David CARLIER (devnexen)
David Demelier (markand)
David Erickson (daviderickson)
David Shah (daveshah1)
David G. F. (davidgfnet)
David Lawson (dmrlawson)
David Walters (hiddenasbestos)
DEX357
diablodiab
dibas
Diego A. (SuperrSonic)
Diego Viola (diegoviola)
digitalisland-nino
Diogo Barros (BlueKore)
DogParty
Dmitry Sergeenkov (DuMOHsmol)
dor3k
Doug Christman (dobyrch)
driver1998
Dudu Akiva (duduke)
duganchen
dukemiller
duskgao
Dylan Scott (dyscott)
eadmaster
Eduard Strehlau (Herdinger)
ekipan
Elvira Khabirova (parport0)
embercold
Emmanuel Martin (daliaetnano)
endrift
erbridge
Ethan Lee (flibitijibibo)
Exvat
extrowerk
Ezio-PS
F (erbridge)
Fabio (Oibaf66)
Fabio Ritrovato (Sephiroth87)
Fayne Aldan (FayneAldan)
fff (felinben)
FIX94
Flame Sage (chris062689)
flyinghead
FmT0
francescotintori
Francisco Javier Trujillo Mata (fjtrujy)
Francisco José García García (frangarcj)
FreeShippingParty
fuzzydunlops732 (JKoppel93)
Gabriel (Ghabry)
GameDragon2k
Garrett Brown (garbear)
gatecat (daveshah1)
GavinDarkglider
gblues
Geoffrey Plitt (GeoffreyPlitt)
Glenn Hevey (hevey)
Googer
gordon-fish
gouchi
grant2258
Gregor Richards (GregorR)
Grzegorz Raciborski (graciborski)
Gui Andrade (archshift)
Guillaume Thiolliere (thiolliere)
Guo Yunhe (guoyunhe)
Gustavo Maciel Dias Vieira (gmdvieira)
gvbr
H. İbrahim Güngör (igungor)
@@ -122,44 +183,61 @@ hadess
Hans-Kristian Arntzen (Themaister)
Henri Gomez (hgomez)
Henri Gomez (hgomez-sonarsource)
Higor Eurípedes (heuripedes)
Hisman Yosika (dnjstlr555)
Henry Castro (hcvcastro)
Higor E. (heuripedes)
hizzlekizzle
Hugo B. (hug0b)
Hugo Hromic (hhromic)
hunterk
hyarsan
Hyllian
HyperspaceMadness
i30817
iAmGhost
im4potato
ImJezze
Jack (jakcron)
Jacob (cubtekki)
Jacob Patterson (jacobpa)
jacobsson (Roet-Ivar)
Jake Stine (jstine35)
James Le Cuirot (chewi)
James Sexton (Bezier89)
Jamiras
Jan Holthuis (Holzhaus)
Jason Tomsic (plaidman)
Javier Martinez Canillas (martinezjavier)
Jay McCarthy (jeapostrophe)
jdgleaver
Jean-André Santoni (kivutar)
Jean-Paul Mari (djipi)
Jean-Sébastien Guay (Skylark13)
Jesse Bryan (winneon)
Jeff (jeffbdavenport)
Jeff Sousa (LordeIlluminati)
jess (winneon)
Joan Coll Cerdán (johanbcn)
Job Adrian Salinas Gonzalez (efylan)
Joe Osborn (JoeOsborn)
Joel (joel16)
Joerg Sonnenberger (jsonn)
Johannes Schickel (lordhoto)
John Parton (john-parton)
John Regan (jprjr)
Jon Maddox (maddox)
Jonathan (JonnyMe)
Jonathan Relf (jonathanrelf)
Joohan Lee (losernator)
Jools Wills (joolswills)
Jose Lage Miguez (Joselagem)
Joseph Carter (iKarith)
Joseph Conan Montgomery (Grotke)
Josh Palmer (ShiftyAxel)
jsd1982 (JamesDunne)
JuanVCS
Justin Jacobs (dorkster)
Justin Weiss (justinweiss)
JustMeDaFaq
Karl Forshaw (karlforshaw)
Keith Bowes (keithbowes)
Ken Rossato (rossato)
Kopert
krzys_h (krzys-h)
kurumushi
kwyxz
@@ -167,10 +245,12 @@ l3iggs
lambolighting
lasers
Lawrence Kesteloot (lkesteloot)
lifajucejo
liffy (lifning)
LazyBumHorse
LazyFunker
Lennard Kittner (Lennard599)
Lionel Flandrin (simias)
littleguy77
liushuyu
Logan (loganmc10)
lordashram
Lothar Serra Mari (lotharsm)
@@ -178,51 +258,63 @@ Lubosz Sarnecki (lubosz)
lucianposton
lxerandrew
m4xw
mahoneyt944
Mahyar Koshkouei (deltabeard)
Mai M. (lioncash)
maksun
Manuel Alfayate Corchete (vanfanel)
Marcelo Munhoz Pélos (mpelos)
Marcus Crisostomo (mcrisostomo)
markwkidd
Maschell
Mat M. (lioncash)
Mats A. (Datamats)
Mats (m4tsa)
Matt Sephton (gingerbeardman)
Matthew Bauer (matthewbauer)
Matthew Wang (asakous)
Max K. (langerhans)
Maxime Gauduin (alucryd)
mcrisostomo
meancoot
meepingsnesroms
meleu
Merry Mello (merryMellody)
micechal
Michael Burgardt (DisasterMo)
Michael K. (kuxii2016)
Michael Lelli (ToadKing)
Michał Durak (micechal)
mickski56
Mico Chopitea (micochops)
miguelpinheiro
Mike Swanson (chungy)
miqlas (extrowerk)
mikeOSX
minucce
misson20000
Monroe88
Morgane (Niouby)
mprobinson
MrHuu
MrJs (mrjschulte)
mudlord
Muhamed Hobi (mmhobi7)
muzuiget
mwtremblay
myfreeweb
Nargash
Nathan S. (natinusala)
NathanStrong-Tripwire
nattycleopatra
nayslayer
Nephilim
negativeExponent
Neil Barkhina (nbarkhina)
Nephilim (Nephil1m)
netux79
nfnty
nia (ensra)
nia (alarixnia)
Nicolas Adenis-Lamarre (nadenislamarre)
Nicolas Guillaumin (nguillaumin)
Nicolas Lopez Fernandez (pyroesp)
Nikita Vakhrushev (SwooodGa)
Nicolas Roehm (NicolasRoehm)
Nikita Vakhrushev (XF10C)
Nikola Kocić (nikola-kocic)
Niouby
Nikos Chantziaras (realnc)
Nils Hasenbanck (hasenbanck)
njordan64
nosh01
not6 (r-type)
notaz
@@ -231,51 +323,77 @@ nurupo
Oggom
Oleg Shevchenko (olsh)
opendata26
Ophidon
orbea
Oschowa
OsirizX
OV2
Palmic (mpalomas)
pamapa
Paolo Bonzini (bonzini)
Paul McCarty (notabeatle)
pcjco
Pedro Ferraz (ferrazpedro)
Pedro Ribeiro (pedrib)
pinumbernumber
pjft
pponso1
pyroesp
R-YaTian
Ramiro Morales (ramiro)
Raphaël Zumer (rzumer)
retro-wertz
Reid Kleckner (rnk)
repojohnray
retrotails
revvv
reztek
Richard Howell (rmaz)
rlnilsen
Rob Loach (RobLoach)
Robin de Rooij (rrooij)
Romain Gay (vikbez)
Romain Graillot (notnotme)
Romain TISSERAND (rtissera)
Roman Fomin (rfomin)
Roman Kalashnikov (lunixoid)
Royerson
rrooij
rsn8887
Ryan C. Gordon (icculus)
Ryunam
rz5
Saggi Mizrahi (ficoos)
SAKUJ0
Sam Pagenkopf (44100hertz)
Sam Lantinga (slouken)
Sam Stenvall (Jalle19)
Samuel P. (p-sam)
Sanaki
Scheiker
Sebastien Ronsse (sronsse)
SecularSteve
Sefa Eyeoglu (Scrumplex)
Sergei Nikitin (Kert)
Sergi Granell (xerpi)
Sergio Padrino (sergiou87)
sergio-br2 (sergiobenrocha2)
Seth Kingsley (sethk)
Shadow (ShadowOne333)
Shane Mouton (ismouton)
shantigilbert
Shfty
Shizeeg Unadequatov (shizeeg)
SimpleTease
SindenLightgun
Sirrempat
slotek
Soar Qin (soarqin)
sparklewind
spec-chum
Stefan (gizmo98)
stefan-gr
stellarporter
Steven M. Vascellaro (stevoisiak)
Stephanie Gawroriski (XerTheSquirrel)
Stevoisiak
stoofin
Stuart Carnie (stuartcarnie)
Sunguk Lee (d3m3vilurr)
Supernature2k
@@ -283,39 +401,56 @@ Sven (RetroSven)
Swingflip
Swizzy
Sylvain Colinet (Skarsnik)
Szunti
Tadek Kijkowski (monkeyman79)
Tatsuya79
Terry Lewis (terry-au)
thedax
theheroGAC
TheMrIron2
TheOfficialFloW
thiolliere
ThePhxRises
Thomas Lorblanchès (Zlika)
Tim Van den Langenbergh (tmtvl)
Tobias Gruetzmacher (TobiX)
Tobias Jakobi (tobiasjakobi)
Todd Laney (ToddLa)
Tomáš Kelemen (ToKe79)
Tony (sonninnos)
Tor Arne Vestbø (torarnv)
Torsten Paul (t-paul)
toshixm
TotalCaesar659
TroggleMonkey
Twinaphex
tunip3
Tyler Loch (TylerLoch)
unrelentingtech
URBANsUNITED
Valerio Proietti (kamicane)
vgmoose
Vicki Pfau (endrift)
Vicky C Lau (vickychenglau)
vin (suseme)
Vladimir Panteleev (CyberShadow)
Vladimir Serbinenko (phcoder)
Víctor "IlDucci" (IlDucci)
waitingmoon
Wang Vincent (susemm)
webgeek1234
Weedy Weed Smoker (WeedyWeedSmoker)
WerWolv
whorsemaster
Wiimpathy
Wiktor Strzębała (wiktorek140)
Woohyun Shin (sinusinu)
xenomorph-us
xhp-creations
Yari (hyarsan)
yesfish (huwpascoe)
Yongwoon Cho (ssangkong)
yoshisuga
Zer0xFF
zeromus
zlice
Zoran Vuckovic (casdevel)
Érico Nogueira Rolim (ericonr)
Ömercan Kömür (fpscan)
シーはディー四を取る (cxd4)
)";
+66
View File
@@ -1,5 +1,71 @@
# Future
# 1.9.10
- 3DS: Add bottom screen idle state
- 3DS: Add unique IDs for Gearboy/Gearcoleco/Gearsystem, correct CAP32 code
- 3DS/SAVESTATES: Fix RAM states to file when core deinits
- AUDIO/MIXER: Pad sample buffers to prevent potential heap-buffer-overflows when resampling (fixes crash when using 30 kHz menu audio files)
- CHEEVOS: Don't write achievement credentials to overrides
- CHEEVOS: Disable slowmotion when enabling hardcore mode
- D3D9: Fixed MVP matrix issue for RGUI texture (main game frame still won't show up though)
- D3D11/D3D12/HDR: Fixed contrast to be more correct - now scales from 0-10 linearly and behaves more the way you'd expect it to - changed name to ditch legacy settings users may have
- D3D11/HDR: Fixed D3D11's blend, rasterizer and topology states not being set to the sames when using HDR and leaving the menu - caused issues with PCSX2's Shadow of the Colossus
- D3D11/D3D12/HDR: Added ability to skip inverse tonemapper to the shader via the constant buffer using 'inverse_tonemap' - set to 0.0f to skip
- D3D11/D3D12/HDR: Fixed potential bug when swapping between hdr and sdr and the bit depth not being set correctly
- D3D11/D3D12/HDR: Added numerous helper functions to help create the correct values to colour the UI - normally the white UI elements should be rendered at paper white not max brightness for various reasons
- BUGFIX/ANDROID: Fix crash that could happen on Android with Sameboy core - would crash on rumble function
- GFX/WIDGETS: New regular widget message appearance
- INPUT/MOUSE: Add distinct mouse zero index label for drivers that do not support multimouse
- INPUT/RUMBLE: Add generic rumble gain to input settings
- INPUT/UDEV/X11: Add workaround to fix keyboard input when using X11 + Udev
- LIBNX/SWITCH: Add Video Filters support
- LOCALIZATION: Fetch translations from Crowdin
- OPENDINGUX/BETA: Disable OpenAL
- PLAYLISTS: Add 'Refresh Playlist' option
- UWP/VFS/XBOX: Improvements and bugfixes to UWP VFS driver
- VIDEO/REFRESH RATE: Automatic PAL/NTSC refresh rate switch where available - as long as the platform display server allows changing refresh rates and the display has the desired refresh rate
- VIDEO FILTERS: Add 'Picoscale_256x-320x240' video filter
- WIIU/HID: Fix analog inputs on HID devices
# 1.9.9
- 3DS: Add bottom touchscreen menu
- 3DS/SAVESTATES: Save and load save states to and from RAM
- AUDIO/MIXER: Ensure than menu sounds are re-enabled when calling CMD_EVENT_AUDIO_REINIT
- AUDIO/RESAMPLER/MIXER: Fix menu sounds (audio mixing) when using the 'sinc' resampler with quality lower than 'normal'
- AUDIO/CONVERSION/ARM NEON: Add intrinsic NEON versions for float_to_s16/s16_to_float - should lead to optimized codepaths for AArch64/ARMv7 architectures without being dependent on ASM codepaths.
- AUDIO/RESAMPLER/ARM NEON: Add intrinsic NEON version for lanczos sinc function - should lead to optimized codepaths for AArch64/ARMv7 architectures without being dependent on ASM codepaths.
- CHEEVOS: Upgrade to rcheevos 10.2
- CHEATS: Add enhanced search functionality to the 'Cheats' menu
- CHEATS/RUNAHEAD: Fix cheats when using second instance runahead
- CONFIG: Add option to (force-)write current core options to disk (Quick Menu)
- CORE INFO CACHE: Remove core path from core info cache. Should make core info caches portable now (for example: you can move RetroArch to a separate dir and they would still work).
- D3D11: Use Shader Model 5.0 for frontend shaders if D3D11 Feature level is at least 11.0 or higher. Should fix some new shaders that require SM 5.0 (like AMD FSR)
- D3D11: Add HDR support (disabled for UWP for now)
- D3D12: Add HDR support (disabled for UWP for now)
- EMSCRIPTEN: Fixed web player bug with filesystem and runtime
- INPUT/OVERLAY: Fix overlay input when analog to digital mapping is enabled
- INPUT/UDEV: Look for "ID_INPUT_KEY", not "ID_INPUT_KEYBOARD"
- INPUT/WINRAW: Fix crash when overlay is enabled
- MAC/METAL: Add Discord RPC support
- MENU: Allow 'Custom Aspect Ratio (X Position)/(Y Position)/(Width)/(Height)' to be entered manually via keyboard
- MENU: Allow 'Vertical Refresh Rate' to be entered manually via keyboard
- MENU/SHADERS: Highlight currently selected value in Shader Parameter drop-down lists
- STABILITY: Safer way of avoiding the race condition in
audio_driver_sample/audio_driver_sample_batch - we can check
audio-suspended to see if we're doing a fs/windowed toggle - enhances stability when fullscreen toggling/tearing down context
- STABILITY: When audio driver write callback function fails, don't
turn audio off completely - look if audio_driver_output_samples_conv_buf
is non-NULL first before we attempt to write audio - enhances stability when fullscreen toggling/tearing down context
- STABILITY: Input robustness for cores that use internal threading
(full teardown/setup), no audio should be processed at this point in
time
- VIDEO: Screen resolution list sanitizing
- VULKAN: Fix some Vulkan validation layer errors
- UWP: Updated icons courtesy of Danp142
- UWP/XBOX: Disable CPU model check on Xbox as it doesn't work and can even crash
- UWP/VFS/XBOX: Code cleanup and simplification of UWP VFS driver
# 1.9.8
- AUDIO/WINDOWS/WASAPI: Stop deactivating audio on fast forward
- CHEEVOS: Hide challenge indicators when resetting
+86 -43
View File
@@ -3,64 +3,107 @@ Struct ordering
For POD-types, try to order structs as follows (first to last):
* long double (8 bytes, 16 bytes [64bit x86], 12 bytes [32bit x86])
* double (8 bytes)
* int64_t (8 bytes, 8 bytes [32bit ARM], 4 bytes [32bit x86])
* uint64_t (4 bytes [32bit], 8 bytes [32bit ARM], 8 bytes [64bit])
* pointer (4 bytes [32bit], 8 bytes [64bit] [1])
* intptr_t (4 bytes [32bit], 8 bytes [64bit] [1])
* uintptr_t (4 bytes [32bit], 8 bytes [64bit] [1])
* ptrdiff_t (4 bytes [32bit], 8 bytes [64bit] [1])
* ssize_t (4 bytes [32bit], 8 bytes [64bit])
* size_t (4 bytes [32bit], 8 bytes [64bit])
* jmp_buf (4 bytes)
* long (4 bytes [64bit Win], 8 bytes [64bit non-Win], 4 bytes [32bit])
* int32_t (4 bytes)
* unsigned (4 bytes)
* float (4 bytes)
* int (4 bytes)
* enum (4 bytes)
* int16_t (2 bytes)
* char (1 byte)
* long double (8 bytes, 16 bytes [64bit x86], 12 bytes [32bit x86])
* double (8 bytes)
* int64_t (8 bytes, 8 bytes [32bit ARM],
4 bytes [32bit x86])
* uint64_t (4 bytes [32bit], 8 bytes [32bit ARM], 8 bytes [64bit])
* pointer (4 bytes [32bit], 8 bytes [64bit] [1])
* intptr_t (4 bytes [32bit], 8 bytes [64bit] [1])
* uintptr_t (4 bytes [32bit], 8 bytes [64bit] [1])
* ptrdiff_t (4 bytes [32bit], 8 bytes [64bit] [1])
* ssize_t (4 bytes [32bit], 8 bytes [64bit])
* size_t (4 bytes [32bit], 8 bytes [64bit])
* jmp_buf (4 bytes)
* long (4 bytes [64bit Win], 8 bytes [64bit non-Win],
4 bytes [32bit])
* int32_t (4 bytes)
* unsigned (4 bytes)
* float (4 bytes)
* int (4 bytes)
* enum (4 bytes)
* int16_t (2 bytes)
* char (1 byte)
* bool (1 byte)
[1] PS3 uses 4 byte pointers despite having a 64bit processor
[1] PS3 uses 4 byte pointers despite having a 64bit processor
Struct members should be sorted by alignment. Therefore, structs
should be sorted by the largest type inside them.
Struct members should be sorted by alignment. Therefore, structs
should be sorted by the largest type inside them.
For example, take a struct like this:
For example, take a struct like this:
typedef struct
{
size_t capacity;
bool old_format;
bool compress;
bool fuzzy_archive_match;
bool autofix_paths;
char path[PATH_MAX_LENGTH];
char base_content_directory[PATH_MAX_LENGTH];
} playlist_config_t;
typedef struct
{
size_t capacity;
bool old_format;
bool compress;
bool fuzzy_archive_match;
bool autofix_paths;
char path[PATH_MAX_LENGTH];
char base_content_directory[PATH_MAX_LENGTH];
} playlist_config_t;
size_t has the biggest alignment here, so 'struct playlist_config_t' inside a struct should come before or after size_t.
size_t has the biggest alignment here, so 'struct playlist_config_t'
inside a struct should come before or after size_t.
*** BEST PRACTICES ***
* If we have pointers and size variable pairs, it's best to interleave them to increase the probability they go in the same cacheline. It also makes the code more readable, that these two variables are connected.
* If we have pointers and size variable pairs, it's best to
interleave them to increase the probability they go in the
same cacheline. It also makes the code more readable, that
these two variables are connected.
Example:
struct a
{
char* b;
size_t b_len;
char* c;
size_t c_len;
};
struct a
{
char* b;
size_t b_len;
char* c;
size_t c_len;
};
Stack size
----------
You have to assume that stack size is going to be limited in RetroArch. Some game consoles (and other embedded systems) might have a default stack size as low as 128Kb or less. Be conservative with stack size but don't try to put very small structs on heap either [to avoid memory fragmentation among other things].
You have to assume that stack size is going to be limited in
RetroArch. Some game consoles (and other embedded systems)
might have a default stack size as low as 128Kb or less.
Be conservative with stack size but don't try to put very
small structs on heap either [to avoid memory fragmentation
among other things]. A balancing act here is necessary.
Be mindful that heap allocations are slow compared to stack.
Functions
---------
- Avoid doing small getter/setter functions. We want a function
to justify its function call overhead by doing a significant
body of work. Small one-line getter/setter functions for what
is predominantly C-style structs is not useful, plus it leads
to people thinking this function is more complex than it
actually is, thus obfuscating the sourcecode instead of it
being easier to read.
If you can find examples in the codebase that violate this
guideline, do not hesitate to point them out to us.
Variable declaration
--------------------
For C source files, we have to insist you stick to the following:
- Declare variables either at the start of a function or the start
of a code block, depending on the scope they need.
- Do not do initial for loop declarations. Refer to the bulletpoint above:
either declare them at the start of the function, or at the start
of the code block.
Not doing this would break compilation on platforms where we are compiling
these C source files in C89 compatibility mode. If such issues occur in pull
requests, we have to request that it be fixed.
VLA (Variable Length Array)
---------------------------
Do not use VLAs (Variable Length Array) in C source files. These are not
C89-compliant.
+11 -23
View File
@@ -134,7 +134,6 @@ ifneq ($(findstring Darwin,$(OS)),)
MINVERFLAGS=
ifeq ($(shell uname -p),arm)
MINVERFLAGS = -mmacosx-version-min=10.15 -stdlib=libc++ # macOS (Metal, ARM 64bit)
MINVERFLAGS += -DDONT_WANT_ARM_ASM_OPTIMIZATIONS
else ifeq ($(HAVE_METAL),1)
MINVERFLAGS = -mmacosx-version-min=10.13 -stdlib=libc++ # macOS (Metal, x86 64bit)
else ifeq ($(shell uname -p),powerpc)
@@ -148,7 +147,6 @@ ifneq ($(findstring Darwin,$(OS)),)
# Build for a specific architecture when ARCH is defined as a switch
ifeq ($(ARCH),arm64)
MINVERFLAGS = -mmacosx-version-min=10.15 -stdlib=libc++ # macOS (Metal, ARM 64bit)
MINVERFLAGS += -DDONT_WANT_ARM_ASM_OPTIMIZATIONS
ARCHFLAGS = -arch arm64
else ifeq ($(ARCH),x86_64)
ifeq ($(HAVE_METAL),1)
@@ -190,6 +188,10 @@ endif
ifeq ($(HAVE_UNIX), 1)
OBJ += frontend/drivers/platform_unix.o
ifeq ($(UNIX_CWD_ENV), 1)
DEF_FLAGS += -DRARCH_UNIX_CWD_ENV
endif
endif
ifeq ($(TARGET), retroarch_3ds)
@@ -970,10 +972,6 @@ ifeq ($(HW_CONTEXT_MENU_DRIVERS), 1)
HAVE_XMB = 1
endif
ifeq ($(HAVE_STRIPES),)
HAVE_STRIPES = 0
endif
ifeq ($(HAVE_OZONE),)
HAVE_OZONE = 1
endif
@@ -981,7 +979,6 @@ else
HAVE_RGUI ?= 0
HAVE_MATERIALUI ?= 0
HAVE_XMB ?= 0
HAVE_STRIPES ?= 0
HAVE_OZONE ?= 0
endif
@@ -1013,22 +1010,12 @@ ifeq ($(HAVE_MENU), 1)
endif
ifeq ($(HAVE_OZONE), 1)
OBJ += menu/drivers/ozone/ozone.o \
menu/drivers/ozone/ozone_entries.o \
menu/drivers/ozone/ozone_display.o \
menu/drivers/ozone/ozone_texture.o \
menu/drivers/ozone/ozone_theme.o \
menu/drivers/ozone/ozone_sidebar.o
OBJ += menu/drivers/ozone.o
DEFINES += -DHAVE_OZONE
HAVE_ASSETS = 1
HAVE_MENU_SCREENSAVER = 1
endif
ifeq ($(HAVE_STRIPES), 1)
OBJ += menu/drivers/stripes.o
DEFINES += -DHAVE_STRIPES
endif
ifeq ($(HAVE_MENU_SCREENSAVER), 1)
OBJ += menu/menu_screensaver.o
endif
@@ -1048,6 +1035,7 @@ endif
ifeq ($(HAVE_MENU_COMMON), 1)
OBJ += menu/menu_setting.o \
menu/menu_driver.o \
menu/cbs/menu_cbs_ok.o \
menu/cbs/menu_cbs_cancel.o \
menu/cbs/menu_cbs_select.o \
@@ -2111,10 +2099,9 @@ ifeq ($(HAVE_NETWORKING), 1)
# Netplay
DEFINES += -DHAVE_NETWORK_CMD
OBJ += network/netplay/netplay_handshake.o \
network/netplay/netplay_io.o \
network/netplay/netplay_discovery.o \
network/netplay/netplay_room_parse.o
OBJ += \
network/netplay/netplay_frontend.o \
network/netplay/netplay_room_parse.o
# RetroAchievements
ifeq ($(HAVE_CHEEVOS), 1)
@@ -2379,7 +2366,8 @@ ifeq ($(HAVE_STATIC_VIDEO_FILTERS), 1)
gfx/video_filters/dot_matrix_3x.o \
gfx/video_filters/dot_matrix_4x.o \
gfx/video_filters/upscale_1_5x.o \
gfx/video_filters/upscale_256x_320x240.o
gfx/video_filters/upscale_256x_320x240.o \
gfx/video_filters/picoscale_256x_320x240.o
endif
ifeq ($(WANT_IOSUHAX), 1)
+5
View File
@@ -2,6 +2,7 @@ TARGET := retroarch_3ds
LIBRETRO =
DEBUG = 0
CONSOLE_LOG = 0
GRIFFIN_BUILD = 1
WHOLE_ARCHIVE_LINK = 0
BUILD_3DSX = 1
@@ -154,6 +155,10 @@ else
CFLAGS += -O3
endif
ifeq ($(CONSOLE_LOG), 1)
CFLAGS += -DCONSOLE_LOG
endif
ifeq ($(LIBCTRU_NO_DEPRECATION), 1)
CFLAGS += -DLIBCTRU_NO_DEPRECATION
endif
+5
View File
@@ -2,6 +2,7 @@ TARGET := retroarch_3ds_salamander
LIBRETRO =
DEBUG = 0
CONSOLE_LOG = 0
BUILD_3DSX = 1
BUILD_3DS = 0
BUILD_CIA = 1
@@ -95,6 +96,10 @@ else
CFLAGS += -O3
endif
ifeq ($(CONSOLE_LOG), 1)
CFLAGS += -DCONSOLE_LOG
endif
CFLAGS += -I. -Ideps/7zip -Ideps/stb -Ilibretro-common/include -Ilibretro-common/include/compat/zlib
#CFLAGS += -DRARCH_INTERNAL
+5 -1
View File
@@ -40,6 +40,7 @@ HAVE_DSP_FILTER = 1
HAVE_VIDEO_FILTER = 1
HAVE_STATIC_VIDEO_FILTERS = 1
HAVE_STATIC_AUDIO_FILTERS = 1
HAVE_FILTERS_BUILTIN = 1
HAVE_MENU = 1
HAVE_CONFIGFILE = 1
HAVE_PATCH = 1
@@ -78,7 +79,6 @@ else
HAVE_MATERIALUI = 0
HAVE_XMB = 0
HAVE_OZONE = 0
HAVE_STRIPES = 0
endif
include Makefile.common
@@ -129,6 +129,10 @@ CFLAGS := -g -Wall -O3 -fcommon -ffast-math -ffunction-sections \
CFLAGS += $(INCLUDE) -DSWITCH=1 -DHAVE_LIBNX=1 -DNXLINK=1 -DHAVE_SHADERPIPELINE -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_STB_FONT #-DHAVE_FREETYPE
ifeq ($(HAVE_FILTERS_BUILTIN), 1)
CFLAGS += -DHAVE_FILTERS_BUILTIN
endif
ifeq ($(strip $(HAVE_STATIC_DUMMY)),1)
CFLAGS += -DHAVE_STATIC_DUMMY=1
endif
+2 -2
View File
@@ -44,7 +44,7 @@ DINGUX_BETA = 1
HAVE_SCREENSHOTS = 0
HAVE_REWIND = 1
HAVE_7ZIP = 1
HAVE_AL = 1
HAVE_AL = 0
HAVE_ALSA = 1
HAVE_DSP_FILTER = 1
HAVE_VIDEO_FILTER = 1
@@ -117,6 +117,7 @@ OBJ :=
LINK := $(CXX)
DEF_FLAGS := -mplt -mno-shared
DEF_FLAGS += -ffunction-sections -fdata-sections
DEF_FLAGS += -ffast-math
DEF_FLAGS += -I. -Ideps -Ideps/stb -DDINGUX=1 -DDINGUX_BETA=1 -MMD
DEF_FLAGS += -Wall -Wno-unused-variable
DEF_FLAGS += -std=gnu99 -D_GNU_SOURCE -flto
@@ -131,7 +132,6 @@ LIBRARY_DIRS = -L$(GCW0_LIB_DIR)
DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1
DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
DEFINES += -DHAVE_AL=1
DEFINES += -DHAVE_FILTERS_BUILTIN
DEFINES += -DHAVE_UDEV=1
DEFINES += -DHAVE_ALSA
+1 -1
View File
@@ -24,7 +24,7 @@
#include <sys/audioio.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#include "../../retroarch.h"
+1 -1
View File
@@ -30,7 +30,7 @@
#include <retro_endianness.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#include "../../retroarch.h"
-6
View File
@@ -29,12 +29,6 @@
#include <audio/audio_resampler.h>
#if (defined(__ARM_NEON__) && !defined(DONT_WANT_ARM_ASM_OPTIMIZATIONS)) || defined(HAVE_NEON)
#ifndef HAVE_ARM_NEON_ASM_OPTIMIZATIONS
#define HAVE_ARM_NEON_ASM_OPTIMIZATIONS
#endif
#endif
/* Since SSE and NEON don't provide support for trigonometric functions
* we approximate those with polynoms
*
+624 -5
View File
@@ -22,11 +22,36 @@
#include <net/net_compat.h>
#include <net/net_socket.h>
#endif
#include <lists/dir_list.h>
#include <streams/stdin_stream.h>
#include <streams/file_stream.h>
#include <string/stdstring.h>
#include "verbosity.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_CHEEVOS
#include "cheevos/cheevos.h"
#endif
#ifdef HAVE_GFX_WIDGETS
#include "gfx/gfx_widgets.h"
#endif
#ifdef HAVE_NETWORKING
#include "network/netplay/netplay.h"
#endif
#include "command.h"
#include "cheat_manager.h"
#include "content.h"
#include "dynamic.h"
#include "list_special.h"
#include "paths.h"
#include "verbosity.h"
#include "version.h"
#include "version_git.h"
#define CMD_BUF_SIZE 4096
@@ -91,10 +116,7 @@ static void command_parse_sub_msg(command_t *handle, const char *tok)
handle->state[map[index].id] = true;
}
else
RARCH_WARN("%s \"%s\" %s.\n",
msg_hash_to_str(MSG_UNRECOGNIZED_COMMAND),
tok,
msg_hash_to_str(MSG_RECEIVED));
RARCH_WARN(msg_hash_to_str(MSG_UNRECOGNIZED_COMMAND), tok);
}
static void command_parse_msg(
@@ -532,4 +554,601 @@ bool command_network_send(const char *cmd_)
}
#endif
bool command_show_osd_msg(command_t *cmd, const char* arg)
{
runloop_msg_queue_push(arg, 1, 180, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return true;
}
#if defined(HAVE_CHEEVOS)
bool command_read_ram(command_t *cmd, const char *arg)
{
unsigned i;
char *reply = NULL;
const uint8_t *data = NULL;
char *reply_at = NULL;
unsigned int nbytes = 0;
unsigned int alloc_size = 0;
unsigned int addr = -1;
unsigned int len = 0;
if (sscanf(arg, "%x %u", &addr, &nbytes) != 2)
return true;
/* We allocate more than needed, saving 20 bytes is not really relevant */
alloc_size = 40 + nbytes * 3;
reply = (char*)malloc(alloc_size);
reply[0] = '\0';
reply_at = reply + snprintf(
reply, alloc_size - 1, "READ_CORE_RAM" " %x", addr);
if ((data = rcheevos_patch_address(addr)))
{
for (i = 0; i < nbytes; i++)
snprintf(reply_at + 3 * i, 4, " %.2X", data[i]);
reply_at[3 * nbytes] = '\n';
len = reply_at + 3 * nbytes + 1 - reply;
}
else
{
strlcpy(reply_at, " -1\n", sizeof(reply) - strlen(reply));
len = reply_at + STRLEN_CONST(" -1\n") - reply;
}
cmd->replier(cmd, reply, len);
free(reply);
return true;
}
bool command_write_ram(command_t *cmd, const char *arg)
{
unsigned int addr = (unsigned int)strtoul(arg, (char**)&arg, 16);
uint8_t *data = (uint8_t *)rcheevos_patch_address(addr);
if (!data)
return false;
if (rcheevos_hardcore_active())
{
RARCH_LOG("Achievements hardcore mode disabled by WRITE_CORE_RAM\n");
rcheevos_pause_hardcore();
}
while (*arg)
{
*data = strtoul(arg, (char**)&arg, 16);
data++;
}
return true;
}
#endif
bool command_version(command_t *cmd, const char* arg)
{
char reply[256] = {0};
snprintf(reply, sizeof(reply), "%s\n", PACKAGE_VERSION);
cmd->replier(cmd, reply, strlen(reply));
return true;
}
static const rarch_memory_descriptor_t* command_memory_get_descriptor(const rarch_memory_map_t* mmap, unsigned address)
{
const rarch_memory_descriptor_t* desc = mmap->descriptors;
const rarch_memory_descriptor_t* end = desc + mmap->num_descriptors;
for (; desc < end; desc++)
{
if (desc->core.select == 0)
{
/* if select is 0, attempt to explicitly match the address */
if (address >= desc->core.start && address < desc->core.start + desc->core.len)
return desc;
}
else
{
/* otherwise, attempt to match the address by matching the select bits */
if (((desc->core.start ^ address) & desc->core.select) == 0)
{
/* sanity check - make sure the descriptor is large enough to hold the target address */
if (address - desc->core.start < desc->core.len)
return desc;
}
}
}
return NULL;
}
uint8_t *command_memory_get_pointer(
const rarch_system_info_t* system,
unsigned address,
unsigned int* max_bytes,
int for_write,
char *reply_at,
size_t len)
{
if (!system || system->mmaps.num_descriptors == 0)
strlcpy(reply_at, " -1 no memory map defined\n", len);
else
{
const rarch_memory_descriptor_t* desc = command_memory_get_descriptor(&system->mmaps, address);
if (!desc)
strlcpy(reply_at, " -1 no descriptor for address\n", len);
else if (!desc->core.ptr)
strlcpy(reply_at, " -1 no data for descriptor\n", len);
else if (for_write && (desc->core.flags & RETRO_MEMDESC_CONST))
strlcpy(reply_at, " -1 descriptor data is readonly\n", len);
else
{
const size_t offset = address - desc->core.start;
*max_bytes = (desc->core.len - offset);
return (uint8_t*)desc->core.ptr + desc->core.offset + offset;
}
}
*max_bytes = 0;
return NULL;
}
#endif
void command_event_set_volume(
settings_t *settings,
float gain,
bool widgets_active,
bool audio_driver_mute_enable)
{
char msg[128];
float new_volume = settings->floats.audio_volume + gain;
new_volume = MAX(new_volume, -80.0f);
new_volume = MIN(new_volume, 12.0f);
configuration_set_float(settings, settings->floats.audio_volume, new_volume);
snprintf(msg, sizeof(msg), "%s: %.1f dB",
msg_hash_to_str(MSG_AUDIO_VOLUME),
new_volume);
#if defined(HAVE_GFX_WIDGETS)
if (widgets_active)
gfx_widget_volume_update_and_show(new_volume,
audio_driver_mute_enable);
else
#endif
runloop_msg_queue_push(msg, 1, 180, true, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
RARCH_LOG("[Audio]: %s\n", msg);
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, new_volume);
}
/**
* event_set_mixer_volume:
* @gain : amount of gain to be applied to current volume level.
*
* Adjusts the current audio volume level.
*
**/
void command_event_set_mixer_volume(
settings_t *settings,
float gain)
{
char msg[128];
float new_volume = settings->floats.audio_mixer_volume + gain;
new_volume = MAX(new_volume, -80.0f);
new_volume = MIN(new_volume, 12.0f);
configuration_set_float(settings, settings->floats.audio_mixer_volume, new_volume);
snprintf(msg, sizeof(msg), "%s: %.1f dB",
msg_hash_to_str(MSG_AUDIO_VOLUME),
new_volume);
runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
RARCH_LOG("[Audio]: %s\n", msg);
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, new_volume);
}
void command_event_init_controllers(rarch_system_info_t *info,
settings_t *settings, unsigned num_active_users)
{
unsigned port;
unsigned num_core_ports = info->ports.size;
for (port = 0; port < num_core_ports; port++)
{
unsigned i;
retro_ctx_controller_info_t pad;
unsigned device = RETRO_DEVICE_NONE;
const struct retro_controller_description *desc = NULL;
/* Check whether current core port is mapped
* to an input device
* > If is not, leave 'device' set to
* 'RETRO_DEVICE_NONE'
* > For example: if input ports 0 and 1 are
* mapped to core port 0, core port 1 will
* be unmapped and should be disabled */
for (i = 0; i < num_active_users; i++)
{
if (i >= MAX_USERS)
break;
if (port == settings->uints.input_remap_ports[i])
{
device = input_config_get_device(port);
break;
}
}
desc = libretro_find_controller_description(
&info->ports.data[port], device);
if (desc && !desc->desc)
{
/* If we're trying to connect a completely unknown device,
* revert back to JOYPAD. */
if (device != RETRO_DEVICE_JOYPAD && device != RETRO_DEVICE_NONE)
{
/* Do not fix device,
* because any use of dummy core will reset this,
* which is not a good idea. */
RARCH_WARN("[Input]: Input device ID %u is unknown to this "
"libretro implementation. Using RETRO_DEVICE_JOYPAD.\n",
device);
device = RETRO_DEVICE_JOYPAD;
}
}
pad.device = device;
pad.port = port;
core_set_controller_port_device(&pad);
}
}
#ifdef HAVE_CONFIGFILE
bool command_event_save_config(
const char *config_path,
char *s, size_t len)
{
bool path_exists = !string_is_empty(config_path);
const char *str = path_exists ? config_path :
path_get(RARCH_PATH_CONFIG);
if (path_exists && config_save_file(config_path))
{
snprintf(s, len, "%s \"%s\".",
msg_hash_to_str(MSG_SAVED_NEW_CONFIG_TO),
config_path);
RARCH_LOG("[Config]: %s\n", s);
return true;
}
if (!string_is_empty(str))
{
snprintf(s, len, "%s \"%s\".",
msg_hash_to_str(MSG_FAILED_SAVING_CONFIG_TO),
str);
RARCH_ERR("[Config]: %s\n", s);
}
return false;
}
#endif
void command_event_undo_save_state(char *s, size_t len)
{
if (content_undo_save_buf_is_empty())
{
strlcpy(s,
msg_hash_to_str(MSG_NO_SAVE_STATE_HAS_BEEN_OVERWRITTEN_YET), len);
return;
}
if (!content_undo_save_state())
{
strlcpy(s,
msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE), len);
return;
}
strlcpy(s,
msg_hash_to_str(MSG_UNDOING_SAVE_STATE), len);
}
void command_event_undo_load_state(char *s, size_t len)
{
if (content_undo_load_buf_is_empty())
{
strlcpy(s,
msg_hash_to_str(MSG_NO_STATE_HAS_BEEN_LOADED_YET),
len);
return;
}
if (!content_undo_load_state())
{
snprintf(s, len, "%s \"%s\".",
msg_hash_to_str(MSG_FAILED_TO_UNDO_LOAD_STATE),
"RAM");
return;
}
#ifdef HAVE_NETWORKING
netplay_driver_ctl(RARCH_NETPLAY_CTL_LOAD_SAVESTATE, NULL);
#endif
strlcpy(s,
msg_hash_to_str(MSG_UNDID_LOAD_STATE), len);
}
bool command_event_resize_windowed_scale(settings_t *settings,
unsigned window_scale)
{
unsigned idx = 0;
bool video_fullscreen = settings->bools.video_fullscreen;
if (window_scale == 0)
return false;
configuration_set_float(settings, settings->floats.video_scale, (float)window_scale);
if (!video_fullscreen)
command_event(CMD_EVENT_REINIT, NULL);
rarch_ctl(RARCH_CTL_SET_WINDOWED_SCALE, &idx);
return true;
}
bool command_event_save_auto_state(
bool savestate_auto_save,
global_t *global,
const enum rarch_core_type current_core_type)
{
bool ret = false;
char savestate_name_auto[PATH_MAX_LENGTH];
if (!global || !savestate_auto_save)
return false;
if (current_core_type == CORE_TYPE_DUMMY)
return false;
if (string_is_empty(path_basename(path_get(RARCH_PATH_BASENAME))))
return false;
#ifdef HAVE_CHEEVOS
if (rcheevos_hardcore_active())
return false;
#endif
savestate_name_auto[0] = '\0';
fill_pathname_noext(savestate_name_auto, global->name.savestate,
".auto", sizeof(savestate_name_auto));
ret = content_save_state((const char*)savestate_name_auto, true, true);
RARCH_LOG("%s \"%s\" %s.\n",
msg_hash_to_str(MSG_AUTO_SAVE_STATE_TO),
savestate_name_auto, ret ?
"succeeded" : "failed");
return true;
}
#ifdef HAVE_CHEATS
void command_event_init_cheats(
bool apply_cheats_after_load,
const char *path_cheat_db,
void *bsv_movie_data)
{
#ifdef HAVE_NETWORKING
bool allow_cheats = !netplay_driver_ctl(
RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL);
#else
bool allow_cheats = true;
#endif
#ifdef HAVE_BSV_MOVIE
bsv_movie_t *
bsv_movie_state_handle = (bsv_movie_t*)bsv_movie_data;
allow_cheats &= !(bsv_movie_state_handle != NULL);
#endif
if (!allow_cheats)
return;
cheat_manager_alloc_if_empty();
cheat_manager_load_game_specific_cheats(path_cheat_db);
if (apply_cheats_after_load)
cheat_manager_apply_cheats();
}
#endif
void command_event_load_auto_state(global_t *global)
{
char savestate_name_auto[PATH_MAX_LENGTH];
bool ret = false;
#ifdef HAVE_CHEEVOS
if (rcheevos_hardcore_active())
return;
#endif
#ifdef HAVE_NETWORKING
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
return;
#endif
savestate_name_auto[0] = '\0';
fill_pathname_noext(savestate_name_auto, global->name.savestate,
".auto", sizeof(savestate_name_auto));
if (!path_is_valid(savestate_name_auto))
return;
ret = content_load_state(savestate_name_auto, false, true);
RARCH_LOG("%s: %s\n%s \"%s\" %s.\n",
msg_hash_to_str(MSG_FOUND_AUTO_SAVESTATE_IN),
savestate_name_auto,
msg_hash_to_str(MSG_AUTOLOADING_SAVESTATE_FROM),
savestate_name_auto, ret ? "succeeded" : "failed"
);
}
void command_event_set_savestate_auto_index(
settings_t *settings,
const global_t *global)
{
size_t i;
char state_dir[PATH_MAX_LENGTH];
char state_base[PATH_MAX_LENGTH];
struct string_list *dir_list = NULL;
unsigned max_idx = 0;
bool savestate_auto_index = settings->bools.savestate_auto_index;
bool show_hidden_files = settings->bools.show_hidden_files;
if (!global || !savestate_auto_index)
return;
state_dir[0] = state_base[0] = '\0';
/* Find the file in the same directory as global->savestate_name
* with the largest numeral suffix.
*
* E.g. /foo/path/content.state, will try to find
* /foo/path/content.state%d, where %d is the largest number available.
*/
fill_pathname_basedir(state_dir, global->name.savestate,
sizeof(state_dir));
dir_list = dir_list_new_special(state_dir, DIR_LIST_PLAIN, NULL,
show_hidden_files);
if (!dir_list)
return;
fill_pathname_base(state_base, global->name.savestate,
sizeof(state_base));
for (i = 0; i < dir_list->size; i++)
{
unsigned idx;
char elem_base[128] = {0};
const char *end = NULL;
const char *dir_elem = dir_list->elems[i].data;
fill_pathname_base(elem_base, dir_elem, sizeof(elem_base));
if (strstr(elem_base, state_base) != elem_base)
continue;
end = dir_elem + strlen(dir_elem);
while ((end > dir_elem) && ISDIGIT((int)end[-1]))
end--;
idx = (unsigned)strtoul(end, NULL, 0);
if (idx > max_idx)
max_idx = idx;
}
dir_list_free(dir_list);
configuration_set_int(settings, settings->ints.state_slot, max_idx);
RARCH_LOG("%s: #%d\n",
msg_hash_to_str(MSG_FOUND_LAST_STATE_SLOT),
max_idx);
}
void command_event_set_savestate_garbage_collect(
const global_t *global,
unsigned max_to_keep,
bool show_hidden_files
)
{
size_t i, cnt = 0;
char state_dir[PATH_MAX_LENGTH];
char state_base[PATH_MAX_LENGTH];
struct string_list *dir_list = NULL;
unsigned min_idx = UINT_MAX;
const char *oldest_save = NULL;
state_dir[0] = '\0';
state_base[0] = '\0';
/* Similar to command_event_set_savestate_auto_index(),
* this will find the lowest numbered save-state */
fill_pathname_basedir(state_dir, global->name.savestate,
sizeof(state_dir));
dir_list = dir_list_new_special(state_dir, DIR_LIST_PLAIN, NULL,
show_hidden_files);
if (!dir_list)
return;
fill_pathname_base(state_base, global->name.savestate,
sizeof(state_base));
for (i = 0; i < dir_list->size; i++)
{
unsigned idx;
char elem_base[128];
const char *ext = NULL;
const char *end = NULL;
const char *dir_elem = dir_list->elems[i].data;
elem_base[0] = '\0';
if (string_is_empty(dir_elem))
continue;
fill_pathname_base(elem_base, dir_elem, sizeof(elem_base));
/* Only consider files with a '.state' extension
* > i.e. Ignore '.state.auto', '.state.bak', etc. */
ext = path_get_extension(elem_base);
if (string_is_empty(ext) ||
!string_starts_with_size(ext, "state", STRLEN_CONST("state")))
continue;
/* Check whether this file is associated with
* the current content */
if (!string_starts_with(elem_base, state_base))
continue;
/* This looks like a valid save */
cnt++;
/* > Get index */
end = dir_elem + strlen(dir_elem);
while ((end > dir_elem) && ISDIGIT((int)end[-1]))
end--;
idx = string_to_unsigned(end);
/* > Check if this is the lowest index so far */
if (idx < min_idx)
{
min_idx = idx;
oldest_save = dir_elem;
}
}
/* Only delete one save state per save action
* > Conservative behaviour, designed to minimise
* the risk of deleting multiple incorrect files
* in case of accident */
if (!string_is_empty(oldest_save) && (cnt > max_to_keep))
filestream_delete(oldest_save);
dir_list_free(dir_list);
}
+126 -12
View File
@@ -23,13 +23,16 @@
#include <boolean.h>
#include <retro_common_api.h>
#include "retroarch.h"
#include "input/input_defines.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <streams/interface_stream.h>
#include "retroarch.h"
#include "input/input_defines.h"
RETRO_BEGIN_DECLS
#define MAX_CMD_DRIVERS 3
@@ -73,16 +76,22 @@ enum event_command
/* Loads core. */
CMD_EVENT_LOAD_CORE,
CMD_EVENT_LOAD_CORE_PERSIST,
#if defined(HAVE_RUNAHEAD) && (defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB))
CMD_EVENT_LOAD_SECOND_CORE,
#endif
CMD_EVENT_UNLOAD_CORE,
CMD_EVENT_CLOSE_CONTENT,
CMD_EVENT_LOAD_STATE,
CMD_EVENT_LOAD_STATE_FROM_RAM,
/* Swaps the current state with what's on the undo load buffer */
CMD_EVENT_UNDO_LOAD_STATE,
/* Rewrites a savestate on disk */
CMD_EVENT_UNDO_SAVE_STATE,
CMD_EVENT_SAVE_STATE,
CMD_EVENT_SAVE_STATE_TO_RAM,
CMD_EVENT_SAVE_STATE_DECREMENT,
CMD_EVENT_SAVE_STATE_INCREMENT,
CMD_EVENT_RAM_STATE_TO_FILE,
/* Takes screenshot. */
CMD_EVENT_TAKE_SCREENSHOT,
/* Quits RetroArch. */
@@ -274,12 +283,116 @@ command_t* command_uds_new(void);
bool command_network_send(const char *cmd_);
/* These forward declarations need to be declared before
* the global state is declared */
#ifdef HAVE_BSV_MOVIE
struct bsv_state
{
/* Movie playback/recording support. */
char movie_path[PATH_MAX_LENGTH];
/* Immediate playback/recording. */
char movie_start_path[PATH_MAX_LENGTH];
bool movie_start_recording;
bool movie_start_playback;
bool movie_playback;
bool eof_exit;
bool movie_end;
};
struct bsv_movie
{
intfstream_t *file;
uint8_t *state;
/* A ring buffer keeping track of positions
* in the file for each frame. */
size_t *frame_pos;
size_t frame_mask;
size_t frame_ptr;
size_t min_file_pos;
size_t state_size;
bool playback;
bool first_rewind;
bool did_rewind;
};
typedef struct bsv_movie bsv_movie_t;
#endif
#ifdef HAVE_CONFIGFILE
bool command_event_save_config(
const char *config_path,
char *s, size_t len);
#endif
void command_event_undo_save_state(char *s, size_t len);
void command_event_undo_load_state(char *s, size_t len);
void command_event_set_mixer_volume(
settings_t *settings,
float gain);
bool command_event_resize_windowed_scale(settings_t *settings,
unsigned window_scale);
bool command_event_save_auto_state(
bool savestate_auto_save,
global_t *global,
const enum rarch_core_type current_core_type);
/**
* event_set_volume:
* @gain : amount of gain to be applied to current volume level.
*
* Adjusts the current audio volume level.
*
**/
void command_event_set_volume(
settings_t *settings,
float gain,
bool widgets_active,
bool audio_driver_mute_enable);
/**
* command_event_init_controllers:
*
* Initialize libretro controllers.
**/
void command_event_init_controllers(rarch_system_info_t *info,
settings_t *settings, unsigned num_active_users);
void command_event_load_auto_state(global_t *global);
void command_event_set_savestate_auto_index(
settings_t *settings,
const global_t *global);
void command_event_set_savestate_garbage_collect(
const global_t *global,
unsigned max_to_keep,
bool show_hidden_files
);
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
bool command_set_shader(command_t *cmd, const char *arg);
#endif
#ifdef HAVE_CHEATS
void command_event_init_cheats(
bool apply_cheats_after_load,
const char *path_cheat_db,
void *bsv_movie_data);
#endif
#if defined(HAVE_COMMAND)
struct cmd_action_map
{
const char *str;
bool (*action)(command_t* cmd, const char *arg);
const char *arg_desc;
};
bool command_version(command_t *cmd, const char* arg);
bool command_get_status(command_t *cmd, const char* arg);
bool command_get_config_param(command_t *cmd, const char* arg);
@@ -290,13 +403,13 @@ bool command_write_ram(command_t *cmd, const char *arg);
#endif
bool command_read_memory(command_t *cmd, const char *arg);
bool command_write_memory(command_t *cmd, const char *arg);
struct cmd_action_map
{
const char *str;
bool (*action)(command_t* cmd, const char *arg);
const char *arg_desc;
};
uint8_t *command_memory_get_pointer(
const rarch_system_info_t* system,
unsigned address,
unsigned int* max_bytes,
int for_write,
char *reply_at,
size_t len);
static const struct cmd_action_map action_map[] = {
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
@@ -368,6 +481,7 @@ static const struct cmd_map map[] = {
};
#endif
RETRO_END_DECLS
#endif
+18 -1
View File
@@ -412,6 +412,21 @@
#define DEFAULT_SHADER_ENABLE false
#endif
/* Should we enable hdr when its supported*/
#define DEFAULT_VIDEO_HDR_ENABLE false
/* The maximum nunmber of nits the actual display can show - needs to be calibrated */
#define DEFAULT_VIDEO_HDR_MAX_NITS 1000.0f
/* The number of nits that paper white is at */
#define DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS 200.0f
/* The contrast setting for hdr used to calculate the display gamma by dividing this value by gamma 2.2 */
#define DEFAULT_VIDEO_HDR_CONTRAST 5.0f
/* Should we expand the colour gamut when using hdr */
#define DEFAULT_VIDEO_HDR_EXPAND_GAMUT true
/* When presets are saved they will be saved using the #reference
* directive by default */
#define DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE true
@@ -1449,7 +1464,9 @@ static const bool enable_device_vibration = false;
/* Defines the strength of rumble effects
* on OpenDingux devices */
#if defined(DINGUX) && defined(HAVE_LIBSHAKE)
#define DEFAULT_DINGUX_RUMBLE_GAIN 50
#define DEFAULT_RUMBLE_GAIN 50
#else
#define DEFAULT_RUMBLE_GAIN 100
#endif
#ifdef HAVE_VULKAN
+694 -19
View File
@@ -259,6 +259,100 @@ enum midi_driver_enum
MIDI_NULL
};
#define DECLARE_BIND(base, bind, desc) { #base, desc, 0, bind, true }
#define DECLARE_META_BIND(level, base, bind, desc) { #base, desc, level, bind, true }
const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B),
DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_Y),
DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT,MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_SELECT),
DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_START),
DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_UP),
DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_DOWN),
DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LEFT),
DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_RIGHT),
DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_A),
DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_X),
DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L),
DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R),
DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L2),
DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R2),
DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L3),
DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R3),
DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_PLUS),
DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_MINUS),
DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_PLUS),
DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_MINUS),
DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_PLUS),
DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_MINUS),
DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_PLUS),
DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_MINUS),
DECLARE_BIND(gun_trigger, RARCH_LIGHTGUN_TRIGGER, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER ),
DECLARE_BIND(gun_offscreen_shot, RARCH_LIGHTGUN_RELOAD, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_RELOAD ),
DECLARE_BIND(gun_aux_a, RARCH_LIGHTGUN_AUX_A, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_A ),
DECLARE_BIND(gun_aux_b, RARCH_LIGHTGUN_AUX_B, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_B ),
DECLARE_BIND(gun_aux_c, RARCH_LIGHTGUN_AUX_C, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_C ),
DECLARE_BIND(gun_start, RARCH_LIGHTGUN_START, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_START ),
DECLARE_BIND(gun_select, RARCH_LIGHTGUN_SELECT, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_SELECT ),
DECLARE_BIND(gun_dpad_up, RARCH_LIGHTGUN_DPAD_UP, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_UP ),
DECLARE_BIND(gun_dpad_down, RARCH_LIGHTGUN_DPAD_DOWN, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_DOWN ),
DECLARE_BIND(gun_dpad_left, RARCH_LIGHTGUN_DPAD_LEFT, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_LEFT ),
DECLARE_BIND(gun_dpad_right, RARCH_LIGHTGUN_DPAD_RIGHT, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_RIGHT ),
DECLARE_BIND(turbo, RARCH_TURBO_ENABLE, MENU_ENUM_LABEL_VALUE_INPUT_TURBO_ENABLE),
DECLARE_META_BIND(1, toggle_fast_forward, RARCH_FAST_FORWARD_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_KEY),
DECLARE_META_BIND(2, hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_HOLD_KEY),
DECLARE_META_BIND(1, toggle_slowmotion, RARCH_SLOWMOTION_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION_KEY),
DECLARE_META_BIND(2, hold_slowmotion, RARCH_SLOWMOTION_HOLD_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION_HOLD_KEY),
DECLARE_META_BIND(1, load_state, RARCH_LOAD_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY),
DECLARE_META_BIND(1, save_state, RARCH_SAVE_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY),
DECLARE_META_BIND(2, toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY),
DECLARE_META_BIND(2, close_content, RARCH_CLOSE_CONTENT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_CLOSE_CONTENT_KEY),
#ifdef HAVE_LAKKA
DECLARE_META_BIND(2, exit_emulator, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY),
#else
DECLARE_META_BIND(2, exit_emulator, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY),
#endif
DECLARE_META_BIND(2, state_slot_increase, RARCH_STATE_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS),
DECLARE_META_BIND(2, state_slot_decrease, RARCH_STATE_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS),
DECLARE_META_BIND(1, rewind, RARCH_REWIND, MENU_ENUM_LABEL_VALUE_INPUT_META_REWIND),
DECLARE_META_BIND(2, movie_record_toggle, RARCH_BSV_RECORD_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_BSV_RECORD_TOGGLE),
DECLARE_META_BIND(2, pause_toggle, RARCH_PAUSE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_PAUSE_TOGGLE),
DECLARE_META_BIND(2, frame_advance, RARCH_FRAMEADVANCE, MENU_ENUM_LABEL_VALUE_INPUT_META_FRAMEADVANCE),
DECLARE_META_BIND(2, reset, RARCH_RESET, MENU_ENUM_LABEL_VALUE_INPUT_META_RESET),
DECLARE_META_BIND(2, shader_next, RARCH_SHADER_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_NEXT),
DECLARE_META_BIND(2, shader_prev, RARCH_SHADER_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_PREV),
DECLARE_META_BIND(2, cheat_index_plus, RARCH_CHEAT_INDEX_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_INDEX_PLUS),
DECLARE_META_BIND(2, cheat_index_minus, RARCH_CHEAT_INDEX_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_INDEX_MINUS),
DECLARE_META_BIND(2, cheat_toggle, RARCH_CHEAT_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_TOGGLE),
DECLARE_META_BIND(2, screenshot, RARCH_SCREENSHOT, MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT),
DECLARE_META_BIND(2, audio_mute, RARCH_MUTE, MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE),
DECLARE_META_BIND(2, osk_toggle, RARCH_OSK, MENU_ENUM_LABEL_VALUE_INPUT_META_OSK),
DECLARE_META_BIND(2, fps_toggle, RARCH_FPS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_FPS_TOGGLE),
DECLARE_META_BIND(2, send_debug_info, RARCH_SEND_DEBUG_INFO, MENU_ENUM_LABEL_VALUE_INPUT_META_SEND_DEBUG_INFO),
DECLARE_META_BIND(2, netplay_host_toggle, RARCH_NETPLAY_HOST_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_HOST_TOGGLE),
DECLARE_META_BIND(2, netplay_game_watch, RARCH_NETPLAY_GAME_WATCH, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH),
DECLARE_META_BIND(2, enable_hotkey, RARCH_ENABLE_HOTKEY, MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY),
DECLARE_META_BIND(2, volume_up, RARCH_VOLUME_UP, MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_UP),
DECLARE_META_BIND(2, volume_down, RARCH_VOLUME_DOWN, MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_DOWN),
DECLARE_META_BIND(2, overlay_next, RARCH_OVERLAY_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT),
DECLARE_META_BIND(2, disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_EJECT_TOGGLE),
DECLARE_META_BIND(2, disk_next, RARCH_DISK_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_NEXT),
DECLARE_META_BIND(2, disk_prev, RARCH_DISK_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV),
DECLARE_META_BIND(2, grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE),
DECLARE_META_BIND(2, game_focus_toggle, RARCH_GAME_FOCUS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GAME_FOCUS_TOGGLE),
DECLARE_META_BIND(2, desktop_menu_toggle, RARCH_UI_COMPANION_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_UI_COMPANION_TOGGLE),
#ifdef HAVE_MENU
DECLARE_META_BIND(1, menu_toggle, RARCH_MENU_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE),
#endif
DECLARE_META_BIND(2, recording_toggle, RARCH_RECORDING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_RECORDING_TOGGLE),
DECLARE_META_BIND(2, streaming_toggle, RARCH_STREAMING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_STREAMING_TOGGLE),
DECLARE_META_BIND(2, runahead_toggle, RARCH_RUNAHEAD_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE),
DECLARE_META_BIND(2, ai_service, RARCH_AI_SERVICE, MENU_ENUM_LABEL_VALUE_INPUT_META_AI_SERVICE),
};
#if defined(HAVE_METAL)
/* iOS supports both the OpenGL and Metal video drivers; default to OpenGL since Metal support is preliminary */
#if defined(HAVE_COCOATOUCH) && defined(HAVE_OPENGL)
@@ -1562,7 +1656,7 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("video_scale_integer", &settings->bools.video_scale_integer, true, DEFAULT_SCALE_INTEGER, false);
SETTING_BOOL("video_scale_integer_overscale", &settings->bools.video_scale_integer_overscale, true, DEFAULT_SCALE_INTEGER_OVERSCALE, 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_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);
#if defined(DINGUX)
SETTING_BOOL("video_dingux_ipu_keep_aspect", &settings->bools.video_dingux_ipu_keep_aspect, true, DEFAULT_DINGUX_IPU_KEEP_ASPECT, false);
@@ -1572,6 +1666,8 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, DEFAULT_AUTO_SCREENSHOT_FILENAME, false);
SETTING_BOOL("video_force_srgb_disable", &settings->bools.video_force_srgb_disable, true, false, false);
SETTING_BOOL("video_fullscreen", &settings->bools.video_fullscreen, true, DEFAULT_FULLSCREEN, false);
SETTING_BOOL("video_hdr_enable", &settings->bools.video_hdr_enable, true, DEFAULT_VIDEO_HDR_ENABLE, false);
SETTING_BOOL("video_hdr_expand_gamut", &settings->bools.video_hdr_expand_gamut, true, DEFAULT_VIDEO_HDR_EXPAND_GAMUT, false);
SETTING_BOOL("bundle_assets_extract_enable", &settings->bools.bundle_assets_extract_enable, true, DEFAULT_BUNDLE_ASSETS_EXTRACT_ENABLE, false);
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, DEFAULT_VSYNC, false);
SETTING_BOOL("video_adaptive_vsync", &settings->bools.video_adaptive_vsync, true, DEFAULT_ADAPTIVE_VSYNC, false);
@@ -1945,6 +2041,10 @@ static struct config_float_setting *populate_settings_float(
SETTING_FLOAT("input_analog_sensitivity", &settings->floats.input_analog_sensitivity, true, DEFAULT_ANALOG_SENSITIVITY, false);
SETTING_FLOAT("video_msg_bgcolor_opacity", &settings->floats.video_msg_bgcolor_opacity, true, message_bgcolor_opacity, false);
SETTING_FLOAT("video_hdr_max_nits", &settings->floats.video_hdr_max_nits, true, DEFAULT_VIDEO_HDR_MAX_NITS, false);
SETTING_FLOAT("video_hdr_paper_white_nits", &settings->floats.video_hdr_paper_white_nits, true, DEFAULT_VIDEO_HDR_PAPER_WHITE_NITS, false);
SETTING_FLOAT("video_hdr_display_contrast", &settings->floats.video_hdr_display_contrast, true, DEFAULT_VIDEO_HDR_CONTRAST, false);
*size = count;
return tmp;
@@ -1980,9 +2080,7 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false);
#endif
SETTING_UINT("input_touch_scale", &settings->uints.input_touch_scale, true, DEFAULT_TOUCH_SCALE, false);
#if defined(DINGUX) && defined(HAVE_LIBSHAKE)
SETTING_UINT("input_dingux_rumble_gain", &settings->uints.input_dingux_rumble_gain, true, DEFAULT_DINGUX_RUMBLE_GAIN, false);
#endif
SETTING_UINT("input_rumble_gain", &settings->uints.input_rumble_gain, true, DEFAULT_RUMBLE_GAIN, false);
SETTING_UINT("input_auto_game_focus", &settings->uints.input_auto_game_focus, true, DEFAULT_INPUT_AUTO_GAME_FOCUS, false);
SETTING_UINT("audio_latency", &settings->uints.audio_latency, false, 0 /* TODO */, false);
SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, audio_resampler_quality_level, false);
@@ -2505,7 +2603,7 @@ void config_set_defaults(void *data)
settings->uints.input_mouse_index[i] = i;
}
video_driver_reset_custom_viewport();
video_driver_reset_custom_viewport(settings);
/* Make sure settings from other configs carry over into defaults
* for another config. */
@@ -3083,7 +3181,6 @@ static bool config_load_file(global_t *global,
{
unsigned i;
char tmp_str[PATH_MAX_LENGTH];
bool ret = false;
unsigned tmp_uint = 0;
bool tmp_bool = false;
static bool first_load = true;
@@ -3098,24 +3195,33 @@ static bool config_load_file(global_t *global,
int size_settings_size = sizeof(settings->sizes) / sizeof(settings->sizes.placeholder);
int array_settings_size = sizeof(settings->arrays) / sizeof(settings->arrays.placeholder);
int path_settings_size = sizeof(settings->paths) / sizeof(settings->paths.placeholder);
struct config_bool_setting *bool_settings = populate_settings_bool (settings, &bool_settings_size);
struct config_float_setting *float_settings = populate_settings_float (settings, &float_settings_size);
struct config_int_setting *int_settings = populate_settings_int (settings, &int_settings_size);
struct config_uint_setting *uint_settings = populate_settings_uint (settings, &uint_settings_size);
struct config_size_setting *size_settings = populate_settings_size (settings, &size_settings_size);
struct config_array_setting *array_settings = populate_settings_array (settings, &array_settings_size);
struct config_path_setting *path_settings = populate_settings_path (settings, &path_settings_size);
struct config_bool_setting *bool_settings = NULL;
struct config_float_setting *float_settings = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
struct config_size_setting *size_settings = NULL;
struct config_array_setting *array_settings = NULL;
struct config_path_setting *path_settings = NULL;
config_file_t *conf = path ? config_file_new_from_path_to_string(path) : open_default_config_file();
tmp_str[0] = '\0';
tmp_str[0] = '\0';
if (!conf)
{
first_load = false;
if (!path)
ret = true;
goto end;
return true;
return false;
}
bool_settings = populate_settings_bool (settings, &bool_settings_size);
float_settings = populate_settings_float (settings, &float_settings_size);
int_settings = populate_settings_int (settings, &int_settings_size);
uint_settings = populate_settings_uint (settings, &uint_settings_size);
size_settings = populate_settings_size (settings, &size_settings_size);
array_settings = populate_settings_array (settings, &array_settings_size);
path_settings = populate_settings_path (settings, &path_settings_size);
if (!path_is_empty(RARCH_PATH_CONFIG_APPEND))
{
/* Don't destroy append_config_path, store in temporary
@@ -3608,8 +3714,6 @@ static bool config_load_file(global_t *global,
settings->ints.content_favorites_size = (int)settings->uints.content_history_size;
}
ret = true;
end:
if (conf)
config_file_free(conf);
if (bool_settings)
@@ -3627,7 +3731,7 @@ end:
if (size_settings)
free(size_settings);
first_load = false;
return ret;
return true;
}
/**
@@ -4007,6 +4111,245 @@ static void video_driver_save_settings(global_t *global, config_file_t *conf)
global->console.screen.flicker_filter_index);
}
static void save_keybind_hat(config_file_t *conf, const char *key,
const struct retro_keybind *bind)
{
char config[16];
unsigned hat = (unsigned)GET_HAT(bind->joykey);
const char *dir = NULL;
config[0] = '\0';
switch (GET_HAT_DIR(bind->joykey))
{
case HAT_UP_MASK:
dir = "up";
break;
case HAT_DOWN_MASK:
dir = "down";
break;
case HAT_LEFT_MASK:
dir = "left";
break;
case HAT_RIGHT_MASK:
dir = "right";
break;
default:
break;
}
snprintf(config, sizeof(config), "h%u%s", hat, dir);
config_set_string(conf, key, config);
}
static void save_keybind_joykey(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind, bool save_empty)
{
char key[64];
key[0] = '\0';
fill_pathname_join_delim_concat(key, prefix,
base, '_', "_btn", sizeof(key));
if (bind->joykey == NO_BTN)
{
if (save_empty)
config_set_string(conf, key, "nul");
}
else if (GET_HAT_DIR(bind->joykey))
save_keybind_hat(conf, key, bind);
else
config_set_uint64(conf, key, bind->joykey);
}
static void save_keybind_axis(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind, bool save_empty)
{
char key[64];
unsigned axis = 0;
char dir = '\0';
key[0] = '\0';
fill_pathname_join_delim_concat(key,
prefix, base, '_',
"_axis",
sizeof(key));
if (bind->joyaxis == AXIS_NONE)
{
if (save_empty)
config_set_string(conf, key, "nul");
}
else if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE)
{
dir = '-';
axis = AXIS_NEG_GET(bind->joyaxis);
}
else if (AXIS_POS_GET(bind->joyaxis) != AXIS_DIR_NONE)
{
dir = '+';
axis = AXIS_POS_GET(bind->joyaxis);
}
if (dir)
{
char config[16];
config[0] = '\0';
snprintf(config, sizeof(config), "%c%u", dir, axis);
config_set_string(conf, key, config);
}
}
static void save_keybind_mbutton(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind, bool save_empty)
{
char key[64];
key[0] = '\0';
fill_pathname_join_delim_concat(key, prefix,
base, '_', "_mbtn", sizeof(key));
switch (bind->mbutton)
{
case RETRO_DEVICE_ID_MOUSE_LEFT:
config_set_uint64(conf, key, 1);
break;
case RETRO_DEVICE_ID_MOUSE_RIGHT:
config_set_uint64(conf, key, 2);
break;
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
config_set_uint64(conf, key, 3);
break;
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
config_set_uint64(conf, key, 4);
break;
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
config_set_uint64(conf, key, 5);
break;
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
config_set_string(conf, key, "wu");
break;
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
config_set_string(conf, key, "wd");
break;
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
config_set_string(conf, key, "whu");
break;
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
config_set_string(conf, key, "whd");
break;
default:
if (save_empty)
config_set_string(conf, key, "nul");
break;
}
}
/**
* input_config_save_keybind:
* @conf : pointer to config file object
* @prefix : prefix name of keybind
* @base : base name of keybind
* @bind : pointer to key binding object
* @kb : save keyboard binds
*
* Save a key binding to the config file.
*/
static void input_config_save_keybind(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind,
bool save_empty)
{
save_keybind_joykey (conf, prefix, base, bind, save_empty);
save_keybind_axis (conf, prefix, base, bind, save_empty);
save_keybind_mbutton(conf, prefix, base, bind, save_empty);
}
const char *input_config_get_prefix(unsigned user, bool meta)
{
static const char *bind_user_prefix[MAX_USERS] = {
"input_player1",
"input_player2",
"input_player3",
"input_player4",
"input_player5",
"input_player6",
"input_player7",
"input_player8",
"input_player9",
"input_player10",
"input_player11",
"input_player12",
"input_player13",
"input_player14",
"input_player15",
"input_player16",
};
if (meta)
{
if (user == 0)
return "input";
/* Don't bother with meta bind for anyone else than first user. */
return NULL;
}
return bind_user_prefix[user];
}
/**
* input_config_save_keybinds_user:
* @conf : pointer to config file object
* @user : user number
*
* Save the current keybinds of a user (@user) to the config file (@conf).
*/
static void input_config_save_keybinds_user(config_file_t *conf, unsigned user)
{
unsigned i = 0;
for (i = 0; input_config_bind_map_get_valid(i); i++)
{
char key[64];
char btn[64];
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(i);
bool meta = keybind ? keybind->meta : false;
const char *prefix = input_config_get_prefix(user, meta);
const struct retro_keybind *bind = &input_config_binds[user][i];
const char *base = NULL;
if (!prefix || !bind->valid || !keybind)
continue;
base = keybind->base;
key[0] = btn[0] = '\0';
fill_pathname_join_delim(key, prefix, base, '_', sizeof(key));
input_keymaps_translate_rk_to_str(bind->key, btn, sizeof(btn));
config_set_string(conf, key, btn);
input_config_save_keybind(conf, prefix, base, bind, true);
}
}
/**
* config_save_autoconf_profile:
* @device_name : Input device name
@@ -4514,8 +4857,26 @@ bool config_save_overrides(enum override_type type, void *data)
for (i = 0; i < (unsigned)array_settings_size; i++)
{
if (!string_is_equal(array_settings[i].ptr, array_overrides[i].ptr))
{
#ifdef HAVE_CHEEVOS
/* As authentication doesn't occur until after content is loaded,
* the achievement authentication token might only exist in the
* override set, and therefore differ from the master config set.
* Storing the achievement authentication token in an override
* is a recipe for disaster. If it expires and the user generates
* a new token, then the override will be out of date and the
* user will have to reauthenticate for each override (and also
* remember to update each override). Also exclude the username
* as it's directly tied to the token and password.
*/
if (string_is_equal(array_settings[i].ident, "cheevos_token") ||
string_is_equal(array_settings[i].ident, "cheevos_password") ||
string_is_equal(array_settings[i].ident, "cheevos_username"))
continue;
#endif
config_set_string(conf, array_overrides[i].ident,
array_overrides[i].ptr);
}
}
for (i = 0; i < (unsigned)path_settings_size; i++)
@@ -5029,3 +5390,317 @@ end:
config_file_free(config);
}
#endif
bool input_config_bind_map_get_valid(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return false;
return keybind->valid;
}
unsigned input_config_bind_map_get_meta(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return 0;
return keybind->meta;
}
const char *input_config_bind_map_get_base(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return NULL;
return keybind->base;
}
const char *input_config_bind_map_get_desc(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return NULL;
return msg_hash_to_str(keybind->desc);
}
uint8_t input_config_bind_map_get_retro_key(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return 0;
return keybind->retro_key;
}
void input_config_reset_autoconfig_binds(unsigned port)
{
unsigned i;
if (port >= MAX_USERS)
return;
for (i = 0; i < RARCH_BIND_LIST_END; i++)
{
input_autoconf_binds[port][i].joykey = NO_BTN;
input_autoconf_binds[port][i].joyaxis = AXIS_NONE;
if (input_autoconf_binds[port][i].joykey_label)
{
free(input_autoconf_binds[port][i].joykey_label);
input_autoconf_binds[port][i].joykey_label = NULL;
}
if (input_autoconf_binds[port][i].joyaxis_label)
{
free(input_autoconf_binds[port][i].joyaxis_label);
input_autoconf_binds[port][i].joyaxis_label = NULL;
}
}
}
void input_config_set_autoconfig_binds(unsigned port, void *data)
{
unsigned i;
config_file_t *config = (config_file_t*)data;
struct retro_keybind *binds = NULL;
if ((port >= MAX_USERS) || !config)
return;
binds = input_autoconf_binds[port];
for (i = 0; i < RARCH_BIND_LIST_END; i++)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(i);
if (keybind)
{
char str[256];
const char *base = keybind->base;
str[0] = '\0';
fill_pathname_join_delim(str, "input", base, '_', sizeof(str));
input_config_parse_joy_button(str, config, "input", base, &binds[i]);
input_config_parse_joy_axis (str, config, "input", base, &binds[i]);
}
}
}
void input_config_parse_mouse_button(
char *s,
void *conf_data, const char *prefix,
const char *btn, void *bind_data)
{
int val;
char tmp[64];
char key[64];
config_file_t *conf = (config_file_t*)conf_data;
struct retro_keybind *bind = (struct retro_keybind*)bind_data;
tmp[0] = key[0] = '\0';
fill_pathname_join_delim(key, s, "mbtn", '_', sizeof(key));
if (config_get_array(conf, key, tmp, sizeof(tmp)))
{
bind->mbutton = NO_BTN;
if (tmp[0]=='w')
{
switch (tmp[1])
{
case 'u':
bind->mbutton = RETRO_DEVICE_ID_MOUSE_WHEELUP;
break;
case 'd':
bind->mbutton = RETRO_DEVICE_ID_MOUSE_WHEELDOWN;
break;
case 'h':
switch (tmp[2])
{
case 'u':
bind->mbutton = RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP;
break;
case 'd':
bind->mbutton = RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN;
break;
}
break;
}
}
else
{
val = atoi(tmp);
switch (val)
{
case 1:
bind->mbutton = RETRO_DEVICE_ID_MOUSE_LEFT;
break;
case 2:
bind->mbutton = RETRO_DEVICE_ID_MOUSE_RIGHT;
break;
case 3:
bind->mbutton = RETRO_DEVICE_ID_MOUSE_MIDDLE;
break;
case 4:
bind->mbutton = RETRO_DEVICE_ID_MOUSE_BUTTON_4;
break;
case 5:
bind->mbutton = RETRO_DEVICE_ID_MOUSE_BUTTON_5;
break;
}
}
}
}
void input_config_parse_joy_axis(
char *s,
void *conf_data, const char *prefix,
const char *axis, void *bind_data)
{
char tmp[64];
char key[64];
char key_label[64];
config_file_t *conf = (config_file_t*)conf_data;
struct retro_keybind *bind = (struct retro_keybind*)bind_data;
struct config_entry_list *tmp_a = NULL;
tmp[0] = key[0] = key_label[0] = '\0';
fill_pathname_join_delim(key, s,
"axis", '_', sizeof(key));
fill_pathname_join_delim(key_label, s,
"axis_label", '_', sizeof(key_label));
if (config_get_array(conf, key, tmp, sizeof(tmp)))
{
if ( tmp[0] == 'n'
&& tmp[1] == 'u'
&& tmp[2] == 'l'
&& tmp[3] == '\0'
)
bind->joyaxis = AXIS_NONE;
else if (strlen(tmp) >= 2 && (*tmp == '+' || *tmp == '-'))
{
int i_axis = (int)strtol(tmp + 1, NULL, 0);
if (*tmp == '+')
bind->joyaxis = AXIS_POS(i_axis);
else
bind->joyaxis = AXIS_NEG(i_axis);
}
/* Ensure that D-pad emulation doesn't screw this over. */
bind->orig_joyaxis = bind->joyaxis;
}
tmp_a = config_get_entry(conf, key_label);
if (tmp_a && (!string_is_empty(tmp_a->value)))
{
if (bind->joyaxis_label &&
!string_is_empty(bind->joyaxis_label))
free(bind->joyaxis_label);
bind->joyaxis_label = strdup(tmp_a->value);
}
}
static uint16_t input_config_parse_hat(const char *dir)
{
if ( dir[0] == 'u'
&& dir[1] == 'p'
&& dir[2] == '\0'
)
return HAT_UP_MASK;
else if (
dir[0] == 'd'
&& dir[1] == 'o'
&& dir[2] == 'w'
&& dir[3] == 'n'
&& dir[4] == '\0'
)
return HAT_DOWN_MASK;
else if (
dir[0] == 'l'
&& dir[1] == 'e'
&& dir[2] == 'f'
&& dir[3] == 't'
&& dir[4] == '\0'
)
return HAT_LEFT_MASK;
else if (
dir[0] == 'r'
&& dir[1] == 'i'
&& dir[2] == 'g'
&& dir[3] == 'h'
&& dir[4] == 't'
&& dir[5] == '\0'
)
return HAT_RIGHT_MASK;
return 0;
}
void input_config_parse_joy_button(
char *s,
void *data, const char *prefix,
const char *btn, void *bind_data)
{
char tmp[64];
char key[64];
char key_label[64];
config_file_t *conf = (config_file_t*)data;
struct retro_keybind *bind = (struct retro_keybind*)bind_data;
struct config_entry_list *tmp_a = NULL;
tmp[0] = key[0] = key_label[0] = '\0';
fill_pathname_join_delim(key, s,
"btn", '_', sizeof(key));
fill_pathname_join_delim(key_label, s,
"btn_label", '_', sizeof(key_label));
if (config_get_array(conf, key, tmp, sizeof(tmp)))
{
btn = tmp;
if ( btn[0] == 'n'
&& btn[1] == 'u'
&& btn[2] == 'l'
&& btn[3] == '\0'
)
bind->joykey = NO_BTN;
else
{
if (*btn == 'h')
{
const char *str = btn + 1;
/* Parse hat? */
if (str && ISDIGIT((int)*str))
{
char *dir = NULL;
uint16_t hat = strtoul(str, &dir, 0);
uint16_t hat_dir = dir ? input_config_parse_hat(dir) : 0;
if (hat_dir)
bind->joykey = HAT_MAP(hat, hat_dir);
}
}
else
bind->joykey = strtoull(tmp, NULL, 0);
}
}
tmp_a = config_get_entry(conf, key_label);
if (tmp_a && !string_is_empty(tmp_a->value))
{
if (!string_is_empty(bind->joykey_label))
free(bind->joykey_label);
bind->joykey_label = strdup(tmp_a->value);
}
}
+54 -1
View File
@@ -25,6 +25,10 @@
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gfx/video_defines.h"
#include "input/input_defines.h"
#include "led/led_defines.h"
@@ -33,6 +37,8 @@
#include "lakka.h"
#endif
#include "msg_hash.h"
#define configuration_set_float(settings, var, newvar) \
{ \
settings->modified = true; \
@@ -63,6 +69,8 @@
strlcpy(var, newvar, sizeof(var)); \
}
#define INPUT_CONFIG_BIND_MAP_GET(i) ((const struct input_bind_map*)&input_config_bind_map[(i)])
enum crt_switch_type
{
CRT_SWITCH_NONE = 0,
@@ -82,6 +90,25 @@ enum override_type
RETRO_BEGIN_DECLS
/* Input config. */
struct input_bind_map
{
const char *base;
enum msg_hash_enums desc;
/* Meta binds get input as prefix, not input_playerN".
* 0 = libretro related.
* 1 = Common hotkey.
* 2 = Uncommon/obscure hotkey.
*/
uint8_t meta;
uint8_t retro_key;
bool valid;
};
typedef struct settings
{
struct
@@ -163,7 +190,7 @@ typedef struct settings
unsigned input_menu_toggle_gamepad_combo;
unsigned input_keyboard_gamepad_mapping_type;
unsigned input_poll_type_behavior;
unsigned input_dingux_rumble_gain;
unsigned input_rumble_gain;
unsigned input_auto_game_focus;
unsigned input_max_users;
@@ -318,6 +345,9 @@ typedef struct settings
float video_msg_color_g;
float video_msg_color_b;
float video_msg_bgcolor_opacity;
float video_hdr_max_nits;
float video_hdr_paper_white_nits;
float video_hdr_display_contrast;
float menu_scale_factor;
float menu_widget_scale_factor;
@@ -526,6 +556,8 @@ typedef struct settings
#ifdef HAVE_VIDEO_LAYOUT
bool video_layout_enable;
#endif
bool video_hdr_enable;
bool video_hdr_expand_gamut;
/* Accessibility */
bool accessibility_enable;
@@ -1049,6 +1081,27 @@ const char *config_get_all_timezones(void);
void config_set_timezone(char *timezone);
#endif
bool input_config_bind_map_get_valid(unsigned bind_index);
void input_config_parse_joy_button(
char *s,
void *data, const char *prefix,
const char *btn, void *bind_data);
void input_config_parse_joy_axis(
char *s,
void *conf_data, const char *prefix,
const char *axis, void *bind_data);
void input_config_parse_mouse_button(
char *s,
void *conf_data, const char *prefix,
const char *btn, void *bind_data);
const char *input_config_get_prefix(unsigned user, bool meta);
extern const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL];
RETRO_END_DECLS
#endif
+12
View File
@@ -45,12 +45,24 @@ bool content_load_ram_file(unsigned slot);
/* Save a RAM state from memory to disk. */
bool content_save_ram_file(unsigned slot, bool compress);
/* Load a state from memory. */
bool content_load_state_from_ram(void);
/* Save a state to memory. */
bool content_save_state_to_ram(void);
/* Save a ram state from memory to disk. */
bool content_ram_state_to_file(const char *path);
/* Load a state from disk to memory. */
bool content_load_state(const char* path, bool load_to_backup_buffer, bool autoload);
/* Save a state from memory to disk. */
bool content_save_state(const char *path, bool save_to_disk, bool autosave);
/* Check a ram state write to disk. */
bool content_ram_state_pending(void);
/* Gets the number of bytes required to serialize the state. */
size_t content_get_serialized_size(void);
+1 -1
View File
@@ -8,7 +8,7 @@
#ifdef RARCH_INTERNAL
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#endif
+1 -1
View File
@@ -8,7 +8,7 @@
#ifdef RARCH_INTERNAL
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#endif
+21
View File
@@ -1,3 +1,24 @@
# v10.2.0
* add RC_MEMSIZE_16_BITS_BE, RC_MEMSIZE_24_BITS_BE, and RC_MEMSIZE_32_BITS_BE
* add secondary flag for RC_CONDITION_MEASURED that tells the UI when to show progress as raw vs. as a percentage
* add rapi calls for fetch_leaderboard_info, fetch_achievement_info and fetch_game_list
* add hash support for RC_CONSOLE_PSP
* add RCHEEVOS_URL_SSL compile flag to use https in rurl functions
* add space to "PC Engine" label
* update RC_CONSOLE_INTELLIVISION memory map to acknowledge non-8-bit addresses
* standardize to z64 format when hashing RC_CONSOLE_N64
* prevent generating hash for PSX disc when requesting RC_CONSOLE_PLAYSTATION2
* fix wrong error message being returned when a leaderboard was only slightly malformed
# v10.1.0
* add RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED
* add rc_runtime_validate_addresses
* add external memory to memory map for Magnavox Odyssey 2
* fix memory map base address for NeoGeo Pocket
* fix bitcount always returning 0 when used in rich presence
# v10.0.0
* add rapi sublibrary for communicating with server (eliminates need for client-side JSON parsing; client must still
+182
View File
@@ -0,0 +1,182 @@
#ifndef RC_API_INFO_H
#define RC_API_INFO_H
#include "rc_api_request.h"
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
/* --- Fetch Achievement Info --- */
/**
* API parameters for a fetch achievement info request.
*/
typedef struct rc_api_fetch_achievement_info_request_t {
/* The username of the player */
const char* username;
/* The API token from the login request */
const char* api_token;
/* The unique identifier of the achievement */
unsigned achievement_id;
/* The 1-based index of the first entry to retrieve */
unsigned first_entry;
/* The number of entries to retrieve */
unsigned count;
/* Non-zero to only return unlocks earned by the user's friends */
unsigned friends_only;
}
rc_api_fetch_achievement_info_request_t;
/* An achievement awarded entry */
typedef struct rc_api_achievement_awarded_entry_t {
/* The user associated to the entry */
const char* username;
/* When the achievement was awarded */
time_t awarded;
}
rc_api_achievement_awarded_entry_t;
/**
* Response data for a fetch achievement info request.
*/
typedef struct rc_api_fetch_achievement_info_response_t {
/* The unique identifier of the achievement */
unsigned id;
/* The unique identifier of the game to which the leaderboard is associated */
unsigned game_id;
/* The number of times the achievement has been awarded */
unsigned num_awarded;
/* The number of players that have earned at least one achievement for the game */
unsigned num_players;
/* An array of recently rewarded entries */
rc_api_achievement_awarded_entry_t* recently_awarded;
/* The number of items in the recently_awarded array */
unsigned num_recently_awarded;
/* Common server-provided response information */
rc_api_response_t response;
}
rc_api_fetch_achievement_info_response_t;
int rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params);
int rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response);
void rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response);
/* --- Fetch Leaderboard Info --- */
/**
* API parameters for a fetch leaderboard info request.
*/
typedef struct rc_api_fetch_leaderboard_info_request_t {
/* The unique identifier of the leaderboard */
unsigned leaderboard_id;
/* The number of entries to retrieve */
unsigned count;
/* The 1-based index of the first entry to retrieve */
unsigned first_entry;
/* The username of the player around whom the entries should be returned */
const char* username;
}
rc_api_fetch_leaderboard_info_request_t;
/* A leaderboard info entry */
typedef struct rc_api_lboard_info_entry_t {
/* The user associated to the entry */
const char* username;
/* The rank of the entry */
unsigned rank;
/* The index of the entry */
unsigned index;
/* The value of the entry */
int score;
/* When the entry was submitted */
time_t submitted;
}
rc_api_lboard_info_entry_t;
/**
* Response data for a fetch leaderboard info request.
*/
typedef struct rc_api_fetch_leaderboard_info_response_t {
/* The unique identifier of the leaderboard */
unsigned id;
/* The format to pass to rc_format_value to format the leaderboard value */
int format;
/* If non-zero, indicates that lower scores appear first */
int lower_is_better;
/* The title of the leaderboard */
const char* title;
/* The description of the leaderboard */
const char* description;
/* The definition of the leaderboard to be passed to rc_runtime_activate_lboard */
const char* definition;
/* The unique identifier of the game to which the leaderboard is associated */
unsigned game_id;
/* The author of the leaderboard */
const char* author;
/* When the leaderboard was first uploaded to the server */
time_t created;
/* When the leaderboard was last modified on the server */
time_t updated;
/* An array of requested entries */
rc_api_lboard_info_entry_t* entries;
/* The number of items in the entries array */
unsigned num_entries;
/* Common server-provided response information */
rc_api_response_t response;
}
rc_api_fetch_leaderboard_info_response_t;
int rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params);
int rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response);
void rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response);
/* --- Fetch Games List --- */
/**
* API parameters for a fetch games list request.
*/
typedef struct rc_api_fetch_games_list_request_t {
/* The unique identifier of the console to query */
unsigned console_id;
}
rc_api_fetch_games_list_request_t;
/* A game list entry */
typedef struct rc_api_game_list_entry_t {
/* The unique identifier of the game */
unsigned id;
/* The name of the game */
const char* name;
}
rc_api_game_list_entry_t;
/**
* Response data for a fetch games list request.
*/
typedef struct rc_api_fetch_games_list_response_t {
/* An array of requested entries */
rc_api_game_list_entry_t* entries;
/* The number of items in the entries array */
unsigned num_entries;
/* Common server-provided response information */
rc_api_response_t response;
}
rc_api_fetch_games_list_response_t;
int rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params);
int rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response);
void rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response);
#ifdef __cplusplus
}
#endif
#endif /* RC_API_INFO_H */
+2 -2
View File
@@ -36,9 +36,9 @@ int rc_api_init_fetch_image_request(rc_api_request_t* request, const rc_api_fetc
* API parameters for a resolve hash request.
*/
typedef struct rc_api_resolve_hash_request_t {
/* The username of the player */
/* Unused - hash lookup does not require credentials */
const char* username;
/* The API token from the login request */
/* Unused - hash lookup does not require credentials */
const char* api_token;
/* The generated hash of the game to be identified */
const char* game_hash;
+1 -1
View File
@@ -16,7 +16,7 @@ extern "C" {
/* 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);
int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size);
/* generates a hash from a file.
* returns non-zero on success, or zero on failure.
+3
View File
@@ -7,6 +7,8 @@ extern "C" {
#include "rc_error.h"
#include <stddef.h>
/*****************************************************************************\
| Forward Declarations (defined in rc_runtime_types.h) |
\*****************************************************************************/
@@ -94,6 +96,7 @@ int rc_runtime_activate_achievement(rc_runtime_t* runtime, unsigned id, const ch
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_get_achievement_measured(const rc_runtime_t* runtime, unsigned id, unsigned* measured_value, unsigned* measured_target);
int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, unsigned id, char *buffer, size_t buffer_size);
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);
+6
View File
@@ -51,6 +51,9 @@ enum {
RC_MEMSIZE_BIT_6,
RC_MEMSIZE_BIT_7,
RC_MEMSIZE_BITCOUNT,
RC_MEMSIZE_16_BITS_BE,
RC_MEMSIZE_24_BITS_BE,
RC_MEMSIZE_32_BITS_BE,
RC_MEMSIZE_VARIABLE
};
@@ -255,6 +258,9 @@ struct rc_trigger_t {
/* True if at least one condition has a non-zero required hit count */
char has_required_hits;
/* True if the measured value should be displayed as a percentage */
char measured_as_percent;
};
int rc_trigger_size(const char* memaddr);
+3
View File
@@ -11,6 +11,9 @@ int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const
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_lboard_entries(char* buffer, size_t size, unsigned lboard_id, unsigned first_index, unsigned count);
int rc_url_get_lboard_entries_near_user(char* buffer, size_t size, unsigned lboard_id, const char* user_name, unsigned count);
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);
+130 -49
View File
@@ -20,7 +20,7 @@ static char* g_imagehost = NULL;
/* --- rc_json --- */
static int rc_json_parse_object(const char** json_ptr, rc_json_field_t* fields, size_t field_count);
static int rc_json_parse_object(const char** json_ptr, rc_json_field_t* fields, size_t field_count, unsigned* fields_seen);
static int rc_json_parse_array(const char** json_ptr, rc_json_field_t* field);
static int rc_json_parse_field(const char** json_ptr, rc_json_field_t* field) {
@@ -68,7 +68,7 @@ static int rc_json_parse_field(const char** json_ptr, rc_json_field_t* field) {
break;
case '{': /* object */
result = rc_json_parse_object(json_ptr, NULL, 0);
result = rc_json_parse_object(json_ptr, NULL, 0, &field->array_size);
if (result != RC_OK)
return result;
@@ -127,13 +127,54 @@ static int rc_json_parse_array(const char** json_ptr, rc_json_field_t* field) {
return RC_OK;
}
static int rc_json_parse_object(const char** json_ptr, rc_json_field_t* fields, size_t field_count) {
rc_json_field_t non_matching_field;
rc_json_field_t* field;
static int rc_json_get_next_field(rc_json_object_field_iterator_t* iterator) {
const char* json = iterator->json;
while (isspace((unsigned char)*json))
++json;
if (*json != '"')
return RC_INVALID_JSON;
iterator->field.name = ++json;
while (*json != '"') {
if (!*json)
return RC_INVALID_JSON;
++json;
}
iterator->name_len = json - iterator->field.name;
++json;
while (isspace((unsigned char)*json))
++json;
if (*json != ':')
return RC_INVALID_JSON;
++json;
while (isspace((unsigned char)*json))
++json;
if (rc_json_parse_field(&json, &iterator->field) < 0)
return RC_INVALID_JSON;
while (isspace((unsigned char)*json))
++json;
iterator->json = json;
return RC_OK;
}
static int rc_json_parse_object(const char** json_ptr, rc_json_field_t* fields, size_t field_count, unsigned* fields_seen) {
rc_json_object_field_iterator_t iterator;
const char* json = *json_ptr;
const char* key_start;
size_t key_len;
size_t i;
unsigned num_fields = 0;
int result;
if (fields_seen)
*fields_seen = 0;
for (i = 0; i < field_count; ++i)
fields[i].value_start = fields[i].value_end = NULL;
@@ -147,61 +188,50 @@ static int rc_json_parse_object(const char** json_ptr, rc_json_field_t* fields,
return RC_OK;
}
memset(&iterator, 0, sizeof(iterator));
iterator.json = json;
do
{
while (isspace((unsigned char)*json))
++json;
result = rc_json_get_next_field(&iterator);
if (result != RC_OK)
return result;
if (*json != '"')
return RC_INVALID_JSON;
key_start = ++json;
while (*json != '"') {
if (!*json)
return RC_INVALID_JSON;
++json;
}
key_len = json - key_start;
++json;
while (isspace((unsigned char)*json))
++json;
if (*json != ':')
return RC_INVALID_JSON;
++json;
while (isspace((unsigned char)*json))
++json;
field = &non_matching_field;
for (i = 0; i < field_count; ++i) {
if (!fields[i].value_start && strncmp(fields[i].name, key_start, key_len) == 0 && fields[i].name[key_len] == '\0') {
field = &fields[i];
if (!fields[i].value_start && strncmp(fields[i].name, iterator.field.name, iterator.name_len) == 0 &&
fields[i].name[iterator.name_len] == '\0') {
fields[i].value_start = iterator.field.value_start;
fields[i].value_end = iterator.field.value_end;
fields[i].array_size = iterator.field.array_size;
break;
}
}
if (rc_json_parse_field(&json, field) < 0)
return RC_INVALID_JSON;
while (isspace((unsigned char)*json))
++json;
if (*json != ',')
++num_fields;
if (*iterator.json != ',')
break;
++json;
++iterator.json;
} while (1);
if (*json != '}')
if (*iterator.json != '}')
return RC_INVALID_JSON;
*json_ptr = ++json;
if (fields_seen)
*fields_seen = num_fields;
*json_ptr = ++iterator.json;
return RC_OK;
}
int rc_json_get_next_object_field(rc_json_object_field_iterator_t* iterator) {
if (*iterator->json != ',' && *iterator->json != '{')
return 0;
++iterator->json;
return (rc_json_get_next_field(iterator) == RC_OK);
}
int rc_json_parse_response(rc_api_response_t* response, const char* json, rc_json_field_t* fields, size_t field_count) {
#ifndef NDEBUG
if (field_count < 2)
@@ -213,7 +243,7 @@ int rc_json_parse_response(rc_api_response_t* response, const char* json, rc_jso
#endif
if (*json == '{') {
int result = rc_json_parse_object(&json, fields, field_count);
int result = rc_json_parse_object(&json, fields, field_count, NULL);
rc_json_get_optional_string(&response->error_message, response, &fields[1], "Error", NULL);
rc_json_get_optional_bool(&response->succeeded, &fields[0], "Success", 1);
@@ -266,11 +296,15 @@ static int rc_json_missing_field(rc_api_response_t* response, const rc_json_fiel
int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name) {
const char* json = field->value_start;
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
return 0;
#endif
if (!json)
return rc_json_missing_field(response, field);
return (rc_json_parse_object(&json, fields, field_count) == RC_OK);
return (rc_json_parse_object(&json, fields, field_count, &field->array_size) == RC_OK);
}
static int rc_json_get_array_entry_value(rc_json_field_t* field, rc_json_field_t* iterator) {
@@ -322,6 +356,11 @@ int rc_json_get_required_unum_array(unsigned** entries, unsigned* num_entries, r
}
int rc_json_get_required_array(unsigned* num_entries, rc_json_field_t* iterator, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
return 0;
#endif
if (!field->value_start || *field->value_start != '[') {
*num_entries = 0;
return rc_json_missing_field(response, field);
@@ -341,7 +380,7 @@ int rc_json_get_array_entry_object(rc_json_field_t* fields, size_t field_count,
while (isspace((unsigned char)*iterator->value_start))
++iterator->value_start;
rc_json_parse_object(&iterator->value_start, fields, field_count);
rc_json_parse_object(&iterator->value_start, fields, field_count, NULL);
while (isspace((unsigned char)*iterator->value_start))
++iterator->value_start;
@@ -358,7 +397,7 @@ static unsigned rc_json_decode_hex4(const char* input) {
memcpy(hex, input, 4);
hex[4] = '\0';
return strtol(hex, NULL, 16);
return (unsigned)strtoul(hex, NULL, 16);
}
static int rc_json_ucs32_to_utf8(unsigned char* dst, unsigned ucs32_char) {
@@ -604,6 +643,48 @@ int rc_json_get_required_unum(unsigned* out, rc_api_response_t* response, const
return rc_json_missing_field(response, field);
}
int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name) {
struct tm tm;
#ifndef NDEBUG
if (strcmp(field->name, field_name) != 0)
return 0;
#endif
if (*field->value_start == '\"') {
memset(&tm, 0, sizeof(tm));
if (sscanf(field->value_start + 1, "%d-%d-%d %d:%d:%d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
tm.tm_mon--; /* 0-based */
tm.tm_year -= 1900; /* 1900 based */
/* mktime converts a struct tm to a time_t using the local timezone.
* the input string is UTC. since timegm is not universally cross-platform,
* figure out the offset between UTC and local time by applying the
* timezone conversion twice and manually removing the difference */
{
time_t local_timet = mktime(&tm);
struct tm* gmt_tm = gmtime(&local_timet);
time_t skewed_timet = mktime(gmt_tm); /* applies local time adjustment second time */
time_t tz_offset = skewed_timet - local_timet;
*out = local_timet - tz_offset;
}
return 1;
}
}
*out = 0;
return 0;
}
int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name) {
if (rc_json_get_datetime(out, field, field_name))
return 1;
return rc_json_missing_field(response, field);
}
int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name) {
const char* src = field->value_start;
+11
View File
@@ -4,6 +4,7 @@
#include "rc_api_request.h"
#include <stddef.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
@@ -30,11 +31,19 @@ typedef struct rc_json_field_t {
}
rc_json_field_t;
typedef struct rc_json_object_field_iterator_t {
rc_json_field_t field;
const char* json;
size_t name_len;
}
rc_json_object_field_iterator_t;
int rc_json_parse_response(rc_api_response_t* response, const char* json, rc_json_field_t* fields, size_t field_count);
int rc_json_get_string(const char** out, rc_api_buffer_t* buffer, const rc_json_field_t* field, const char* field_name);
int rc_json_get_num(int* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_unum(unsigned* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_bool(int* out, const rc_json_field_t* field, const char* field_name);
int rc_json_get_datetime(time_t* out, const rc_json_field_t* field, const char* field_name);
void rc_json_get_optional_string(const char** out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name, const char* default_value);
void rc_json_get_optional_num(int* out, const rc_json_field_t* field, const char* field_name, int default_value);
void rc_json_get_optional_unum(unsigned* out, const rc_json_field_t* field, const char* field_name, int default_value);
@@ -43,10 +52,12 @@ int rc_json_get_required_string(const char** out, rc_api_response_t* response, c
int rc_json_get_required_num(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum(unsigned* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_bool(int* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_datetime(time_t* out, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_object(rc_json_field_t* fields, size_t field_count, rc_api_response_t* response, rc_json_field_t* field, const char* field_name);
int rc_json_get_required_unum_array(unsigned** entries, unsigned* num_entries, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_required_array(unsigned* num_entries, rc_json_field_t* iterator, rc_api_response_t* response, const rc_json_field_t* field, const char* field_name);
int rc_json_get_array_entry_object(rc_json_field_t* fields, size_t field_count, rc_json_field_t* iterator);
int rc_json_get_next_object_field(rc_json_object_field_iterator_t* iterator);
void rc_buf_init(rc_api_buffer_t* buffer);
void rc_buf_destroy(rc_api_buffer_t* buffer);
+328
View File
@@ -0,0 +1,328 @@
#include "rc_api_info.h"
#include "rc_api_common.h"
#include "rc_runtime_types.h"
#include <stdlib.h>
#include <string.h>
/* --- Fetch Achievement Info --- */
int rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params) {
rc_api_url_builder_t builder;
rc_api_url_build_dorequest_url(request);
if (api_params->achievement_id == 0)
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
if (rc_api_url_build_dorequest(&builder, "achievementwondata", api_params->username, api_params->api_token)) {
rc_url_builder_append_unum_param(&builder, "a", api_params->achievement_id);
if (api_params->friends_only)
rc_url_builder_append_unum_param(&builder, "f", 1);
if (api_params->first_entry > 1)
rc_url_builder_append_unum_param(&builder, "o", api_params->first_entry - 1); /* number of entries to skip */
rc_url_builder_append_unum_param(&builder, "c", api_params->count);
request->post_data = rc_url_builder_finalize(&builder);
}
return builder.result;
}
int rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response) {
rc_api_achievement_awarded_entry_t* entry;
rc_json_field_t iterator;
unsigned timet;
int result;
rc_json_field_t fields[] = {
{"Success"},
{"Error"},
{"AchievementID"},
{"Response"}
/* unused fields
{"Offset"},
{"Count"},
{"FriendsOnly"},
* unused fields */
};
rc_json_field_t response_fields[] = {
{"NumEarned"},
{"TotalPlayers"},
{"GameID"},
{"RecentWinner"} /* array */
};
rc_json_field_t entry_fields[] = {
{"User"},
{"DateAwarded"}
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
result = rc_json_parse_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
if (result != RC_OK)
return result;
if (!rc_json_get_required_unum(&response->id, &response->response, &fields[2], "AchievementID"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_object(response_fields, sizeof(response_fields) / sizeof(response_fields[0]), &response->response, &fields[3], "Response"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&response->num_awarded, &response->response, &response_fields[0], "NumEarned"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&response->num_players, &response->response, &response_fields[1], "TotalPlayers"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&response->game_id, &response->response, &response_fields[2], "GameID"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_array(&response->num_recently_awarded, &iterator, &response->response, &response_fields[3], "RecentWinner"))
return RC_MISSING_VALUE;
if (response->num_recently_awarded) {
response->recently_awarded = (rc_api_achievement_awarded_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_recently_awarded * sizeof(rc_api_achievement_awarded_entry_t));
if (!response->recently_awarded)
return RC_OUT_OF_MEMORY;
entry = response->recently_awarded;
while (rc_json_get_array_entry_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), &iterator)) {
if (!rc_json_get_required_string(&entry->username, &response->response, &entry_fields[0], "User"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&timet, &response->response, &entry_fields[1], "DateAwarded"))
return RC_MISSING_VALUE;
entry->awarded = (time_t)timet;
++entry;
}
}
return RC_OK;
}
void rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response) {
rc_buf_destroy(&response->response.buffer);
}
/* --- Fetch Leaderboard Info --- */
int rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params) {
rc_api_url_builder_t builder;
rc_api_url_build_dorequest_url(request);
if (api_params->leaderboard_id == 0)
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
rc_url_builder_append_str_param(&builder, "r", "lbinfo");
rc_url_builder_append_unum_param(&builder, "i", api_params->leaderboard_id);
if (api_params->username)
rc_url_builder_append_str_param(&builder, "u", api_params->username);
else if (api_params->first_entry > 1)
rc_url_builder_append_unum_param(&builder, "o", api_params->first_entry - 1); /* number of entries to skip */
rc_url_builder_append_unum_param(&builder, "c", api_params->count);
request->post_data = rc_url_builder_finalize(&builder);
return builder.result;
}
int rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response) {
rc_api_lboard_info_entry_t* entry;
rc_json_field_t iterator;
unsigned timet;
int result;
size_t len;
char format[16];
rc_json_field_t fields[] = {
{"Success"},
{"Error"},
{"LeaderboardData"}
};
rc_json_field_t leaderboarddata_fields[] = {
{"LBID"},
{"LBFormat"},
{"LowerIsBetter"},
{"LBTitle"},
{"LBDesc"},
{"LBMem"},
{"GameID"},
{"LBAuthor"},
{"LBCreated"},
{"LBUpdated"},
{"Entries"} /* array */
/* unused fields
{"GameTitle"},
{"ConsoleID"},
{"ConsoleName"},
{"ForumTopicID"},
{"GameIcon"},
* unused fields */
};
rc_json_field_t entry_fields[] = {
{"User"},
{"Rank"},
{"Index"},
{"Score"},
{"DateSubmitted"}
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
result = rc_json_parse_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
if (result != RC_OK)
return result;
if (!rc_json_get_required_object(leaderboarddata_fields, sizeof(leaderboarddata_fields) / sizeof(leaderboarddata_fields[0]), &response->response, &fields[2], "LeaderboardData"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&response->id, &response->response, &leaderboarddata_fields[0], "LBID"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_num(&response->lower_is_better, &response->response, &leaderboarddata_fields[2], "LowerIsBetter"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&response->title, &response->response, &leaderboarddata_fields[3], "LBTitle"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&response->description, &response->response, &leaderboarddata_fields[4], "LBDesc"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&response->definition, &response->response, &leaderboarddata_fields[5], "LBMem"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&response->game_id, &response->response, &leaderboarddata_fields[6], "GameID"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_string(&response->author, &response->response, &leaderboarddata_fields[7], "LBAuthor"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_datetime(&response->created, &response->response, &leaderboarddata_fields[8], "LBCreated"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_datetime(&response->updated, &response->response, &leaderboarddata_fields[9], "LBUpdated"))
return RC_MISSING_VALUE;
if (!leaderboarddata_fields[1].value_end)
return RC_MISSING_VALUE;
len = leaderboarddata_fields[1].value_end - leaderboarddata_fields[1].value_start - 2;
if (len < sizeof(format) - 1) {
memcpy(format, leaderboarddata_fields[1].value_start + 1, len);
format[len] = '\0';
response->format = rc_parse_format(format);
}
else {
response->format = RC_FORMAT_VALUE;
}
if (!rc_json_get_required_array(&response->num_entries, &iterator, &response->response, &leaderboarddata_fields[10], "Entries"))
return RC_MISSING_VALUE;
if (response->num_entries) {
response->entries = (rc_api_lboard_info_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_lboard_info_entry_t));
if (!response->entries)
return RC_OUT_OF_MEMORY;
entry = response->entries;
while (rc_json_get_array_entry_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), &iterator)) {
if (!rc_json_get_required_string(&entry->username, &response->response, &entry_fields[0], "User"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&entry->rank, &response->response, &entry_fields[1], "Rank"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&entry->index, &response->response, &entry_fields[2], "Index"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_num(&entry->score, &response->response, &entry_fields[3], "Score"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&timet, &response->response, &entry_fields[4], "DateSubmitted"))
return RC_MISSING_VALUE;
entry->submitted = (time_t)timet;
++entry;
}
}
return RC_OK;
}
void rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response) {
rc_buf_destroy(&response->response.buffer);
}
/* --- Fetch Games List --- */
int rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params) {
rc_api_url_builder_t builder;
rc_api_url_build_dorequest_url(request);
if (api_params->console_id == 0)
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
rc_url_builder_append_str_param(&builder, "r", "gameslist");
rc_url_builder_append_unum_param(&builder, "c", api_params->console_id);
request->post_data = rc_url_builder_finalize(&builder);
return builder.result;
}
int rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response) {
rc_api_game_list_entry_t* entry;
rc_json_object_field_iterator_t iterator;
int result;
char* end;
rc_json_field_t fields[] = {
{"Success"},
{"Error"},
{"Response"}
};
memset(response, 0, sizeof(*response));
rc_buf_init(&response->response.buffer);
result = rc_json_parse_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
if (result != RC_OK)
return result;
if (!fields[2].value_start) {
/* call rc_json_get_required_object to generate the error message */
rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "Response");
return RC_MISSING_VALUE;
}
response->num_entries = fields[2].array_size;
rc_buf_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_game_list_entry_t)));
response->entries = (rc_api_game_list_entry_t*)rc_buf_alloc(&response->response.buffer, response->num_entries * sizeof(rc_api_game_list_entry_t));
if (!response->entries)
return RC_OUT_OF_MEMORY;
memset(&iterator, 0, sizeof(iterator));
iterator.json = fields[2].value_start;
entry = response->entries;
while (rc_json_get_next_object_field(&iterator)) {
entry->id = strtol(iterator.field.name, &end, 10);
iterator.field.name = "";
if (!rc_json_get_string(&entry->name, &response->response.buffer, &iterator.field, ""))
return RC_MISSING_VALUE;
++entry;
}
return RC_OK;
}
void rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response) {
rc_buf_destroy(&response->response.buffer);
}
+6 -7
View File
@@ -20,10 +20,9 @@ int rc_api_init_resolve_hash_request(rc_api_request_t* request, const rc_api_res
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 48);
if (rc_api_url_build_dorequest(&builder, "gameid", api_params->username, api_params->api_token)) {
rc_url_builder_append_str_param(&builder, "m", api_params->game_hash);
request->post_data = rc_url_builder_finalize(&builder);
}
rc_url_builder_append_str_param(&builder, "r", "gameid");
rc_url_builder_append_str_param(&builder, "m", api_params->game_hash);
request->post_data = rc_url_builder_finalize(&builder);
return builder.result;
}
@@ -130,7 +129,7 @@ int rc_api_process_fetch_game_data_response(rc_api_fetch_game_data_response_t* r
if (result != RC_OK)
return result;
if (!rc_json_get_required_object(patchdata_fields, sizeof(patchdata_fields) / sizeof(patchdata_fields[0]), &response->response, &fields[2], "Response"))
if (!rc_json_get_required_object(patchdata_fields, sizeof(patchdata_fields) / sizeof(patchdata_fields[0]), &response->response, &fields[2], "PatchData"))
return RC_MISSING_VALUE;
if (!rc_json_get_required_unum(&response->id, &response->response, &patchdata_fields[0], "ID"))
@@ -440,8 +439,8 @@ int rc_api_process_submit_lboard_entry_response(rc_api_submit_lboard_entry_respo
{"Rank"},
{"Score"}
/* unused fields
{ "DateSumitted" },
* unused fields */
{"DateSubmitted"},
* unused fields */
};
rc_json_field_t rank_info_fields[] = {
+1
View File
@@ -144,6 +144,7 @@ void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, in
parse->measured_target = 0;
parse->lines_read = 0;
parse->has_required_hits = 0;
parse->measured_as_percent = 0;
}
void rc_destroy_parse_state(rc_parse_state_t* parse)
+1
View File
@@ -55,6 +55,7 @@ int rc_snprintf(char* buffer, size_t size, const char* format, ...)
va_start(args, format);
/* assume buffer is large enough and ignore size */
(void)size;
result = vsprintf(buffer, format, args);
va_end(args);
+7 -2
View File
@@ -86,6 +86,11 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
case 'i': case 'I': self->type = RC_CONDITION_ADD_ADDRESS; can_modify = 1; break;
case 't': case 'T': self->type = RC_CONDITION_TRIGGER; break;
case 'z': case 'Z': self->type = RC_CONDITION_RESET_NEXT_IF; break;
case 'g': case 'G':
parse->measured_as_percent = 1;
self->type = RC_CONDITION_MEASURED;
break;
/* e f h j k l s u v w x y */
default: parse->offset = RC_INVALID_CONDITION_TYPE; return 0;
}
@@ -95,7 +100,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
self->type = RC_CONDITION_STANDARD;
}
result = rc_parse_operand(&self->operand1, &aux, 1, is_indirect, parse);
result = rc_parse_operand(&self->operand1, &aux, is_indirect, parse);
if (result < 0) {
parse->offset = result;
return 0;
@@ -158,7 +163,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
break;
}
result = rc_parse_operand(&self->operand2, &aux, 1, is_indirect, parse);
result = rc_parse_operand(&self->operand2, &aux, is_indirect, parse);
if (result < 0) {
parse->offset = result;
return 0;
+9 -8
View File
@@ -18,7 +18,7 @@ static void rc_update_condition_pause(rc_condition_t* condition, int* in_pause)
case RC_CONDITION_OR_NEXT:
case RC_CONDITION_ADD_ADDRESS:
case RC_CONDITION_RESET_NEXT_IF:
condition->pause = *in_pause;
condition->pause = (char)*in_pause;
break;
default:
@@ -140,7 +140,7 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse, in
return self;
}
static void rc_condset_update_indirect_memrefs(rc_condset_t* self, rc_condition_t* condition, int processing_pause, rc_eval_state_t* eval_state) {
static void rc_condset_update_indirect_memrefs(rc_condition_t* condition, int processing_pause, rc_eval_state_t* eval_state) {
for (; condition != 0; condition = condition->next) {
if (condition->pause != processing_pause)
continue;
@@ -210,7 +210,7 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc
}
/* STEP 2: evaluate the current condition */
condition->is_true = rc_test_condition(condition, eval_state);
condition->is_true = (char)rc_test_condition(condition, eval_state);
eval_state->add_value = 0;
eval_state->add_address = 0;
@@ -311,10 +311,10 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc
* if the set has any indirect memrefs, manually update them now so the deltas are correct */
if (self->has_indirect_memrefs) {
/* first, update any indirect memrefs in the remaining part of the pause subset */
rc_condset_update_indirect_memrefs(self, condition->next, 1, eval_state);
rc_condset_update_indirect_memrefs(condition->next, 1, eval_state);
/* then, update all indirect memrefs in the non-pause subset */
rc_condset_update_indirect_memrefs(self, self->conditions, 0, eval_state);
rc_condset_update_indirect_memrefs(self->conditions, 0, eval_state);
}
return 1;
@@ -371,7 +371,7 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc
/* 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;
eval_state->measured_from_hits = (char)measured_from_hits;
}
return set_valid;
@@ -384,8 +384,9 @@ 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 */
/* one or more Pause conditions exists, if any of them are true, stop processing this group */
self->is_paused = (char)rc_test_condset_internal(self, 1, eval_state);
if (self->is_paused) {
eval_state->primed = 0;
return 0;
}
+41 -15
View File
@@ -136,7 +136,7 @@ const char* rc_console_name(int console_id)
return "PC-FX";
case RC_CONSOLE_PC_ENGINE:
return "PCEngine";
return "PC Engine";
case RC_CONSOLE_PLAYSTATION:
return "PlayStation";
@@ -323,19 +323,45 @@ static const rc_memory_region_t _rc_memory_regions_game_gear[] = {
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 */
/* http://wiki.intellivision.us/index.php/Memory_Map */
/* NOTE: Intellivision memory addresses point at 16-bit values. FreeIntv exposes them as little-endian
* 32-bit values. As such, the addresses are off by a factor of 4 _and_ the data is only where we
* expect it on little-endian systems.
*/
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" },
/* For backwards compatibility, register a 128-byte chunk of video RAM so the system memory
* will start at $0080. $0000-$007F previously tried to map to the STIC video registers as
* RETRO_MEMORY_VIDEO_RAM, and FreeIntv didn't expose any RETRO_MEMORY_VIDEO_RAM, so the first
* byte of RETRO_MEMORY_SYSTEM_RAM was registered at $0080. The data at $0080 is actually the
* STIC registers (4 bytes each), so we need to provide an arbitrary 128-byte padding that
* claims to be video RAM to ensure the system RAM ends up at the right address.
*/
{ 0x000000U, 0x00007FU, 0xFFFFFFU, RC_MEMORY_TYPE_VIDEO_RAM, "" },
/* RetroAchievements address = real address x4 + 0x80.
* These all have to map to RETRO_MEMORY_SYSTEM_RAM (even the video-related fields) as the
* entire block is exposed as a single entity by FreeIntv */
/* $0000-$007F: STIC registers, $0040-$007F are readonly */
{ 0x000080U, 0x00027FU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "STIC Registers" },
/* $0080-$00FF: unused */
{ 0x000280U, 0x00047FU, 0x000080U, RC_MEMORY_TYPE_UNUSED, "" },
/* $0100-$035F: system RAM, $0100-$01EF is scratch memory and only 8-bits per address */
{ 0x000480U, 0x000DFFU, 0x000100U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
/* $0360-$03FF: unused */
{ 0x000E00U, 0x00107FU, 0x000360U, RC_MEMORY_TYPE_UNUSED, "" },
/* $0400-$0FFF: cartridge RAM */
{ 0x001080U, 0x00407FU, 0x000400U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
/* $1000-$1FFF: unused */
{ 0x004080U, 0x00807FU, 0x001000U, RC_MEMORY_TYPE_UNUSED, "" },
/* $2000-$2FFF: cartridge RAM */
{ 0x008080U, 0x00C07FU, 0x002000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
/* $3000-$3FFF: video RAM */
{ 0x00C080U, 0x01007FU, 0x003000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Video RAM" },
/* $4000-$FFFF: cartridge RAM */
{ 0x010080U, 0x04007FU, 0x004000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Cartridge RAM" },
};
static const rc_memory_regions_t rc_memory_regions_intellivision = { _rc_memory_regions_intellivision, 9 };
static const rc_memory_regions_t rc_memory_regions_intellivision = { _rc_memory_regions_intellivision, 10 };
/* ===== Magnavox Odyssey 2 ===== */
/* https://sudonull.com/post/76885-Architecture-and-programming-Philips-Videopac-Magnavox-Odyssey-2 */
@@ -447,13 +473,13 @@ static const rc_memory_regions_t rc_memory_regions_pc8800 = { _rc_memory_regions
/* ===== PC Engine ===== */
/* http://www.archaicpixels.com/Memory_Map */
static const rc_memory_region_t _rc_memory_regions_pcengine[] = {
static const rc_memory_region_t _rc_memory_regions_pc_engine[] = {
{ 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 };
static const rc_memory_regions_t rc_memory_regions_pc_engine = { _rc_memory_regions_pc_engine, 4 };
/* ===== PC-FX ===== */
/* http://daifukkat.su/pcfx/data/memmap.html */
@@ -679,7 +705,7 @@ const rc_memory_regions_t* rc_console_memory_regions(int console_id)
return &rc_memory_regions_pc8800;
case RC_CONSOLE_PC_ENGINE:
return &rc_memory_regions_pcengine;
return &rc_memory_regions_pc_engine;
case RC_CONSOLE_PCFX:
return &rc_memory_regions_pcfx;
+11 -25
View File
@@ -29,10 +29,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
memaddr += 4;
rc_parse_trigger_internal(&self->start, &memaddr, parse);
self->start.memrefs = 0;
if (parse->offset < 0) {
return;
}
}
else if ((memaddr[0] == 'c' || memaddr[0] == 'C') &&
(memaddr[1] == 'a' || memaddr[1] == 'A') &&
@@ -46,10 +42,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
memaddr += 4;
rc_parse_trigger_internal(&self->cancel, &memaddr, parse);
self->cancel.memrefs = 0;
if (parse->offset < 0) {
return;
}
}
else if ((memaddr[0] == 's' || memaddr[0] == 'S') &&
(memaddr[1] == 'u' || memaddr[1] == 'U') &&
@@ -63,10 +55,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
memaddr += 4;
rc_parse_trigger_internal(&self->submit, &memaddr, parse);
self->submit.memrefs = 0;
if (parse->offset < 0) {
return;
}
}
else if ((memaddr[0] == 'v' || memaddr[0] == 'V') &&
(memaddr[1] == 'a' || memaddr[1] == 'A') &&
@@ -80,10 +68,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
memaddr += 4;
rc_parse_value_internal(&self->value, &memaddr, parse);
self->value.memrefs = 0;
if (parse->offset < 0) {
return;
}
}
else if ((memaddr[0] == 'p' || memaddr[0] == 'P') &&
(memaddr[1] == 'r' || memaddr[1] == 'R') &&
@@ -99,20 +83,22 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
self->progress = RC_ALLOC(rc_value_t, parse);
rc_parse_value_internal(self->progress, &memaddr, parse);
self->progress->memrefs = 0;
if (parse->offset < 0) {
return;
}
}
else {
/* encountered an error parsing one of the parts */
if (parse->offset < 0)
return;
/* end of string, or end of quoted string - stop processing */
if (memaddr[0] == '\0' || memaddr[0] == '\"')
break;
/* expect two colons between fields */
if (memaddr[0] != ':' || memaddr[1] != ':') {
parse->offset = RC_INVALID_LBOARD_FIELD;
return;
}
if (memaddr[0] != ':' || memaddr[1] != ':') {
break;
}
memaddr += 2;
}
+95 -52
View File
@@ -53,6 +53,11 @@ int rc_parse_memref(const char** memaddr, char* size, unsigned* address) {
aux++;
switch (*aux++) {
/* ordered by estimated frequency in case compiler doesn't build a jump table */
case 'h': case 'H': *size = RC_MEMSIZE_8_BITS; break;
case ' ': *size = RC_MEMSIZE_16_BITS; break;
case 'x': case 'X': *size = RC_MEMSIZE_32_BITS; break;
case 'm': case 'M': *size = RC_MEMSIZE_BIT_0; break;
case 'n': case 'N': *size = RC_MEMSIZE_BIT_1; break;
case 'o': case 'O': *size = RC_MEMSIZE_BIT_2; break;
@@ -64,17 +69,21 @@ int rc_parse_memref(const char** memaddr, char* size, unsigned* address) {
case 'l': case 'L': *size = RC_MEMSIZE_LOW; break;
case 'u': case 'U': *size = RC_MEMSIZE_HIGH; break;
case 'k': case 'K': *size = RC_MEMSIZE_BITCOUNT; break;
case 'h': case 'H': *size = RC_MEMSIZE_8_BITS; break;
case 'w': case 'W': *size = RC_MEMSIZE_24_BITS; break;
case 'x': case 'X': *size = RC_MEMSIZE_32_BITS; break;
case 'g': case 'G': *size = RC_MEMSIZE_32_BITS_BE; break;
case 'i': case 'I': *size = RC_MEMSIZE_16_BITS_BE; break;
case 'j': case 'J': *size = RC_MEMSIZE_24_BITS_BE; break;
/* case 'v': case 'V': */
/* case 'y': case 'Y': 64 bit? */
/* case 'z': case 'Z': 128 bit? */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
/* legacy support - addresses without a size prefix are assumed to be 16-bit */
aux--;
/* fallthrough */
case ' ':
*size = RC_MEMSIZE_16_BITS;
break;
@@ -97,10 +106,24 @@ int rc_parse_memref(const char** memaddr, char* size, unsigned* address) {
static const unsigned char rc_bits_set[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
unsigned rc_transform_memref_value(unsigned value, char size)
{
unsigned rc_transform_memref_value(unsigned value, char size) {
switch (size)
{
case RC_MEMSIZE_8_BITS:
value = (value & 0x000000ff);
break;
case RC_MEMSIZE_16_BITS:
value = (value & 0x0000ffff);
break;
case RC_MEMSIZE_24_BITS:
value = (value & 0x00ffffff);
break;
case RC_MEMSIZE_32_BITS:
break;
case RC_MEMSIZE_BIT_0:
value = (value >> 0) & 1;
break;
@@ -146,6 +169,24 @@ unsigned rc_transform_memref_value(unsigned value, char size)
+ rc_bits_set[((value >> 4) & 0x0F)];
break;
case RC_MEMSIZE_16_BITS_BE:
value = ((value & 0xFF00) >> 8) |
((value & 0x00FF) << 8);
break;
case RC_MEMSIZE_24_BITS_BE:
value = ((value & 0xFF0000) >> 16) |
(value & 0x00FF00) |
((value & 0x0000FF) << 16);
break;
case RC_MEMSIZE_32_BITS_BE:
value = ((value & 0xFF000000) >> 24) |
((value & 0x00FF0000) >> 8) |
((value & 0x0000FF00) << 8) |
((value & 0x000000FF) << 24);
break;
default:
break;
}
@@ -153,35 +194,48 @@ unsigned rc_transform_memref_value(unsigned value, char size)
return value;
}
char rc_memref_shared_size(char size)
{
switch (size) {
case RC_MEMSIZE_BIT_0:
case RC_MEMSIZE_BIT_1:
case RC_MEMSIZE_BIT_2:
case RC_MEMSIZE_BIT_3:
case RC_MEMSIZE_BIT_4:
case RC_MEMSIZE_BIT_5:
case RC_MEMSIZE_BIT_6:
case RC_MEMSIZE_BIT_7:
case RC_MEMSIZE_LOW:
case RC_MEMSIZE_HIGH:
case RC_MEMSIZE_BITCOUNT:
/* these can all share an 8-bit memref and just mask off the appropriate data in rc_transform_memref_value */
return RC_MEMSIZE_8_BITS;
/* all sizes less than 8-bits (1 byte) are mapped to 8-bits. 24-bit is mapped to 32-bit
* as we don't expect the client to understand a request for 3 bytes. all other reads are
* mapped to the little-endian read of the same size. */
static const char rc_memref_shared_sizes[] = {
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_8_BITS */
RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS */
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS */
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_LOW */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_HIGH */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_0 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_1 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_2 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_3 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_4 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_5 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_6 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_7 */
RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BITCOUNT */
RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS_BE */
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS_BE */
RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS_BE */
RC_MEMSIZE_32_BITS /* RC_MEMSIZE_VARIABLE */
};
default:
return size;
}
char rc_memref_shared_size(char size) {
const size_t index = (size_t)size;
if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0]))
return size;
return rc_memref_shared_sizes[index];
}
static unsigned rc_peek_value(unsigned address, char size, rc_peek_t peek, void* ud) {
unsigned value;
char shared_size;
if (!peek)
return 0;
switch (size)
shared_size = rc_memref_shared_size(size);
switch (shared_size)
{
case RC_MEMSIZE_8_BITS:
value = peek(address, 1, ud);
@@ -191,28 +245,17 @@ static unsigned rc_peek_value(unsigned address, char size, rc_peek_t peek, void*
value = peek(address, 2, ud);
break;
case RC_MEMSIZE_24_BITS:
/* peek 4 bytes - don't expect the caller to understand 24-bit numbers */
value = peek(address, 4, ud) & 0x00FFFFFF;
break;
case RC_MEMSIZE_32_BITS:
value = peek(address, 4, ud);
break;
default:
if (rc_memref_shared_size(size) == RC_MEMSIZE_8_BITS)
{
value = peek(address, 1, ud);
value = rc_transform_memref_value(value, size);
}
else
{
value = 0;
}
break;
return 0;
}
if (shared_size != size)
value = rc_transform_memref_value(value, size);
return value;
}
@@ -242,17 +285,7 @@ void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs)
*memrefs = 0;
}
unsigned rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state) {
/* if this is an indirect reference, handle the indirection. */
if (memref->value.is_indirect) {
const unsigned new_address = memref->address + eval_state->add_address;
rc_update_memref_value(&memref->value, rc_peek_value(new_address, memref->value.size, eval_state->peek, eval_state->peek_userdata));
}
return rc_get_memref_value_value(&memref->value, operand_type);
}
unsigned rc_get_memref_value_value(rc_memref_value_t* memref, int operand_type) {
static unsigned rc_get_memref_value_value(rc_memref_value_t* memref, int operand_type) {
switch (operand_type)
{
/* most common case explicitly first, even though it could be handled by default case.
@@ -271,3 +304,13 @@ unsigned rc_get_memref_value_value(rc_memref_value_t* memref, int operand_type)
return memref->prior;
}
}
unsigned rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state) {
/* if this is an indirect reference, handle the indirection. */
if (memref->value.is_indirect) {
const unsigned new_address = memref->address + eval_state->add_address;
rc_update_memref_value(&memref->value, rc_peek_value(new_address, memref->value.size, eval_state->peek, eval_state->peek_userdata));
}
return rc_get_memref_value_value(&memref->value, operand_type);
}
+55 -43
View File
@@ -103,7 +103,7 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
return ret;
size = rc_memref_shared_size(self->size);
self->value.memref = rc_alloc_memref(parse, address, size, is_indirect);
self->value.memref = rc_alloc_memref(parse, address, size, (char)is_indirect);
if (parse->offset < 0)
return parse->offset;
@@ -111,12 +111,13 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
return RC_OK;
}
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, int is_indirect, rc_parse_state_t* parse) {
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_indirect, rc_parse_state_t* parse) {
const char* aux = *memaddr;
char* end;
int ret;
unsigned long value;
int negative;
int allow_decimal = 0;
self->size = RC_MEMSIZE_32_BITS;
@@ -128,14 +129,11 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, i
}
value = strtoul(++aux, &end, 16);
if (end == aux) {
if (end == aux)
return RC_INVALID_CONST_OPERAND;
}
if (value > 0xffffffffU) {
if (value > 0xffffffffU)
value = 0xffffffffU;
}
self->type = RC_OPERAND_CONST;
self->value.num = (unsigned)value;
@@ -144,47 +142,61 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, i
break;
case 'f': case 'F': /* floating point constant */
self->value.dbl = strtod(++aux, &end);
if (end == aux) {
return RC_INVALID_FP_OPERAND;
}
if (floor(self->value.dbl) == self->value.dbl) {
self->type = RC_OPERAND_CONST;
self->value.num = (unsigned)floor(self->value.dbl);
}
else {
self->type = RC_OPERAND_FP;
}
aux = end;
break;
allow_decimal = 1;
/* fall through */
case 'v': case 'V': /* signed integer constant */
++aux;
/* fallthrough */
/* fall through */
case '+': case '-': /* signed integer constant */
negative = 0;
if (*aux == '-')
{
if (*aux == '-') {
negative = 1;
++aux;
}
else if (*aux == '+')
{
else if (*aux == '+') {
++aux;
}
value = strtoul(aux, &end, 10);
if (end == aux) {
return RC_INVALID_CONST_OPERAND;
if (*end == '.' && allow_decimal) {
/* custom parser for decimal values to ignore locale */
unsigned long shift = 1;
unsigned long fraction = 0;
aux = end + 1;
if (*aux < '0' || *aux > '9')
return RC_INVALID_FP_OPERAND;
do {
fraction *= 10;
fraction += (*aux - '0');
shift *= 10;
++aux;
} while (*aux >= '0' && *aux <= '9');
/* if fractional part is 0, convert to an integer constant */
if (fraction != 0) {
/* non-zero fractional part, convert to double and merge in integer portion */
const double dbl_fraction = ((double)fraction) / ((double)shift);
if (negative)
self->value.dbl = ((double)(-((long)value))) - dbl_fraction;
else
self->value.dbl = (double)value + dbl_fraction;
self->type = RC_OPERAND_FP;
break;
}
} else {
/* not a floating point value, make sure something was read and advance the read pointer */
if (end == aux)
return allow_decimal ? RC_INVALID_FP_OPERAND : RC_INVALID_CONST_OPERAND;
aux = end;
}
if (value > 0x7fffffffU) {
if (value > 0x7fffffffU)
value = 0x7fffffffU;
}
self->type = RC_OPERAND_CONST;
@@ -193,7 +205,6 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, i
else
self->value.num = (unsigned)value;
aux = end;
break;
case '0':
@@ -202,9 +213,8 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, i
default:
ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
if (ret < 0) {
if (ret < 0)
return ret;
}
break;
}
@@ -213,14 +223,11 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, i
case '1': case '2': case '3': case '4': case '5': /* unsigned integer constant */
case '6': case '7': case '8': case '9':
value = strtoul(aux, &end, 10);
if (end == aux) {
if (end == aux)
return RC_INVALID_CONST_OPERAND;
}
if (value > 0xffffffffU) {
if (value > 0xffffffffU)
value = 0xffffffffU;
}
self->type = RC_OPERAND_CONST;
self->value.num = (unsigned)value;
@@ -231,9 +238,8 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, i
case '@':
ret = rc_parse_operand_lua(self, &aux, parse);
if (ret < 0) {
if (ret < 0)
return ret;
}
break;
}
@@ -340,6 +346,7 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state) {
break;
case RC_MEMSIZE_16_BITS:
case RC_MEMSIZE_16_BITS_BE:
value = ((value >> 12) & 0x0f) * 1000
+ ((value >> 8) & 0x0f) * 100
+ ((value >> 4) & 0x0f) * 10
@@ -347,6 +354,7 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state) {
break;
case RC_MEMSIZE_24_BITS:
case RC_MEMSIZE_24_BITS_BE:
value = ((value >> 20) & 0x0f) * 100000
+ ((value >> 16) & 0x0f) * 10000
+ ((value >> 12) & 0x0f) * 1000
@@ -356,6 +364,7 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state) {
break;
case RC_MEMSIZE_32_BITS:
case RC_MEMSIZE_32_BITS_BE:
case RC_MEMSIZE_VARIABLE:
value = ((value >> 28) & 0x0f) * 10000000
+ ((value >> 24) & 0x0f) * 1000000
@@ -385,14 +394,17 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state) {
break;
case RC_MEMSIZE_16_BITS:
case RC_MEMSIZE_16_BITS_BE:
value ^= 0xffff;
break;
case RC_MEMSIZE_24_BITS:
case RC_MEMSIZE_24_BITS_BE:
value ^= 0xffffff;
break;
case RC_MEMSIZE_32_BITS:
case RC_MEMSIZE_32_BITS_BE:
case RC_MEMSIZE_VARIABLE:
value ^= 0xffffffff;
break;
+2 -2
View File
@@ -99,6 +99,7 @@ typedef struct {
int lines_read;
char has_required_hits;
char measured_as_percent;
}
rc_parse_state_t;
@@ -116,7 +117,6 @@ int rc_parse_memref(const char** memaddr, char* size, unsigned* address);
void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud);
void rc_update_memref_value(rc_memref_value_t* memref, unsigned value);
unsigned rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state);
unsigned rc_get_memref_value_value(rc_memref_value_t* memref, int operand_type);
char rc_memref_shared_size(char size);
unsigned rc_transform_memref_value(unsigned value, char size);
@@ -131,7 +131,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state);
int rc_evaluate_condition_value(rc_condition_t* self, rc_eval_state_t* eval_state);
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, int is_indirect, rc_parse_state_t* parse);
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_indirect, rc_parse_state_t* parse);
unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state);
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse);
+6
View File
@@ -89,6 +89,11 @@ static const rc_disallowed_setting_t _rc_disallowed_ppsspp_settings[] = {
{ NULL, NULL }
};
static const rc_disallowed_setting_t _rc_disallowed_smsplus_settings[] = {
{ "smsplus_region", "pal" },
{ NULL, NULL }
};
static const rc_disallowed_setting_t _rc_disallowed_snes9x_settings[] = {
{ "snes9x_region", "pal" },
{ NULL, NULL }
@@ -112,6 +117,7 @@ static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
{ "PPSSPP", _rc_disallowed_ppsspp_settings },
{ "PCSX-ReARMed", _rc_disallowed_pcsx_rearmed_settings },
{ "PicoDrive", _rc_disallowed_picodrive_settings },
{ "SMS Plus GX", _rc_disallowed_smsplus_settings },
{ "Snes9x", _rc_disallowed_snes9x_settings },
{ "Virtual Jaguar", _rc_disallowed_virtual_jaguar_settings },
{ NULL, NULL }
+3 -3
View File
@@ -383,7 +383,7 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
base = 10;
}
first = strtoul(line, &endptr, base);
first = (unsigned)strtoul(line, &endptr, base);
/* check for a range */
if (*endptr != '-') {
@@ -401,7 +401,7 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
base = 10;
}
last = strtoul(line, &endptr, base);
last = (unsigned)strtoul(line, &endptr, base);
}
/* ignore spaces after the number - was previously ignored as string was split on equals */
@@ -493,7 +493,7 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
memcpy(format, line, chars);
format[chars] = '\0';
lookup->format = rc_parse_format(format);
lookup->format = (unsigned short)rc_parse_format(format);
} else {
lookup->format = RC_FORMAT_VALUE;
}
+29 -1
View File
@@ -1,5 +1,6 @@
#include "rc_runtime.h"
#include "rc_internal.h"
#include "rc_compat.h"
#include "../rhash/md5.h"
@@ -241,6 +242,33 @@ int rc_runtime_get_achievement_measured(const rc_runtime_t* runtime, unsigned id
return 1;
}
int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, unsigned id, char* buffer, size_t buffer_size)
{
const rc_trigger_t* trigger = rc_runtime_get_achievement(runtime, id);
unsigned value;
if (!buffer || !buffer_size)
return 0;
if (!trigger || /* no trigger */
trigger->measured_target == 0 || /* not measured */
!rc_trigger_state_active(trigger->state)) { /* don't report measured value for inactive triggers */
*buffer = '\0';
return 0;
}
/* cap the value at the target so we can count past the target: "107 >= 100" */
value = trigger->measured_value;
if (value > trigger->measured_target)
value = trigger->measured_target;
if (trigger->measured_as_percent) {
unsigned percent = (unsigned)(((unsigned long long)value * 100) / trigger->measured_target);
return snprintf(buffer, buffer_size, "%u%%", percent);
}
return snprintf(buffer, buffer_size, "%u/%u", value, trigger->measured_target);
}
static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, unsigned index) {
if (self->lboards[index].owns_memrefs) {
/* if the lboard has one or more memrefs in its buffer, we can't free the buffer.
@@ -507,7 +535,7 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
if (new_state == old_state)
continue;
/* raise an UNPRIMED event when changing from UNPRIMED to anything else */
/* raise an UNPRIMED event when changing from PRIMED to anything else */
if (old_state == RC_TRIGGER_STATE_PRIMED) {
runtime_event.type = RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED;
runtime_event.id = self->triggers[i].id;
+8 -2
View File
@@ -247,7 +247,7 @@ static int rc_runtime_progress_read_condset(rc_runtime_progress_t* progress, rc_
rc_condition_t* cond;
unsigned flags;
condset->is_paused = rc_runtime_progress_read_uint(progress);
condset->is_paused = (char)rc_runtime_progress_read_uint(progress);
cond = condset->conditions;
while (cond) {
@@ -257,12 +257,18 @@ static int rc_runtime_progress_read_condset(rc_runtime_progress_t* progress, rc_
cond->is_true = (flags & RC_COND_FLAG_IS_TRUE) ? 1 : 0;
if (flags & RC_COND_FLAG_OPERAND1_IS_INDIRECT_MEMREF) {
if (!rc_operand_is_memref(&cond->operand1)) /* this should never happen, but better safe than sorry */
return RC_INVALID_STATE;
cond->operand1.value.memref->value.value = rc_runtime_progress_read_uint(progress);
cond->operand1.value.memref->value.prior = rc_runtime_progress_read_uint(progress);
cond->operand1.value.memref->value.changed = (flags & RC_COND_FLAG_OPERAND1_MEMREF_CHANGED_THIS_FRAME) ? 1 : 0;
}
if (flags & RC_COND_FLAG_OPERAND2_IS_INDIRECT_MEMREF) {
if (!rc_operand_is_memref(&cond->operand2)) /* this should never happen, but better safe than sorry */
return RC_INVALID_STATE;
cond->operand2.value.memref->value.value = rc_runtime_progress_read_uint(progress);
cond->operand2.value.memref->value.prior = rc_runtime_progress_read_uint(progress);
cond->operand2.value.memref->value.changed = (flags & RC_COND_FLAG_OPERAND2_MEMREF_CHANGED_THIS_FRAME) ? 1 : 0;
@@ -305,7 +311,7 @@ static int rc_runtime_progress_read_trigger(rc_runtime_progress_t* progress, rc_
rc_condset_t* condset;
int result;
trigger->state = rc_runtime_progress_read_uint(progress);
trigger->state = (char)rc_runtime_progress_read_uint(progress);
trigger->measured_value = rc_runtime_progress_read_uint(progress);
if (trigger->requirement) {
+2
View File
@@ -13,6 +13,7 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars
/* reset in case multiple triggers are parsed by the same parse_state */
parse->measured_target = 0;
parse->has_required_hits = 0;
parse->measured_as_percent = 0;
if (*aux == 's' || *aux == 'S') {
self->requirement = 0;
@@ -43,6 +44,7 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars
self->measured_value = 0;
self->measured_target = parse->measured_target;
self->measured_as_percent = parse->measured_as_percent;
self->state = RC_TRIGGER_STATE_WAITING;
self->has_hits = 0;
self->has_required_hits = parse->has_required_hits;
+13 -11
View File
@@ -72,17 +72,14 @@ void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_parse_stat
*ptr++ = '*';
buffer_ptr = *memaddr + 1;
if (*buffer_ptr == '-') {
/* negative value automatically needs prefix, 'f' handles both float and digits, so use it */
if (*buffer_ptr == '-' || *buffer_ptr == '+')
++buffer_ptr; /* ignore sign */
/* if it looks like a floating point number, add the 'f' prefix */
while (isdigit((unsigned char)*buffer_ptr))
++buffer_ptr;
if (*buffer_ptr == '.')
*ptr++ = 'f';
}
else {
/* if it looks like a floating point number, add the 'f' prefix */
while (isdigit((unsigned char)*buffer_ptr))
++buffer_ptr;
if (*buffer_ptr == '.')
*ptr++ = 'f';
}
break;
default:
@@ -95,7 +92,12 @@ void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_parse_stat
buffer_ptr = buffer;
cond = rc_parse_condition(&buffer_ptr, parse, 0);
if (parse->offset < 0) {
if (parse->offset < 0)
return;
if (*buffer_ptr) {
/* whatever we copied as a single condition was not fully consumed */
parse->offset = RC_INVALID_COMPARISON;
return;
}
+281 -20
View File
@@ -118,7 +118,11 @@ void* rc_file_open(const char* path)
void* handle;
if (!filereader)
{
rc_hash_init_custom_filereader(NULL);
if (!filereader)
return NULL;
}
handle = filereader->open(path);
if (handle && verbose_message_callback)
@@ -360,7 +364,7 @@ static int rc_hash_finalize(md5_state_t* md5, char hash[33])
return 1;
}
static int rc_hash_buffer(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_buffer(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
md5_state_t md5;
md5_init(&md5);
@@ -410,9 +414,9 @@ static int rc_hash_cd_file(md5_state_t* md5, void* track_handle, uint32_t sector
{
md5_append(md5, buffer, (int)num_read);
size -= (unsigned)num_read;
if (size == 0)
if (size <= (unsigned)num_read)
break;
size -= (unsigned)num_read;
++sector;
if (size >= sizeof(buffer))
@@ -494,7 +498,7 @@ static int rc_hash_3do(char hash[33], const char* path)
block_location *= block_size;
/* the file size is at offset 0x10 (assume 0x10 is always 0) */
size = buffer[offset + 0x11] * 65536 + buffer[offset + 0x12] * 256 + buffer[offset + 0x13];
size = (size_t)buffer[offset + 0x11] * 65536 + buffer[offset + 0x12] * 256 + buffer[offset + 0x13];
if (verbose_message_callback)
{
@@ -557,7 +561,7 @@ static int rc_hash_3do(char hash[33], const char* path)
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_7800(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_7800(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (memcmp(&buffer[1], "ATARI7800", 9) == 0)
@@ -644,7 +648,7 @@ static int rc_hash_arcade(char hash[33], const char* path)
return rc_hash_buffer(hash, (uint8_t*)filename, filename_length);
}
static int rc_hash_lynx(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_lynx(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (buffer[0] == 'L' && buffer[1] == 'Y' && buffer[2] == 'N' && buffer[3] == 'X' && buffer[4] == 0)
@@ -658,7 +662,7 @@ static int rc_hash_lynx(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_buffer(hash, buffer, buffer_size);
}
static int rc_hash_nes(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_nes(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
if (buffer[0] == 'N' && buffer[1] == 'E' && buffer[2] == 'S' && buffer[3] == 0x1A)
@@ -679,6 +683,212 @@ static int rc_hash_nes(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_buffer(hash, buffer, buffer_size);
}
static void rc_hash_v64_to_z64(uint8_t* buffer, const uint8_t* stop)
{
uint32_t* ptr = (uint32_t*)buffer;
const uint32_t* stop32 = (const uint32_t*)stop;
while (ptr < stop32)
{
uint32_t temp = *ptr;
temp = (temp & 0xFF00FF00) >> 8 |
(temp & 0x00FF00FF) << 8;
*ptr++ = temp;
}
}
static void rc_hash_n64_to_z64(uint8_t* buffer, const uint8_t* stop)
{
uint32_t* ptr = (uint32_t*)buffer;
const uint32_t* stop32 = (const uint32_t*)stop;
while (ptr < stop32)
{
uint32_t temp = *ptr;
temp = (temp & 0xFF000000) >> 24 |
(temp & 0x00FF0000) >> 8 |
(temp & 0x0000FF00) << 8 |
(temp & 0x000000FF) << 24;
*ptr++ = temp;
}
}
static int rc_hash_n64(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
uint8_t* swapbuffer;
uint8_t* stop;
const size_t swapbuffer_size = 65536;
md5_state_t md5;
size_t remaining;
int is_v64;
if (buffer[0] == 0x80) /* z64 format (big endian [native]) */
{
return rc_hash_buffer(hash, buffer, buffer_size);
}
else if (buffer[0] == 0x37) /* v64 format (byteswapped) */
{
rc_hash_verbose("converting v64 to z64");
is_v64 = 1;
}
else if (buffer[0] == 0x40) /* n64 format (little endian) */
{
rc_hash_verbose("converting n64 to z64");
is_v64 = 0;
}
else
{
rc_hash_verbose("Not a Nintendo 64 ROM");
return 0;
}
swapbuffer = (uint8_t*)malloc(swapbuffer_size);
if (!swapbuffer)
return rc_hash_error("Could not allocate temporary buffer");
stop = swapbuffer + swapbuffer_size;
md5_init(&md5);
if (buffer_size > MAX_BUFFER_SIZE)
remaining = MAX_BUFFER_SIZE;
else
remaining = (size_t)buffer_size;
if (verbose_message_callback)
{
char message[64];
snprintf(message, sizeof(message), "Hashing %u bytes", (unsigned)remaining);
verbose_message_callback(message);
}
while (remaining >= swapbuffer_size)
{
memcpy(swapbuffer, buffer, swapbuffer_size);
if (is_v64)
rc_hash_v64_to_z64(swapbuffer, stop);
else
rc_hash_n64_to_z64(swapbuffer, stop);
md5_append(&md5, swapbuffer, (int)swapbuffer_size);
buffer += swapbuffer_size;
remaining -= swapbuffer_size;
}
if (remaining > 0)
{
memcpy(swapbuffer, buffer, remaining);
stop = swapbuffer + remaining;
if (is_v64)
rc_hash_v64_to_z64(swapbuffer, stop);
else
rc_hash_n64_to_z64(swapbuffer, stop);
md5_append(&md5, swapbuffer, (int)remaining);
}
free(swapbuffer);
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_n64_file(char hash[33], const char* path)
{
uint8_t* buffer;
uint8_t* stop;
const size_t buffer_size = 65536;
md5_state_t md5;
size_t remaining;
void* file_handle;
int is_v64 = 0;
int is_n64 = 0;
file_handle = rc_file_open(path);
if (!file_handle)
return rc_hash_error("Could not open file");
buffer = (uint8_t*)malloc(buffer_size);
if (!buffer)
{
rc_file_close(file_handle);
return rc_hash_error("Could not allocate temporary buffer");
}
stop = buffer + buffer_size;
/* read first byte so we can detect endianness */
rc_file_seek(file_handle, 0, SEEK_SET);
rc_file_read(file_handle, buffer, 1);
if (buffer[0] == 0x80) /* z64 format (big endian [native]) */
{
}
else if (buffer[0] == 0x37) /* v64 format (byteswapped) */
{
rc_hash_verbose("converting v64 to z64");
is_v64 = 1;
}
else if (buffer[0] == 0x40) /* n64 format (little endian) */
{
rc_hash_verbose("converting n64 to z64");
is_n64 = 1;
}
else
{
free(buffer);
rc_file_close(file_handle);
rc_hash_verbose("Not a Nintendo 64 ROM");
return 0;
}
/* calculate total file size */
rc_file_seek(file_handle, 0, SEEK_END);
remaining = (size_t)rc_file_tell(file_handle);
if (remaining > MAX_BUFFER_SIZE)
remaining = MAX_BUFFER_SIZE;
if (verbose_message_callback)
{
char message[64];
snprintf(message, sizeof(message), "Hashing %u bytes", (unsigned)remaining);
verbose_message_callback(message);
}
/* begin hashing */
md5_init(&md5);
rc_file_seek(file_handle, 0, SEEK_SET);
while (remaining >= buffer_size)
{
rc_file_read(file_handle, buffer, (int)buffer_size);
if (is_v64)
rc_hash_v64_to_z64(buffer, stop);
else if (is_n64)
rc_hash_n64_to_z64(buffer, stop);
md5_append(&md5, buffer, (int)buffer_size);
remaining -= buffer_size;
}
if (remaining > 0)
{
rc_file_read(file_handle, buffer, (int)remaining);
stop = buffer + remaining;
if (is_v64)
rc_hash_v64_to_z64(buffer, stop);
else if (is_n64)
rc_hash_n64_to_z64(buffer, stop);
md5_append(&md5, buffer, (int)remaining);
}
/* cleanup */
rc_file_close(file_handle);
free(buffer);
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_nintendo_ds(char hash[33], const char* path)
{
uint8_t header[512];
@@ -790,7 +1000,7 @@ static int rc_hash_nintendo_ds(char hash[33], const char* path)
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_pce(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_pce(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it (expect ROM data to be multiple of 128KB) */
uint32_t calc_size = ((uint32_t)buffer_size / 0x20000) * 0x20000;
@@ -1095,6 +1305,7 @@ static int rc_hash_find_playstation_executable(void* track_handle, const char* b
size = (unsigned)rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer) - 1);
buffer[size] = '\0';
sector = 0;
for (ptr = (char*)buffer; *ptr; ++ptr)
{
if (strncmp(ptr, boot_key, boot_key_len) == 0)
@@ -1170,7 +1381,7 @@ static int rc_hash_psx(char hash[33], const char* path)
{
rc_hash_error("Could not locate primary executable");
}
else if ((rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
else if (rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer)) < sizeof(buffer))
{
rc_hash_error("Could not read primary executable");
}
@@ -1227,7 +1438,7 @@ static int rc_hash_ps2(char hash[33], const char* path)
{
rc_hash_error("Could not locate primary executable");
}
else if ((rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer))) < sizeof(buffer))
else if (rc_cd_read_sector(track_handle, sector, buffer, sizeof(buffer)) < sizeof(buffer))
{
rc_hash_error("Could not read primary executable");
}
@@ -1258,6 +1469,40 @@ static int rc_hash_ps2(char hash[33], const char* path)
return result;
}
static int rc_hash_psp(char hash[33], const char* path)
{
void* track_handle;
uint32_t sector;
unsigned size;
md5_state_t md5;
track_handle = rc_cd_open_track(path, 1);
if (!track_handle)
return rc_hash_error("Could not open track");
/* http://www.romhacking.net/forum/index.php?topic=30899.0
* PSP_GAME/PARAM.SFO contains key/value pairs identifying the game for the system (i.e. serial number,
* name, version). PSP_GAME/SYSDIR/EBOOT.BIN is the encrypted primary executable.
*/
sector = rc_cd_find_file_sector(track_handle, "PSP_GAME\\PARAM.SFO", &size);
if (!sector)
return rc_hash_error("Not a PSP game disc");
md5_init(&md5);
if (!rc_hash_cd_file(&md5, track_handle, sector, NULL, size, "PSP_GAME\\PARAM.SFO"))
return 0;
sector = rc_cd_find_file_sector(track_handle, "PSP_GAME\\SYSDIR\\EBOOT.BIN", &size);
if (!sector)
return rc_hash_error("Could not find primary executable");
if (!rc_hash_cd_file(&md5, track_handle, sector, NULL, size, "PSP_GAME\\SYSDIR\\EBOOT.BIN"))
return 0;
rc_cd_close_track(track_handle);
return rc_hash_finalize(&md5, hash);
}
static int rc_hash_sega_cd(char hash[33], const char* path)
{
uint8_t buffer[512];
@@ -1287,7 +1532,7 @@ static int rc_hash_sega_cd(char hash[33], const char* path)
return rc_hash_buffer(hash, buffer, sizeof(buffer));
}
static int rc_hash_snes(char hash[33], uint8_t* buffer, size_t buffer_size)
static int rc_hash_snes(char hash[33], const uint8_t* buffer, size_t buffer_size)
{
/* if the file contains a header, ignore it */
uint32_t calc_size = ((uint32_t)buffer_size / 0x2000) * 0x2000;
@@ -1302,7 +1547,7 @@ static int rc_hash_snes(char hash[33], uint8_t* buffer, size_t buffer_size)
return rc_hash_buffer(hash, buffer, buffer_size);
}
int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer, size_t buffer_size)
int rc_hash_generate_from_buffer(char hash[33], int console_id, const uint8_t* buffer, size_t buffer_size)
{
switch (console_id)
{
@@ -1327,7 +1572,6 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
case RC_CONSOLE_MEGA_DRIVE:
case RC_CONSOLE_MSX:
case RC_CONSOLE_NEOGEO_POCKET:
case RC_CONSOLE_NINTENDO_64:
case RC_CONSOLE_ORIC:
case RC_CONSOLE_PC8800:
case RC_CONSOLE_POKEMON_MINI:
@@ -1349,6 +1593,9 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
case RC_CONSOLE_NINTENDO:
return rc_hash_nes(hash, buffer, buffer_size);
case RC_CONSOLE_NINTENDO_64:
return rc_hash_n64(hash, buffer, buffer_size);
case RC_CONSOLE_PC_ENGINE: /* NOTE: does not support PCEngine CD */
return rc_hash_pce(hash, buffer, buffer_size);
@@ -1357,7 +1604,7 @@ int rc_hash_generate_from_buffer(char hash[33], int console_id, uint8_t* buffer,
}
}
static int rc_hash_whole_file(char hash[33], int console_id, const char* path)
static int rc_hash_whole_file(char hash[33], const char* path)
{
md5_state_t md5;
uint8_t* buffer;
@@ -1608,7 +1855,6 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_MASTER_SYSTEM:
case RC_CONSOLE_MEGA_DRIVE:
case RC_CONSOLE_NEOGEO_POCKET:
case RC_CONSOLE_NINTENDO_64:
case RC_CONSOLE_ORIC:
case RC_CONSOLE_POKEMON_MINI:
case RC_CONSOLE_SEGA_32X:
@@ -1619,7 +1865,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_VIRTUAL_BOY:
case RC_CONSOLE_WONDERSWAN:
/* generic whole-file hash - don't buffer */
return rc_hash_whole_file(hash, console_id, path);
return rc_hash_whole_file(hash, path);
case RC_CONSOLE_MSX:
case RC_CONSOLE_PC8800:
@@ -1627,7 +1873,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
if (rc_path_compare_extension(path, "m3u"))
return rc_hash_generate_from_playlist(hash, console_id, path);
return rc_hash_whole_file(hash, console_id, path);
return rc_hash_whole_file(hash, path);
case RC_CONSOLE_ATARI_7800:
case RC_CONSOLE_ATARI_LYNX:
@@ -1645,6 +1891,9 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
case RC_CONSOLE_ARCADE:
return rc_hash_arcade(hash, path);
case RC_CONSOLE_NINTENDO_64:
return rc_hash_n64_file(hash, path);
case RC_CONSOLE_NINTENDO_DS:
return rc_hash_nintendo_ds(hash, path);
@@ -1675,6 +1924,9 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
return rc_hash_ps2(hash, path);
case RC_CONSOLE_PSP:
return rc_hash_psp(hash, path);
case RC_CONSOLE_DREAMCAST:
if (rc_path_compare_extension(path, "m3u"))
return rc_hash_generate_from_playlist(hash, console_id, path);
@@ -1690,7 +1942,7 @@ int rc_hash_generate_from_file(char hash[33], int console_id, const char* path)
}
}
static void rc_hash_iterator_append_console(struct rc_hash_iterator* iterator, int console_id)
static void rc_hash_iterator_append_console(struct rc_hash_iterator* iterator, uint8_t console_id)
{
int i = 0;
while (iterator->consoles[i] != 0)
@@ -1916,8 +2168,9 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
if (rc_path_compare_extension(ext, "iso"))
{
iterator->consoles[0] = RC_CONSOLE_PLAYSTATION_2;
iterator->consoles[1] = RC_CONSOLE_3DO;
iterator->consoles[2] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
iterator->consoles[1] = RC_CONSOLE_PSP;
iterator->consoles[2] = RC_CONSOLE_3DO;
iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
need_path = 1;
}
break;
@@ -2061,6 +2314,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
{
iterator->consoles[0] = RC_CONSOLE_VIRTUAL_BOY;
}
else if (rc_path_compare_extension(ext, "v64"))
{
iterator->consoles[0] = RC_CONSOLE_NINTENDO_64;
}
break;
case 'w':
@@ -2081,6 +2338,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
iterator->consoles[0] = RC_CONSOLE_ARCADE;
need_path = 1;
}
else if (rc_path_compare_extension(ext, "z64"))
{
iterator->consoles[0] = RC_CONSOLE_NINTENDO_64;
}
break;
}
+45 -16
View File
@@ -6,6 +6,12 @@
#include <stdio.h>
#include <string.h>
#if RCHEEVOS_URL_SSL
#define RCHEEVOS_URL_PROTOCOL "https"
#else
#define RCHEEVOS_URL_PROTOCOL "http"
#endif
static int rc_url_encode(char* encoded, size_t len, const char* str) {
for (;;) {
switch (*str) {
@@ -67,7 +73,7 @@ int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=awardachievement&u=%s&t=%s&a=%u&h=%d",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=awardachievement&u=%s&t=%s&a=%u&h=%d",
urle_user_name,
urle_login_token,
cheevo_id,
@@ -106,7 +112,7 @@ int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=submitlbentry&u=%s&t=%s&i=%u&s=%d&v=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=submitlbentry&u=%s&t=%s&i=%u&s=%d&v=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
urle_user_name,
urle_login_token,
lboard_id,
@@ -122,7 +128,7 @@ int rc_url_get_gameid(char* buffer, size_t size, const char* hash) {
int written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=gameid&m=%s",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=gameid&m=%s",
hash
);
@@ -145,7 +151,7 @@ int rc_url_get_patch(char* buffer, size_t size, const char* user_name, const cha
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=patch&u=%s&t=%s&g=%u",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=patch&u=%s&t=%s&g=%u",
urle_user_name,
urle_login_token,
gameid
@@ -181,7 +187,7 @@ int rc_url_login_with_password(char* buffer, size_t size, const char* user_name,
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=login&u=%s&p=%s",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=login&u=%s&p=%s",
urle_user_name,
urle_password
);
@@ -205,7 +211,7 @@ int rc_url_login_with_token(char* buffer, size_t size, const char* user_name, co
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=login&u=%s&t=%s",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=login&u=%s&t=%s",
urle_user_name,
urle_login_token
);
@@ -229,7 +235,7 @@ int rc_url_get_unlock_list(char* buffer, size_t size, const char* user_name, con
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=unlocks&u=%s&t=%s&g=%u&h=%d",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=unlocks&u=%s&t=%s&g=%u&h=%d",
urle_user_name,
urle_login_token,
gameid,
@@ -255,7 +261,7 @@ int rc_url_post_playing(char* buffer, size_t size, const char* user_name, const
written = snprintf(
buffer,
size,
"http://retroachievements.org/dorequest.php?r=postactivity&u=%s&t=%s&a=3&m=%u",
RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php?r=postactivity&u=%s&t=%s&a=3&m=%u",
urle_user_name,
urle_login_token,
gameid
@@ -300,8 +306,7 @@ static int rc_url_append_unum(char* buffer, size_t buffer_size, size_t* buffer_o
char num[16];
int chars = snprintf(num, sizeof(num), "%u", value);
if (chars + written < (int)buffer_size)
{
if (chars + written < (int)buffer_size) {
memcpy(&buffer[written], num, chars + 1);
*buffer_offset = written + chars;
return 0;
@@ -314,13 +319,11 @@ static int rc_url_append_unum(char* buffer, size_t buffer_size, size_t* buffer_o
static int rc_url_append_str(char* buffer, size_t buffer_size, size_t* buffer_offset, const char* param, const char* value)
{
int written = rc_url_append_param_equals(buffer, buffer_size, *buffer_offset, param);
if (written > 0)
{
if (written > 0) {
buffer += written;
buffer_size -= written;
if (rc_url_encode(buffer, buffer_size, value) == 0)
{
if (rc_url_encode(buffer, buffer_size, value) == 0) {
written += (int)strlen(buffer);
*buffer_offset = written;
return 0;
@@ -333,7 +336,7 @@ static int rc_url_append_str(char* buffer, size_t buffer_size, size_t* buffer_of
static int rc_url_build_dorequest(char* url_buffer, size_t url_buffer_size, size_t* buffer_offset,
const char* api, const char* user_name)
{
const char* base_url = "http://retroachievements.org/dorequest.php";
const char* base_url = RCHEEVOS_URL_PROTOCOL"://retroachievements.org/dorequest.php";
size_t written = strlen(base_url);
int failure = 0;
@@ -343,7 +346,8 @@ static int rc_url_build_dorequest(char* url_buffer, size_t url_buffer_size, size
url_buffer[written++] = '?';
failure |= rc_url_append_str(url_buffer, url_buffer_size, &written, "r", api);
failure |= rc_url_append_str(url_buffer, url_buffer_size, &written, "u", user_name);
if (user_name)
failure |= rc_url_append_str(url_buffer, url_buffer_size, &written, "u", user_name);
*buffer_offset += written;
return failure;
@@ -371,3 +375,28 @@ int rc_url_ping(char* url_buffer, size_t url_buffer_size, char* post_buffer, siz
return failure;
}
int rc_url_get_lboard_entries(char* buffer, size_t size, unsigned lboard_id, unsigned first_index, unsigned count)
{
size_t written = 0;
int failure = rc_url_build_dorequest(buffer, size, &written, "lbinfo", NULL);
failure |= rc_url_append_unum(buffer, size, &written, "i", lboard_id);
if (first_index > 1)
failure |= rc_url_append_unum(buffer, size, &written, "o", first_index - 1);
failure |= rc_url_append_unum(buffer, size, &written, "c", count);
return failure;
}
int rc_url_get_lboard_entries_near_user(char* buffer, size_t size, unsigned lboard_id, const char* user_name, unsigned count)
{
size_t written = 0;
int failure = rc_url_build_dorequest(buffer, size, &written, "lbinfo", NULL);
failure |= rc_url_append_unum(buffer, size, &written, "i", lboard_id);
failure |= rc_url_append_str(buffer, size, &written, "u", user_name);
failure |= rc_url_append_unum(buffer, size, &written, "c", count);
return failure;
}
#undef RCHEEVOS_URL_PROTOCOL
+4 -7
View File
@@ -298,19 +298,16 @@ bool disk_control_set_eject_state(
/* Set eject state */
if (disk_control->cb.set_eject_state(eject))
snprintf(
msg, sizeof(msg), "%s %s",
msg, sizeof(msg), "%s",
eject ? msg_hash_to_str(MSG_DISK_EJECTED) :
msg_hash_to_str(MSG_DISK_CLOSED),
msg_hash_to_str(MSG_VIRTUAL_DISK_TRAY));
msg_hash_to_str(MSG_DISK_CLOSED));
else
{
error = true;
snprintf(
msg, sizeof(msg), "%s %s %s",
msg_hash_to_str(MSG_FAILED_TO),
msg, sizeof(msg), "%s",
eject ? msg_hash_to_str(MSG_VIRTUAL_DISK_TRAY_EJECT) :
msg_hash_to_str(MSG_VIRTUAL_DISK_TRAY_CLOSE),
msg_hash_to_str(MSG_VIRTUAL_DISK_TRAY));
msg_hash_to_str(MSG_VIRTUAL_DISK_TRAY_CLOSE));
}
if (!string_is_empty(msg))
+12
View File
@@ -83,6 +83,18 @@ typedef struct driver_ctx_info
bool driver_ctl(enum driver_ctl_state state, void *data);
/**
* driver_find_index:
* @label : string of driver type to be found.
* @drv : identifier of driver to be found.
*
* Find index of the driver, based on @label.
*
* Returns: -1 if no driver based on @label and @drv found, otherwise
* index number of the driver found in the array.
**/
int driver_find_index(const char *label, const char *drv);
/* Sets audio and video drivers to nonblock state.
*
* If nonblock state is false, sets blocking state for both
+3 -4
View File
@@ -107,6 +107,9 @@ bool fill_pathname_application_data(char *s, size_t len)
"Library/Application Support/RetroArch", len);
return true;
}
#elif defined(RARCH_UNIX_CWD_ENV)
getcwd(s, len);
return true;
#elif defined(DINGUX)
dingux_get_base_path(s, len);
return true;
@@ -143,10 +146,6 @@ bool fill_pathname_application_data(char *s, size_t len)
const char* xmb_theme_ident(void);
#endif
#ifdef HAVE_STRIPES
const char* stripes_theme_ident(void);
#endif
void fill_pathname_application_special(char *s,
size_t len, enum application_special_type type)
{
+10 -4
View File
@@ -162,8 +162,10 @@ static void frontend_ctr_deinit(void* data)
verbosity_enable();
retro_main_log_file_init(NULL, false);
#ifdef CONSOLE_LOG
if (ctr_bottom_screen_enabled && (ctr_fork_mode == FRONTEND_FORK_NONE))
wait_for_input();
#endif
CFGU_GetModelNintendo2DS(&not_2DS);
@@ -419,13 +421,15 @@ void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id)
id,
(u32*)gfxBottomFramebuffers[id],
(u32*)gfxBottomFramebuffers[id],
240 * 2,
GSP_RGB565_OES);
240 * 3,
GSP_BGR8_OES);
}
}
#endif
#ifdef CONSOLE_LOG
PrintConsole* ctrConsole;
#endif
static void frontend_ctr_init(void* data)
{
@@ -436,10 +440,10 @@ static void frontend_ctr_init(void* data)
verbosity_enable();
gfxInit(GSP_BGR8_OES, GSP_RGB565_OES, false);
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false);
u32 topSize = 400 * 240 * 3;
u32 bottomSize = 320 * 240 * 2;
u32 bottomSize = 320 * 240 * 3;
#ifdef USE_CTRULIB_2
linearFree(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL));
@@ -473,7 +477,9 @@ static void frontend_ctr_init(void* data)
gfxSetFramebufferInfo(GFX_BOTTOM, 0);
gfxSet3D(true);
#ifdef CONSOLE_LOG
ctrConsole = consoleInit(GFX_BOTTOM, NULL);
#endif
/* enable access to all service calls when possible. */
if (svchax_init)
+4 -1
View File
@@ -1792,7 +1792,10 @@ static void frontend_unix_get_env(int *argc,
}
#else
char base_path[PATH_MAX] = {0};
#if defined(DINGUX)
#if defined(RARCH_UNIX_CWD_ENV)
/* The entire path is zero initialized. */
base_path[0] = '.';
#elif defined(DINGUX)
dingux_get_base_path(base_path, sizeof(base_path));
#else
const char *xdg = getenv("XDG_CONFIG_HOME");
+37 -4
View File
@@ -21,8 +21,11 @@
#define COLOR_ABGR(r, g, b, a) (((unsigned)(a) << 24) | ((b) << 16) | ((g) << 8) | ((r) << 0))
#define CTR_TOP_FRAMEBUFFER_WIDTH 400
#define CTR_TOP_FRAMEBUFFER_HEIGHT 240
#define CTR_TOP_FRAMEBUFFER_WIDTH 400
#define CTR_TOP_FRAMEBUFFER_HEIGHT 240
#define CTR_BOTTOM_FRAMEBUFFER_WIDTH 320
#define CTR_BOTTOM_FRAMEBUFFER_HEIGHT 240
#define CTR_STATE_DATE_SIZE 11
#ifdef USE_CTRULIB_2
extern u8* gfxTopLeftFramebuffers[2];
@@ -30,7 +33,9 @@ extern u8* gfxTopRightFramebuffers[2];
extern u8* gfxBottomFramebuffers[2];
#endif
#ifdef CONSOLE_LOG
extern PrintConsole* ctrConsole;
#endif
extern const u8 ctr_sprite_shbin[];
extern const u32 ctr_sprite_shbin_size;
@@ -58,6 +63,13 @@ typedef enum
CTR_VIDEO_MODE_LAST
} ctr_video_mode_enum;
typedef enum
{
CTR_BOTTOM_MENU_NOT_AVAILABLE = 0,
CTR_BOTTOM_MENU_DEFAULT,
CTR_BOTTOM_MENU_SELECT,
} ctr_bottom_menu;
typedef struct ctr_video
{
struct
@@ -67,6 +79,7 @@ typedef struct ctr_video
void* left;
void* right;
}top;
void* bottom;
}drawbuffers;
void* depthbuffer;
@@ -116,11 +129,10 @@ typedef struct ctr_video
bool overlay_full_screen;
#endif
void* empty_framebuffer;
aptHookCookie lcd_aptHook;
ctr_video_mode_enum video_mode;
int current_buffer_top;
int current_buffer_bottom;
bool p3d_event_pending;
bool ppf_event_pending;
@@ -133,6 +145,20 @@ typedef struct ctr_video
int size;
}vertex_cache;
bool init_bottom_menu;
bool refresh_bottom_menu;
bool render_font_bottom;
bool render_state_from_png_file;
bool state_data_exist;
char state_date[CTR_STATE_DATE_SIZE];
int state_slot;
bool bottom_check_idle;
bool bottom_is_idle;
bool bottom_is_fading;
u64 idle_timestamp;
ctr_bottom_menu bottom_menu;
ctr_bottom_menu prev_bottom_menu;
struct ctr_bottom_texture_data *bottom_textures;
} ctr_video_t;
typedef struct ctr_texture
@@ -156,6 +182,13 @@ struct ctr_overlay_data
};
#endif
struct ctr_bottom_texture_data
{
uintptr_t texture;
ctr_vertex_t* frame_coords;
ctr_scale_vector_t scale_vector;
};
static INLINE void ctr_set_scale_vector(ctr_scale_vector_t* vec,
int viewport_width, int viewport_height,
int texture_width, int texture_height)
+33 -11
View File
@@ -226,30 +226,52 @@ bool d3d11_init_shader(
LPCSTR gs_entry,
const D3D11_INPUT_ELEMENT_DESC* input_element_descs,
UINT num_elements,
d3d11_shader_t* out)
d3d11_shader_t* out,
enum d3d11_feature_level_hint hint)
{
D3DBlob vs_code = NULL;
D3DBlob ps_code = NULL;
D3DBlob gs_code = NULL;
D3DBlob vs_code = NULL;
D3DBlob ps_code = NULL;
D3DBlob gs_code = NULL;
bool success = true;
const char *vs_str = NULL;
const char *ps_str = NULL;
const char *gs_str = NULL;
bool success = true;
switch (hint)
{
case D3D11_FEATURE_LEVEL_HINT_11_0:
case D3D11_FEATURE_LEVEL_HINT_11_1:
case D3D11_FEATURE_LEVEL_HINT_12_0:
case D3D11_FEATURE_LEVEL_HINT_12_1:
case D3D11_FEATURE_LEVEL_HINT_12_2:
vs_str = "vs_5_0";
ps_str = "ps_5_0";
gs_str = "gs_5_0";
break;
case D3D11_FEATURE_LEVEL_HINT_DONTCARE:
default:
vs_str = "vs_4_0";
ps_str = "ps_4_0";
gs_str = "gs_4_0";
break;
}
if (!src) /* LPCWSTR filename */
{
if (vs_entry && !d3d_compile_from_file((LPCWSTR)src_name, vs_entry, "vs_4_0", &vs_code))
if (vs_entry && !d3d_compile_from_file((LPCWSTR)src_name, vs_entry, vs_str, &vs_code))
success = false;
if (ps_entry && !d3d_compile_from_file((LPCWSTR)src_name, ps_entry, "ps_4_0", &ps_code))
if (ps_entry && !d3d_compile_from_file((LPCWSTR)src_name, ps_entry, ps_str, &ps_code))
success = false;
if (gs_entry && !d3d_compile_from_file((LPCWSTR)src_name, gs_entry, "gs_4_0", &gs_code))
if (gs_entry && !d3d_compile_from_file((LPCWSTR)src_name, gs_entry, gs_str, &gs_code))
success = false;
}
else /* char array */
{
if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_4_0", &vs_code))
if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, vs_str, &vs_code))
success = false;
if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, "ps_4_0", &ps_code))
if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, ps_str, &ps_code))
success = false;
if (gs_entry && !d3d_compile(src, size, (LPCSTR)src_name, gs_entry, "gs_4_0", &gs_code))
if (gs_entry && !d3d_compile(src, size, (LPCSTR)src_name, gs_entry, gs_str, &gs_code))
success = false;
}
+41 -1
View File
@@ -2529,6 +2529,9 @@ typedef struct
D3D11RasterizerState scissor_disabled;
D3D11Buffer ubo;
d3d11_uniform_t ubo_values;
#ifdef HAVE_DXGI_HDR
d3d11_texture_t back_buffer;
#endif
D3D11SamplerState samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX];
D3D11BlendState blend_enable;
D3D11BlendState blend_disable;
@@ -2549,6 +2552,12 @@ typedef struct
bool has_flip_model;
bool has_allow_tearing;
d3d11_shader_t shaders[GFX_MAX_SHADERS];
#ifdef HAVE_DXGI_HDR
enum dxgi_swapchain_bit_depth
chain_bit_depth;
DXGI_COLOR_SPACE_TYPE chain_color_space;
DXGI_FORMAT chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_COUNT];
#endif
#ifdef __WINRT__
DXGIFactory2 factory;
#else
@@ -2562,6 +2571,20 @@ typedef struct
struct retro_hw_render_interface_d3d11 iface;
} hw;
#ifdef HAVE_DXGI_HDR
struct
{
dxgi_hdr_uniform_t ubo_values;
D3D11Buffer ubo;
float max_output_nits;
float min_output_nits;
float max_cll;
float max_fall;
bool support;
bool enable;
} hdr;
#endif
struct
{
d3d11_shader_t shader;
@@ -2641,6 +2664,22 @@ void d3d11_update_texture(
DXGI_FORMAT d3d11_get_closest_match(
D3D11Device device, DXGI_FORMAT desired_format, UINT desired_format_support);
enum d3d11_feature_level_hint
{
D3D11_FEATURE_LEVEL_HINT_DONTCARE,
D3D11_FEATURE_LEVEL_HINT_1_0_CORE,
D3D11_FEATURE_LEVEL_HINT_9_1,
D3D11_FEATURE_LEVEL_HINT_9_2,
D3D11_FEATURE_LEVEL_HINT_9_3,
D3D11_FEATURE_LEVEL_HINT_10_0,
D3D11_FEATURE_LEVEL_HINT_10_1,
D3D11_FEATURE_LEVEL_HINT_11_0,
D3D11_FEATURE_LEVEL_HINT_11_1,
D3D11_FEATURE_LEVEL_HINT_12_0,
D3D11_FEATURE_LEVEL_HINT_12_1,
D3D11_FEATURE_LEVEL_HINT_12_2
};
bool d3d11_init_shader(
D3D11Device device,
const char* src,
@@ -2651,7 +2690,8 @@ bool d3d11_init_shader(
LPCSTR gs_entry,
const D3D11_INPUT_ELEMENT_DESC* input_element_descs,
UINT num_elements,
d3d11_shader_t* out);
d3d11_shader_t* out,
enum d3d11_feature_level_hint hint);
static INLINE void d3d11_release_shader(d3d11_shader_t* shader)
{
+104 -17
View File
@@ -174,7 +174,6 @@ bool d3d12_init_base(d3d12_video_t* d3d12)
#else
DXGICreateFactory(&d3d12->factory);
#endif
{
int i = 0;
settings_t *settings = config_get_ptr();
@@ -200,7 +199,6 @@ bool d3d12_init_base(d3d12_video_t* d3d12)
if (FAILED(DXGIEnumAdapters(d3d12->factory, i, &adapter)))
break;
#endif
IDXGIAdapter_GetDesc(adapter, &desc);
utf16_to_char_string((const uint16_t*)desc.Description, str, sizeof(str));
@@ -284,13 +282,30 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
{
unsigned i;
HRESULT hr;
HWND hwnd;
#ifdef __WINRT__
DXGI_SWAP_CHAIN_DESC1 desc;
memset(&desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC1));
DXGI_SWAP_CHAIN_DESC1 desc = {{0}};
#else
DXGI_SWAP_CHAIN_DESC desc;
HWND hwnd = (HWND)corewindow;
memset(&desc, 0, sizeof(DXGI_SWAP_CHAIN_DESC));
DXGI_SWAP_CHAIN_DESC desc = {{0}};
#endif
#ifdef HAVE_DXGI_HDR
DXGI_COLOR_SPACE_TYPE color_space;
d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_8] = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_10] = DXGI_FORMAT_R10G10B10A2_UNORM;
d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM;
#endif
hwnd = (HWND)corewindow;
#ifdef HAVE_DXGI_HDR
if (!(d3d12->hdr.support =
dxgi_check_display_hdr_support(d3d12->factory, hwnd)))
d3d12->hdr.enable = false;
d3d12->chain.bit_depth = d3d12->hdr.enable
? DXGI_SWAPCHAIN_BIT_DEPTH_10
: DXGI_SWAPCHAIN_BIT_DEPTH_8;
#endif
desc.BufferCount = countof(d3d12->chain.renderTargets);
@@ -298,24 +313,37 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
#ifdef __WINRT__
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#else
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 0;
desc.BufferDesc.RefreshRate.Denominator = 1;
#endif
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
desc.Format = d3d12->chain.formats[d3d12->chain.bit_depth];
#else
desc.BufferDesc.Format = d3d12->chain.formats[d3d12->chain.bit_depth];
#endif
#else
#ifdef __WINRT__
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#else
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#endif
#endif
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
#ifdef HAVE_WINDOW
desc.OutputWindow = hwnd;
desc.Windowed = TRUE;
desc.OutputWindow = hwnd;
desc.Windowed = TRUE;
#endif
#if 0
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
#else
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#endif
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
@@ -334,6 +362,34 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
#endif
#ifdef HAVE_DXGI_HDR
/* Check display HDR support and
initialize ST.2084 support to match
the display's support. */
#if 0
d3d12->hdr.max_output_nits = 300.0f;
d3d12->hdr.min_output_nits = 0.001f;
d3d12->hdr.max_cll = 0.0f;
d3d12->hdr.max_fall = 0.0f;
#endif
color_space =
d3d12->hdr.enable
? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
dxgi_swapchain_color_space(d3d12->chain.handle,
&d3d12->chain.color_space, color_space);
dxgi_set_hdr_metadata(
d3d12->chain.handle,
d3d12->hdr.support,
d3d12->chain.bit_depth,
d3d12->chain.color_space,
d3d12->hdr.max_output_nits,
d3d12->hdr.min_output_nits,
d3d12->hdr.max_cll,
d3d12->hdr.max_fall);
#endif
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
@@ -343,10 +399,28 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12,
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
}
d3d12->chain.viewport.Width = width;
d3d12->chain.viewport.Height = height;
d3d12->chain.scissorRect.right = width;
d3d12->chain.scissorRect.bottom = height;
#ifdef HAVE_DXGI_HDR
memset(&d3d12->chain.back_buffer,
0, sizeof(d3d12->chain.back_buffer));
d3d12->chain.back_buffer.desc.Width = width;
d3d12->chain.back_buffer.desc.Height = height;
d3d12->chain.back_buffer.desc.Format =
DXGI_FORMAT_R8G8B8A8_UNORM;
d3d12->chain.back_buffer.desc.Flags =
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
d3d12->chain.back_buffer.srv_heap =
&d3d12->desc.srv_heap;
d3d12->chain.back_buffer.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr
+ (countof(d3d12->chain.renderTargets))
* d3d12->desc.rtv_heap.stride;
d3d12_init_texture(d3d12->device, &d3d12->chain.back_buffer);
#endif
d3d12->chain.viewport.Width = width;
d3d12->chain.viewport.Height = height;
d3d12->chain.scissorRect.right = width;
d3d12->chain.scissorRect.bottom = height;
return true;
}
@@ -619,6 +693,19 @@ D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc = {
D3D12_COLOR_WRITE_ENABLE_ALL,
};
D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc = {
FALSE,
FALSE,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_OP_ADD,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_OP_ADD,
D3D12_LOGIC_OP_NOOP,
D3D12_COLOR_WRITE_ENABLE_ALL,
};
bool d3d12_init_pipeline(
D3D12Device device,
D3DBlob vs_code,
+26 -2
View File
@@ -1385,6 +1385,9 @@ typedef struct
{
DXGISwapChain handle;
D3D12Resource renderTargets[2];
#ifdef HAVE_DXGI_HDR
d3d12_texture_t back_buffer;
#endif
D3D12_CPU_DESCRIPTOR_HANDLE desc_handles[2];
D3D12_VIEWPORT viewport;
D3D12_RECT scissorRect;
@@ -1392,6 +1395,11 @@ typedef struct
int frame_index;
bool vsync;
unsigned swap_interval;
#ifdef HAVE_DXGI_HDR
enum dxgi_swapchain_bit_depth bit_depth;
DXGI_COLOR_SPACE_TYPE color_space;
DXGI_FORMAT formats[DXGI_SWAPCHAIN_BIT_DEPTH_COUNT];
#endif
} chain;
struct
@@ -1407,6 +1415,21 @@ typedef struct
int rotation;
} frame;
#ifdef HAVE_DXGI_HDR
struct
{
dxgi_hdr_uniform_t ubo_values;
D3D12Resource ubo;
D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view;
float max_output_nits;
float min_output_nits;
float max_cll;
float max_fall;
bool support;
bool enable;
} hdr;
#endif
struct
{
D3D12Resource vbo;
@@ -1490,19 +1513,20 @@ typedef enum {
ROOT_ID_SAMPLER_T,
ROOT_ID_UBO,
ROOT_ID_PC,
ROOT_ID_MAX,
ROOT_ID_MAX
} root_signature_parameter_index_t;
typedef enum {
CS_ROOT_ID_TEXTURE_T = 0,
CS_ROOT_ID_UAV_T,
CS_ROOT_ID_CONSTANTS,
CS_ROOT_ID_MAX,
CS_ROOT_ID_MAX
} compute_root_index_t;
RETRO_BEGIN_DECLS
extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc;
extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc;
bool d3d12_init_base(d3d12_video_t* d3d12);
+2 -1
View File
@@ -140,7 +140,8 @@ bool d3d_compile(const char* src, size_t size, LPCSTR src_name, LPCSTR entrypoin
{
if (error_msg)
{
RARCH_ERR("D3DCompile failed :\n%s\n", (const char*)D3DGetBufferPointer(error_msg));
const char* msg = (const char*)D3DGetBufferPointer(error_msg);
RARCH_ERR("D3DCompile failed :\n%s\n", msg); /* Place a breakpoint here, if you want, to see shader compilation issues */
Release(error_msg);
}
return false;
+303 -1
View File
@@ -20,7 +20,7 @@
#include <assert.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#include "dxgi_common.h"
@@ -31,6 +31,21 @@
#include "../frontend/frontend_driver.h"
#include "win32_common.h"
const GUID DECLSPEC_SELECTANY libretro_IID_IDXGIOutput6 = { 0x068346e8,0xaaec,
0x4b84, {0xad,0xd7,0x13,0x7f,0x51,0x3f,0x77,0xa1 } };
#ifdef HAVE_DXGI_HDR
/* TODO/FIXME - globals */
static DXGI_HDR_METADATA_HDR10 g_hdr10_meta_data = {0};
typedef enum hdr_root_constants
{
HDR_ROOT_CONSTANTS_REFERENCE_WHITE_NITS = 0,
HDR_ROOT_CONSTANTS_DISPLAY_CURVE,
HDR_ROOT_CONSTANTS_COUNT
} hdr_root_constants_t;
#endif
#if defined(HAVE_DYNAMIC) && !defined(__WINRT__)
#include <dynamic/dylib.h>
@@ -347,3 +362,290 @@ DXGI_FORMAT glslang_format_to_dxgi(glslang_format fmt)
return DXGI_FORMAT_UNKNOWN;
}
#ifdef HAVE_DXGI_HDR
typedef struct display_chromaticities
{
float red_x;
float red_y;
float green_x;
float green_y;
float blue_x;
float blue_y;
float white_x;
float white_y;
} display_chromaticities_t;
inline static int dxgi_compute_intersection_area(
int ax1, int ay1, int ax2, int ay2,
int bx1, int by1, int bx2, int by2)
{
return max(0, min(ax2, bx2) -
max(ax1, bx1))
* max(0, min(ay2, by2) - max(ay1, by1));
}
#ifdef __WINRT__
bool dxgi_check_display_hdr_support(DXGIFactory2 factory, HWND hwnd)
#else
bool dxgi_check_display_hdr_support(DXGIFactory factory, HWND hwnd)
#endif
{
DXGIOutput6 output6 = NULL;
DXGIOutput best_output = NULL;
DXGIOutput current_output = NULL;
DXGIAdapter dxgi_adapter = NULL;
UINT i = 0;
bool supported = false;
float best_intersect_area = -1;
#ifdef __WINRT__
if (!DXGIIsCurrent2(factory))
{
if (FAILED(DXGICreateFactory2(&factory)))
{
RARCH_ERR("[DXGI]: Failed to create DXGI factory\n");
return false;
}
}
if (FAILED(DXGIEnumAdapters2(factory, 0, &dxgi_adapter)))
{
RARCH_ERR("[DXGI]: Failed to enumerate adapters\n");
return false;
}
#else
if (!DXGIIsCurrent(factory))
{
if (FAILED(DXGICreateFactory(&factory)))
{
RARCH_ERR("[DXGI]: Failed to create DXGI factory\n");
return false;
}
}
if (FAILED(DXGIEnumAdapters(factory, 0, &dxgi_adapter)))
{
RARCH_ERR("[DXGI]: Failed to enumerate adapters\n");
return false;
}
#endif
while ( DXGIEnumOutputs(dxgi_adapter, i, &current_output)
!= DXGI_ERROR_NOT_FOUND)
{
RECT r, rect;
DXGI_OUTPUT_DESC desc;
int intersect_area;
int bx1, by1, bx2, by2;
int ax1 = 0;
int ay1 = 0;
int ax2 = 0;
int ay2 = 0;
if (win32_get_client_rect(&rect))
{
ax1 = rect.left;
ay1 = rect.top;
ax2 = rect.right;
ay2 = rect.bottom;
}
/* Get the rectangle bounds of current output */
if (FAILED(DXGIGetOutputDesc(current_output, &desc)))
{
RARCH_ERR("[DXGI]: Failed to get DXGI output description\n");
goto error;
}
/* TODO/FIXME - DesktopCoordinates won't work for WinRT */
r = desc.DesktopCoordinates;
bx1 = r.left;
by1 = r.top;
bx2 = r.right;
by2 = r.bottom;
/* Compute the intersection */
intersect_area = dxgi_compute_intersection_area(
ax1, ay1, ax2, ay2, bx1, by1, bx2, by2);
if (intersect_area > best_intersect_area)
{
best_output = current_output;
AddRef(best_output);
best_intersect_area = (float)intersect_area;
}
i++;
}
if (SUCCEEDED(best_output->lpVtbl->QueryInterface(
best_output,
&libretro_IID_IDXGIOutput6, (void**)&output6)))
{
DXGI_OUTPUT_DESC1 desc1;
if (SUCCEEDED(DXGIGetOutputDesc1(output6, &desc1)))
{
supported = (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
if (supported)
video_driver_set_hdr_support();
else
{
settings_t* settings = config_get_ptr();
settings->modified = true;
settings->bools.video_hdr_enable = false;
video_driver_unset_hdr_support();
}
}
else
{
RARCH_ERR("[DXGI]: Failed to get DXGI Output 6 description\n");
}
Release(output6);
}
else
{
RARCH_ERR("[DXGI]: Failed to get DXGI Output 6 from best output\n");
}
error:
Release(best_output);
Release(current_output);
Release(dxgi_adapter);
return supported;
}
void dxgi_swapchain_color_space(
DXGISwapChain chain_handle,
DXGI_COLOR_SPACE_TYPE *chain_color_space,
DXGI_COLOR_SPACE_TYPE color_space)
{
if (*chain_color_space != color_space)
{
UINT color_space_support = 0;
if (SUCCEEDED(DXGICheckColorSpaceSupport(
chain_handle, color_space,
&color_space_support))
&& ((color_space_support &
DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)
== DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT))
{
if (FAILED(DXGISetColorSpace1(chain_handle, color_space)))
{
RARCH_ERR("[DXGI]: Failed to set DXGI swapchain colour space\n");
/* TODO/FIXME/CLARIFICATION: Was this fall-through intentional?
* Should chain color space still be set even when this fails?
* Going to assume this was wrong and early return instead
*/
return;
}
*chain_color_space = color_space;
}
}
}
void dxgi_set_hdr_metadata(
DXGISwapChain handle,
bool hdr_supported,
enum dxgi_swapchain_bit_depth chain_bit_depth,
DXGI_COLOR_SPACE_TYPE chain_color_space,
float max_output_nits,
float min_output_nits,
float max_cll,
float max_fall
)
{
static const display_chromaticities_t
display_chromaticity_list[] =
{
{ 0.64000f, 0.33000f, 0.30000f, 0.60000f, 0.15000f, 0.06000f, 0.31270f, 0.32900f }, /* Rec709 */
{ 0.70800f, 0.29200f, 0.17000f, 0.79700f, 0.13100f, 0.04600f, 0.31270f, 0.32900f }, /* Rec2020 */
};
const display_chromaticities_t* chroma = NULL;
DXGI_HDR_METADATA_HDR10 hdr10_meta_data = {0};
int selected_chroma = 0;
if (!handle)
return;
/* Clear the hdr meta data if the monitor does not support HDR */
if (!hdr_supported)
{
if (FAILED(DXGISetHDRMetaData(handle,
DXGI_HDR_METADATA_TYPE_NONE, 0, NULL)))
{
RARCH_ERR("[DXGI]: Failed to set HDR meta data to none\n");
}
return;
}
/* Now select the chromacity based on colour space */
if ( chain_bit_depth == DXGI_SWAPCHAIN_BIT_DEPTH_10
&& chain_color_space ==
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
selected_chroma = 1;
else
{
if (FAILED(DXGISetHDRMetaData(handle,
DXGI_HDR_METADATA_TYPE_NONE, 0, NULL)))
{
RARCH_ERR("[DXGI]: Failed to set HDR meta data to none\n");
}
return;
}
/* Set the HDR meta data */
chroma =
&display_chromaticity_list[selected_chroma];
hdr10_meta_data.RedPrimary[0] =
(UINT16)(chroma->red_x * 50000.0f);
hdr10_meta_data.RedPrimary[1] =
(UINT16)(chroma->red_y * 50000.0f);
hdr10_meta_data.GreenPrimary[0] =
(UINT16)(chroma->green_x * 50000.0f);
hdr10_meta_data.GreenPrimary[1] =
(UINT16)(chroma->green_y * 50000.0f);
hdr10_meta_data.BluePrimary[0] =
(UINT16)(chroma->blue_x * 50000.0f);
hdr10_meta_data.BluePrimary[1] =
(UINT16)(chroma->blue_y * 50000.0f);
hdr10_meta_data.WhitePoint[0] =
(UINT16)(chroma->white_x * 50000.0f);
hdr10_meta_data.WhitePoint[1] =
(UINT16)(chroma->white_y * 50000.0f);
hdr10_meta_data.MaxMasteringLuminance =
(UINT)(max_output_nits * 10000.0f);
hdr10_meta_data.MinMasteringLuminance =
(UINT)(min_output_nits * 10000.0f);
hdr10_meta_data.MaxContentLightLevel =
(UINT16)(max_cll);
hdr10_meta_data.MaxFrameAverageLightLevel =
(UINT16)(max_fall);
if(g_hdr10_meta_data.RedPrimary != hdr10_meta_data.RedPrimary ||
g_hdr10_meta_data.GreenPrimary != hdr10_meta_data.GreenPrimary ||
g_hdr10_meta_data.BluePrimary != hdr10_meta_data.BluePrimary ||
g_hdr10_meta_data.WhitePoint != hdr10_meta_data.WhitePoint ||
g_hdr10_meta_data.MaxContentLightLevel != hdr10_meta_data.MaxContentLightLevel ||
g_hdr10_meta_data.MaxMasteringLuminance != hdr10_meta_data.MaxMasteringLuminance ||
g_hdr10_meta_data.MinMasteringLuminance != hdr10_meta_data.MinMasteringLuminance ||
g_hdr10_meta_data.MaxFrameAverageLightLevel != hdr10_meta_data.MaxFrameAverageLightLevel)
{
if (FAILED(DXGISetHDRMetaData(handle,
DXGI_HDR_METADATA_TYPE_HDR10,
sizeof(DXGI_HDR_METADATA_HDR10), &hdr10_meta_data)))
{
RARCH_ERR("[DXGI]: Failed to set HDR meta data for HDR10\n");
return;
}
g_hdr10_meta_data = hdr10_meta_data;
}
}
#endif
+76 -4
View File
@@ -2,6 +2,40 @@
#include <retro_inline.h>
#ifndef HAVE_DXGI_HDR
#define HAVE_DXGI_HDR
#endif
#ifdef HAVE_DXGI_HDR
#ifndef ALIGN
#ifdef _MSC_VER
#define ALIGN(x) __declspec(align(x))
#else
#define ALIGN(x) __attribute__((aligned(x)))
#endif
#endif
#include <gfx/math/matrix_4x4.h>
typedef struct ALIGN(16)
{
math_matrix_4x4 mvp;
float contrast; /* 2.0f */
float paper_white_nits; /* 200.0f */
float max_nits; /* 1000.0f */
float expand_gamut; /* 1.0f */
float inverse_tonemap; /* 1.0f */
} dxgi_hdr_uniform_t;
enum dxgi_swapchain_bit_depth
{
DXGI_SWAPCHAIN_BIT_DEPTH_8 = 0,
DXGI_SWAPCHAIN_BIT_DEPTH_10,
DXGI_SWAPCHAIN_BIT_DEPTH_16,
DXGI_SWAPCHAIN_BIT_DEPTH_COUNT
};
#endif
#ifdef __MINGW32__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
/* Pointer parameters */
@@ -233,7 +267,7 @@
#endif
#include <assert.h>
#include <dxgi1_5.h>
#include <dxgi1_6.h>
#ifndef countof
#define countof(a) (sizeof(a) / sizeof(*a))
@@ -281,6 +315,7 @@ typedef IDXGIResource* DXGIResource;
typedef IDXGIKeyedMutex* DXGIKeyedMutex;
typedef IDXGISurface1* DXGISurface;
typedef IDXGIOutput* DXGIOutput;
typedef IDXGIOutput6* DXGIOutput6;
typedef IDXGIDevice* DXGIDevice;
typedef IDXGIFactory1* DXGIFactory;
#ifdef __WINRT__
@@ -292,7 +327,7 @@ typedef IDXGIOutputDuplication* DXGIOutputDuplication;
typedef IDXGIDecodeSwapChain* DXGIDecodeSwapChain;
typedef IDXGIFactoryMedia* DXGIFactoryMedia;
typedef IDXGISwapChainMedia* DXGISwapChainMedia;
typedef IDXGISwapChain3* DXGISwapChain;
typedef IDXGISwapChain4* DXGISwapChain;
#if !defined(__cplusplus) || defined(CINTERFACE)
static INLINE ULONG DXGIReleaseDeviceSubObject(DXGIDeviceSubObject device_sub_object)
@@ -392,6 +427,14 @@ static INLINE HRESULT DXGIGetDisplaySurfaceData(DXGIOutput output, DXGISurface d
{
return output->lpVtbl->GetDisplaySurfaceData(output, (IDXGISurface*)destination);
}
static INLINE HRESULT DXGIGetOutputDesc(DXGIOutput output, DXGI_OUTPUT_DESC* desc)
{
return output->lpVtbl->GetDesc(output, desc);
}
static INLINE HRESULT DXGIGetOutputDesc1(DXGIOutput6 output, DXGI_OUTPUT_DESC1* desc)
{
return output->lpVtbl->GetDesc1(output, desc);
}
static INLINE ULONG DXGIReleaseDevice(DXGIDevice device) { return device->lpVtbl->Release(device); }
static INLINE HRESULT DXGICreateSurface(
DXGIDevice device,
@@ -457,6 +500,12 @@ static INLINE BOOL DXGIIsCurrent(DXGIFactory factory)
{
return factory->lpVtbl->IsCurrent(factory);
}
#ifdef __WINRT__
static INLINE BOOL DXGIIsCurrent2(DXGIFactory2 factory)
{
return factory->lpVtbl->IsCurrent(factory);
}
#endif
static INLINE ULONG DXGIReleaseAdapter(DXGIAdapter adapter)
{
return adapter->lpVtbl->Release(adapter);
@@ -769,11 +818,14 @@ static INLINE HRESULT DXGICheckColorSpaceSupport(
{
return swap_chain->lpVtbl->CheckColorSpaceSupport(swap_chain, color_space, color_space_support);
}
static INLINE HRESULT
DXGISetColorSpace1(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space)
static INLINE HRESULT DXGISetColorSpace1(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space)
{
return swap_chain->lpVtbl->SetColorSpace1(swap_chain, color_space);
}
static INLINE HRESULT DXGISetHDRMetaData(DXGISwapChain swap_chain, DXGI_HDR_METADATA_TYPE type, UINT size, void *metaData)
{
return swap_chain->lpVtbl->SetHDRMetaData(swap_chain, type, size, metaData);
}
#endif
/* end of auto-generated */
@@ -821,6 +873,26 @@ void dxgi_copy(
int dst_pitch,
void* dst_data);
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
bool dxgi_check_display_hdr_support(DXGIFactory2 factory, HWND hwnd);
#else
bool dxgi_check_display_hdr_support(DXGIFactory factory, HWND hwnd);
#endif
void dxgi_swapchain_color_space(DXGISwapChain handle, DXGI_COLOR_SPACE_TYPE
*chain_color_space, DXGI_COLOR_SPACE_TYPE color_space);
void dxgi_set_hdr_metadata(
DXGISwapChain handle,
bool hdr_supported,
enum dxgi_swapchain_bit_depth chain_bit_depth,
DXGI_COLOR_SPACE_TYPE chain_color_space,
float max_output_nits,
float min_output_nits,
float max_cll,
float max_fall
);
#endif
DXGI_FORMAT glslang_format_to_dxgi(glslang_format fmt);
RETRO_END_DECLS
+13 -3
View File
@@ -932,6 +932,12 @@ static LRESULT CALLBACK wnd_proc_common(
/* fall-through */
case WM_MOVE:
win32_save_position();
#if 0
#if !defined(_XBOX)
if(d3d12)
d3d12_check_display_hdr_support(d3d12, hwnd);
#endif
#endif
break;
case WM_SIZE:
/* Do not send resize message if we minimize. */
@@ -1925,8 +1931,7 @@ void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
* for black frame insertion using video_refresh_rate set to a portion
* of the display refresh rate, as well as higher vsync swap intervals. */
float refresh_mod = bfi + 1.0f;
unsigned refresh = roundf(video_refresh * refresh_mod
* swap_interval);
float refresh_rate = (video_refresh * refresh_mod * swap_interval);
if (windowed_full)
{
@@ -1939,7 +1944,7 @@ void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
*style = WS_POPUP | WS_VISIBLE;
if (!win32_monitor_set_fullscreen(*width, *height,
refresh, current_mon->szDevice)) { }
(int)refresh_rate, current_mon->szDevice)) { }
/* Display settings might have changed, get new coordinates. */
GetMonitorInfo(*hm_to_use, (LPMONITORINFO)current_mon);
@@ -2345,6 +2350,11 @@ HWND win32_get_window(void)
#endif
}
bool win32_get_client_rect(RECT* rect)
{
return GetWindowRect(main_window.hwnd, rect);
}
void win32_window_reset(void)
{
win32_common_state_t
+2
View File
@@ -97,6 +97,8 @@ void win32_show_cursor(void *data, bool state);
HWND win32_get_window(void);
bool win32_get_client_rect(RECT* rect);
bool is_running_on_xbox(void);
bool win32_has_focus(void *data);
+65 -3
View File
@@ -79,6 +79,10 @@ static Atom g_x11_quit_atom;
static XIM g_x11_xim;
static XIC g_x11_xic;
static enum retro_key x11_keysym_lut[RETROK_LAST];
static unsigned *x11_keysym_rlut = NULL;
static unsigned x11_keysym_rlut_size = 0;
static void x11_hide_mouse(Display *dpy, Window win)
{
Cursor no_ptr;
@@ -277,7 +281,7 @@ float x11_get_refresh_rate(void *data)
static bool get_video_mode(
Display *dpy, unsigned width, unsigned height,
XF86VidModeModeInfo *mode, XF86VidModeModeInfo *desktop_mode)
XF86VidModeModeInfo *mode, XF86VidModeModeInfo *x11_desktop_mode)
{
int i, num_modes = 0;
bool ret = false;
@@ -296,7 +300,7 @@ static bool get_video_mode(
return false;
}
*desktop_mode = *modes[0];
*x11_desktop_mode = *modes[0];
/* If we use black frame insertion, we fake a 60 Hz monitor
* for 120 Hz one, etc, so try to match that. */
@@ -352,9 +356,39 @@ void x11_exit_fullscreen(Display *dpy)
XF86VidModeSetViewPort(dpy, DefaultScreen(dpy), 0, 0);
}
static void x11_init_keyboard_lut(void)
{
const struct rarch_key_map *map = rarch_key_map_x11;
const struct rarch_key_map *map_start = rarch_key_map_x11;
memset(x11_keysym_lut, 0, sizeof(x11_keysym_lut));
x11_keysym_rlut_size = 0;
for (; map->rk != RETROK_UNKNOWN; map++)
{
x11_keysym_lut[map->rk] = (enum retro_key)map->sym;
if (map->sym > x11_keysym_rlut_size)
x11_keysym_rlut_size = map->sym;
}
if (x11_keysym_rlut_size < 65536)
{
if (x11_keysym_rlut)
free(x11_keysym_rlut);
x11_keysym_rlut = (unsigned*)calloc(++x11_keysym_rlut_size, sizeof(unsigned));
for (map = map_start; map->rk != RETROK_UNKNOWN; map++)
x11_keysym_rlut[map->sym] = (enum retro_key)map->rk;
}
else
x11_keysym_rlut_size = 0;
}
bool x11_create_input_context(Display *dpy, Window win, XIM *xim, XIC *xic)
{
x11_destroy_input_context(xim, xic);
x11_init_keyboard_lut();
g_x11_has_focus = true;
*xim = XOpenIM(dpy, NULL, NULL, NULL);
@@ -391,6 +425,14 @@ void x11_destroy_input_context(XIM *xim, XIC *xic)
XCloseIM(*xim);
*xim = NULL;
}
memset(x11_keysym_lut, 0, sizeof(x11_keysym_lut));
if (x11_keysym_rlut)
{
free(x11_keysym_rlut);
x11_keysym_rlut = NULL;
}
x11_keysym_rlut_size = 0;
}
bool x11_get_metrics(void *data,
@@ -433,6 +475,26 @@ bool x11_get_metrics(void *data,
return true;
}
static enum retro_key x11_translate_keysym_to_rk(unsigned sym)
{
size_t i;
/* Fast path */
if (x11_keysym_rlut && sym < x11_keysym_rlut_size)
return (enum retro_key)x11_keysym_rlut[sym];
/* Slow path */
for (i = 0; i < ARRAY_SIZE(x11_keysym_lut); i++)
{
if (x11_keysym_lut[i] != sym)
continue;
return (enum retro_key)i;
}
return RETROK_UNKNOWN;
}
static void x11_handle_key_event(unsigned keycode, XEvent *event, XIC ic, bool filter)
{
int i;
@@ -486,7 +548,7 @@ static void x11_handle_key_event(unsigned keycode, XEvent *event, XIC ic, bool f
/* Get the real keycode,
that correctly ignores international layouts as windows code does. */
key = input_keymaps_translate_keysym_to_rk(keycode);
key = x11_translate_keysym_to_rk(keycode);
if (state & ShiftMask)
mod |= RETROKMOD_SHIFT;
+1 -1
View File
@@ -239,7 +239,7 @@ static bool win32_display_server_set_resolution(void *data,
if (serv->orig_height == 0)
serv->orig_height = GetSystemMetrics(SM_CYSCREEN);
if (serv->orig_refresh == 0)
serv->orig_refresh = dm.dmDisplayFrequency;
serv->orig_refresh = video_driver_get_refresh_rate();
/* Used to stop super resolution bug */
if (width == dm.dmPelsWidth)
+4
View File
@@ -270,6 +270,10 @@ static const video_poke_interface_t caca_poke_interface = {
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void caca_gfx_get_poke_interface(void *data,
+771 -56
View File
@@ -50,11 +50,24 @@
#include "../../tasks/tasks_internal.h"
#endif
enum
{
CTR_TEXTURE_BOTTOM_MENU,
CTR_TEXTURE_STATE_THUMBNAIL,
CTR_TEXTURE_LAST
};
/* TODO/FIXME - global referenced outside */
extern uint64_t lifecycle_state;
/* An annoyance...
* Have to keep track of bottom screen enable state
* externally, otherwise cannot detect current state
* when reinitialising... */
bool ctr_bottom_screen_enabled = true;
int fadeCount = 256;
static void ctr_set_bottom_screen_enable(bool enabled, bool idle);
static INLINE void ctr_check_3D_slider(ctr_video_t* ctr, ctr_video_mode_enum video_mode)
{
@@ -244,6 +257,616 @@ static void ctr_update_viewport(
}
static const char *ctr_texture_path(unsigned id)
{
switch (id)
{
case CTR_TEXTURE_BOTTOM_MENU:
return "ctr/bottom_menu.png";
case CTR_TEXTURE_STATE_THUMBNAIL:
{
static char texture_path[PATH_MAX_LENGTH];
char state_path[PATH_MAX_LENGTH];
if (!retroarch_get_current_savestate_path(state_path,
sizeof(state_path)))
return NULL;
snprintf(texture_path, sizeof(texture_path),
"%s.png", state_path);
return path_basename(texture_path);
}
}
return NULL;
}
static void ctr_update_state_date(void *data)
{
ctr_video_t *ctr = (ctr_video_t*)data;
time_t now = time(NULL);
struct tm *t = localtime(&now);
sprintf(ctr->state_date, "%02d/%02d/%d",
t->tm_mon + 1, t->tm_mday, t->tm_year + 1900);
}
static bool ctr_update_state_date_from_file(void *data)
{
char state_path[PATH_MAX_LENGTH];
ctr_video_t *ctr = (ctr_video_t*)data;
if (!retroarch_get_current_savestate_path(state_path, sizeof(state_path)))
return false;
#ifdef USE_CTRULIB_2
time_t mtime;
bool file_exists = archive_getmtime(state_path + 5, &mtime) == 0;
#else
u64 mtime;
bool file_exists = sdmc_getmtime(state_path + 5, &mtime) == 0;
#endif
if (!file_exists)
{
ctr->state_data_exist = false;
snprintf(ctr->state_date, sizeof(ctr->state_date), "00/00/0000");
return false;
}
ctr->state_data_exist = true;
#ifdef USE_CTRULIB_2
struct tm *t = localtime(&mtime);
#else
time_t ft = mtime;
struct tm *t = localtime(&ft);
#endif
sprintf(ctr->state_date, "%02d/%02d/%d",
t->tm_mon + 1, t->tm_mday, t->tm_year + 1900);
return true;
}
static void ctr_state_thumbnail_geom(void *data)
{
ctr_video_t *ctr = (ctr_video_t *) data;
struct ctr_bottom_texture_data *o = NULL;
const int target_width = 120;
const int target_height = 90;
unsigned width, height;
if (ctr)
o = &ctr->bottom_textures[CTR_TEXTURE_STATE_THUMBNAIL];
if (!o)
return;
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
if (!texture)
return;
float scale = (float) target_width / texture->active_width;
if (target_width > texture->active_width * scale) {
scale = (float) (target_width + 1) / texture->active_width;
}
o->frame_coords->u0 = 0;
o->frame_coords->v0 = 0;
o->frame_coords->u1 = texture->active_width;
o->frame_coords->v1 = texture->active_height;
int x_offset = 184;
int y_offset = 46 + (target_height - texture->active_height * scale) / 2;
o->frame_coords->x0 = x_offset;
o->frame_coords->y0 = y_offset;
o->frame_coords->x1 = o->frame_coords->x0 + texture->active_width * scale;
o->frame_coords->y1 = o->frame_coords->y0 + texture->active_height * scale;
ctr_set_scale_vector(&o->scale_vector,
CTR_BOTTOM_FRAMEBUFFER_WIDTH,
CTR_BOTTOM_FRAMEBUFFER_HEIGHT,
texture->width,
texture->height);
}
static bool ctr_load_bottom_texture(void *data)
{
unsigned i;
const char *dir_assets;
ctr_video_t *ctr = (ctr_video_t *)data;
settings_t *settings = config_get_ptr();
for (i = 0; i < CTR_TEXTURE_LAST; i++)
{
if (i == CTR_TEXTURE_STATE_THUMBNAIL)
dir_assets = dir_get_ptr(RARCH_DIR_SAVESTATE);
else
dir_assets = settings->paths.directory_assets;
if (gfx_display_reset_textures_list(
ctr_texture_path(i), dir_assets,
&ctr->bottom_textures[i].texture,
TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
{
struct ctr_bottom_texture_data *o = &ctr->bottom_textures[i];
o->frame_coords = linearAlloc(sizeof(ctr_vertex_t));
if (i == CTR_TEXTURE_STATE_THUMBNAIL)
{
ctr_state_thumbnail_geom(ctr);
ctr->render_state_from_png_file = true;
}
else
{
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
o->frame_coords->u0 = 0;
o->frame_coords->v0 = 0;
o->frame_coords->u1 = texture->width;
o->frame_coords->v1 = texture->height;
o->frame_coords->x0 = 0;
o->frame_coords->y0 = 0;
o->frame_coords->x1 = o->frame_coords->x0 + texture->width;
o->frame_coords->y1 = o->frame_coords->y0 + texture->height;
ctr_set_scale_vector(&o->scale_vector,
CTR_BOTTOM_FRAMEBUFFER_WIDTH,
CTR_BOTTOM_FRAMEBUFFER_HEIGHT,
texture->width,
texture->height);
}
}
else if (i == CTR_TEXTURE_BOTTOM_MENU)
return false;
}
return true;
}
static void save_state_to_file(void *data)
{
ctr_video_t *ctr = (ctr_video_t*)data;
char state_path[PATH_MAX_LENGTH];
retroarch_get_current_savestate_path(state_path, sizeof(state_path));
command_event(CMD_EVENT_RAM_STATE_TO_FILE, state_path);
}
static void bottom_menu_control(void* data, bool lcd_bottom)
{
touchPosition state_tmp_touch;
uint32_t state_tmp = 0;
ctr_video_t *ctr = (ctr_video_t*)data;
settings_t *settings = config_get_ptr();
int config_slot = settings->ints.state_slot;
if (!ctr->init_bottom_menu)
{
if (ctr_load_bottom_texture(ctr))
{
ctr_update_state_date_from_file(ctr);
ctr->bottom_menu = CTR_BOTTOM_MENU_DEFAULT;
}
ctr->init_bottom_menu = true;
}
BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
if (!rarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL))
{
if (!ctr->bottom_is_idle)
{
ctr->bottom_is_idle = true;
ctr_set_bottom_screen_enable(false, ctr->bottom_is_idle);
}
return;
}
state_tmp = hidKeysDown();
hidTouchRead(&state_tmp_touch);
if (!state_tmp)
{
if (!ctr->bottom_check_idle && !ctr->bottom_is_idle)
{
ctr->idle_timestamp = svcGetSystemTick();
ctr->bottom_check_idle = true;
}
}
if (state_tmp & KEY_TOUCH)
{
#ifdef CONSOLE_LOG
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
return;
#endif
if (!lcd_bottom ||
ctr->bottom_menu == CTR_BOTTOM_MENU_NOT_AVAILABLE)
{
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
return;
}
if (ctr->bottom_is_idle)
{
ctr->bottom_is_idle = false;
ctr->bottom_is_fading = false;
fadeCount = 256;
ctr_set_bottom_screen_enable(true,true);
}
else if (ctr->bottom_check_idle)
{
ctr->bottom_check_idle = false;
ctr->bottom_is_fading = false;
fadeCount = 256;
}
switch (ctr->bottom_menu)
{
case CTR_BOTTOM_MENU_DEFAULT:
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
break;
case CTR_BOTTOM_MENU_SELECT:
if (state_tmp_touch.px > 8 &&
state_tmp_touch.px < 164 &&
state_tmp_touch.py > 9 &&
state_tmp_touch.py < 86)
{
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
}
else if (state_tmp_touch.px > 8 &&
state_tmp_touch.px < 164 &&
state_tmp_touch.py > 99 &&
state_tmp_touch.py < 230)
{
char screenshot_full_path[PATH_MAX_LENGTH];
struct ctr_bottom_texture_data *o =
&ctr->bottom_textures[CTR_TEXTURE_STATE_THUMBNAIL];
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
if (texture)
linearFree(texture->data);
else
{
o->texture = (uintptr_t) calloc(1, sizeof(ctr_texture_t));
o->frame_coords = linearAlloc(sizeof(ctr_vertex_t));
texture = (ctr_texture_t *) o->texture;
}
texture->width = ctr->texture_width;
texture->height = ctr->texture_width;
texture->active_width = ctr->frame_coords->u1;
texture->active_height = ctr->frame_coords->v1;
texture->data = linearAlloc(
ctr->texture_width * ctr->texture_height *
(ctr->rgb32? 4:2));
memcpy(texture->data, ctr->texture_swizzled,
ctr->texture_width * ctr->texture_height *
(ctr->rgb32? 4:2));
ctr_state_thumbnail_geom(ctr);
ctr->state_data_exist = true;
ctr->render_state_from_png_file = false;
ctr_update_state_date(ctr);
command_event(CMD_EVENT_SAVE_STATE_TO_RAM, NULL);
if (settings->bools.savestate_thumbnail_enable)
{
sprintf(screenshot_full_path, "%s/%s",
dir_get_ptr(RARCH_DIR_SAVESTATE),
ctr_texture_path(CTR_TEXTURE_STATE_THUMBNAIL));
take_screenshot(NULL, screenshot_full_path, true,
video_driver_cached_frame_has_valid_framebuffer(),
true, true);
}
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
}
else if (state_tmp_touch.px > 176 &&
state_tmp_touch.px < 311 &&
state_tmp_touch.py > 9 &&
state_tmp_touch.py < 230 &&
ctr->state_data_exist)
{
if (!command_event(CMD_EVENT_LOAD_STATE_FROM_RAM, NULL))
command_event(CMD_EVENT_LOAD_STATE, NULL);
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
}
break;
}
ctr->bottom_check_idle = false;
ctr->refresh_bottom_menu = true;
}
if (ctr->bottom_menu == CTR_BOTTOM_MENU_NOT_AVAILABLE ||
!rarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL))
return;
if (ctr->state_slot != config_slot)
{
save_state_to_file(ctr);
ctr->state_slot = config_slot;
struct ctr_bottom_texture_data *o = &ctr->bottom_textures[CTR_TEXTURE_STATE_THUMBNAIL];
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
if (texture)
{
linearFree(texture->data);
linearFree(o->frame_coords);
o->texture = 0;
}
if (ctr_update_state_date_from_file(ctr))
{
if(gfx_display_reset_textures_list(
ctr_texture_path(CTR_TEXTURE_STATE_THUMBNAIL),
dir_get_ptr(RARCH_DIR_SAVESTATE),
&o->texture,
TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
{
o->frame_coords = linearAlloc(sizeof(ctr_vertex_t));
ctr_state_thumbnail_geom(ctr);
ctr->render_state_from_png_file = true;
}
}
ctr->refresh_bottom_menu = true;
}
if (menu_driver_is_alive())
ctr->bottom_menu = CTR_BOTTOM_MENU_SELECT;
else
ctr->bottom_menu = CTR_BOTTOM_MENU_DEFAULT;
if (ctr->prev_bottom_menu != ctr->bottom_menu)
{
ctr->prev_bottom_menu = ctr->bottom_menu;
ctr->refresh_bottom_menu = true;
}
}
static void font_driver_render_msg_bottom(
void *data,
const char *msg,
const void *_params,
void *font_data)
{
ctr_video_t *ctr = (ctr_video_t*)data;
ctr->render_font_bottom = true;
font_driver_render_msg(ctr, msg, _params, font_data);
ctr->render_font_bottom = false;
}
static void ctr_render_bottom_screen(void *data)
{
ctr_video_t *ctr = (ctr_video_t*)data;
if (!ctr)
return;
if (!ctr->refresh_bottom_menu)
return;
struct font_params params = { 0, };
params.text_align = TEXT_ALIGN_CENTER;
params.color = COLOR_ABGR(255, 255, 255, 255);
switch (ctr->bottom_menu)
{
case CTR_BOTTOM_MENU_NOT_AVAILABLE:
{
params.scale = 1.6f;
params.x = 0.0f;
params.y = 0.5f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_ASSET_NOT_FOUND),
&params, NULL);
}
break;
case CTR_BOTTOM_MENU_DEFAULT:
{
params.scale = 1.6f;
params.x = 0.0f;
params.y = 0.5f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_DEFAULT),
&params, NULL);
}
break;
case CTR_BOTTOM_MENU_SELECT:
{
params.scale = 1.48f;
params.color = COLOR_ABGR(255, 255, 255, 255);
/* draw state thumbnail */
if (ctr->state_data_exist) {
struct ctr_bottom_texture_data *o = (struct ctr_bottom_texture_data*)
&ctr->bottom_textures[CTR_TEXTURE_STATE_THUMBNAIL];
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
if (texture)
{
GPU_TEXCOLOR colorType = GPU_RGBA8;
if (!ctr->render_state_from_png_file && !ctr->rgb32)
colorType = GPU_RGB565;
ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(texture->data),
texture->width, texture->height,
GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE),
colorType);
GPUCMD_AddWrite(GPUREG_GSH_BOOLUNIFORM, 0);
ctrGuSetVertexShaderFloatUniform(0, (float*)&o->scale_vector, 1);
ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(o->frame_coords));
GPU_SetViewport(NULL,
VIRT_TO_PHYS(ctr->drawbuffers.bottom),
0, 0, CTR_BOTTOM_FRAMEBUFFER_HEIGHT,
CTR_BOTTOM_FRAMEBUFFER_WIDTH);
GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1);
}
else
{
params.x = 0.266f;
params.y = 0.64f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_NO_STATE_THUMBNAIL),
&params, NULL);
}
}
else
{
params.x = 0.266f;
params.y = 0.64f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_NO_STATE_DATA),
&params, NULL);
}
/* draw bottom menu */
struct ctr_bottom_texture_data *o = &ctr->bottom_textures[CTR_TEXTURE_BOTTOM_MENU];
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(texture->data),
texture->width, texture->height,
GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE),
GPU_RGBA8);
GPUCMD_AddWrite(GPUREG_GSH_BOOLUNIFORM, 0);
ctrGuSetVertexShaderFloatUniform(0, (float*)&o->scale_vector, 1);
ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(o->frame_coords));
GPU_SetViewport(NULL,
VIRT_TO_PHYS(ctr->drawbuffers.bottom),
0, 0, CTR_BOTTOM_FRAMEBUFFER_HEIGHT,
CTR_BOTTOM_FRAMEBUFFER_WIDTH);
GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1);
/* draw resume game */
params.x = -0.178f;
params.y = 0.78f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_RESUME),
&params, NULL);
/* draw create restore point */
params.x = -0.178f;
params.y = 0.33f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_SAVE_STATE),
&params, NULL);
/* draw load restore point */
params.x = 0.266f;
params.y = 0.24f;
font_driver_render_msg_bottom(ctr,
msg_hash_to_str(MSG_3DS_BOTTOM_MENU_LOAD_STATE),
&params, NULL);
/* draw date */
params.x = 0.266f;
params.y = 0.87f;
font_driver_render_msg_bottom(ctr, ctr->state_date,
&params, NULL);
}
break;
}
}
// graphic function originates from here:
// https://github.com/smealum/3ds_hb_menu/blob/master/source/gfx.c
void ctr_fade_bottom_screen(gfxScreen_t screen, gfx3dSide_t side, u32 f)
{
u16 fbWidth, fbHeight;
u8* fbAdr=gfxGetFramebuffer(screen, side, &fbWidth, &fbHeight);
int i; for(i=0; i<fbWidth*fbHeight/2; i++)
{
*fbAdr=(*fbAdr*f)>>8;fbAdr++;
*fbAdr=(*fbAdr*f)>>8;fbAdr++;
*fbAdr=(*fbAdr*f)>>8;fbAdr++;
*fbAdr=(*fbAdr*f)>>8;fbAdr++;
*fbAdr=(*fbAdr*f)>>8;fbAdr++;
*fbAdr=(*fbAdr*f)>>8;fbAdr++;
}
}
static void ctr_set_bottom_screen_idle(ctr_video_t * ctr)
{
if (ctr->bottom_menu == CTR_BOTTOM_MENU_SELECT)
return;
u64 elapsed_tick = ( svcGetSystemTick() - ctr->idle_timestamp );
if ( elapsed_tick > 2000000000 )
{
if (!ctr->bottom_is_fading)
{
ctr->bottom_is_fading = true;
ctr->refresh_bottom_menu = true;
return;
}
if ( fadeCount > 0 )
{
fadeCount--;
ctr_fade_bottom_screen(GFX_BOTTOM, GFX_LEFT, fadeCount);
if ( fadeCount <= 128 )
{
ctr->bottom_is_idle = true;
ctr->bottom_is_fading = false;
ctr->bottom_check_idle = false;
fadeCount = 256;
ctr_set_bottom_screen_enable(false,true);
return;
}
}
}
}
static void ctr_set_bottom_screen_enable(bool enabled, bool idle)
{
Handle lcd_handle;
u8 not_2DS;
CFGU_GetModelNintendo2DS(&not_2DS);
if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = enabled? 0x00110040: 0x00120040;
cmdbuf[1] = 2;
svcSendSyncRequest(lcd_handle);
svcCloseHandle(lcd_handle);
}
if (!idle)
ctr_bottom_screen_enabled = enabled;
}
static void ctr_lcd_aptHook(APT_HookType hook, void* param)
{
ctr_video_t *ctr = (ctr_video_t*)param;
@@ -303,17 +926,9 @@ static void ctr_lcd_aptHook(APT_HookType hook, void* param)
if ((hook == APTHOOK_ONSUSPEND) || (hook == APTHOOK_ONRESTORE) || (hook == APTHOOK_ONWAKEUP))
{
Handle lcd_handle;
u8 not_2DS;
CFGU_GetModelNintendo2DS(&not_2DS);
if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = ((hook == APTHOOK_ONSUSPEND) || ctr_bottom_screen_enabled)? 0x00110040: 0x00120040;
cmdbuf[1] = 2;
svcSendSyncRequest(lcd_handle);
svcCloseHandle(lcd_handle);
}
ctr_set_bottom_screen_enable(hook == APTHOOK_ONSUSPEND, ctr->bottom_is_idle);
save_state_to_file(ctr);
}
if (menu_driver_is_alive())
@@ -342,34 +957,11 @@ static bool ctr_tasks_finder(retro_task_t *task,void *userdata)
task_finder_data_t ctr_tasks_finder_data = {ctr_tasks_finder, NULL};
#endif
static void ctr_set_bottom_screen_enable(void* data, bool enabled)
{
Handle lcd_handle;
u8 not_2DS;
ctr_video_t *ctr = (ctr_video_t*)data;
if (!ctr)
return;
gfxBottomFramebuffers[0] = enabled ? (u8*)ctrConsole->frameBuffer:
(u8*)ctr->empty_framebuffer;
CFGU_GetModelNintendo2DS(&not_2DS);
if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = enabled? 0x00110040: 0x00120040;
cmdbuf[1] = 2;
svcSendSyncRequest(lcd_handle);
svcCloseHandle(lcd_handle);
}
ctr_bottom_screen_enabled = enabled;
}
static void* ctr_init(const video_info_t* video,
input_driver_t** input, void** input_data)
{
size_t i;
float refresh_rate;
u8 device_model = 0xFF;
void* ctrinput = NULL;
@@ -392,6 +984,7 @@ static void* ctr_init(const video_info_t* video,
ctr->drawbuffers.top.left = vramAlloc(CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * 2 * sizeof(uint32_t));
ctr->drawbuffers.top.right = (void*)((uint32_t*)ctr->drawbuffers.top.left + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT);
ctr->drawbuffers.bottom = vramAlloc(CTR_BOTTOM_FRAMEBUFFER_WIDTH * CTR_BOTTOM_FRAMEBUFFER_HEIGHT * 2 * sizeof(uint32_t));
ctr->display_list_size = 0x4000;
ctr->display_list = linearAlloc(ctr->display_list_size * sizeof(uint32_t));
@@ -401,6 +994,25 @@ static void* ctr_init(const video_info_t* video,
ctr->vertex_cache.buffer = linearAlloc(ctr->vertex_cache.size * sizeof(ctr_vertex_t));
ctr->vertex_cache.current = ctr->vertex_cache.buffer;
ctr->bottom_textures = (struct ctr_bottom_texture_data *)calloc(CTR_TEXTURE_LAST,
sizeof(*ctr->bottom_textures));
ctr->init_bottom_menu = false;
ctr->state_data_exist = false;
ctr->render_font_bottom = false;
ctr->refresh_bottom_menu = true;
ctr->render_state_from_png_file = false;
ctr->bottom_menu = CTR_BOTTOM_MENU_NOT_AVAILABLE;
ctr->prev_bottom_menu = CTR_BOTTOM_MENU_NOT_AVAILABLE;
ctr->bottom_check_idle = false;
ctr->bottom_is_idle = false;
ctr->bottom_is_fading = false;
ctr->idle_timestamp = 0;
ctr->state_slot = settings->ints.state_slot;
snprintf(ctr->state_date, sizeof(ctr->state_date), "%s", "00/00/0000");
ctr->state_date[CTR_STATE_DATE_SIZE - 1] = '\0';
ctr->rgb32 = video->rgb32;
ctr->texture_width = video->input_scale * RARCH_SCALE_BASE;
ctr->texture_height = video->input_scale * RARCH_SCALE_BASE;
@@ -512,6 +1124,7 @@ static void* ctr_init(const video_info_t* video,
ctr->smooth = video->smooth;
ctr->vsync = video->vsync;
ctr->current_buffer_top = 0;
ctr->current_buffer_bottom = 0;
/* Only O3DS and O3DSXL support running in 'dual-framebuffer'
* mode with the parallax barrier disabled
@@ -520,9 +1133,6 @@ static void* ctr_init(const video_info_t* video,
CFGU_GetSystemModel(&device_model); /* (0 = O3DS, 1 = O3DSXL, 2 = N3DS, 3 = 2DS, 4 = N3DSXL, 5 = N2DSXL) */
ctr->supports_parallax_disable = (device_model == 0) || (device_model == 1);
ctr->empty_framebuffer = linearAlloc(320 * 240 * 2);
memset(ctr->empty_framebuffer, 0, 320 * 240 * 2);
refresh_rate = (32730.0 * 8192.0) / 4481134.0;
driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &refresh_rate);
@@ -539,7 +1149,7 @@ static void* ctr_init(const video_info_t* video,
/* Set bottom screen enable state, if required */
if (lcd_bottom != ctr_bottom_screen_enabled)
ctr_set_bottom_screen_enable(ctr, lcd_bottom);
ctr_set_bottom_screen_enable(lcd_bottom, false);
gspSetEventCallback(GSPGPU_EVENT_VBlank0,
(ThreadFunc)ctr_vsync_hook, ctr, false);
@@ -557,12 +1167,10 @@ static bool ctr_frame(void* data, const void* frame,
unsigned pitch, const char* msg, video_frame_info_t *video_info)
{
static uint64_t currentTick,lastTick;
touchPosition state_tmp_touch;
extern GSPGPU_FramebufferInfo topFramebufferInfo;
extern GSPGPU_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo;
extern u8* gfxSharedMemory;
extern u8 gfxThreadID;
uint32_t diff;
uint32_t state_tmp = 0;
ctr_video_t *ctr = (ctr_video_t*)data;
static float fps = 0.0;
static int total_frames = 0;
@@ -584,6 +1192,7 @@ static bool ctr_frame(void* data, const void* frame,
#ifdef HAVE_GFX_WIDGETS
bool widgets_active = video_info->widgets_active;
#endif
bool lcd_bottom = false;
if (!width || !height || !settings)
{
@@ -591,12 +1200,19 @@ static bool ctr_frame(void* data, const void* frame,
return true;
}
state_tmp = hidKeysDown();
hidTouchRead(&state_tmp_touch);
if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120))
lcd_bottom = settings->bools.video_3ds_lcd_bottom;
if (lcd_bottom != ctr_bottom_screen_enabled)
{
ctr_set_bottom_screen_enable(ctr, !ctr_bottom_screen_enabled);
if (rarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL))
{
ctr_set_bottom_screen_enable(lcd_bottom, false);
if (lcd_bottom)
ctr->refresh_bottom_menu = true;
}
else
ctr_bottom_screen_enabled = lcd_bottom;
}
bottom_menu_control(data, lcd_bottom);
if (ctr->p3d_event_pending)
{
@@ -742,11 +1358,23 @@ static bool ctr_frame(void* data, const void* frame,
custom_vp_height
);
ctrGuSetMemoryFill(true, (u32*)ctr->drawbuffers.top.left, 0x00000000,
(u32*)ctr->drawbuffers.top.left + 2 * CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT,
0x201, NULL, 0x00000000,
0,
0x201);
if (ctr->refresh_bottom_menu)
{
ctrGuSetMemoryFill(true, (u32*)ctr->drawbuffers.top.left, 0x00000000,
(u32*)ctr->drawbuffers.top.left + 2 * CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT,
0x201,
(u32*)ctr->drawbuffers.bottom, 0x00000000,
(u32*)ctr->drawbuffers.bottom + 2 * CTR_BOTTOM_FRAMEBUFFER_WIDTH * CTR_BOTTOM_FRAMEBUFFER_HEIGHT,
0x201);
}
else
{
ctrGuSetMemoryFill(true, (u32*)ctr->drawbuffers.top.left, 0x00000000,
(u32*)ctr->drawbuffers.top.left + 2 * CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT,
0x201, NULL, 0x00000000,
0,
0x201);
}
GPUCMD_SetBufferOffset(0);
@@ -923,6 +1551,20 @@ static bool ctr_frame(void* data, const void* frame,
gfx_widgets_frame(video_info);
#endif
#ifndef CONSOLE_LOG
if (ctr_bottom_screen_enabled &&
rarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL))
{
if ( !ctr->bottom_is_idle )
{
ctr_render_bottom_screen(ctr);
if ( ctr->bottom_check_idle )
ctr_set_bottom_screen_idle(ctr);
}
}
#endif
if (msg)
font_driver_render_msg(ctr, msg, NULL, NULL);
@@ -943,10 +1585,19 @@ static bool ctr_frame(void* data, const void* frame,
CTRGU_RGBA8,
gfxTopRightFramebuffers[ctr->current_buffer_top], 240, CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE);
#ifndef CONSOLE_LOG
if (ctr->refresh_bottom_menu)
ctrGuDisplayTransfer(true,
ctr->drawbuffers.bottom,
240,
320,
CTRGU_RGBA8,
gfxBottomFramebuffers[ctr->current_buffer_bottom], 240, CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE);
#endif
/* Swap buffers : */
#ifdef USE_CTRULIB_2
u32 *buf0, *buf1;
u32 *buf0, *buf1, *bottom;
u32 stride;
buf0 = (u32*)gfxTopLeftFramebuffers[ctr->current_buffer_top];
@@ -970,6 +1621,20 @@ static bool ctr_frame(void* data, const void* frame,
gspPresentBuffer(GFX_TOP, ctr->current_buffer_top, buf0, buf1,
stride, (1<<8)|((1^bit5)<<6)|((bit5)<<5)|GSP_BGR8_OES);
#ifndef CONSOLE_LOG
if (ctr->refresh_bottom_menu)
{
bottom = (u32*)gfxBottomFramebuffers[ctr->current_buffer_bottom];
stride = 240 * 3;
gspPresentBuffer(GFX_BOTTOM, ctr->current_buffer_bottom, bottom, bottom,
stride, GSP_BGR8_OES);
}
else if (ctr->bottom_is_fading)
{
gfxScreenSwapBuffers(GFX_BOTTOM,false);
}
#endif
#else
topFramebufferInfo.
active_framebuf = ctr->current_buffer_top;
@@ -990,7 +1655,7 @@ static bool ctr_frame(void* data, const void* frame,
framebuf1_vaddr = (u32*)gfxTopRightFramebuffers[ctr->current_buffer_top];
else
topFramebufferInfo.
framebuf1_vaddr = topFramebufferInfo.framebuf0_vaddr;
framebuf1_vaddr = topFramebufferInfo.framebuf0_vaddr;
topFramebufferInfo.
framebuf_widthbytesize = 240 * 3;
@@ -1008,11 +1673,44 @@ static bool ctr_frame(void* data, const void* frame,
framebufferInfoHeader[0x0] ^= 1;
framebufferInfo[framebufferInfoHeader[0x0]] = topFramebufferInfo;
framebufferInfoHeader[0x1] = 1;
#endif
#ifndef CONSOLE_LOG
if (ctr->refresh_bottom_menu)
{
bottomFramebufferInfo.
active_framebuf = ctr->current_buffer_bottom;
bottomFramebufferInfo.
framebuf0_vaddr = (u32*)gfxBottomFramebuffers[
ctr->current_buffer_bottom];
bottomFramebufferInfo.
framebuf1_vaddr = (u32*)(gfxBottomFramebuffers[
ctr->current_buffer_bottom] + 240 * 3);
bottomFramebufferInfo.
framebuf_widthbytesize = 240 * 3;
bottomFramebufferInfo.format = GSP_BGR8_OES;
bottomFramebufferInfo.
framebuf_dispselect = ctr->current_buffer_bottom;
bottomFramebufferInfo.unk = 0x00000000;
u8* framebufferInfoHeader2 = gfxSharedMemory+0x200+gfxThreadID*0x80+0x40;
GSPGPU_FramebufferInfo*
framebufferInfo2 =
(GSPGPU_FramebufferInfo*)&framebufferInfoHeader2[0x4];
framebufferInfoHeader2[0x0] ^= 1;
framebufferInfo2[framebufferInfoHeader2[0x0]] = bottomFramebufferInfo;
framebufferInfoHeader2[0x1] = 1;
}
#endif
#endif
ctr->current_buffer_top ^= 1;
if (ctr->refresh_bottom_menu || ctr->bottom_is_fading)
ctr->current_buffer_bottom ^= 1;
ctr->p3d_event_pending = true;
ctr->ppf_event_pending = true;
ctr->refresh_bottom_menu = false;
return true;
}
@@ -1047,6 +1745,7 @@ static bool ctr_suppress_screensaver(void* data, bool enable)
static void ctr_free(void* data)
{
unsigned i;
ctr_video_t* ctr = (ctr_video_t*)data;
if (!ctr)
@@ -1057,6 +1756,19 @@ static void ctr_free(void* data)
shaderProgramFree(&ctr->shader);
DVLB_Free(ctr->dvlb);
vramFree(ctr->drawbuffers.top.left);
vramFree(ctr->drawbuffers.bottom);
for (i = 0; i < CTR_TEXTURE_LAST; i++)
{
struct ctr_bottom_texture_data *o = &ctr->bottom_textures[i];
ctr_texture_t *texture = (ctr_texture_t *) o->texture;
if (texture)
{
linearFree(texture->data);
linearFree(o->frame_coords);
o->texture = 0;
}
}
free(ctr->bottom_textures);
linearFree(ctr->display_list);
linearFree(ctr->texture_linear);
linearFree(ctr->texture_swizzled);
@@ -1064,7 +1776,6 @@ static void ctr_free(void* data)
linearFree(ctr->menu.texture_linear);
linearFree(ctr->menu.texture_swizzled);
linearFree(ctr->menu.frame_coords);
linearFree(ctr->empty_framebuffer);
linearFree(ctr->vertex_cache.buffer);
linearFree(ctr);
#if 0
@@ -1535,7 +2246,11 @@ static const video_poke_interface_t ctr_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void ctr_get_poke_interface(void* data,
+5 -1
View File
@@ -1008,7 +1008,7 @@ static void *d3d10_gfx_init(const video_info_t* video,
#else
DXGICreateFactory(&d3d10->factory);
#endif
{
int i = 0;
int gpu_index = settings->ints.d3d10_gpu_index;
@@ -1800,6 +1800,10 @@ static const video_poke_interface_t d3d10_poke_interface = {
#else
NULL, /* get_hw_render_interface */
#endif
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void d3d10_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)
+464 -39
View File
@@ -255,6 +255,79 @@ static void d3d11_get_overlay_interface(
}
#endif
#ifdef HAVE_DXGI_HDR
static void d3d11_set_hdr_max_nits(void *data, float max_nits)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->hdr.max_output_nits = max_nits;
d3d11->hdr.ubo_values.max_nits = max_nits;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_ubo);
{
dxgi_hdr_uniform_t *ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
}
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
dxgi_set_hdr_metadata(
d3d11->swapChain,
d3d11->hdr.support,
d3d11->chain_bit_depth,
d3d11->chain_color_space,
d3d11->hdr.max_output_nits,
d3d11->hdr.min_output_nits,
d3d11->hdr.max_cll,
d3d11->hdr.max_fall);
}
static void d3d11_set_hdr_paper_white_nits(void* data, float paper_white_nits)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
dxgi_hdr_uniform_t *ubo = NULL;
d3d11_video_t *d3d11 = (d3d11_video_t*)data;
d3d11->hdr.ubo_values.paper_white_nits = paper_white_nits;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
}
static void d3d11_set_hdr_contrast(void* data, float contrast)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
dxgi_hdr_uniform_t *ubo = NULL;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->hdr.ubo_values.contrast = contrast;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo,
0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
}
static void d3d11_set_hdr_expand_gamut(void* data, bool expand_gamut)
{
D3D11_MAPPED_SUBRESOURCE mapped_ubo;
dxgi_hdr_uniform_t *ubo = NULL;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
d3d11->hdr.ubo_values.expand_gamut = expand_gamut;
D3D11MapBuffer(d3d11->context, d3d11->hdr.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo);
ubo = (dxgi_hdr_uniform_t*)mapped_ubo.pData;
*ubo = d3d11->hdr.ubo_values;
D3D11UnmapBuffer(d3d11->context, d3d11->hdr.ubo, 0);
}
#endif
static void d3d11_set_filtering(void* data, unsigned index,
bool smooth, bool ctx_scaling)
{
@@ -360,13 +433,39 @@ static void d3d11_free_shader_preset(d3d11_video_t* d3d11)
static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path)
{
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
enum d3d11_feature_level_hint
feat_level_hint = D3D11_FEATURE_LEVEL_HINT_DONTCARE;
unsigned i;
d3d11_texture_t* source = NULL;
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
unsigned shader_model = 40;
if (!d3d11)
return false;
/* Feature Level 11.0 and up should all support Shader Model 5.0 */
switch (d3d11->supportedFeatureLevel)
{
case D3D_FEATURE_LEVEL_11_0:
shader_model = 50;
feat_level_hint = D3D11_FEATURE_LEVEL_HINT_11_0;
break;
case D3D_FEATURE_LEVEL_11_1:
shader_model = 50;
feat_level_hint = D3D11_FEATURE_LEVEL_HINT_11_1;
break;
case D3D_FEATURE_LEVEL_12_0:
shader_model = 50;
feat_level_hint = D3D11_FEATURE_LEVEL_HINT_12_0;
break;
case D3D_FEATURE_LEVEL_12_1:
shader_model = 50;
feat_level_hint = D3D11_FEATURE_LEVEL_HINT_12_1;
break;
default:
break;
}
D3D11Flush(d3d11->context);
d3d11_free_shader_preset(d3d11);
@@ -426,7 +525,8 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
/* clang-format on */
if (!slang_process(
d3d11->shader_preset, i, RARCH_SHADER_HLSL, 40, &semantics_map,
d3d11->shader_preset, i, RARCH_SHADER_HLSL, shader_model,
&semantics_map,
&d3d11->pass[i].semantics))
goto error;
@@ -457,12 +557,16 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
if (!d3d11_init_shader(
d3d11->device, vs_src, 0, vs_path, "main", NULL, NULL, desc, countof(desc),
&d3d11->pass[i].shader))
&d3d11->pass[i].shader,
feat_level_hint
))
save_hlsl = true;
if (!d3d11_init_shader(
d3d11->device, ps_src, 0, ps_path, NULL, "main", NULL, NULL, 0,
&d3d11->pass[i].shader))
&d3d11->pass[i].shader,
feat_level_hint
))
save_hlsl = true;
if (save_hlsl)
@@ -559,6 +663,10 @@ static void d3d11_gfx_free(void* data)
d3d11_release_texture(&d3d11->menu.texture);
Release(d3d11->menu.vbo);
#ifdef HAVE_DXGI_HDR
Release(d3d11->hdr.ubo);
#endif
d3d11_release_shader(&d3d11->sprites.shader);
d3d11_release_shader(&d3d11->sprites.shader_font);
Release(d3d11->sprites.vbo);
@@ -580,6 +688,10 @@ static void d3d11_gfx_free(void* data)
Release(d3d11->samplers[RARCH_FILTER_NEAREST][i]);
}
#ifdef HAVE_DXGI_HDR
d3d11_release_texture(&d3d11->back_buffer);
#endif
Release(d3d11->scissor_enabled);
Release(d3d11->scissor_disabled);
Release(d3d11->swapChain);
@@ -607,6 +719,10 @@ static void d3d11_gfx_free(void* data)
}
}
#ifdef HAVE_DXGI_HDR
video_driver_unset_hdr_support();
#endif
#ifdef HAVE_MONITOR
win32_monitor_from_window();
#endif
@@ -622,6 +738,7 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
D3D11DeviceContext *cached_context,
void *corewindow)
{
HWND hwnd;
#ifdef __WINRT__
IDXGIFactory2* dxgiFactory = NULL;
#else
@@ -646,19 +763,51 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
#endif
UINT number_feature_levels = ARRAY_SIZE(requested_feature_levels);
#ifdef HAVE_DXGI_HDR
DXGI_COLOR_SPACE_TYPE color_space;
d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_8] = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_10] = DXGI_FORMAT_R10G10B10A2_UNORM;
d3d11->chain_formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM;
#endif
hwnd = (HWND)corewindow;
#ifdef HAVE_DXGI_HDR
if (!(d3d11->hdr.support =
dxgi_check_display_hdr_support(d3d11->factory, hwnd)))
d3d11->hdr.enable = false;
d3d11->chain_bit_depth = d3d11->hdr.enable
? DXGI_SWAPCHAIN_BIT_DEPTH_10
: DXGI_SWAPCHAIN_BIT_DEPTH_8;
#endif
#ifdef __WINRT__
/* Flip model forces us to do double-buffering */
desc.BufferCount = 2;
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.support)
desc.Format = d3d11->chain_formats[
d3d11->chain_bit_depth];
else
#endif
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#else
desc.BufferCount = 2;
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.support)
desc.BufferDesc.Format = d3d11->chain_formats[
d3d11->chain_bit_depth];
else
#endif
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
#endif
@@ -695,6 +844,39 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
D3D11_SDK_VERSION, &d3d11->device,
&d3d11->supportedFeatureLevel, &d3d11->context)))
return false;
switch (d3d11->supportedFeatureLevel)
{
case D3D_FEATURE_LEVEL_9_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 9.1)\n");
break;
case D3D_FEATURE_LEVEL_9_2:
RARCH_LOG("[D3D11] Device created (Feature Level: 9.2)\n");
break;
case D3D_FEATURE_LEVEL_9_3:
RARCH_LOG("[D3D11] Device created (Feature Level: 9.3)\n");
break;
case D3D_FEATURE_LEVEL_10_0:
RARCH_LOG("[D3D11] Device created (Feature Level: 10.0)\n");
break;
case D3D_FEATURE_LEVEL_10_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 10.1)\n");
break;
case D3D_FEATURE_LEVEL_11_0:
RARCH_LOG("[D3D11] Device created (Feature Level: 11.0)\n");
break;
case D3D_FEATURE_LEVEL_11_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 11.1)\n");
break;
case D3D_FEATURE_LEVEL_12_0:
RARCH_LOG("[D3D11] Device created (Feature Level: 12.0)\n");
break;
case D3D_FEATURE_LEVEL_12_1:
RARCH_LOG("[D3D11] Device created (Feature Level: 12.1)\n");
break;
default:
RARCH_LOG("[D3D11] Device created (Feature Level: N/A)\n");
break;
}
}
d3d11->device->lpVtbl->QueryInterface(
@@ -777,7 +959,44 @@ static bool d3d11_init_swapchain(d3d11_video_t* d3d11,
}
#endif
#endif // __WINRT__
#endif /* __WINRT__ */
#ifdef HAVE_DXGI_HDR
/* Check display HDR support and
initialize ST.2084 support to match
the display's support. */
#if 0
d3d11->hdr.max_output_nits = 300.0f;
d3d11->hdr.min_output_nits = 0.001f;
d3d11->hdr.max_cll = 0.0f;
d3d11->hdr.max_fall = 0.0f;
#endif
color_space =
d3d11->hdr.enable
? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
dxgi_swapchain_color_space(
d3d11->swapChain,
&d3d11->chain_color_space,
color_space);
dxgi_set_hdr_metadata(
d3d11->swapChain,
d3d11->hdr.support,
d3d11->chain_bit_depth,
d3d11->chain_color_space,
d3d11->hdr.max_output_nits,
d3d11->hdr.min_output_nits,
d3d11->hdr.max_cll,
d3d11->hdr.max_fall);
memset(&d3d11->back_buffer, 0, sizeof(d3d11->back_buffer));
d3d11->back_buffer.desc.Width = width;
d3d11->back_buffer.desc.Height = height;
d3d11->back_buffer.desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d11->back_buffer.desc.BindFlags = D3D11_BIND_RENDER_TARGET;
d3d11_init_texture(d3d11->device, &d3d11->back_buffer);
#endif
dxgiFactory->lpVtbl->Release(dxgiFactory);
adapter->lpVtbl->Release(adapter);
@@ -840,6 +1059,19 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d_input_driver(settings->arrays.input_driver, settings->arrays.input_joypad_driver, input, input_data);
#ifdef __WINRT__
DXGICreateFactory2(&d3d11->factory);
#else
DXGICreateFactory(&d3d11->factory);
#endif
#ifdef HAVE_DXGI_HDR
d3d11->hdr.enable = settings->bools.video_hdr_enable;
d3d11->hdr.max_output_nits = settings->floats.video_hdr_max_nits;
d3d11->hdr.min_output_nits = 0.001f;
d3d11->hdr.max_cll = 0.0f;
d3d11->hdr.max_fall = 0.0f;
#endif
#ifdef __WINRT__
if (!d3d11_init_swapchain(d3d11,
d3d11->vp.full_width,
@@ -905,6 +1137,40 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d11_gfx_set_rotation(d3d11, 0);
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.enable)
{
D3D11_BUFFER_DESC desc;
D3D11_SUBRESOURCE_DATA ubo_data;
matrix_4x4_ortho(d3d11->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
d3d11->hdr.ubo_values.mvp =
d3d11->mvp_no_rot;
d3d11->hdr.ubo_values.max_nits =
settings->floats.video_hdr_max_nits;
d3d11->hdr.ubo_values.paper_white_nits =
settings->floats.video_hdr_paper_white_nits;
d3d11->hdr.ubo_values.contrast =
VIDEO_HDR_MAX_CONTRAST - settings->floats.video_hdr_display_contrast;
d3d11->hdr.ubo_values.expand_gamut =
settings->bools.video_hdr_expand_gamut;
d3d11->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
desc.ByteWidth = sizeof(dxgi_hdr_uniform_t);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
ubo_data.pSysMem = &d3d11->hdr.ubo_values.mvp;
ubo_data.SysMemPitch = 0;
ubo_data.SysMemSlicePitch = 0;
D3D11CreateBuffer(d3d11->device, &desc, &ubo_data, &d3d11->hdr.ubo);
}
#endif
{
D3D11_SAMPLER_DESC desc = { D3D11_FILTER_MIN_MAG_MIP_POINT };
desc.MaxAnisotropy = 1;
@@ -974,6 +1240,35 @@ static void *d3d11_gfx_init(const video_info_t* video,
D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->sprites.vbo);
}
#ifdef HAVE_DXGI_HDR
if (d3d11->hdr.enable)
{
D3D11_INPUT_ELEMENT_DESC desc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0,
offsetof(d3d11_vertex_t, position),
D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0,
offsetof(d3d11_vertex_t, texcoord),
D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
offsetof(d3d11_vertex_t, color),
D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
static const char shader[] =
#include "d3d_shaders/hdr_sm5.hlsl.h"
;
if (!d3d11_init_shader(
d3d11->device, shader, sizeof(shader),
NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_STOCK_HDR],
D3D11_FEATURE_LEVEL_HINT_DONTCARE
))
goto error;
}
#endif
{
D3D11_INPUT_ELEMENT_DESC desc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, position),
@@ -990,7 +1285,9 @@ static void *d3d11_gfx_init(const video_info_t* video,
if (!d3d11_init_shader(
d3d11->device, shader, sizeof(shader), NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_STOCK_BLEND]))
countof(desc), &d3d11->shaders[VIDEO_SHADER_STOCK_BLEND],
D3D11_FEATURE_LEVEL_HINT_DONTCARE
))
goto error;
}
@@ -1018,11 +1315,13 @@ static void *d3d11_gfx_init(const video_info_t* video,
if (!d3d11_init_shader(
d3d11->device, shader, sizeof(shader), NULL, "VSMain", "PSMain", "GSMain", desc,
countof(desc), &d3d11->sprites.shader))
countof(desc), &d3d11->sprites.shader,
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
if (!d3d11_init_shader(
d3d11->device, shader, sizeof(shader), NULL, "VSMain", "PSMainA8", "GSMain", desc,
countof(desc), &d3d11->sprites.shader_font))
countof(desc), &d3d11->sprites.shader_font,
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
}
@@ -1042,12 +1341,14 @@ static void *d3d11_gfx_init(const video_info_t* video,
if (!d3d11_init_shader(
d3d11->device, ribbon, sizeof(ribbon), NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU]))
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU],
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
if (!d3d11_init_shader(
d3d11->device, ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "PSMain", NULL,
desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_2]))
desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_2],
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
}
@@ -1074,21 +1375,25 @@ static void *d3d11_gfx_init(const video_info_t* video,
if (!d3d11_init_shader(
d3d11->device, simple_snow, sizeof(simple_snow), NULL, "VSMain", "PSMain", NULL,
desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_3]))
desc, countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_3],
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
if (!d3d11_init_shader(
d3d11->device, snow, sizeof(snow), NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_4]))
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_4],
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
if (!d3d11_init_shader(
d3d11->device, bokeh, sizeof(bokeh), NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_5]))
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_5],
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
if (!d3d11_init_shader(
d3d11->device, snowflake, sizeof(snowflake), NULL, "VSMain", "PSMain", NULL, desc,
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_6]))
countof(desc), &d3d11->shaders[VIDEO_SHADER_MENU_6],
D3D11_FEATURE_LEVEL_HINT_DONTCARE))
goto error;
}
}
@@ -1156,12 +1461,6 @@ static void *d3d11_gfx_init(const video_info_t* video,
d3d11->hw.iface.D3DCompile = D3DCompile;
}
#ifdef __WINRT__
DXGICreateFactory2(&d3d11->factory);
#else
DXGICreateFactory(&d3d11->factory);
#endif
{
int i = 0;
int gpu_index = settings->ints.d3d11_gpu_index;
@@ -1384,32 +1683,97 @@ static bool d3d11_gfx_frame(
#ifdef HAVE_GFX_WIDGETS
bool widgets_active = video_info->widgets_active;
#endif
#ifdef HAVE_DXGI_HDR
bool video_hdr_enable = video_info->hdr_enable;
if ( d3d11->resize_chain ||
(d3d11->hdr.enable != video_hdr_enable))
#else
if (d3d11->resize_chain)
#endif
{
UINT swapchain_flags = d3d11->has_allow_tearing
UINT swapchain_flags = d3d11->has_allow_tearing
? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0, DXGI_FORMAT_UNKNOWN,
swapchain_flags);
#ifdef HAVE_DXGI_HDR
d3d11->hdr.enable = video_hdr_enable;
d3d11->viewport.Width = video_width;
d3d11->viewport.Height = video_height;
d3d11->scissor.right = video_width;
d3d11->scissor.bottom = video_height;
if(d3d11->hdr.enable)
d3d11_release_texture(&d3d11->back_buffer);
DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0,
d3d11->chain_formats[d3d11->chain_bit_depth],
swapchain_flags);
#else
DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0,
DXGI_FORMAT_UNKNOWN,
swapchain_flags);
#endif
d3d11->viewport.Width = video_width;
d3d11->viewport.Height = video_height;
d3d11->scissor.right = video_width;
d3d11->scissor.bottom = video_height;
d3d11->ubo_values.OutputSize.width = d3d11->viewport.Width;
d3d11->ubo_values.OutputSize.height = d3d11->viewport.Height;
d3d11->resize_chain = false;
d3d11->resize_viewport = true;
d3d11->resize_chain = false;
d3d11->resize_viewport = true;
video_driver_set_size(video_width, video_height);
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
if (!(d3d11->hdr.support =
dxgi_check_display_hdr_support(d3d11->factory, uwp_get_corewindow())))
d3d11->hdr.enable = false;
#else
if (!(d3d11->hdr.support =
dxgi_check_display_hdr_support(d3d11->factory, main_window.hwnd)))
d3d11->hdr.enable = false;
#endif
if(d3d11->hdr.enable)
{
memset(&d3d11->back_buffer, 0, sizeof(d3d11->back_buffer));
d3d11->back_buffer.desc.Width = video_width;
d3d11->back_buffer.desc.Height = video_height;
d3d11->back_buffer.desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d11->back_buffer.desc.BindFlags = D3D11_BIND_RENDER_TARGET;
d3d11_init_texture(d3d11->device, &d3d11->back_buffer);
dxgi_swapchain_color_space(
d3d11->swapChain,
&d3d11->chain_color_space,
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
d3d11->chain_bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_10;
}
else
{
dxgi_swapchain_color_space(
d3d11->swapChain,
&d3d11->chain_color_space,
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
d3d11->chain_bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_8;
}
dxgi_set_hdr_metadata(
d3d11->swapChain,
d3d11->hdr.support,
d3d11->chain_bit_depth,
d3d11->chain_color_space,
d3d11->hdr.max_output_nits,
d3d11->hdr.min_output_nits,
d3d11->hdr.max_cll,
d3d11->hdr.max_fall);
#endif
}
{
D3D11Texture2D backBuffer;
DXGIGetSwapChainBufferD3D11(d3d11->swapChain, 0, &backBuffer);
D3D11CreateTexture2DRenderTargetView(d3d11->device, backBuffer, NULL, &rtv);
Release(backBuffer);
D3D11Texture2D back_buffer;
DXGIGetSwapChainBufferD3D11(d3d11->swapChain, 0, &back_buffer);
D3D11CreateTexture2DRenderTargetView(d3d11->device, back_buffer, NULL, &rtv);
Release(back_buffer);
}
/* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */
@@ -1593,9 +1957,6 @@ static bool d3d11_gfx_frame(
}
D3D11SetRenderTargets(context, 1, &d3d11->pass[i].rt.rt_view, NULL);
#if 0
D3D11ClearRenderTargetView(context, d3d11->pass[i].rt.rt_view, d3d11->clearcolor);
#endif
D3D11SetViewports(context, 1, &d3d11->pass[i].viewport);
D3D11Draw(context, 4, 0);
@@ -1603,8 +1964,20 @@ static bool d3d11_gfx_frame(
}
}
D3D11SetRenderTargets(context, 1, &rtv, NULL);
D3D11ClearRenderTargetView(context, rtv, d3d11->clearcolor);
#ifdef HAVE_DXGI_HDR
if(d3d11->hdr.enable)
{
D3D11SetRenderTargets(context, 1, &d3d11->back_buffer.rt_view, NULL);
D3D11ClearRenderTargetView(context, d3d11->back_buffer.rt_view, d3d11->clearcolor);
}
else
#endif
{
D3D11SetRenderTargets(context, 1, &rtv, NULL);
D3D11ClearRenderTargetView(context, rtv, d3d11->clearcolor);
}
D3D11SetViewports(context, 1, &d3d11->frame.viewport);
if (texture)
@@ -1702,6 +2075,47 @@ static bool d3d11_gfx_frame(
#if defined(_WIN32) && !defined(__WINRT__)
win32_update_title();
#endif
#ifdef HAVE_DXGI_HDR
/* Copy over back buffer to swap chain render targets */
if(d3d11->hdr.enable)
{
ID3D11ShaderResourceView* nullSRV[1] = {NULL};
D3D11SetRenderTargets(context, 1, &rtv, NULL);
D3D11ClearRenderTargetView(context, rtv,
d3d11->clearcolor);
D3D11SetViewports(context, 1,
&d3d11->viewport);
D3D11SetScissorRects(context, 1,
&d3d11->scissor);
d3d11_set_shader(context,
&d3d11->shaders[VIDEO_SHADER_STOCK_HDR]);
D3D11SetVShaderConstantBuffer(context, 0,
d3d11->hdr.ubo);
D3D11SetPShaderResources(context, 0, 1,
&d3d11->back_buffer.view);
D3D11SetPShaderSamplers(context, 0, 1,
&d3d11->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D11SetPShaderConstantBuffer(context, 0, d3d11->hdr.ubo);
D3D11SetVertexBuffer(context, 0, d3d11->frame.vbo,
sizeof(d3d11_vertex_t), 0);
D3D11SetRasterizerState(context, d3d11->scissor_disabled);
D3D11SetBlendState(context, d3d11->blend_disable, NULL,
D3D11_DEFAULT_SAMPLE_MASK);
D3D11SetPrimitiveTopology(context,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D11Draw(context, 4, 0);
D3D11SetPShaderResources(context, 0, 1, nullSRV);
D3D11SetRasterizerState(context, d3d11->scissor_enabled);
D3D11SetBlendState(d3d11->context, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
D3D11SetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
}
#endif
DXGIPresent(d3d11->swapChain, !!vsync, present_flags);
Release(rtv);
@@ -1957,6 +2371,17 @@ static const video_poke_interface_t d3d11_poke_interface = {
d3d11_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
d3d11_get_hw_render_interface,
#ifdef HAVE_DXGI_HDR
d3d11_set_hdr_max_nits,
d3d11_set_hdr_paper_white_nits,
d3d11_set_hdr_contrast,
d3d11_set_hdr_expand_gamut
#else
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
#endif
};
static void d3d11_gfx_get_poke_interface(void* data,
+466 -91
View File
@@ -238,6 +238,70 @@ static void d3d12_get_overlay_interface(void* data, const video_overlay_interfac
}
#endif
#ifdef HAVE_DXGI_HDR
static void d3d12_set_hdr_max_nits(void* data, float max_nits)
{
dxgi_hdr_uniform_t *mapped_ubo = NULL;
D3D12_RANGE read_range = { 0, 0 };
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
d3d12->hdr.max_output_nits = max_nits;
d3d12->hdr.ubo_values.max_nits = max_nits;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
dxgi_set_hdr_metadata(
d3d12->chain.handle,
d3d12->hdr.support,
d3d12->chain.bit_depth,
d3d12->chain.color_space,
d3d12->hdr.max_output_nits,
d3d12->hdr.min_output_nits,
d3d12->hdr.max_cll,
d3d12->hdr.max_fall);
}
static void d3d12_set_hdr_paper_white_nits(void* data, float paper_white_nits)
{
D3D12_RANGE read_range = { 0, 0 };
dxgi_hdr_uniform_t *mapped_ubo = NULL;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
d3d12->hdr.ubo_values.paper_white_nits = paper_white_nits;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
static void d3d12_set_hdr_contrast(void* data, float contrast)
{
D3D12_RANGE read_range = { 0, 0 };
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
dxgi_hdr_uniform_t *mapped_ubo = NULL;
d3d12->hdr.ubo_values.contrast = contrast;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
static void d3d12_set_hdr_expand_gamut(void* data, bool expand_gamut)
{
D3D12_RANGE read_range = { 0, 0 };
dxgi_hdr_uniform_t *mapped_ubo = NULL;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
d3d12->hdr.ubo_values.expand_gamut = expand_gamut;
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
#endif
static void d3d12_set_filtering(void* data, unsigned index, bool smooth, bool ctx_scaling)
{
int i;
@@ -494,9 +558,18 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
if (!d3d12->pass[i].pipe)
goto error;
#ifdef HAVE_DXGI_HDR
d3d12->pass[i].rt.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr +
(countof(d3d12->chain.renderTargets) + (2 * i)) * d3d12->desc.rtv_heap.stride;
d3d12->desc.rtv_heap.cpu.ptr +
(countof(d3d12->chain.renderTargets) + 1 + (2 * i))
* d3d12->desc.rtv_heap.stride;
#else
d3d12->pass[i].rt.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr +
(countof(d3d12->chain.renderTargets) + (2 * i))
* d3d12->desc.rtv_heap.stride;
#endif
d3d12->pass[i].feedback.rt_view.ptr = d3d12->pass[i].rt.rt_view.ptr + d3d12->desc.rtv_heap.stride;
d3d12->pass[i].textures.ptr =
@@ -562,12 +635,51 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12)
settings_t * settings = config_get_ptr();
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { d3d12->desc.rootSignature };
desc.BlendState.RenderTarget[0] = d3d12_blend_disable_desc;
#ifdef HAVE_DXGI_HDR
desc.RTVFormats[0] = DXGI_FORMAT_R10G10B10A2_UNORM;
{
static const char shader[] =
#include "d3d_shaders/hdr_sm5.hlsl.h"
;
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position),
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord),
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_vertex_t, color),
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
if (!d3d_compile(shader, sizeof(shader), NULL, "VSMain", "vs_5_0", &vs_code))
goto error;
if (!d3d_compile(shader, sizeof(shader), NULL, "PSMain", "ps_5_0", &ps_code))
goto error;
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
desc.InputLayout.pInputElementDescs = inputElementDesc;
desc.InputLayout.NumElements = countof(inputElementDesc);
if (!d3d12_init_pipeline(
d3d12->device, vs_code, ps_code, NULL, &desc,
&d3d12->pipes[VIDEO_SHADER_STOCK_HDR]))
goto error;
Release(vs_code);
Release(ps_code);
vs_code = NULL;
ps_code = NULL;
}
#endif
desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc;
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
{
static const char shader[] =
#include "../drivers/d3d_shaders/opaque_sm5.hlsl.h"
#include "d3d_shaders/opaque_sm5.hlsl.h"
;
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
@@ -839,6 +951,10 @@ static void d3d12_gfx_free(void* data)
Release(d3d12->sprites.vbo);
Release(d3d12->menu_pipeline_vbo);
#ifdef HAVE_DXGI_HDR
Release(d3d12->hdr.ubo);
#endif
Release(d3d12->frame.ubo);
Release(d3d12->frame.vbo);
Release(d3d12->frame.texture[0].handle);
@@ -847,6 +963,10 @@ static void d3d12_gfx_free(void* data)
Release(d3d12->menu.texture.handle);
Release(d3d12->menu.texture.upload_buffer);
#ifdef HAVE_DXGI_HDR
d3d12_release_texture(&d3d12->chain.back_buffer);
d3d12->chain.back_buffer.handle = NULL;
#endif
free(d3d12->desc.sampler_heap.map);
free(d3d12->desc.srv_heap.map);
free(d3d12->desc.rtv_heap.map);
@@ -890,6 +1010,10 @@ static void d3d12_gfx_free(void* data)
}
}
#ifdef HAVE_DXGI_HDR
video_driver_unset_hdr_support();
#endif
#ifdef HAVE_MONITOR
win32_monitor_from_window();
#endif
@@ -951,6 +1075,14 @@ static void *d3d12_gfx_init(const video_info_t* video,
goto error;
}
#ifdef HAVE_DXGI_HDR
d3d12->hdr.enable = settings->bools.video_hdr_enable;
d3d12->hdr.max_output_nits = settings->floats.video_hdr_max_nits;
d3d12->hdr.min_output_nits = 0.001f;
d3d12->hdr.max_cll = 0.0f;
d3d12->hdr.max_fall = 0.0f;
#endif
d3d_input_driver(settings->arrays.input_driver, settings->arrays.input_joypad_driver, input, input_data);
if (!d3d12_init_base(d3d12))
@@ -1007,6 +1139,27 @@ static void *d3d12_gfx_init(const video_info_t* video,
D3D12Unmap(d3d12->ubo, 0, NULL);
}
#ifdef HAVE_DXGI_HDR
d3d12->hdr.ubo_view.SizeInBytes = sizeof(dxgi_hdr_uniform_t);
d3d12->hdr.ubo_view.BufferLocation =
d3d12_create_buffer(d3d12->device, d3d12->hdr.ubo_view.SizeInBytes, &d3d12->hdr.ubo);
d3d12->hdr.ubo_values.mvp = d3d12->mvp_no_rot;
d3d12->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits;
d3d12->hdr.ubo_values.paper_white_nits = settings->floats.video_hdr_paper_white_nits;
d3d12->hdr.ubo_values.contrast = VIDEO_HDR_MAX_CONTRAST - settings->floats.video_hdr_display_contrast;
d3d12->hdr.ubo_values.expand_gamut = settings->bools.video_hdr_expand_gamut;
d3d12->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
{
dxgi_hdr_uniform_t* mapped_ubo;
D3D12_RANGE read_range = { 0, 0 };
D3D12Map(d3d12->hdr.ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->hdr.ubo_values;
D3D12Unmap(d3d12->hdr.ubo, 0, NULL);
}
#endif
d3d12_gfx_set_rotation(d3d12, 0);
video_driver_set_size(d3d12->vp.full_width, d3d12->vp.full_height);
d3d12->chain.viewport.Width = d3d12->vp.full_width;
@@ -1197,53 +1350,138 @@ static bool d3d12_gfx_frame(
#ifdef HAVE_GFX_WIDGETS
bool widgets_active = video_info->widgets_active;
#endif
#ifdef HAVE_DXGI_HDR
bool video_hdr_enable = video_info->hdr_enable;
if (d3d12->resize_chain || (d3d12->hdr.enable != video_hdr_enable))
#else
if (d3d12->resize_chain)
#endif
{
unsigned i;
#ifdef HAVE_DXGI_HDR
d3d12->hdr.enable = video_hdr_enable;
#endif
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
Release(d3d12->chain.renderTargets[i]);
DXGIResizeBuffers(d3d12->chain.handle, 0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING);
#ifdef HAVE_DXGI_HDR
if (d3d12->hdr.enable)
{
d3d12_release_texture(&d3d12->chain.back_buffer);
d3d12->chain.back_buffer.handle = NULL;
}
DXGIResizeBuffers(d3d12->chain.handle,
countof(d3d12->chain.renderTargets),
video_width,
video_height,
d3d12->chain.formats[d3d12->chain.bit_depth],
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING);
#else
DXGIResizeBuffers(d3d12->chain.handle,
0,
0,
0,
DXGI_FORMAT_UNKNOWN,
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING);
#endif
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
{
DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]);
DXGIGetSwapChainBuffer(d3d12->chain.handle, i,
&d3d12->chain.renderTargets[i]);
D3D12CreateRenderTargetView(
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
d3d12->device, d3d12->chain.renderTargets[i],
NULL, d3d12->chain.desc_handles[i]);
}
d3d12->chain.viewport.Width = video_width;
d3d12->chain.viewport.Height = video_height;
d3d12->chain.scissorRect.right = video_width;
d3d12->chain.scissorRect.bottom = video_height;
d3d12->resize_chain = false;
d3d12->resize_viewport = true;
d3d12->chain.viewport.Width = video_width;
d3d12->chain.viewport.Height = video_height;
d3d12->chain.scissorRect.right = video_width;
d3d12->chain.scissorRect.bottom = video_height;
d3d12->resize_chain = false;
d3d12->resize_viewport = true;
d3d12->ubo_values.OutputSize.width = d3d12->chain.viewport.Width;
d3d12->ubo_values.OutputSize.height = d3d12->chain.viewport.Height;
video_driver_set_size(video_width, video_height);
#ifdef HAVE_DXGI_HDR
#ifdef __WINRT__
if (!(d3d12->hdr.support =
dxgi_check_display_hdr_support(d3d12->factory, uwp_get_corewindow())))
d3d12->hdr.enable = false;
#else
if (!(d3d12->hdr.support =
dxgi_check_display_hdr_support(d3d12->factory, main_window.hwnd)))
d3d12->hdr.enable = false;
#endif
if(d3d12->hdr.enable)
{
memset(&d3d12->chain.back_buffer,
0, sizeof(d3d12->chain.back_buffer));
d3d12->chain.back_buffer.desc.Width = video_width;
d3d12->chain.back_buffer.desc.Height = video_height;
d3d12->chain.back_buffer.desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
d3d12->chain.back_buffer.desc.Flags =
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
d3d12->chain.back_buffer.srv_heap = &d3d12->desc.srv_heap;
d3d12->chain.back_buffer.rt_view.ptr =
d3d12->desc.rtv_heap.cpu.ptr
+ countof(d3d12->chain.renderTargets)
* d3d12->desc.rtv_heap.stride;
d3d12_init_texture(d3d12->device, &d3d12->chain.back_buffer);
dxgi_swapchain_color_space(d3d12->chain.handle,
&d3d12->chain.color_space,
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
d3d12->chain.bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_10;
}
else
{
dxgi_swapchain_color_space(d3d12->chain.handle,
&d3d12->chain.color_space,
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
d3d12->chain.bit_depth = DXGI_SWAPCHAIN_BIT_DEPTH_8;
}
dxgi_set_hdr_metadata(
d3d12->chain.handle,
d3d12->hdr.support,
d3d12->chain.bit_depth,
d3d12->chain.color_space,
d3d12->hdr.max_output_nits,
d3d12->hdr.min_output_nits,
d3d12->hdr.max_cll,
d3d12->hdr.max_fall);
#endif
}
D3D12ResetCommandAllocator(d3d12->queue.allocator);
D3D12ResetGraphicsCommandList(
d3d12->queue.cmd, d3d12->queue.allocator, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
d3d12->queue.cmd, d3d12->queue.allocator,
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
{
D3D12DescriptorHeap desc_heaps[] = { d3d12->desc.srv_heap.handle,
d3d12->desc.sampler_heap.handle };
D3D12SetDescriptorHeaps(d3d12->queue.cmd, countof(desc_heaps), desc_heaps);
D3D12SetDescriptorHeaps(d3d12->queue.cmd,
countof(desc_heaps), desc_heaps);
}
#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */
#if 0
/* Custom viewport doesn't call apply_state_changes,
so we can't rely on this for now */
if (d3d12->resize_viewport)
#endif
d3d12_update_viewport(d3d12, false);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
if (frame && width && height)
{
@@ -1260,7 +1498,8 @@ static bool d3d12_gfx_frame(
if (d3d12->resize_render_targets)
{
/* release all render targets first to avoid memory fragmentation */
/* Release all render targets first
to avoid memory fragmentation */
for (i = 0; i < d3d12->shader_preset->passes; i++)
{
d3d12_release_texture(&d3d12->pass[i].rt);
@@ -1277,9 +1516,10 @@ static bool d3d12_gfx_frame(
else
{
int k;
/* todo: what about frame-duping ?
/* TODO/FIXME: what about frame-duping ?
* maybe clone d3d12_texture_t with AddRef */
d3d12_texture_t tmp = d3d12->frame.texture[d3d12->shader_preset->history_size];
d3d12_texture_t tmp =
d3d12->frame.texture[d3d12->shader_preset->history_size];
for (k = d3d12->shader_preset->history_size; k > 0; k--)
d3d12->frame.texture[k] = d3d12->frame.texture[k - 1];
d3d12->frame.texture[0] = tmp;
@@ -1287,8 +1527,9 @@ static bool d3d12_gfx_frame(
}
}
/* either no history, or we moved a texture of a different size in the front slot */
if (d3d12->frame.texture[0].desc.Width != width ||
/* Either no history, or we moved a texture
of a different size in the front slot */
if (d3d12->frame.texture[0].desc.Width != width ||
d3d12->frame.texture[0].desc.Height != height)
{
d3d12->frame.texture[0].desc.Width = width;
@@ -1300,7 +1541,8 @@ static bool d3d12_gfx_frame(
if (d3d12->resize_render_targets)
d3d12_init_render_targets(d3d12, width, height);
d3d12_update_texture(width, height, pitch, d3d12->format, frame, &d3d12->frame.texture[0]);
d3d12_update_texture(width, height, pitch, d3d12->format,
frame, &d3d12->frame.texture[0]);
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture[0],
d3d12);
@@ -1311,7 +1553,8 @@ static bool d3d12_gfx_frame(
if (d3d12->shader_preset)
{
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.sl_rootSignature);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd,
d3d12->desc.sl_rootSignature);
for (i = 0; i < d3d12->shader_preset->passes; i++)
{
@@ -1330,16 +1573,17 @@ static bool d3d12_gfx_frame(
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pass[i].pipe);
if (d3d12->shader_preset->pass[i].frame_count_mod)
d3d12->pass[i].frame_count =
frame_count % d3d12->shader_preset->pass[i].frame_count_mod;
d3d12->pass[i].frame_count = frame_count
% d3d12->shader_preset->pass[i].frame_count_mod;
else
d3d12->pass[i].frame_count = frame_count;
#ifdef HAVE_REWIND
d3d12->pass[i].frame_direction = state_manager_frame_is_reversed() ? -1 : 1;
#else
d3d12->pass[i].frame_direction = 1;
if (state_manager_frame_is_reversed())
d3d12->pass[i].frame_direction = -1;
else
#endif
d3d12->pass[i].frame_direction = 1;
for (j = 0; j < SLANG_CBUFFER_MAX; j++)
{
@@ -1351,17 +1595,21 @@ static bool d3d12_gfx_frame(
uint8_t* mapped_data = NULL;
uniform_sem_t* uniform = buffer_sem->uniforms;
D3D12Map(d3d12->pass[i].buffers[j], 0, &range, (void**)&mapped_data);
D3D12Map(d3d12->pass[i].buffers[j], 0, &range,
(void**)&mapped_data);
while (uniform->size)
{
if (uniform->data)
memcpy(mapped_data + uniform->offset, uniform->data, uniform->size);
memcpy(mapped_data + uniform->offset,
uniform->data, uniform->size);
uniform++;
}
D3D12Unmap(d3d12->pass[i].buffers[j], 0, NULL);
D3D12SetGraphicsRootConstantBufferView(
d3d12->queue.cmd, j == SLANG_CBUFFER_UBO ? ROOT_ID_UBO : ROOT_ID_PC,
d3d12->queue.cmd, j == SLANG_CBUFFER_UBO
? ROOT_ID_UBO
: ROOT_ID_PC,
d3d12->pass[i].buffer_view[j].BufferLocation);
}
}
@@ -1375,15 +1623,19 @@ static bool d3d12_gfx_frame(
{
{
D3D12_CPU_DESCRIPTOR_HANDLE handle = {
d3d12->pass[i].textures.ptr - d3d12->desc.srv_heap.gpu.ptr +
d3d12->desc.srv_heap.cpu.ptr +
texture_sem->binding * d3d12->desc.srv_heap.stride
d3d12->pass[i].textures.ptr
- d3d12->desc.srv_heap.gpu.ptr
+ d3d12->desc.srv_heap.cpu.ptr
+ texture_sem->binding * d3d12->desc.srv_heap.stride
};
d3d12_texture_t* tex = (d3d12_texture_t*)texture_sem->texture_data;
d3d12_texture_t* tex =
(d3d12_texture_t*)texture_sem->texture_data;
D3D12_SHADER_RESOURCE_VIEW_DESC desc = { tex->desc.Format };
desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
desc.Shader4ComponentMapping =
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.ViewDimension =
D3D12_SRV_DIMENSION_TEXTURE2D;
desc.Texture2D.MipLevels = tex->desc.MipLevels;
D3D12CreateShaderResourceView(d3d12->device,
@@ -1392,9 +1644,11 @@ static bool d3d12_gfx_frame(
{
D3D12_CPU_DESCRIPTOR_HANDLE handle = {
d3d12->pass[i].samplers.ptr - d3d12->desc.sampler_heap.gpu.ptr +
d3d12->desc.sampler_heap.cpu.ptr +
texture_sem->binding * d3d12->desc.sampler_heap.stride
d3d12->pass[i].samplers.ptr
- d3d12->desc.sampler_heap.gpu.ptr
+ d3d12->desc.sampler_heap.cpu.ptr
+ texture_sem->binding
* d3d12->desc.sampler_heap.stride
};
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_LINEAR };
@@ -1435,29 +1689,37 @@ static bool d3d12_gfx_frame(
}
D3D12SetGraphicsRootDescriptorTable(
d3d12->queue.cmd, ROOT_ID_TEXTURE_T, d3d12->pass[i].textures);
d3d12->queue.cmd, ROOT_ID_TEXTURE_T,
d3d12->pass[i].textures);
D3D12SetGraphicsRootDescriptorTable(
d3d12->queue.cmd, ROOT_ID_SAMPLER_T, d3d12->pass[i].samplers);
d3d12->queue.cmd, ROOT_ID_SAMPLER_T,
d3d12->pass[i].samplers);
}
if (d3d12->pass[i].rt.handle)
{
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->pass[i].rt.handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12OMSetRenderTargets(d3d12->queue.cmd, 1, &d3d12->pass[i].rt.rt_view, FALSE, NULL);
D3D12OMSetRenderTargets(d3d12->queue.cmd, 1,
&d3d12->pass[i].rt.rt_view, FALSE, NULL);
#if 0
D3D12ClearRenderTargetView(
d3d12->queue.cmd, d3d12->pass[i].rt.rt_view, d3d12->chain.clearcolor, 0, NULL);
d3d12->queue.cmd, d3d12->pass[i].rt.rt_view,
d3d12->chain.clearcolor, 0, NULL);
#endif
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->pass[i].viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->pass[i].scissorRect);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->pass[i].viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->pass[i].scissorRect);
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->pass[i].rt.handle, D3D12_RESOURCE_STATE_RENDER_TARGET,
d3d12->queue.cmd, d3d12->pass[i].rt.handle,
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
texture = &d3d12->pass[i].rt;
}
@@ -1471,31 +1733,68 @@ static bool d3d12_gfx_frame(
if (texture)
{
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd,
d3d12->desc.rootSignature);
d3d12_set_texture(d3d12->queue.cmd, &d3d12->frame.texture[0]);
d3d12_set_sampler(d3d12->queue.cmd, d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
d3d12_set_sampler(d3d12->queue.cmd,
d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D12SetGraphicsRootConstantBufferView(
d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation);
d3d12->queue.cmd, ROOT_ID_UBO,
d3d12->frame.ubo_view.BufferLocation);
}
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(
d3d12->chain.handle);
D3D12OMSetRenderTargets(
d3d12->queue.cmd, 1, &d3d12->chain.desc_handles[d3d12->chain.frame_index], FALSE, NULL);
D3D12ClearRenderTargetView(
d3d12->queue.cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index],
d3d12->chain.clearcolor, 0, NULL);
#ifdef HAVE_DXGI_HDR
if(d3d12->hdr.enable)
{
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.back_buffer.handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12OMSetRenderTargets(
d3d12->queue.cmd, 1,
&d3d12->chain.back_buffer.rt_view, FALSE, NULL);
/* TODO/FIXME - fix this warning that shows up with Debug logging
* EXECUTIONWARNING #820: CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE
* We need to set clear value during resource creation to NULL for
* D3D12_RESOURCE_DIMENSION_BUFFER, yet we get spammed with this
* warning
*/
D3D12ClearRenderTargetView(
d3d12->queue.cmd, d3d12->chain.back_buffer.rt_view,
d3d12->chain.clearcolor, 0, NULL);
}
else
#endif
{
d3d12_resource_transition(
d3d12->queue.cmd,
d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12OMSetRenderTargets(
d3d12->queue.cmd, 1,
&d3d12->chain.desc_handles[d3d12->chain.frame_index],
FALSE, NULL);
D3D12ClearRenderTargetView(
d3d12->queue.cmd,
d3d12->chain.desc_handles[d3d12->chain.frame_index],
d3d12->chain.clearcolor, 0, NULL);
}
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect);
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature);
if (d3d12->menu.enabled && d3d12->menu.texture.handle)
@@ -1520,7 +1819,8 @@ static bool d3d12_gfx_frame(
d3d12->sprites.pipe = d3d12->sprites.pipe_noblend;
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd,
D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
d3d12->sprites.enabled = true;
@@ -1529,9 +1829,12 @@ static bool d3d12_gfx_frame(
if (d3d12->menu.enabled)
#endif
{
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->sprites.vbo_view);
}
#endif
@@ -1544,10 +1847,14 @@ static bool d3d12_gfx_frame(
{
if (osd_params)
{
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->sprites.vbo_view);
font_driver_render_msg(d3d12, stat_text,
(const struct font_params*)osd_params, NULL);
}
@@ -1557,17 +1864,21 @@ static bool d3d12_gfx_frame(
{
if (d3d12->overlays.fullscreen)
{
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
}
else
{
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->frame.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->frame.scissorRect);
}
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->overlays.vbo_view);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->overlays.vbo_view);
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_blend);
D3D12SetGraphicsRootDescriptorTable(
@@ -1582,7 +1893,8 @@ static bool d3d12_gfx_frame(
d3d12);
D3D12SetGraphicsRootDescriptorTable(
d3d12->queue.cmd, ROOT_ID_TEXTURE_T, d3d12->overlays.textures[i].gpu_descriptor[0]);
d3d12->queue.cmd, ROOT_ID_TEXTURE_T,
d3d12->overlays.textures[i].gpu_descriptor[0]);
D3D12DrawInstanced(d3d12->queue.cmd, 1, 1, i, 0);
}
}
@@ -1595,31 +1907,83 @@ static bool d3d12_gfx_frame(
if (msg && *msg)
{
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->sprites.pipe_blend);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->sprites.vbo_view);
font_driver_render_msg(d3d12, msg, NULL, NULL);
}
d3d12->sprites.enabled = false;
#ifdef HAVE_DXGI_HDR
/* Copy over back buffer to swap chain render targets */
if (d3d12->hdr.enable)
{
d3d12_resource_transition(
d3d12->queue.cmd,
d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET);
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.back_buffer.handle,
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
D3D12SetPipelineState(d3d12->queue.cmd,
d3d12->pipes[VIDEO_SHADER_STOCK_HDR]);
D3D12OMSetRenderTargets(
d3d12->queue.cmd, 1,
&d3d12->chain.desc_handles[d3d12->chain.frame_index],
FALSE, NULL);
D3D12ClearRenderTargetView(
d3d12->queue.cmd,
d3d12->chain.desc_handles[d3d12->chain.frame_index],
d3d12->chain.clearcolor, 0, NULL);
D3D12SetGraphicsRootSignature(d3d12->queue.cmd,
d3d12->desc.rootSignature);
d3d12_set_texture(d3d12->queue.cmd, &d3d12->chain.back_buffer);
d3d12_set_sampler(d3d12->queue.cmd,
d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D12SetGraphicsRootConstantBufferView(
d3d12->queue.cmd, ROOT_ID_UBO,
d3d12->hdr.ubo_view.BufferLocation);
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1,
&d3d12->frame.vbo_view);
D3D12IASetPrimitiveTopology(d3d12->queue.cmd,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D12RSSetViewports(d3d12->queue.cmd, 1,
&d3d12->chain.viewport);
D3D12RSSetScissorRects(d3d12->queue.cmd, 1,
&d3d12->chain.scissorRect);
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
}
#endif
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
d3d12->queue.cmd,
d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT);
D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd);
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1,
&d3d12->queue.cmd);
#if defined(_WIN32) && !defined(__WINRT__)
win32_update_title();
#endif
#if 1
DXGIPresent(d3d12->chain.handle, sync_interval, present_flags);
#else
DXGI_PRESENT_PARAMETERS pp = { 0 };
DXGIPresent1(d3d12->swapchain, 0, 0, &pp);
#endif
/* Sync after Present for minimal delay */
d3d12_gfx_sync(d3d12);
@@ -1890,6 +2254,17 @@ static const video_poke_interface_t d3d12_poke_interface = {
d3d12_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
#ifdef HAVE_DXGI_HDR
d3d12_set_hdr_max_nits,
d3d12_set_hdr_paper_white_nits,
d3d12_set_hdr_contrast,
d3d12_set_hdr_expand_gamut,
#else
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
#endif
};
static void d3d12_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)
+5 -1
View File
@@ -1831,7 +1831,11 @@ static const video_poke_interface_t d3d_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void d3d8_get_poke_interface(void *data,
+6 -2
View File
@@ -1578,7 +1578,7 @@ static bool d3d9_frame(void *data, const void *frame,
#ifdef HAVE_MENU
if (d3d->menu && d3d->menu->enabled)
{
d3d9_set_mvp(d3d->dev, &d3d->mvp);
d3d9_set_mvp(d3d->dev, &d3d->mvp_transposed);
d3d9_overlay_render(d3d, width, height, d3d->menu, false);
d3d->menu_display.offset = 0;
@@ -1976,7 +1976,11 @@ static const video_poke_interface_t d3d9_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void d3d9_get_poke_interface(void *data,
+130
View File
@@ -0,0 +1,130 @@
#define SRC(...) #__VA_ARGS__
SRC(
struct UBO
{
float4x4 modelViewProj;
float contrast; /* 2.0f; */
float paper_white_nits; /* 200.0f; */
float max_nits; /* 1000.0f; */
float expand_gamut; /* 1.0f; */
float inverse_tonemap;
};
uniform UBO global;
struct PSInput
{
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
float4 color : COLOR;
};
PSInput VSMain(float4 position : POSITION, float2 texcoord : TEXCOORD0, float4 color : COLOR)
{
PSInput result;
result.position = mul(global.modelViewProj, position);
result.texcoord = texcoord;
result.color = color;
return result;
}
uniform sampler s0;
uniform Texture2D <float4> t0;
static const float kMaxNitsFor2084 = 10000.0f;
static const float kEpsilon = 0.0001f;
static const float kLumaChannelRatio = 0.25f;
static const float3x3 k709to2020 =
{
{ 0.6274040f, 0.3292820f, 0.0433136f },
{ 0.0690970f, 0.9195400f, 0.0113612f },
{ 0.0163916f, 0.0880132f, 0.8955950f }
};
static const float3x3 kP3to2020 =
{
{ 0.753845f, 0.198593f, 0.047562f },
{ 0.0457456f, 0.941777f, 0.0124772f },
{ -0.00121055f, 0.0176041f, 0.983607f }
};
/* START Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */
static const float3x3 kExpanded709to2020 =
{
{ 0.6274040f, 0.3292820f, 0.0433136f },
{ 0.0457456, 0.941777, 0.0124772 },
{ -0.00121055, 0.0176041, 0.983607 }
};
float3 LinearToST2084(float3 normalizedLinearValue)
{
float3 ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), 0.1593017578f)) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), 0.1593017578f)), 78.84375f);
return ST2084; /* Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits */
}
/* END Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */
float3 SRGBToLinear(float3 color)
{
float3 scale = color / 12.92f;
float3 gamma = pow(abs(color + 0.055f) / 1.055f, 2.4f);
return float3( color.x < 0.04045f ? scale.x : gamma.x,
color.y < 0.04045f ? scale.y : gamma.y,
color.z < 0.04045f ? scale.z : gamma.z);
}
float4 Hdr(float4 sdr)
{
float3 hdr;
if(global.inverse_tonemap)
{
sdr.xyz = pow(abs(sdr.xyz), global.contrast / 2.2f ); /* Display Gamma - needs to be determined by calibration screen */
float luma = dot(sdr.xyz, float3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */
/* Inverse reinhard tonemap */
float maxValue = (global.max_nits / global.paper_white_nits) + kEpsilon;
float elbow = maxValue / (maxValue - 1.0f); /* Convert (1.0 + epsilon) to infinite to range 1001 -> 1.0 */
float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); /* Convert 1001 to 1.0 to range 0.5 -> 1.0 */
float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma));
float sdrLumaInvTonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap;
float3 perLuma = sdr.xyz / (luma + kEpsilon) * lumaInvTonemap;
float3 hdrInvTonemap = offset + ((sdr.xyz * elbow) / (elbow - sdr.xyz));
float3 sdrInvTonemap = sdr.xyz / ((1.0f + kEpsilon) - sdr.xyz); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */
float3 perChannel = float3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x,
sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y,
sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z);
hdr = lerp(perLuma, perChannel, kLumaChannelRatio);
}
else
{
hdr = SRGBToLinear(sdr.xyz);
}
/* Now convert into HDR10 */
float3 rec2020 = mul(k709to2020, hdr);
if(global.expand_gamut > 0.0f)
{
rec2020 = mul( kExpanded709to2020, hdr);
}
float3 linearColour = rec2020 * (global.paper_white_nits / kMaxNitsFor2084);
float3 hdr10 = LinearToST2084(linearColour);
return float4(hdr10, sdr.w);
}
float4 PSMain(PSInput input) : SV_TARGET
{
float4 sdr = input.color * t0.Sample(s0, input.texcoord);
return Hdr(sdr);
};
)
+5 -1
View File
@@ -600,7 +600,11 @@ static const video_poke_interface_t dispmanx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void dispmanx_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -956,7 +956,11 @@ static const video_poke_interface_t drm_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void drm_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -1498,7 +1498,11 @@ static const video_poke_interface_t exynos_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void exynos_gfx_get_poke_interface(void *data,
+4
View File
@@ -386,6 +386,10 @@ static const video_poke_interface_t fpga_poke_interface = {
#ifdef HAVE_MENU
NULL,
#endif
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void fpga_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -724,7 +724,11 @@ static const video_poke_interface_t gdi_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gdi_gfx_get_poke_interface(void *data,
+6 -2
View File
@@ -34,7 +34,7 @@
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#include <compat/strl.h>
@@ -4588,7 +4588,11 @@ static const video_poke_interface_t gl2_poke_interface = {
NULL,
gl2_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gl2_get_poke_interface(void *data,
+5 -1
View File
@@ -1448,7 +1448,11 @@ static const video_poke_interface_t gl1_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gl1_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -20,7 +20,7 @@
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../../config.h"
#endif
#include "../common/gl_core_common.h"
@@ -2287,6 +2287,10 @@ static const video_poke_interface_t gl_core_poke_interface = {
gl_core_get_current_shader,
NULL,
NULL,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gl_core_get_poke_interface(void *data,
+4
View File
@@ -1735,6 +1735,10 @@ static const video_poke_interface_t wiiu_poke_interface = {
wiiu_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void wiiu_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -1372,7 +1372,11 @@ static const video_poke_interface_t gx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void gx_get_poke_interface(void *data,
+25 -13
View File
@@ -399,19 +399,31 @@ static uint32_t metal_get_flags(void *data)
}
static const video_poke_interface_t metal_poke_interface = {
.get_flags = metal_get_flags,
.load_texture = metal_load_texture,
.unload_texture = metal_unload_texture,
.set_video_mode = metal_set_video_mode,
.get_refresh_rate = metal_get_refresh_rate,
.set_filtering = metal_set_filtering,
.set_aspect_ratio = metal_set_aspect_ratio,
.apply_state_changes = metal_apply_state_changes,
.set_texture_frame = metal_set_texture_frame,
.set_texture_enable = metal_set_texture_enable,
.set_osd_msg = font_driver_render_msg,
.show_mouse = metal_show_mouse,
.get_current_shader = metal_get_current_shader,
metal_get_flags,
metal_load_texture,
metal_unload_texture,
metal_set_video_mode,
metal_get_refresh_rate,
metal_set_filtering,
NULL, /* get_video_output_size */
NULL, /* get_video_output_prev */
NULL, /* get_video_output_next */
NULL, /* get_current_framebuffer */
NULL, /* get_proc_address */
metal_set_aspect_ratio,
metal_apply_state_changes,
metal_set_texture_frame,
metal_set_texture_enable,
font_driver_render_msg,
metal_show_mouse,
NULL, /* grab_mouse_toggle */
metal_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void metal_get_poke_interface(void *data,
+5 -1
View File
@@ -1123,7 +1123,11 @@ static const video_poke_interface_t omap_gfx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void omap_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -465,7 +465,11 @@ static const video_poke_interface_t ps2_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
ps2_get_hw_render_interface /* get_hw_render_interface */
ps2_get_hw_render_interface, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void ps2_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -802,7 +802,11 @@ static const video_poke_interface_t psp_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void psp_get_poke_interface(void *data,
+5 -1
View File
@@ -720,7 +720,11 @@ static const video_poke_interface_t rsx_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void rsx_get_poke_interface(void* data,
+5 -1
View File
@@ -1106,7 +1106,11 @@ static const video_poke_interface_t sdl_dingux_poke_interface = {
NULL, /* sdl_grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sdl_dingux_get_poke_interface(void *data, const video_poke_interface_t **iface)
+5 -1
View File
@@ -547,7 +547,11 @@ static const video_poke_interface_t sdl_poke_interface = {
sdl_grab_mouse_toggle,
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sdl_get_poke_interface(void *data, const video_poke_interface_t **iface)
+5 -1
View File
@@ -1393,7 +1393,11 @@ static const video_poke_interface_t sdl_rs90_poke_interface = {
NULL, /* sdl_grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sdl_rs90_get_poke_interface(void *data, const video_poke_interface_t **iface)
+4
View File
@@ -551,6 +551,10 @@ static const video_poke_interface_t sixel_poke_interface = {
NULL,
NULL,
NULL,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sixel_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -951,7 +951,11 @@ static const video_poke_interface_t sunxi_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void sunxi_gfx_get_poke_interface(void *data,
+4
View File
@@ -397,6 +397,10 @@ static const video_poke_interface_t switch_poke_interface = {
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void switch_get_poke_interface(void *data,
+4
View File
@@ -682,6 +682,10 @@ static const video_poke_interface_t switch_poke_interface = {
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void switch_get_poke_interface(void *data,
+5 -1
View File
@@ -385,7 +385,11 @@ static const video_poke_interface_t vga_poke_interface = {
NULL, /* grab_mouse_toggle */
NULL, /* get_current_shader */
NULL, /* get_current_software_framebuffer */
NULL /* get_hw_render_interface */
NULL, /* get_hw_render_interface */
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void vga_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -824,7 +824,11 @@ static const video_poke_interface_t vita_poke_interface = {
NULL,
NULL,
vita_get_current_sw_framebuffer,
NULL
NULL,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void vita2d_gfx_get_poke_interface(void *data,
+5 -1
View File
@@ -1894,7 +1894,7 @@ static bool vulkan_frame(void *data, const void *frame,
if (vk->hw.enable)
{
/* Does this make that this can happen at all? */
if (vk->hw.image)
if (vk->hw.image && vk->hw.image->create_info.image)
{
input.image = vk->hw.image->create_info.image;
input.view = vk->hw.image->image_view;
@@ -2638,6 +2638,10 @@ static const video_poke_interface_t vulkan_poke_interface = {
vulkan_get_current_shader,
vulkan_get_current_sw_framebuffer,
vulkan_get_hw_render_interface,
NULL, /* set_hdr_max_nits */
NULL, /* set_hdr_paper_white_nits */
NULL, /* set_hdr_contrast */
NULL /* set_hdr_expand_gamut */
};
static void vulkan_get_poke_interface(void *data,
Loaded 100 of 319 files, more files were not shown because too many files have changed in this diff. Show more